Biju Das needs a patch for rz-du merged in 7.0-rc3
Unified · Split
| @@ -219,6 +219,7 @@ Daniele Alessandrelli <daniele.alessandrelli@gmail.com> <daniele.alessandrelli@i · 218 unmodified lines | ||
| 219 | 219 | Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com> |
| 220 | 220 | David Brownell <david-b@pacbell.net> |
| 221 | 221 | David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org> |
| 222 | +David Gow <david@davidgow.net> <davidgow@google.com> | |
| 222 | 223 | David Heidelberg <david@ixit.cz> <d.okias@gmail.com> |
| 223 | 224 | David Hildenbrand <david@kernel.org> <david@redhat.com> |
| 224 | 225 | David Rheinsberg <david@readahead.eu> <dh.herrmann@gmail.com> |
| @@ -353,6 +354,7 @@ Jarkko Sakkinen <jarkko@kernel.org> <jarkko.sakkinen@opinsys.com> · 128 unmodified lines | ||
| 353 | 354 | Jason Gunthorpe <jgg@ziepe.ca> <jgg@mellanox.com> |
| 354 | 355 | Jason Gunthorpe <jgg@ziepe.ca> <jgg@nvidia.com> |
| 355 | 356 | Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com> |
| 357 | +Jason Xing <kerneljasonxing@gmail.com> <kernelxing@tencent.com> | |
| 356 | 358 | <javier@osg.samsung.com> <javier.martinez@collabora.co.uk> |
| 357 | 359 | Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com> |
| 358 | 360 | Jayachandran C <c.jayachandran@gmail.com> <jayachandranc@netlogicmicro.com> |
| @@ -401,6 +403,7 @@ Jiri Slaby <jirislaby@kernel.org> <xslaby@fi.muni.cz> · 42 unmodified lines | ||
| 401 | 403 | Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com> |
| 402 | 404 | Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com> |
| 403 | 405 | Jishnu Prakash <quic_jprakash@quicinc.com> <jprakash@codeaurora.org> |
| 406 | +Joe Damato <joe@dama.to> <jdamato@fastly.com> | |
| 404 | 407 | Joel Granados <joel.granados@kernel.org> <j.granados@samsung.com> |
| 405 | 408 | Johan Hovold <johan@kernel.org> <jhovold@gmail.com> |
| 406 | 409 | Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com> |
| @@ -1242,6 +1242,10 @@ N: Veaceslav Falico · 1241 unmodified lines | ||
| 1242 | 1242 | E: vfalico@gmail.com |
| 1243 | 1243 | D: Co-maintainer and co-author of the network bonding driver. |
| 1244 | 1244 | |
| 1245 | +N: Thomas Falcon | |
| 1246 | +E: tlfalcon@linux.ibm.com | |
| 1247 | +D: Initial author of the IBM ibmvnic network driver | |
| 1248 | + | |
| 1245 | 1249 | N: János Farkas |
| 1246 | 1250 | E: chexum@shadow.banki.hu |
| 1247 | 1251 | D: romfs, various (mostly networking) fixes |
| @@ -2415,6 +2419,10 @@ S: Am Muehlenweg 38 · 1167 unmodified lines | ||
| 2415 | 2419 | S: D53424 Remagen |
| 2416 | 2420 | S: Germany |
| 2417 | 2421 | |
| 2422 | +N: Jonathan Lemon | |
| 2423 | +E: jonathan.lemon@gmail.com | |
| 2424 | +D: OpenCompute PTP clock driver (ptp_ocp) | |
| 2425 | + | |
| 2418 | 2426 | N: Colin Leroy |
| 2419 | 2427 | E: colin@colino.net |
| 2420 | 2428 | W: http://www.geekounet.org/ |
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/bus/platform/devices/INOU0000:XX/fn_lock_toggle_enable | |
| 1 | +What: /sys/bus/platform/devices/INOU0000:XX/fn_lock | |
| 2 | 2 | Date: November 2025 |
| 3 | 3 | KernelVersion: 6.19 |
| 4 | 4 | Contact: Armin Wolf <W_Armin@gmx.de> |
| @@ -8,15 +8,15 @@ Description: · 3 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | Reading this file returns the current enable status of the FN lock functionality. |
| 10 | 10 | |
| 11 | −What: /sys/bus/platform/devices/INOU0000:XX/super_key_toggle_enable | |
| 11 | +What: /sys/bus/platform/devices/INOU0000:XX/super_key_enable | |
| 12 | 12 | Date: November 2025 |
| 13 | 13 | KernelVersion: 6.19 |
| 14 | 14 | Contact: Armin Wolf <W_Armin@gmx.de> |
| 15 | 15 | Description: |
| 16 | − Allows userspace applications to enable/disable the super key functionality | |
| 17 | − of the integrated keyboard by writing "1"/"0" into this file. | |
| 16 | + Allows userspace applications to enable/disable the super key of the integrated | |
| 17 | + keyboard by writing "1"/"0" into this file. | |
| 18 | 18 | |
| 19 | − Reading this file returns the current enable status of the super key functionality. | |
| 19 | + Reading this file returns the current enable status of the super key. | |
| 20 | 20 | |
| 21 | 21 | What: /sys/bus/platform/devices/INOU0000:XX/touchpad_toggle_enable |
| 22 | 22 | Date: November 2025 |
| @@ -74,6 +74,7 @@ · 73 unmodified lines | ||
| 74 | 74 | TPM TPM drivers are enabled. |
| 75 | 75 | UMS USB Mass Storage support is enabled. |
| 76 | 76 | USB USB support is enabled. |
| 77 | + NVME NVMe support is enabled | |
| 77 | 78 | USBHID USB Human Interface Device support is enabled. |
| 78 | 79 | V4L Video For Linux support is enabled. |
| 79 | 80 | VGA The VGA console has been enabled. |
| @@ -4787,6 +4788,18 @@ Kernel parameters · 4707 unmodified lines | ||
| 4787 | 4788 | This can be set from sysctl after boot. |
| 4788 | 4789 | See Documentation/admin-guide/sysctl/vm.rst for details. |
| 4789 | 4790 | |
| 4791 | + nvme.quirks= [NVME] A list of quirk entries to augment the built-in | |
| 4792 | + nvme quirk list. List entries are separated by a | |
| 4793 | + '-' character. | |
| 4794 | + Each entry has the form VendorID:ProductID:quirk_names. | |
| 4795 | + The IDs are 4-digits hex numbers and quirk_names is a | |
| 4796 | + list of quirk names separated by commas. A quirk name | |
| 4797 | + can be prefixed by '^', meaning that the specified | |
| 4798 | + quirk must be disabled. | |
| 4799 | + | |
| 4800 | + Example: | |
| 4801 | + nvme.quirks=7710:2267:bogus_nid,^identify_cns-9900:7711:broken_msi | |
| 4802 | + | |
| 4790 | 4803 | ohci1394_dma=early [HW,EARLY] enable debugging via the ohci1394 driver. |
| 4791 | 4804 | See Documentation/core-api/debugging-via-ohci1394.rst for more |
| 4792 | 4805 | info. |
| @@ -24,7 +24,7 @@ Keyboard settings · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | The ``uniwill-laptop`` driver allows the user to enable/disable: |
| 26 | 26 | |
| 27 | − - the FN and super key lock functionality of the integrated keyboard | |
| 27 | + - the FN lock and super key of the integrated keyboard | |
| 28 | 28 | - the touchpad toggle functionality of the integrated touchpad |
| 29 | 29 | |
| 30 | 30 | See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details. |
| @@ -16,7 +16,6 @@ description: | · 15 unmodified lines | ||
| 16 | 16 | properties: |
| 17 | 17 | compatible: |
| 18 | 18 | enum: |
| 19 | − - kontron,sa67mcu-hwmon | |
| 20 | 19 | - kontron,sl28cpld-fan |
| 21 | 20 | |
| 22 | 21 | reg: |
| @@ -87,6 +87,7 @@ required: · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | allOf: |
| 89 | 89 | - $ref: can-controller.yaml# |
| 90 | + - $ref: /schemas/memory-controllers/mc-peripheral-props.yaml | |
| 90 | 91 | - if: |
| 91 | 92 | properties: |
| 92 | 93 | compatible: |
| @@ -23,6 +23,7 @@ properties: · 22 unmodified lines | ||
| 23 | 23 | enum: |
| 24 | 24 | - nvidia,tegra210-audio-graph-card |
| 25 | 25 | - nvidia,tegra186-audio-graph-card |
| 26 | + - nvidia,tegra238-audio-graph-card | |
| 26 | 27 | - nvidia,tegra264-audio-graph-card |
| 27 | 28 | |
| 28 | 29 | clocks: |
| @@ -20,6 +20,7 @@ properties: · 19 unmodified lines | ||
| 20 | 20 | - renesas,r9a07g044-ssi # RZ/G2{L,LC} |
| 21 | 21 | - renesas,r9a07g054-ssi # RZ/V2L |
| 22 | 22 | - renesas,r9a08g045-ssi # RZ/G3S |
| 23 | + - renesas,r9a08g046-ssi # RZ/G3L | |
| 23 | 24 | - const: renesas,rz-ssi |
| 24 | 25 | |
| 25 | 26 | reg: |
| @@ -57,7 +57,7 @@ Supported chips: · 56 unmodified lines | ||
| 57 | 57 | - https://ww1.microchip.com/downloads/en/DeviceDoc/EMC1438%20DS%20Rev.%201.0%20(04-29-10).pdf |
| 58 | 58 | |
| 59 | 59 | Author: |
| 60 | − Kalhan Trisal <kalhan.trisal@intel.com | |
| 60 | + Kalhan Trisal <kalhan.trisal@intel.com> | |
| 61 | 61 | |
| 62 | 62 | |
| 63 | 63 | Description |
| @@ -220,7 +220,6 @@ Hardware Monitoring Kernel Drivers · 219 unmodified lines | ||
| 220 | 220 | q54sj108a2 |
| 221 | 221 | qnap-mcu-hwmon |
| 222 | 222 | raspberrypi-hwmon |
| 223 | − sa67 | |
| 224 | 223 | sbrmi |
| 225 | 224 | sbtsi_temp |
| 226 | 225 | sch5627 |
| @@ -1,41 +0,0 @@ | ||
| 1 | −.. SPDX-License-Identifier: GPL-2.0-only | |
| 2 | − | |
| 3 | −Kernel driver sa67mcu | |
| 4 | −===================== | |
| 5 | − | |
| 6 | −Supported chips: | |
| 7 | − | |
| 8 | − * Kontron sa67mcu | |
| 9 | − | |
| 10 | − Prefix: 'sa67mcu' | |
| 11 | − | |
| 12 | − Datasheet: not available | |
| 13 | − | |
| 14 | −Authors: Michael Walle <mwalle@kernel.org> | |
| 15 | − | |
| 16 | −Description | |
| 17 | −----------- | |
| 18 | − | |
| 19 | −The sa67mcu is a board management controller which also exposes a hardware | |
| 20 | −monitoring controller. | |
| 21 | − | |
| 22 | −The controller has two voltage and one temperature sensor. The values are | |
| 23 | −hold in two 8 bit registers to form one 16 bit value. Reading the lower byte | |
| 24 | −will also capture the high byte to make the access atomic. The unit of the | |
| 25 | −volatge sensors are 1mV and the unit of the temperature sensor is 0.1degC. | |
| 26 | − | |
| 27 | −Sysfs entries | |
| 28 | −------------- | |
| 29 | − | |
| 30 | −The following attributes are supported. | |
| 31 | − | |
| 32 | −======================= ======================================================== | |
| 33 | −in0_label "VDDIN" | |
| 34 | −in0_input Measured VDDIN voltage. | |
| 35 | − | |
| 36 | −in1_label "VDD_RTC" | |
| 37 | −in1_input Measured VDD_RTC voltage. | |
| 38 | − | |
| 39 | −temp1_input MCU temperature. Roughly the board temperature. | |
| 40 | −======================= ======================================================== | |
| 41 | − | |
| @@ -152,7 +152,7 @@ operations: · 151 unmodified lines | ||
| 152 | 152 | - compound-ops |
| 153 | 153 | - |
| 154 | 154 | name: threads-set |
| 155 | − doc: set the number of running threads | |
| 155 | + doc: set the maximum number of running threads | |
| 156 | 156 | attribute-set: server |
| 157 | 157 | flags: [admin-perm] |
| 158 | 158 | do: |
| @@ -165,7 +165,7 @@ operations: · 6 unmodified lines | ||
| 165 | 165 | - min-threads |
| 166 | 166 | - |
| 167 | 167 | name: threads-get |
| 168 | − doc: get the number of running threads | |
| 168 | + doc: get the maximum number of running threads | |
| 169 | 169 | attribute-set: server |
| 170 | 170 | do: |
| 171 | 171 | reply: |
| @@ -2372,6 +2372,10 @@ quirk_flags · 2371 unmodified lines | ||
| 2372 | 2372 | audible volume |
| 2373 | 2373 | * bit 25: ``mixer_capture_min_mute`` |
| 2374 | 2374 | Similar to bit 24 but for capture streams |
| 2375 | + * bit 26: ``skip_iface_setup`` | |
| 2376 | + Skip the probe-time interface setup (usb_set_interface, | |
| 2377 | + init_pitch, init_sample_rate); redundant with | |
| 2378 | + snd_usb_endpoint_prepare() at stream-open time | |
| 2375 | 2379 | |
| 2376 | 2380 | This module supports multiple devices, autoprobe and hotplugging. |
| 2377 | 2381 | |
| @@ -993,10 +993,8 @@ F: Documentation/devicetree/bindings/thermal/amazon,al-thermal.yaml · 992 unmodified lines | ||
| 993 | 993 | F: drivers/thermal/thermal_mmio.c |
| 994 | 994 | |
| 995 | 995 | AMAZON ETHERNET DRIVERS |
| 996 | −M: Shay Agroskin <shayagr@amazon.com> | |
| 997 | 996 | M: Arthur Kiyanovski <akiyano@amazon.com> |
| 998 | −R: David Arinzon <darinzon@amazon.com> | |
| 999 | −R: Saeed Bishara <saeedb@amazon.com> | |
| 997 | +M: David Arinzon <darinzon@amazon.com> | |
| 1000 | 998 | L: netdev@vger.kernel.org |
| 1001 | 999 | S: Maintained |
| 1002 | 1000 | F: Documentation/networking/device_drivers/ethernet/amazon/ena.rst |
| @@ -4617,7 +4615,6 @@ F: drivers/bluetooth/ · 3614 unmodified lines | ||
| 4617 | 4615 | |
| 4618 | 4616 | BLUETOOTH SUBSYSTEM |
| 4619 | 4617 | M: Marcel Holtmann <marcel@holtmann.org> |
| 4620 | −M: Johan Hedberg <johan.hedberg@gmail.com> | |
| 4621 | 4618 | M: Luiz Augusto von Dentz <luiz.dentz@gmail.com> |
| 4622 | 4619 | L: linux-bluetooth@vger.kernel.org |
| 4623 | 4620 | S: Supported |
| @@ -10187,8 +10184,8 @@ F: drivers/i2c/busses/i2c-cpm.c · 5563 unmodified lines | ||
| 10187 | 10184 | |
| 10188 | 10185 | FREESCALE IMX / MXC FEC DRIVER |
| 10189 | 10186 | M: Wei Fang <wei.fang@nxp.com> |
| 10187 | +R: Frank Li <frank.li@nxp.com> | |
| 10190 | 10188 | R: Shenwei Wang <shenwei.wang@nxp.com> |
| 10191 | −R: Clark Wang <xiaoning.wang@nxp.com> | |
| 10192 | 10189 | L: imx@lists.linux.dev |
| 10193 | 10190 | L: netdev@vger.kernel.org |
| 10194 | 10191 | S: Maintained |
| @@ -10500,7 +10497,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git · 305 unmodified lines | ||
| 10500 | 10497 | F: Documentation/trace/ftrace* |
| 10501 | 10498 | F: arch/*/*/*/*ftrace* |
| 10502 | 10499 | F: arch/*/*/*ftrace* |
| 10503 | −F: include/*/ftrace.h | |
| 10500 | +F: include/*/*ftrace* | |
| 10504 | 10501 | F: kernel/trace/fgraph.c |
| 10505 | 10502 | F: kernel/trace/ftrace* |
| 10506 | 10503 | F: samples/ftrace |
| @@ -12233,7 +12230,6 @@ IBM Power SRIOV Virtual NIC Device Driver · 1726 unmodified lines | ||
| 12233 | 12230 | M: Haren Myneni <haren@linux.ibm.com> |
| 12234 | 12231 | M: Rick Lindsley <ricklind@linux.ibm.com> |
| 12235 | 12232 | R: Nick Child <nnac123@linux.ibm.com> |
| 12236 | −R: Thomas Falcon <tlfalcon@linux.ibm.com> | |
| 12237 | 12233 | L: netdev@vger.kernel.org |
| 12238 | 12234 | S: Maintained |
| 12239 | 12235 | F: drivers/net/ethernet/ibm/ibmvnic.* |
| @@ -13958,7 +13954,7 @@ F: fs/smb/server/ · 1718 unmodified lines | ||
| 13958 | 13954 | |
| 13959 | 13955 | KERNEL UNIT TESTING FRAMEWORK (KUnit) |
| 13960 | 13956 | M: Brendan Higgins <brendan.higgins@linux.dev> |
| 13961 | −M: David Gow <davidgow@google.com> | |
| 13957 | +M: David Gow <david@davidgow.net> | |
| 13962 | 13958 | R: Rae Moar <raemoar63@gmail.com> |
| 13963 | 13959 | L: linux-kselftest@vger.kernel.org |
| 13964 | 13960 | L: kunit-dev@googlegroups.com |
| @@ -14778,7 +14774,7 @@ F: drivers/misc/lis3lv02d/ · 813 unmodified lines | ||
| 14778 | 14774 | F: drivers/platform/x86/hp/hp_accel.c |
| 14779 | 14775 | |
| 14780 | 14776 | LIST KUNIT TEST |
| 14781 | −M: David Gow <davidgow@google.com> | |
| 14777 | +M: David Gow <david@davidgow.net> | |
| 14782 | 14778 | L: linux-kselftest@vger.kernel.org |
| 14783 | 14779 | L: kunit-dev@googlegroups.com |
| 14784 | 14780 | S: Maintained |
| @@ -15391,10 +15387,8 @@ F: drivers/crypto/marvell/ · 606 unmodified lines | ||
| 15391 | 15387 | F: include/linux/soc/marvell/octeontx2/ |
| 15392 | 15388 | |
| 15393 | 15389 | MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) |
| 15394 | −M: Mirko Lindner <mlindner@marvell.com> | |
| 15395 | −M: Stephen Hemminger <stephen@networkplumber.org> | |
| 15396 | 15390 | L: netdev@vger.kernel.org |
| 15397 | −S: Odd fixes | |
| 15391 | +S: Orphan | |
| 15398 | 15392 | F: drivers/net/ethernet/marvell/sk* |
| 15399 | 15393 | |
| 15400 | 15394 | MARVELL LIBERTAS WIRELESS DRIVER |
| @@ -15491,7 +15485,6 @@ MARVELL OCTEONTX2 RVU ADMIN FUNCTION DRIVER · 90 unmodified lines | ||
| 15491 | 15485 | M: Sunil Goutham <sgoutham@marvell.com> |
| 15492 | 15486 | M: Linu Cherian <lcherian@marvell.com> |
| 15493 | 15487 | M: Geetha sowjanya <gakula@marvell.com> |
| 15494 | −M: Jerin Jacob <jerinj@marvell.com> | |
| 15495 | 15488 | M: hariprasad <hkelam@marvell.com> |
| 15496 | 15489 | M: Subbaraya Sundeep <sbhatta@marvell.com> |
| 15497 | 15490 | L: netdev@vger.kernel.org |
| @@ -15506,7 +15499,7 @@ S: Supported · 8 unmodified lines | ||
| 15506 | 15499 | F: drivers/perf/marvell_pem_pmu.c |
| 15507 | 15500 | |
| 15508 | 15501 | MARVELL PRESTERA ETHERNET SWITCH DRIVER |
| 15509 | −M: Taras Chornyi <taras.chornyi@plvision.eu> | |
| 15502 | +M: Elad Nachman <enachman@marvell.com> | |
| 15510 | 15503 | S: Supported |
| 15511 | 15504 | W: https://github.com/Marvell-switching/switchdev-prestera |
| 15512 | 15505 | F: drivers/net/ethernet/marvell/prestera/ |
| @@ -16180,7 +16173,6 @@ F: drivers/dma/mediatek/ · 667 unmodified lines | ||
| 16180 | 16173 | |
| 16181 | 16174 | MEDIATEK ETHERNET DRIVER |
| 16182 | 16175 | M: Felix Fietkau <nbd@nbd.name> |
| 16183 | −M: Sean Wang <sean.wang@mediatek.com> | |
| 16184 | 16176 | M: Lorenzo Bianconi <lorenzo@kernel.org> |
| 16185 | 16177 | L: netdev@vger.kernel.org |
| 16186 | 16178 | S: Maintained |
| @@ -16373,8 +16365,6 @@ F: include/soc/mediatek/smi.h · 186 unmodified lines | ||
| 16373 | 16365 | MEDIATEK SWITCH DRIVER |
| 16374 | 16366 | M: Chester A. Unal <chester.a.unal@arinc9.com> |
| 16375 | 16367 | M: Daniel Golle <daniel@makrotopia.org> |
| 16376 | −M: DENG Qingfang <dqfext@gmail.com> | |
| 16377 | −M: Sean Wang <sean.wang@mediatek.com> | |
| 16378 | 16368 | L: netdev@vger.kernel.org |
| 16379 | 16369 | S: Maintained |
| 16380 | 16370 | F: drivers/net/dsa/mt7530-mdio.c |
| @@ -19242,8 +19232,6 @@ F: tools/objtool/ · 2861 unmodified lines | ||
| 19242 | 19232 | |
| 19243 | 19233 | OCELOT ETHERNET SWITCH DRIVER |
| 19244 | 19234 | M: Vladimir Oltean <vladimir.oltean@nxp.com> |
| 19245 | −M: Claudiu Manoil <claudiu.manoil@nxp.com> | |
| 19246 | −M: Alexandre Belloni <alexandre.belloni@bootlin.com> | |
| 19247 | 19235 | M: UNGLinuxDriver@microchip.com |
| 19248 | 19236 | L: netdev@vger.kernel.org |
| 19249 | 19237 | S: Supported |
| @@ -19829,7 +19817,6 @@ F: arch/*/boot/dts/ · 579 unmodified lines | ||
| 19829 | 19817 | F: include/dt-bindings/ |
| 19830 | 19818 | |
| 19831 | 19819 | OPENCOMPUTE PTP CLOCK DRIVER |
| 19832 | −M: Jonathan Lemon <jonathan.lemon@gmail.com> | |
| 19833 | 19820 | M: Vadim Fedorenko <vadim.fedorenko@linux.dev> |
| 19834 | 19821 | L: netdev@vger.kernel.org |
| 19835 | 19822 | S: Maintained |
| @@ -20137,9 +20124,8 @@ F: Documentation/devicetree/bindings/pci/marvell,armada-3700-pcie.yaml · 301 unmodified lines | ||
| 20137 | 20124 | F: drivers/pci/controller/pci-aardvark.c |
| 20138 | 20125 | |
| 20139 | 20126 | PCI DRIVER FOR ALTERA PCIE IP |
| 20140 | −M: Joyce Ooi <joyce.ooi@intel.com> | |
| 20141 | 20127 | L: linux-pci@vger.kernel.org |
| 20142 | −S: Supported | |
| 20128 | +S: Orphan | |
| 20143 | 20129 | F: Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml |
| 20144 | 20130 | F: drivers/pci/controller/pcie-altera.c |
| 20145 | 20131 | |
| @@ -20384,9 +20370,8 @@ S: Supported · 238 unmodified lines | ||
| 20384 | 20370 | F: Documentation/PCI/pci-error-recovery.rst |
| 20385 | 20371 | |
| 20386 | 20372 | PCI MSI DRIVER FOR ALTERA MSI IP |
| 20387 | −M: Joyce Ooi <joyce.ooi@intel.com> | |
| 20388 | 20373 | L: linux-pci@vger.kernel.org |
| 20389 | −S: Supported | |
| 20374 | +S: Orphan | |
| 20390 | 20375 | F: Documentation/devicetree/bindings/interrupt-controller/altr,msi-controller.yaml |
| 20391 | 20376 | F: drivers/pci/controller/pcie-altera-msi.c |
| 20392 | 20377 | |
| @@ -21473,9 +21458,8 @@ S: Supported · 1080 unmodified lines | ||
| 21473 | 21458 | F: drivers/scsi/qedi/ |
| 21474 | 21459 | |
| 21475 | 21460 | QLOGIC QL4xxx ETHERNET DRIVER |
| 21476 | −M: Manish Chopra <manishc@marvell.com> | |
| 21477 | 21461 | L: netdev@vger.kernel.org |
| 21478 | −S: Maintained | |
| 21462 | +S: Orphan | |
| 21479 | 21463 | F: drivers/net/ethernet/qlogic/qed/ |
| 21480 | 21464 | F: drivers/net/ethernet/qlogic/qede/ |
| 21481 | 21465 | F: include/linux/qed/ |
| @@ -24353,7 +24337,6 @@ F: Documentation/devicetree/bindings/interrupt-controller/kontron,sl28cpld-intc. · 2871 unmodified lines | ||
| 24353 | 24337 | F: Documentation/devicetree/bindings/pwm/kontron,sl28cpld-pwm.yaml |
| 24354 | 24338 | F: Documentation/devicetree/bindings/watchdog/kontron,sl28cpld-wdt.yaml |
| 24355 | 24339 | F: drivers/gpio/gpio-sl28cpld.c |
| 24356 | −F: drivers/hwmon/sa67mcu-hwmon.c | |
| 24357 | 24340 | F: drivers/hwmon/sl28cpld-hwmon.c |
| 24358 | 24341 | F: drivers/irqchip/irq-sl28cpld.c |
| 24359 | 24342 | F: drivers/pwm/pwm-sl28cpld.c |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 7 |
| 3 | 3 | PATCHLEVEL = 0 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc2 | |
| 5 | +EXTRAVERSION = -rc3 | |
| 6 | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -1497,13 +1497,13 @@ ifneq ($(wildcard $(resolve_btfids_O)),) · 1488 unmodified lines | ||
| 1497 | 1497 | $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean |
| 1498 | 1498 | endif |
| 1499 | 1499 | |
| 1500 | −PHONY += objtool_clean | |
| 1500 | +PHONY += objtool_clean objtool_mrproper | |
| 1501 | 1501 | |
| 1502 | 1502 | objtool_O = $(abspath $(objtree))/tools/objtool |
| 1503 | 1503 | |
| 1504 | −objtool_clean: | |
| 1504 | +objtool_clean objtool_mrproper: | |
| 1505 | 1505 | ifneq ($(wildcard $(objtool_O)),) |
| 1506 | − $(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) clean | |
| 1506 | + $(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) $(patsubst objtool_%,%,$@) | |
| 1507 | 1507 | endif |
| 1508 | 1508 | |
| 1509 | 1509 | tools/: FORCE |
| @@ -1686,7 +1686,7 @@ PHONY += $(mrproper-dirs) mrproper · 176 unmodified lines | ||
| 1686 | 1686 | $(mrproper-dirs): |
| 1687 | 1687 | $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) |
| 1688 | 1688 | |
| 1689 | −mrproper: clean $(mrproper-dirs) | |
| 1689 | +mrproper: clean objtool_mrproper $(mrproper-dirs) | |
| 1690 | 1690 | $(call cmd,rmfiles) |
| 1691 | 1691 | @find . $(RCS_FIND_IGNORE) \ |
| 1692 | 1692 | \( -name '*.rmeta' \) \ |
| @@ -71,6 +71,7 @@ SECTIONS · 70 unmodified lines | ||
| 71 | 71 | |
| 72 | 72 | STABS_DEBUG |
| 73 | 73 | DWARF_DEBUG |
| 74 | + MODINFO | |
| 74 | 75 | ELF_DETAILS |
| 75 | 76 | |
| 76 | 77 | DISCARDS |
| @@ -123,6 +123,7 @@ SECTIONS · 122 unmodified lines | ||
| 123 | 123 | _end = . ; |
| 124 | 124 | |
| 125 | 125 | STABS_DEBUG |
| 126 | + MODINFO | |
| 126 | 127 | ELF_DETAILS |
| 127 | 128 | DISCARDS |
| 128 | 129 | |
| @@ -21,6 +21,7 @@ SECTIONS · 20 unmodified lines | ||
| 21 | 21 | COMMON_DISCARDS |
| 22 | 22 | *(.ARM.exidx*) |
| 23 | 23 | *(.ARM.extab*) |
| 24 | + *(.modinfo) | |
| 24 | 25 | *(.note.*) |
| 25 | 26 | *(.rel.*) |
| 26 | 27 | *(.printk_index) |
| @@ -154,6 +154,7 @@ SECTIONS · 153 unmodified lines | ||
| 154 | 154 | |
| 155 | 155 | STABS_DEBUG |
| 156 | 156 | DWARF_DEBUG |
| 157 | + MODINFO | |
| 157 | 158 | ARM_DETAILS |
| 158 | 159 | |
| 159 | 160 | ARM_ASSERTS |
| @@ -153,6 +153,7 @@ SECTIONS · 152 unmodified lines | ||
| 153 | 153 | |
| 154 | 154 | STABS_DEBUG |
| 155 | 155 | DWARF_DEBUG |
| 156 | + MODINFO | |
| 156 | 157 | ARM_DETAILS |
| 157 | 158 | |
| 158 | 159 | ARM_ASSERTS |
| @@ -91,8 +91,9 @@ __XCHG_GEN(_mb) · 90 unmodified lines | ||
| 91 | 91 | #define __xchg_wrapper(sfx, ptr, x) \ |
| 92 | 92 | ({ \ |
| 93 | 93 | __typeof__(*(ptr)) __ret; \ |
| 94 | − __ret = (__typeof__(*(ptr))) \ | |
| 95 | − __arch_xchg##sfx((unsigned long)(x), (ptr), sizeof(*(ptr))); \ | |
| 94 | + __ret = (__force __typeof__(*(ptr))) \ | |
| 95 | + __arch_xchg##sfx((__force unsigned long)(x), (ptr), \ | |
| 96 | + sizeof(*(ptr))); \ | |
| 96 | 97 | __ret; \ |
| 97 | 98 | }) |
| 98 | 99 | |
| @@ -175,9 +176,10 @@ __CMPXCHG_GEN(_mb) · 76 unmodified lines | ||
| 175 | 176 | #define __cmpxchg_wrapper(sfx, ptr, o, n) \ |
| 176 | 177 | ({ \ |
| 177 | 178 | __typeof__(*(ptr)) __ret; \ |
| 178 | − __ret = (__typeof__(*(ptr))) \ | |
| 179 | − __cmpxchg##sfx((ptr), (unsigned long)(o), \ | |
| 180 | − (unsigned long)(n), sizeof(*(ptr))); \ | |
| 179 | + __ret = (__force __typeof__(*(ptr))) \ | |
| 180 | + __cmpxchg##sfx((ptr), (__force unsigned long)(o), \ | |
| 181 | + (__force unsigned long)(n), \ | |
| 182 | + sizeof(*(ptr))); \ | |
| 181 | 183 | __ret; \ |
| 182 | 184 | }) |
| 183 | 185 | |
| @@ -50,11 +50,11 @@ · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | #define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) |
| 52 | 52 | |
| 53 | −#define _PAGE_KERNEL (PROT_NORMAL) | |
| 54 | −#define _PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) | |
| 55 | −#define _PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) | |
| 56 | −#define _PAGE_KERNEL_EXEC (PROT_NORMAL & ~PTE_PXN) | |
| 57 | −#define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT) | |
| 53 | +#define _PAGE_KERNEL (PROT_NORMAL | PTE_DIRTY) | |
| 54 | +#define _PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY | PTE_DIRTY) | |
| 55 | +#define _PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY | PTE_DIRTY) | |
| 56 | +#define _PAGE_KERNEL_EXEC ((PROT_NORMAL & ~PTE_PXN) | PTE_DIRTY) | |
| 57 | +#define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT | PTE_DIRTY) | |
| 58 | 58 | |
| 59 | 59 | #define _PAGE_SHARED (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) |
| 60 | 60 | #define _PAGE_SHARED_EXEC (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE) |
| @@ -2,6 +2,10 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef _ASM_RUNTIME_CONST_H |
| 3 | 3 | #define _ASM_RUNTIME_CONST_H |
| 4 | 4 | |
| 5 | +#ifdef MODULE | |
| 6 | + #error "Cannot use runtime-const infrastructure from modules" | |
| 7 | +#endif | |
| 8 | + | |
| 5 | 9 | #include <asm/cacheflush.h> |
| 6 | 10 | |
| 7 | 11 | /* Sigh. You can still run arm64 in BE mode */ |
| @@ -349,6 +349,7 @@ SECTIONS · 348 unmodified lines | ||
| 349 | 349 | |
| 350 | 350 | STABS_DEBUG |
| 351 | 351 | DWARF_DEBUG |
| 352 | + MODINFO | |
| 352 | 353 | ELF_DETAILS |
| 353 | 354 | |
| 354 | 355 | HEAD_SYMBOLS |
| @@ -599,6 +599,27 @@ void contpte_clear_young_dirty_ptes(struct vm_area_struct *vma, · 598 unmodified lines | ||
| 599 | 599 | } |
| 600 | 600 | EXPORT_SYMBOL_GPL(contpte_clear_young_dirty_ptes); |
| 601 | 601 | |
| 602 | +static bool contpte_all_subptes_match_access_flags(pte_t *ptep, pte_t entry) | |
| 603 | +{ | |
| 604 | + pte_t *cont_ptep = contpte_align_down(ptep); | |
| 605 | + /* | |
| 606 | + * PFNs differ per sub-PTE. Match only bits consumed by | |
| 607 | + * __ptep_set_access_flags(): AF, DIRTY and write permission. | |
| 608 | + */ | |
| 609 | + const pteval_t cmp_mask = PTE_RDONLY | PTE_AF | PTE_WRITE | PTE_DIRTY; | |
| 610 | + pteval_t entry_cmp = pte_val(entry) & cmp_mask; | |
| 611 | + int i; | |
| 612 | + | |
| 613 | + for (i = 0; i < CONT_PTES; i++) { | |
| 614 | + pteval_t pte_cmp = pte_val(__ptep_get(cont_ptep + i)) & cmp_mask; | |
| 615 | + | |
| 616 | + if (pte_cmp != entry_cmp) | |
| 617 | + return false; | |
| 618 | + } | |
| 619 | + | |
| 620 | + return true; | |
| 621 | +} | |
| 622 | + | |
| 602 | 623 | int contpte_ptep_set_access_flags(struct vm_area_struct *vma, |
| 603 | 624 | unsigned long addr, pte_t *ptep, |
| 604 | 625 | pte_t entry, int dirty) |
| @@ -608,13 +629,37 @@ int contpte_ptep_set_access_flags(struct vm_area_struct *vma, · 3 unmodified lines | ||
| 608 | 629 | int i; |
| 609 | 630 | |
| 610 | 631 | /* |
| 611 | − * Gather the access/dirty bits for the contiguous range. If nothing has | |
| 612 | − * changed, its a noop. | |
| 632 | + * Check whether all sub-PTEs in the CONT block already match the | |
| 633 | + * requested access flags/write permission, using raw per-PTE values | |
| 634 | + * rather than the gathered ptep_get() view. | |
| 635 | + * | |
| 636 | + * __ptep_set_access_flags() can update AF, dirty and write | |
| 637 | + * permission, but only to make the mapping more permissive. | |
| 638 | + * | |
| 639 | + * ptep_get() gathers AF/dirty state across the whole CONT block, | |
| 640 | + * which is correct for a CPU with FEAT_HAFDBS. But page-table | |
| 641 | + * walkers that evaluate each descriptor individually (e.g. a CPU | |
| 642 | + * without DBM support, or an SMMU without HTTU, or with HA/HD | |
| 643 | + * disabled in CD.TCR) can keep faulting on the target sub-PTE if | |
| 644 | + * only a sibling has been updated. Gathering can therefore cause | |
| 645 | + * false no-ops when only a sibling has been updated: | |
| 646 | + * - write faults: target still has PTE_RDONLY (needs PTE_RDONLY cleared) | |
| 647 | + * - read faults: target still lacks PTE_AF | |
| 648 | + * | |
| 649 | + * Per Arm ARM (DDI 0487) D8.7.1, any sub-PTE in a CONT range may | |
| 650 | + * become the effective cached translation, so all entries must have | |
| 651 | + * consistent attributes. Check the full CONT block before returning | |
| 652 | + * no-op, and when any sub-PTE mismatches, proceed to update the whole | |
| 653 | + * range. | |
| 613 | 654 | */ |
| 614 | − orig_pte = pte_mknoncont(ptep_get(ptep)); | |
| 615 | − if (pte_val(orig_pte) == pte_val(entry)) | |
| 655 | + if (contpte_all_subptes_match_access_flags(ptep, entry)) | |
| 616 | 656 | return 0; |
| 617 | 657 | |
| 658 | + /* | |
| 659 | + * Use raw target pte (not gathered) for write-bit unfold decision. | |
| 660 | + */ | |
| 661 | + orig_pte = pte_mknoncont(__ptep_get(ptep)); | |
| 662 | + | |
| 618 | 663 | /* |
| 619 | 664 | * We can fix up access/dirty bits without having to unfold the contig |
| 620 | 665 | * range. But if the write bit is changing, we must unfold. |
| @@ -109,6 +109,7 @@ SECTIONS · 108 unmodified lines | ||
| 109 | 109 | |
| 110 | 110 | STABS_DEBUG |
| 111 | 111 | DWARF_DEBUG |
| 112 | + MODINFO | |
| 112 | 113 | ELF_DETAILS |
| 113 | 114 | |
| 114 | 115 | DISCARDS |
| @@ -62,6 +62,7 @@ SECTIONS · 61 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | STABS_DEBUG |
| 64 | 64 | DWARF_DEBUG |
| 65 | + MODINFO | |
| 65 | 66 | ELF_DETAILS |
| 66 | 67 | .hexagon.attributes 0 : { *(.hexagon.attributes) } |
| 67 | 68 | |
| @@ -147,6 +147,7 @@ SECTIONS · 146 unmodified lines | ||
| 147 | 147 | |
| 148 | 148 | STABS_DEBUG |
| 149 | 149 | DWARF_DEBUG |
| 150 | + MODINFO | |
| 150 | 151 | ELF_DETAILS |
| 151 | 152 | |
| 152 | 153 | #ifdef CONFIG_EFI_STUB |
| @@ -85,6 +85,7 @@ SECTIONS { · 84 unmodified lines | ||
| 85 | 85 | _end = .; |
| 86 | 86 | |
| 87 | 87 | STABS_DEBUG |
| 88 | + MODINFO | |
| 88 | 89 | ELF_DETAILS |
| 89 | 90 | |
| 90 | 91 | /* Sections to be discarded */ |
| @@ -58,6 +58,7 @@ SECTIONS · 57 unmodified lines | ||
| 58 | 58 | _end = . ; |
| 59 | 59 | |
| 60 | 60 | STABS_DEBUG |
| 61 | + MODINFO | |
| 61 | 62 | ELF_DETAILS |
| 62 | 63 | |
| 63 | 64 | /* Sections to be discarded */ |
| @@ -51,6 +51,7 @@ __init_begin = .; · 50 unmodified lines | ||
| 51 | 51 | _end = . ; |
| 52 | 52 | |
| 53 | 53 | STABS_DEBUG |
| 54 | + MODINFO | |
| 54 | 55 | ELF_DETAILS |
| 55 | 56 | |
| 56 | 57 | /* Sections to be discarded */ |
| @@ -217,6 +217,7 @@ SECTIONS · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | STABS_DEBUG |
| 219 | 219 | DWARF_DEBUG |
| 220 | + MODINFO | |
| 220 | 221 | ELF_DETAILS |
| 221 | 222 | |
| 222 | 223 | /* These must appear regardless of . */ |
| @@ -57,6 +57,7 @@ SECTIONS · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | STABS_DEBUG |
| 59 | 59 | DWARF_DEBUG |
| 60 | + MODINFO | |
| 60 | 61 | ELF_DETAILS |
| 61 | 62 | |
| 62 | 63 | DISCARDS |
| @@ -101,6 +101,7 @@ SECTIONS · 100 unmodified lines | ||
| 101 | 101 | /* Throw in the debugging sections */ |
| 102 | 102 | STABS_DEBUG |
| 103 | 103 | DWARF_DEBUG |
| 104 | + MODINFO | |
| 104 | 105 | ELF_DETAILS |
| 105 | 106 | |
| 106 | 107 | /* Sections to be discarded -- must be last */ |
| @@ -90,6 +90,7 @@ SECTIONS · 89 unmodified lines | ||
| 90 | 90 | /* Sections to be discarded */ |
| 91 | 91 | DISCARDS |
| 92 | 92 | /DISCARD/ : { |
| 93 | + *(.modinfo) | |
| 93 | 94 | #ifdef CONFIG_64BIT |
| 94 | 95 | /* temporary hack until binutils is fixed to not emit these |
| 95 | 96 | * for static binaries |
| @@ -85,7 +85,7 @@ extern void __update_cache(pte_t pte); · 84 unmodified lines | ||
| 85 | 85 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e)) |
| 86 | 86 | |
| 87 | 87 | /* This is the size of the initially mapped kernel memory */ |
| 88 | −#if defined(CONFIG_64BIT) | |
| 88 | +#if defined(CONFIG_64BIT) || defined(CONFIG_KALLSYMS) | |
| 89 | 89 | #define KERNEL_INITIAL_ORDER 26 /* 1<<26 = 64MB */ |
| 90 | 90 | #else |
| 91 | 91 | #define KERNEL_INITIAL_ORDER 25 /* 1<<25 = 32MB */ |
| @@ -56,6 +56,7 @@ ENTRY(parisc_kernel_start) · 55 unmodified lines | ||
| 56 | 56 | |
| 57 | 57 | .import __bss_start,data |
| 58 | 58 | .import __bss_stop,data |
| 59 | + .import __end,data | |
| 59 | 60 | |
| 60 | 61 | load32 PA(__bss_start),%r3 |
| 61 | 62 | load32 PA(__bss_stop),%r4 |
| @@ -149,7 +150,11 @@ $cpu_ok: · 87 unmodified lines | ||
| 149 | 150 | * everything ... it will get remapped correctly later */ |
| 150 | 151 | ldo 0+_PAGE_KERNEL_RWX(%r0),%r3 /* Hardwired 0 phys addr start */ |
| 151 | 152 | load32 (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */ |
| 152 | − load32 PA(pg0),%r1 | |
| 153 | + load32 PA(_end),%r1 | |
| 154 | + SHRREG %r1,PAGE_SHIFT,%r1 /* %r1 is PFN count for _end symbol */ | |
| 155 | + cmpb,<<,n %r11,%r1,1f | |
| 156 | + copy %r1,%r11 /* %r1 PFN count smaller than %r11 */ | |
| 157 | +1: load32 PA(pg0),%r1 | |
| 153 | 158 | |
| 154 | 159 | $pgt_fill_loop: |
| 155 | 160 | STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1) |
| @@ -120,14 +120,6 @@ void __init setup_arch(char **cmdline_p) · 119 unmodified lines | ||
| 120 | 120 | #endif |
| 121 | 121 | printk(KERN_CONT ".\n"); |
| 122 | 122 | |
| 123 | − /* | |
| 124 | − * Check if initial kernel page mappings are sufficient. | |
| 125 | − * panic early if not, else we may access kernel functions | |
| 126 | − * and variables which can't be reached. | |
| 127 | − */ | |
| 128 | − if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE) | |
| 129 | − panic("KERNEL_INITIAL_ORDER too small!"); | |
| 130 | − | |
| 131 | 123 | #ifdef CONFIG_64BIT |
| 132 | 124 | if(parisc_narrow_firmware) { |
| 133 | 125 | printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n"); |
| @@ -279,6 +271,18 @@ void __init start_parisc(void) · 145 unmodified lines | ||
| 279 | 271 | int ret, cpunum; |
| 280 | 272 | struct pdc_coproc_cfg coproc_cfg; |
| 281 | 273 | |
| 274 | + /* | |
| 275 | + * Check if initial kernel page mapping is sufficient. | |
| 276 | + * Print warning if not, because we may access kernel functions and | |
| 277 | + * variables which can't be reached yet through the initial mappings. | |
| 278 | + * Note that the panic() and printk() functions are not functional | |
| 279 | + * yet, so we need to use direct iodc() firmware calls instead. | |
| 280 | + */ | |
| 281 | + const char warn1[] = "CRITICAL: Kernel may crash because " | |
| 282 | + "KERNEL_INITIAL_ORDER is too small.\n"; | |
| 283 | + if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE) | |
| 284 | + pdc_iodc_print(warn1, sizeof(warn1) - 1); | |
| 285 | + | |
| 282 | 286 | /* check QEMU/SeaBIOS marker in PAGE0 */ |
| 283 | 287 | running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0); |
| 284 | 288 | |
| @@ -165,6 +165,7 @@ SECTIONS · 164 unmodified lines | ||
| 165 | 165 | _end = . ; |
| 166 | 166 | |
| 167 | 167 | STABS_DEBUG |
| 168 | + MODINFO | |
| 168 | 169 | ELF_DETAILS |
| 169 | 170 | .note 0 : { *(.note) } |
| 170 | 171 | |
| @@ -212,6 +212,13 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, · 211 unmodified lines | ||
| 212 | 212 | dev->error_state = pci_channel_io_normal; |
| 213 | 213 | dev->dma_mask = 0xffffffff; |
| 214 | 214 | |
| 215 | + /* | |
| 216 | + * Assume 64-bit addresses for MSI initially. Will be changed to 32-bit | |
| 217 | + * if MSI (rather than MSI-X) capability does not have | |
| 218 | + * PCI_MSI_FLAGS_64BIT. Can also be overridden by driver. | |
| 219 | + */ | |
| 220 | + dev->msi_addr_mask = DMA_BIT_MASK(64); | |
| 221 | + | |
| 215 | 222 | /* Early fixups, before probing the BARs */ |
| 216 | 223 | pci_fixup_device(pci_fixup_early, dev); |
| 217 | 224 | |
| @@ -397,6 +397,7 @@ SECTIONS · 396 unmodified lines | ||
| 397 | 397 | _end = . ; |
| 398 | 398 | |
| 399 | 399 | DWARF_DEBUG |
| 400 | + MODINFO | |
| 400 | 401 | ELF_DETAILS |
| 401 | 402 | |
| 402 | 403 | DISCARDS |
| @@ -170,6 +170,7 @@ SECTIONS · 169 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | STABS_DEBUG |
| 172 | 172 | DWARF_DEBUG |
| 173 | + MODINFO | |
| 173 | 174 | ELF_DETAILS |
| 174 | 175 | .riscv.attributes 0 : { *(.riscv.attributes) } |
| 175 | 176 | |
| @@ -159,7 +159,7 @@ static __always_inline void __stackleak_poison(unsigned long erase_low, · 158 unmodified lines | ||
| 159 | 159 | " j 4f\n" |
| 160 | 160 | "3: mvc 8(1,%[addr]),0(%[addr])\n" |
| 161 | 161 | "4:" |
| 162 | − : [addr] "+&a" (erase_low), [count] "+&d" (count), [tmp] "=&a" (tmp) | |
| 162 | + : [addr] "+&a" (erase_low), [count] "+&a" (count), [tmp] "=&a" (tmp) | |
| 163 | 163 | : [poison] "d" (poison) |
| 164 | 164 | : "memory", "cc" |
| 165 | 165 | ); |
| @@ -221,6 +221,7 @@ SECTIONS · 220 unmodified lines | ||
| 221 | 221 | /* Debugging sections. */ |
| 222 | 222 | STABS_DEBUG |
| 223 | 223 | DWARF_DEBUG |
| 224 | + MODINFO | |
| 224 | 225 | ELF_DETAILS |
| 225 | 226 | |
| 226 | 227 | /* |
| @@ -28,8 +28,8 @@ static void xor_xc_2(unsigned long bytes, unsigned long * __restrict p1, · 27 unmodified lines | ||
| 28 | 28 | " j 3f\n" |
| 29 | 29 | "2: xc 0(1,%1),0(%2)\n" |
| 30 | 30 | "3:" |
| 31 | − : : "d" (bytes), "a" (p1), "a" (p2) | |
| 32 | − : "0", "cc", "memory"); | |
| 31 | + : "+a" (bytes), "+a" (p1), "+a" (p2) | |
| 32 | + : : "0", "cc", "memory"); | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | static void xor_xc_3(unsigned long bytes, unsigned long * __restrict p1, |
| @@ -54,7 +54,7 @@ static void xor_xc_3(unsigned long bytes, unsigned long * __restrict p1, · 18 unmodified lines | ||
| 54 | 54 | "2: xc 0(1,%1),0(%2)\n" |
| 55 | 55 | "3: xc 0(1,%1),0(%3)\n" |
| 56 | 56 | "4:" |
| 57 | − : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3) | |
| 57 | + : "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3) | |
| 58 | 58 | : : "0", "cc", "memory"); |
| 59 | 59 | } |
| 60 | 60 | |
| @@ -85,7 +85,7 @@ static void xor_xc_4(unsigned long bytes, unsigned long * __restrict p1, · 24 unmodified lines | ||
| 85 | 85 | "3: xc 0(1,%1),0(%3)\n" |
| 86 | 86 | "4: xc 0(1,%1),0(%4)\n" |
| 87 | 87 | "5:" |
| 88 | − : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4) | |
| 88 | + : "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4) | |
| 89 | 89 | : : "0", "cc", "memory"); |
| 90 | 90 | } |
| 91 | 91 | |
| @@ -96,7 +96,6 @@ static void xor_xc_5(unsigned long bytes, unsigned long * __restrict p1, · 4 unmodified lines | ||
| 96 | 96 | const unsigned long * __restrict p5) |
| 97 | 97 | { |
| 98 | 98 | asm volatile( |
| 99 | − " larl 1,2f\n" | |
| 100 | 99 | " aghi %0,-1\n" |
| 101 | 100 | " jm 6f\n" |
| 102 | 101 | " srlg 0,%0,8\n" |
| @@ -122,7 +121,7 @@ static void xor_xc_5(unsigned long bytes, unsigned long * __restrict p1, · 19 unmodified lines | ||
| 122 | 121 | "4: xc 0(1,%1),0(%4)\n" |
| 123 | 122 | "5: xc 0(1,%1),0(%5)\n" |
| 124 | 123 | "6:" |
| 125 | − : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4), | |
| 124 | + : "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4), | |
| 126 | 125 | "+a" (p5) |
| 127 | 126 | : : "0", "cc", "memory"); |
| 128 | 127 | } |
| @@ -89,6 +89,7 @@ SECTIONS · 88 unmodified lines | ||
| 89 | 89 | |
| 90 | 90 | STABS_DEBUG |
| 91 | 91 | DWARF_DEBUG |
| 92 | + MODINFO | |
| 92 | 93 | ELF_DETAILS |
| 93 | 94 | |
| 94 | 95 | DISCARDS |
| @@ -355,6 +355,13 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, · 354 unmodified lines | ||
| 355 | 355 | dev->error_state = pci_channel_io_normal; |
| 356 | 356 | dev->dma_mask = 0xffffffff; |
| 357 | 357 | |
| 358 | + /* | |
| 359 | + * Assume 64-bit addresses for MSI initially. Will be changed to 32-bit | |
| 360 | + * if MSI (rather than MSI-X) capability does not have | |
| 361 | + * PCI_MSI_FLAGS_64BIT. Can also be overridden by driver. | |
| 362 | + */ | |
| 363 | + dev->msi_addr_mask = DMA_BIT_MASK(64); | |
| 364 | + | |
| 358 | 365 | if (of_node_name_eq(node, "pci")) { |
| 359 | 366 | /* a PCI-PCI bridge */ |
| 360 | 367 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; |
| @@ -191,6 +191,7 @@ SECTIONS · 190 unmodified lines | ||
| 191 | 191 | |
| 192 | 192 | STABS_DEBUG |
| 193 | 193 | DWARF_DEBUG |
| 194 | + MODINFO | |
| 194 | 195 | ELF_DETAILS |
| 195 | 196 | |
| 196 | 197 | DISCARDS |
| @@ -172,6 +172,7 @@ SECTIONS · 171 unmodified lines | ||
| 172 | 172 | |
| 173 | 173 | STABS_DEBUG |
| 174 | 174 | DWARF_DEBUG |
| 175 | + MODINFO | |
| 175 | 176 | ELF_DETAILS |
| 176 | 177 | |
| 177 | 178 | DISCARDS |
| @@ -113,6 +113,7 @@ SECTIONS · 112 unmodified lines | ||
| 113 | 113 | |
| 114 | 114 | STABS_DEBUG |
| 115 | 115 | DWARF_DEBUG |
| 116 | + MODINFO | |
| 116 | 117 | ELF_DETAILS |
| 117 | 118 | |
| 118 | 119 | DISCARDS |
| @@ -113,6 +113,7 @@ vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o · 112 unmodified lines | ||
| 113 | 113 | |
| 114 | 114 | ifdef CONFIG_EFI_SBAT |
| 115 | 115 | $(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE) |
| 116 | +AFLAGS_sbat.o += -I $(srctree) | |
| 116 | 117 | endif |
| 117 | 118 | |
| 118 | 119 | $(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE |
| @@ -28,17 +28,17 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "sev.h" |
| 29 | 29 | |
| 30 | 30 | static struct ghcb boot_ghcb_page __aligned(PAGE_SIZE); |
| 31 | −struct ghcb *boot_ghcb; | |
| 31 | +struct ghcb *boot_ghcb __section(".data"); | |
| 32 | 32 | |
| 33 | 33 | #undef __init |
| 34 | 34 | #define __init |
| 35 | 35 | |
| 36 | 36 | #define __BOOT_COMPRESSED |
| 37 | 37 | |
| 38 | −u8 snp_vmpl; | |
| 39 | −u16 ghcb_version; | |
| 38 | +u8 snp_vmpl __section(".data"); | |
| 39 | +u16 ghcb_version __section(".data"); | |
| 40 | 40 | |
| 41 | −u64 boot_svsm_caa_pa; | |
| 41 | +u64 boot_svsm_caa_pa __section(".data"); | |
| 42 | 42 | |
| 43 | 43 | /* Include code for early handlers */ |
| 44 | 44 | #include "../../boot/startup/sev-shared.c" |
| @@ -188,6 +188,7 @@ bool sev_es_check_ghcb_fault(unsigned long address) · 143 unmodified lines | ||
| 188 | 188 | MSR_AMD64_SNP_RESERVED_BIT13 | \ |
| 189 | 189 | MSR_AMD64_SNP_RESERVED_BIT15 | \ |
| 190 | 190 | MSR_AMD64_SNP_SECURE_AVIC | \ |
| 191 | + MSR_AMD64_SNP_RESERVED_BITS19_22 | \ | |
| 191 | 192 | MSR_AMD64_SNP_RESERVED_MASK) |
| 192 | 193 | |
| 193 | 194 | #ifdef CONFIG_AMD_SECURE_AVIC |
| @@ -88,7 +88,7 @@ SECTIONS · 87 unmodified lines | ||
| 88 | 88 | /DISCARD/ : { |
| 89 | 89 | *(.dynamic) *(.dynsym) *(.dynstr) *(.dynbss) |
| 90 | 90 | *(.hash) *(.gnu.hash) |
| 91 | − *(.note.*) | |
| 91 | + *(.note.*) *(.modinfo) | |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | .got.plt (INFO) : { |
| @@ -31,7 +31,7 @@ static u32 cpuid_std_range_max __ro_after_init; · 30 unmodified lines | ||
| 31 | 31 | static u32 cpuid_hyp_range_max __ro_after_init; |
| 32 | 32 | static u32 cpuid_ext_range_max __ro_after_init; |
| 33 | 33 | |
| 34 | −bool sev_snp_needs_sfw; | |
| 34 | +bool sev_snp_needs_sfw __section(".data"); | |
| 35 | 35 | |
| 36 | 36 | void __noreturn |
| 37 | 37 | sev_es_terminate(unsigned int set, unsigned int reason) |
| @@ -89,6 +89,7 @@ static const char * const sev_status_feat_names[] = { · 88 unmodified lines | ||
| 89 | 89 | [MSR_AMD64_SNP_VMSA_REG_PROT_BIT] = "VMSARegProt", |
| 90 | 90 | [MSR_AMD64_SNP_SMT_PROT_BIT] = "SMTProt", |
| 91 | 91 | [MSR_AMD64_SNP_SECURE_AVIC_BIT] = "SecureAVIC", |
| 92 | + [MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT] = "IBPBOnEntry", | |
| 92 | 93 | }; |
| 93 | 94 | |
| 94 | 95 | /* |
| @@ -35,9 +35,38 @@ · 34 unmodified lines | ||
| 35 | 35 | #endif |
| 36 | 36 | .endm |
| 37 | 37 | |
| 38 | +/* | |
| 39 | + * WARNING: | |
| 40 | + * | |
| 41 | + * A bug in the libgcc unwinder as of at least gcc 15.2 (2026) means that | |
| 42 | + * the unwinder fails to recognize the signal frame flag. | |
| 43 | + * | |
| 44 | + * There is a hacky legacy fallback path in libgcc which ends up | |
| 45 | + * getting invoked instead. It happens to work as long as BOTH of the | |
| 46 | + * following conditions are true: | |
| 47 | + * | |
| 48 | + * 1. There is at least one byte before the each of the sigreturn | |
| 49 | + * functions which falls outside any function. This is enforced by | |
| 50 | + * an explicit nop instruction before the ALIGN. | |
| 51 | + * 2. The code sequences between the entry point up to and including | |
| 52 | + * the int $0x80 below need to match EXACTLY. Do not change them | |
| 53 | + * in any way. The exact byte sequences are: | |
| 54 | + * | |
| 55 | + * __kernel_sigreturn: | |
| 56 | + * 0: 58 pop %eax | |
| 57 | + * 1: b8 77 00 00 00 mov $0x77,%eax | |
| 58 | + * 6: cd 80 int $0x80 | |
| 59 | + * | |
| 60 | + * __kernel_rt_sigreturn: | |
| 61 | + * 0: b8 ad 00 00 00 mov $0xad,%eax | |
| 62 | + * 5: cd 80 int $0x80 | |
| 63 | + * | |
| 64 | + * For details, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124050 | |
| 65 | + */ | |
| 38 | 66 | .text |
| 39 | 67 | .globl __kernel_sigreturn |
| 40 | 68 | .type __kernel_sigreturn,@function |
| 69 | + nop /* libgcc hack: see comment above */ | |
| 41 | 70 | ALIGN |
| 42 | 71 | __kernel_sigreturn: |
| 43 | 72 | STARTPROC_SIGNAL_FRAME IA32_SIGFRAME_sigcontext |
| @@ -52,6 +81,7 @@ SYM_INNER_LABEL(vdso32_sigreturn_landing_pad, SYM_L_GLOBAL) · 8 unmodified lines | ||
| 52 | 81 | |
| 53 | 82 | .globl __kernel_rt_sigreturn |
| 54 | 83 | .type __kernel_rt_sigreturn,@function |
| 84 | + nop /* libgcc hack: see comment above */ | |
| 55 | 85 | ALIGN |
| 56 | 86 | __kernel_rt_sigreturn: |
| 57 | 87 | STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext |
| @@ -138,7 +138,7 @@ extern void __init efi_apply_memmap_quirks(void); · 137 unmodified lines | ||
| 138 | 138 | extern int __init efi_reuse_config(u64 tables, int nr_tables); |
| 139 | 139 | extern void efi_delete_dummy_variable(void); |
| 140 | 140 | extern void efi_crash_gracefully_on_page_fault(unsigned long phys_addr); |
| 141 | −extern void efi_free_boot_services(void); | |
| 141 | +extern void efi_unmap_boot_services(void); | |
| 142 | 142 | |
| 143 | 143 | void arch_efi_call_virt_setup(void); |
| 144 | 144 | void arch_efi_call_virt_teardown(void); |
| @@ -740,7 +740,10 @@ · 739 unmodified lines | ||
| 740 | 740 | #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT) |
| 741 | 741 | #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18 |
| 742 | 742 | #define MSR_AMD64_SNP_SECURE_AVIC BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT) |
| 743 | −#define MSR_AMD64_SNP_RESV_BIT 19 | |
| 743 | +#define MSR_AMD64_SNP_RESERVED_BITS19_22 GENMASK_ULL(22, 19) | |
| 744 | +#define MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT 23 | |
| 745 | +#define MSR_AMD64_SNP_IBPB_ON_ENTRY BIT_ULL(MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT) | |
| 746 | +#define MSR_AMD64_SNP_RESV_BIT 24 | |
| 744 | 747 | #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT) |
| 745 | 748 | #define MSR_AMD64_SAVIC_CONTROL 0xc0010138 |
| 746 | 749 | #define MSR_AMD64_SAVIC_EN_BIT 0 |
| @@ -22,6 +22,7 @@ extern int numa_off; · 21 unmodified lines | ||
| 22 | 22 | */ |
| 23 | 23 | extern s16 __apicid_to_node[MAX_LOCAL_APIC]; |
| 24 | 24 | extern nodemask_t numa_nodes_parsed __initdata; |
| 25 | +extern nodemask_t numa_phys_nodes_parsed __initdata; | |
| 25 | 26 | |
| 26 | 27 | static inline void set_apicid_to_node(int apicid, s16 node) |
| 27 | 28 | { |
| @@ -48,6 +49,7 @@ extern void __init init_cpu_to_node(void); · 20 unmodified lines | ||
| 48 | 49 | extern void numa_add_cpu(unsigned int cpu); |
| 49 | 50 | extern void numa_remove_cpu(unsigned int cpu); |
| 50 | 51 | extern void init_gi_nodes(void); |
| 52 | +extern int num_phys_nodes(void); | |
| 51 | 53 | #else /* CONFIG_NUMA */ |
| 52 | 54 | static inline void numa_set_node(int cpu, int node) { } |
| 53 | 55 | static inline void numa_clear_node(int cpu) { } |
| @@ -55,6 +57,10 @@ static inline void init_cpu_to_node(void) { } · 1 unmodified line | ||
| 55 | 57 | static inline void numa_add_cpu(unsigned int cpu) { } |
| 56 | 58 | static inline void numa_remove_cpu(unsigned int cpu) { } |
| 57 | 59 | static inline void init_gi_nodes(void) { } |
| 60 | +static inline int num_phys_nodes(void) | |
| 61 | +{ | |
| 62 | + return 1; | |
| 63 | +} | |
| 58 | 64 | #endif /* CONFIG_NUMA */ |
| 59 | 65 | |
| 60 | 66 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS |
| @@ -19,10 +19,8 @@ · 18 unmodified lines | ||
| 19 | 19 | extern p4d_t level4_kernel_pgt[512]; |
| 20 | 20 | extern p4d_t level4_ident_pgt[512]; |
| 21 | 21 | extern pud_t level3_kernel_pgt[512]; |
| 22 | −extern pud_t level3_ident_pgt[512]; | |
| 23 | 22 | extern pmd_t level2_kernel_pgt[512]; |
| 24 | 23 | extern pmd_t level2_fixmap_pgt[512]; |
| 25 | −extern pmd_t level2_ident_pgt[512]; | |
| 26 | 24 | extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM]; |
| 27 | 25 | extern pgd_t init_top_pgt[]; |
| 28 | 26 | |
| @@ -155,6 +155,7 @@ extern unsigned int __max_logical_packages; · 154 unmodified lines | ||
| 155 | 155 | extern unsigned int __max_threads_per_core; |
| 156 | 156 | extern unsigned int __num_threads_per_package; |
| 157 | 157 | extern unsigned int __num_cores_per_package; |
| 158 | +extern unsigned int __num_nodes_per_package; | |
| 158 | 159 | |
| 159 | 160 | const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c); |
| 160 | 161 | enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c); |
| @@ -179,6 +180,11 @@ static inline unsigned int topology_num_threads_per_package(void) · 18 unmodified lines | ||
| 179 | 180 | return __num_threads_per_package; |
| 180 | 181 | } |
| 181 | 182 | |
| 183 | +static inline unsigned int topology_num_nodes_per_package(void) | |
| 184 | +{ | |
| 185 | + return __num_nodes_per_package; | |
| 186 | +} | |
| 187 | + | |
| 182 | 188 | #ifdef CONFIG_X86_LOCAL_APIC |
| 183 | 189 | int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level); |
| 184 | 190 | #else |
| @@ -95,6 +95,9 @@ EXPORT_SYMBOL(__max_dies_per_package); · 94 unmodified lines | ||
| 95 | 95 | unsigned int __max_logical_packages __ro_after_init = 1; |
| 96 | 96 | EXPORT_SYMBOL(__max_logical_packages); |
| 97 | 97 | |
| 98 | +unsigned int __num_nodes_per_package __ro_after_init = 1; | |
| 99 | +EXPORT_SYMBOL(__num_nodes_per_package); | |
| 100 | + | |
| 98 | 101 | unsigned int __num_cores_per_package __ro_after_init = 1; |
| 99 | 102 | EXPORT_SYMBOL(__num_cores_per_package); |
| 100 | 103 | |
| @@ -364,7 +364,7 @@ void arch_mon_domain_online(struct rdt_resource *r, struct rdt_l3_mon_domain *d) · 363 unmodified lines | ||
| 364 | 364 | msr_clear_bit(MSR_RMID_SNC_CONFIG, 0); |
| 365 | 365 | } |
| 366 | 366 | |
| 367 | −/* CPU models that support MSR_RMID_SNC_CONFIG */ | |
| 367 | +/* CPU models that support SNC and MSR_RMID_SNC_CONFIG */ | |
| 368 | 368 | static const struct x86_cpu_id snc_cpu_ids[] __initconst = { |
| 369 | 369 | X86_MATCH_VFM(INTEL_ICELAKE_X, 0), |
| 370 | 370 | X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, 0), |
| @@ -375,40 +375,14 @@ static const struct x86_cpu_id snc_cpu_ids[] __initconst = { · 4 unmodified lines | ||
| 375 | 375 | {} |
| 376 | 376 | }; |
| 377 | 377 | |
| 378 | −/* | |
| 379 | − * There isn't a simple hardware bit that indicates whether a CPU is running | |
| 380 | − * in Sub-NUMA Cluster (SNC) mode. Infer the state by comparing the | |
| 381 | − * number of CPUs sharing the L3 cache with CPU0 to the number of CPUs in | |
| 382 | − * the same NUMA node as CPU0. | |
| 383 | − * It is not possible to accurately determine SNC state if the system is | |
| 384 | − * booted with a maxcpus=N parameter. That distorts the ratio of SNC nodes | |
| 385 | − * to L3 caches. It will be OK if system is booted with hyperthreading | |
| 386 | − * disabled (since this doesn't affect the ratio). | |
| 387 | − */ | |
| 388 | 378 | static __init int snc_get_config(void) |
| 389 | 379 | { |
| 390 | − struct cacheinfo *ci = get_cpu_cacheinfo_level(0, RESCTRL_L3_CACHE); | |
| 391 | − const cpumask_t *node0_cpumask; | |
| 392 | − int cpus_per_node, cpus_per_l3; | |
| 393 | − int ret; | |
| 394 | − | |
| 395 | − if (!x86_match_cpu(snc_cpu_ids) || !ci) | |
| 396 | − return 1; | |
| 380 | + int ret = topology_num_nodes_per_package(); | |
| 397 | 381 | |
| 398 | − cpus_read_lock(); | |
| 399 | − if (num_online_cpus() != num_present_cpus()) | |
| 400 | − pr_warn("Some CPUs offline, SNC detection may be incorrect\n"); | |
| 401 | − cpus_read_unlock(); | |
| 402 | − | |
| 403 | − node0_cpumask = cpumask_of_node(cpu_to_node(0)); | |
| 404 | − | |
| 405 | − cpus_per_node = cpumask_weight(node0_cpumask); | |
| 406 | − cpus_per_l3 = cpumask_weight(&ci->shared_cpu_map); | |
| 407 | − | |
| 408 | − if (!cpus_per_node || !cpus_per_l3) | |
| 382 | + if (ret > 1 && !x86_match_cpu(snc_cpu_ids)) { | |
| 383 | + pr_warn("CoD enabled system? Resctrl not supported\n"); | |
| 409 | 384 | return 1; |
| 410 | − | |
| 411 | − ret = cpus_per_l3 / cpus_per_node; | |
| 385 | + } | |
| 412 | 386 | |
| 413 | 387 | /* sanity check: Only valid results are 1, 2, 3, 4, 6 */ |
| 414 | 388 | switch (ret) { |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <asm/mpspec.h> |
| 32 | 32 | #include <asm/msr.h> |
| 33 | 33 | #include <asm/smp.h> |
| 34 | +#include <asm/numa.h> | |
| 34 | 35 | |
| 35 | 36 | #include "cpu.h" |
| 36 | 37 | |
| @@ -492,11 +493,19 @@ void __init topology_init_possible_cpus(void) · 455 unmodified lines | ||
| 492 | 493 | set_nr_cpu_ids(allowed); |
| 493 | 494 | |
| 494 | 495 | cnta = domain_weight(TOPO_PKG_DOMAIN); |
| 495 | − cntb = domain_weight(TOPO_DIE_DOMAIN); | |
| 496 | 496 | __max_logical_packages = cnta; |
| 497 | + | |
| 498 | + pr_info("Max. logical packages: %3u\n", __max_logical_packages); | |
| 499 | + | |
| 500 | + cntb = num_phys_nodes(); | |
| 501 | + __num_nodes_per_package = DIV_ROUND_UP(cntb, cnta); | |
| 502 | + | |
| 503 | + pr_info("Max. logical nodes: %3u\n", cntb); | |
| 504 | + pr_info("Num. nodes per package:%3u\n", __num_nodes_per_package); | |
| 505 | + | |
| 506 | + cntb = domain_weight(TOPO_DIE_DOMAIN); | |
| 497 | 507 | __max_dies_per_package = 1U << (get_count_order(cntb) - get_count_order(cnta)); |
| 498 | 508 | |
| 499 | − pr_info("Max. logical packages: %3u\n", cnta); | |
| 500 | 509 | pr_info("Max. logical dies: %3u\n", cntb); |
| 501 | 510 | pr_info("Max. dies per package: %3u\n", __max_dies_per_package); |
| 502 | 511 | |
| @@ -616,38 +616,10 @@ SYM_DATA(early_recursion_flag, .long 0) · 615 unmodified lines | ||
| 616 | 616 | |
| 617 | 617 | .data |
| 618 | 618 | |
| 619 | −#if defined(CONFIG_XEN_PV) || defined(CONFIG_PVH) | |
| 620 | −SYM_DATA_START_PTI_ALIGNED(init_top_pgt) | |
| 621 | − .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC | |
| 622 | − .org init_top_pgt + L4_PAGE_OFFSET*8, 0 | |
| 623 | − .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC | |
| 624 | − .org init_top_pgt + L4_START_KERNEL*8, 0 | |
| 625 | − /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ | |
| 626 | − .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC | |
| 627 | − .fill PTI_USER_PGD_FILL,8,0 | |
| 628 | −SYM_DATA_END(init_top_pgt) | |
| 629 | − | |
| 630 | −SYM_DATA_START_PAGE_ALIGNED(level3_ident_pgt) | |
| 631 | − .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC | |
| 632 | − .fill 511, 8, 0 | |
| 633 | −SYM_DATA_END(level3_ident_pgt) | |
| 634 | −SYM_DATA_START_PAGE_ALIGNED(level2_ident_pgt) | |
| 635 | − /* | |
| 636 | − * Since I easily can, map the first 1G. | |
| 637 | − * Don't set NX because code runs from these pages. | |
| 638 | − * | |
| 639 | − * Note: This sets _PAGE_GLOBAL despite whether | |
| 640 | − * the CPU supports it or it is enabled. But, | |
| 641 | − * the CPU should ignore the bit. | |
| 642 | − */ | |
| 643 | − PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD) | |
| 644 | −SYM_DATA_END(level2_ident_pgt) | |
| 645 | −#else | |
| 646 | 619 | SYM_DATA_START_PTI_ALIGNED(init_top_pgt) |
| 647 | 620 | .fill 512,8,0 |
| 648 | 621 | .fill PTI_USER_PGD_FILL,8,0 |
| 649 | 622 | SYM_DATA_END(init_top_pgt) |
| 650 | −#endif | |
| 651 | 623 | |
| 652 | 624 | SYM_DATA_START_PAGE_ALIGNED(level4_kernel_pgt) |
| 653 | 625 | .fill 511,8,0 |
| @@ -468,13 +468,6 @@ static int x86_cluster_flags(void) · 467 unmodified lines | ||
| 468 | 468 | } |
| 469 | 469 | #endif |
| 470 | 470 | |
| 471 | −/* | |
| 472 | − * Set if a package/die has multiple NUMA nodes inside. | |
| 473 | − * AMD Magny-Cours, Intel Cluster-on-Die, and Intel | |
| 474 | − * Sub-NUMA Clustering have this. | |
| 475 | − */ | |
| 476 | −static bool x86_has_numa_in_package; | |
| 477 | − | |
| 478 | 471 | static struct sched_domain_topology_level x86_topology[] = { |
| 479 | 472 | SDTL_INIT(tl_smt_mask, cpu_smt_flags, SMT), |
| 480 | 473 | #ifdef CONFIG_SCHED_CLUSTER |
| @@ -496,7 +489,7 @@ static void __init build_sched_topology(void) · 15 unmodified lines | ||
| 496 | 489 | * PKG domain since the NUMA domains will auto-magically create the |
| 497 | 490 | * right spanning domains based on the SLIT. |
| 498 | 491 | */ |
| 499 | − if (x86_has_numa_in_package) { | |
| 492 | + if (topology_num_nodes_per_package() > 1) { | |
| 500 | 493 | unsigned int pkgdom = ARRAY_SIZE(x86_topology) - 2; |
| 501 | 494 | |
| 502 | 495 | memset(&x86_topology[pkgdom], 0, sizeof(x86_topology[pkgdom])); |
| @@ -513,33 +506,149 @@ static void __init build_sched_topology(void) · 10 unmodified lines | ||
| 513 | 506 | } |
| 514 | 507 | |
| 515 | 508 | #ifdef CONFIG_NUMA |
| 516 | −static int sched_avg_remote_distance; | |
| 517 | −static int avg_remote_numa_distance(void) | |
| 509 | +/* | |
| 510 | + * Test if the on-trace cluster at (N,N) is symmetric. | |
| 511 | + * Uses upper triangle iteration to avoid obvious duplicates. | |
| 512 | + */ | |
| 513 | +static bool slit_cluster_symmetric(int N) | |
| 518 | 514 | { |
| 519 | − int i, j; | |
| 520 | − int distance, nr_remote, total_distance; | |
| 521 | − | |
| 522 | − if (sched_avg_remote_distance > 0) | |
| 523 | − return sched_avg_remote_distance; | |
| 524 | − | |
| 525 | − nr_remote = 0; | |
| 526 | − total_distance = 0; | |
| 527 | − for_each_node_state(i, N_CPU) { | |
| 528 | − for_each_node_state(j, N_CPU) { | |
| 529 | − distance = node_distance(i, j); | |
| 530 | − | |
| 531 | − if (distance >= REMOTE_DISTANCE) { | |
| 532 | − nr_remote++; | |
| 533 | − total_distance += distance; | |
| 534 | − } | |
| 515 | + int u = topology_num_nodes_per_package(); | |
| 516 | + | |
| 517 | + for (int k = 0; k < u; k++) { | |
| 518 | + for (int l = k; l < u; l++) { | |
| 519 | + if (node_distance(N + k, N + l) != | |
| 520 | + node_distance(N + l, N + k)) | |
| 521 | + return false; | |
| 535 | 522 | } |
| 536 | 523 | } |
| 537 | − if (nr_remote) | |
| 538 | − sched_avg_remote_distance = total_distance / nr_remote; | |
| 539 | − else | |
| 540 | − sched_avg_remote_distance = REMOTE_DISTANCE; | |
| 541 | 524 | |
| 542 | − return sched_avg_remote_distance; | |
| 525 | + return true; | |
| 526 | +} | |
| 527 | + | |
| 528 | +/* | |
| 529 | + * Return the package-id of the cluster, or ~0 if indeterminate. | |
| 530 | + * Each node in the on-trace cluster should have the same package-id. | |
| 531 | + */ | |
| 532 | +static u32 slit_cluster_package(int N) | |
| 533 | +{ | |
| 534 | + int u = topology_num_nodes_per_package(); | |
| 535 | + u32 pkg_id = ~0; | |
| 536 | + | |
| 537 | + for (int n = 0; n < u; n++) { | |
| 538 | + const struct cpumask *cpus = cpumask_of_node(N + n); | |
| 539 | + int cpu; | |
| 540 | + | |
| 541 | + for_each_cpu(cpu, cpus) { | |
| 542 | + u32 id = topology_logical_package_id(cpu); | |
| 543 | + | |
| 544 | + if (pkg_id == ~0) | |
| 545 | + pkg_id = id; | |
| 546 | + if (pkg_id != id) | |
| 547 | + return ~0; | |
| 548 | + } | |
| 549 | + } | |
| 550 | + | |
| 551 | + return pkg_id; | |
| 552 | +} | |
| 553 | + | |
| 554 | +/* | |
| 555 | + * Validate the SLIT table is of the form expected for SNC, specifically: | |
| 556 | + * | |
| 557 | + * - each on-trace cluster should be symmetric, | |
| 558 | + * - each on-trace cluster should have a unique package-id. | |
| 559 | + * | |
| 560 | + * If you NUMA_EMU on top of SNC, you get to keep the pieces. | |
| 561 | + */ | |
| 562 | +static bool slit_validate(void) | |
| 563 | +{ | |
| 564 | + int u = topology_num_nodes_per_package(); | |
| 565 | + u32 pkg_id, prev_pkg_id = ~0; | |
| 566 | + | |
| 567 | + for (int pkg = 0; pkg < topology_max_packages(); pkg++) { | |
| 568 | + int n = pkg * u; | |
| 569 | + | |
| 570 | + /* | |
| 571 | + * Ensure the on-trace cluster is symmetric and each cluster | |
| 572 | + * has a different package id. | |
| 573 | + */ | |
| 574 | + if (!slit_cluster_symmetric(n)) | |
| 575 | + return false; | |
| 576 | + pkg_id = slit_cluster_package(n); | |
| 577 | + if (pkg_id == ~0) | |
| 578 | + return false; | |
| 579 | + if (pkg && pkg_id == prev_pkg_id) | |
| 580 | + return false; | |
| 581 | + | |
| 582 | + prev_pkg_id = pkg_id; | |
| 583 | + } | |
| 584 | + | |
| 585 | + return true; | |
| 586 | +} | |
| 587 | + | |
| 588 | +/* | |
| 589 | + * Compute a sanitized SLIT table for SNC; notably SNC-3 can end up with | |
| 590 | + * asymmetric off-trace clusters, reflecting physical assymmetries. However | |
| 591 | + * this leads to 'unfortunate' sched_domain configurations. | |
| 592 | + * | |
| 593 | + * For example dual socket GNR with SNC-3: | |
| 594 | + * | |
| 595 | + * node distances: | |
| 596 | + * node 0 1 2 3 4 5 | |
| 597 | + * 0: 10 15 17 21 28 26 | |
| 598 | + * 1: 15 10 15 23 26 23 | |
| 599 | + * 2: 17 15 10 26 23 21 | |
| 600 | + * 3: 21 28 26 10 15 17 | |
| 601 | + * 4: 23 26 23 15 10 15 | |
| 602 | + * 5: 26 23 21 17 15 10 | |
| 603 | + * | |
| 604 | + * Fix things up by averaging out the off-trace clusters; resulting in: | |
| 605 | + * | |
| 606 | + * node 0 1 2 3 4 5 | |
| 607 | + * 0: 10 15 17 24 24 24 | |
| 608 | + * 1: 15 10 15 24 24 24 | |
| 609 | + * 2: 17 15 10 24 24 24 | |
| 610 | + * 3: 24 24 24 10 15 17 | |
| 611 | + * 4: 24 24 24 15 10 15 | |
| 612 | + * 5: 24 24 24 17 15 10 | |
| 613 | + */ | |
| 614 | +static int slit_cluster_distance(int i, int j) | |
| 615 | +{ | |
| 616 | + static int slit_valid = -1; | |
| 617 | + int u = topology_num_nodes_per_package(); | |
| 618 | + long d = 0; | |
| 619 | + int x, y; | |
| 620 | + | |
| 621 | + if (slit_valid < 0) { | |
| 622 | + slit_valid = slit_validate(); | |
| 623 | + if (!slit_valid) | |
| 624 | + pr_err(FW_BUG "SLIT table doesn't have the expected form for SNC -- fixup disabled!\n"); | |
| 625 | + else | |
| 626 | + pr_info("Fixing up SNC SLIT table.\n"); | |
| 627 | + } | |
| 628 | + | |
| 629 | + /* | |
| 630 | + * Is this a unit cluster on the trace? | |
| 631 | + */ | |
| 632 | + if ((i / u) == (j / u) || !slit_valid) | |
| 633 | + return node_distance(i, j); | |
| 634 | + | |
| 635 | + /* | |
| 636 | + * Off-trace cluster. | |
| 637 | + * | |
| 638 | + * Notably average out the symmetric pair of off-trace clusters to | |
| 639 | + * ensure the resulting SLIT table is symmetric. | |
| 640 | + */ | |
| 641 | + x = i - (i % u); | |
| 642 | + y = j - (j % u); | |
| 643 | + | |
| 644 | + for (i = x; i < x + u; i++) { | |
| 645 | + for (j = y; j < y + u; j++) { | |
| 646 | + d += node_distance(i, j); | |
| 647 | + d += node_distance(j, i); | |
| 648 | + } | |
| 649 | + } | |
| 650 | + | |
| 651 | + return d / (2*u*u); | |
| 543 | 652 | } |
| 544 | 653 | |
| 545 | 654 | int arch_sched_node_distance(int from, int to) |
| @@ -549,34 +658,14 @@ int arch_sched_node_distance(int from, int to) · 3 unmodified lines | ||
| 549 | 658 | switch (boot_cpu_data.x86_vfm) { |
| 550 | 659 | case INTEL_GRANITERAPIDS_X: |
| 551 | 660 | case INTEL_ATOM_DARKMONT_X: |
| 552 | − | |
| 553 | − if (!x86_has_numa_in_package || topology_max_packages() == 1 || | |
| 554 | − d < REMOTE_DISTANCE) | |
| 661 | + if (topology_max_packages() == 1 || | |
| 662 | + topology_num_nodes_per_package() < 3) | |
| 555 | 663 | return d; |
| 556 | 664 | |
| 557 | 665 | /* |
| 558 | − * With SNC enabled, there could be too many levels of remote | |
| 559 | − * NUMA node distances, creating NUMA domain levels | |
| 560 | − * including local nodes and partial remote nodes. | |
| 561 | − * | |
| 562 | − * Trim finer distance tuning for NUMA nodes in remote package | |
| 563 | − * for the purpose of building sched domains. Group NUMA nodes | |
| 564 | − * in the remote package in the same sched group. | |
| 565 | − * Simplify NUMA domains and avoid extra NUMA levels including | |
| 566 | − * different remote NUMA nodes and local nodes. | |
| 567 | − * | |
| 568 | − * GNR and CWF don't expect systems with more than 2 packages | |
| 569 | − * and more than 2 hops between packages. Single average remote | |
| 570 | − * distance won't be appropriate if there are more than 2 | |
| 571 | − * packages as average distance to different remote packages | |
| 572 | − * could be different. | |
| 666 | + * Handle SNC-3 asymmetries. | |
| 573 | 667 | */ |
| 574 | − WARN_ONCE(topology_max_packages() > 2, | |
| 575 | − "sched: Expect only up to 2 packages for GNR or CWF, " | |
| 576 | − "but saw %d packages when building sched domains.", | |
| 577 | − topology_max_packages()); | |
| 578 | − | |
| 579 | − d = avg_remote_numa_distance(); | |
| 668 | + return slit_cluster_distance(from, to); | |
| 580 | 669 | } |
| 581 | 670 | return d; |
| 582 | 671 | } |
| @@ -606,7 +695,7 @@ void set_cpu_sibling_map(int cpu) · 23 unmodified lines | ||
| 606 | 695 | o = &cpu_data(i); |
| 607 | 696 | |
| 608 | 697 | if (match_pkg(c, o) && !topology_same_node(c, o)) |
| 609 | − x86_has_numa_in_package = true; | |
| 698 | + WARN_ON_ONCE(topology_num_nodes_per_package() == 1); | |
| 610 | 699 | |
| 611 | 700 | if ((i == cpu) || (has_smt && match_smt(c, o))) |
| 612 | 701 | link_mask(topology_sibling_cpumask, cpu, i); |
| @@ -427,6 +427,7 @@ SECTIONS · 426 unmodified lines | ||
| 427 | 427 | .llvm_bb_addr_map : { *(.llvm_bb_addr_map) } |
| 428 | 428 | #endif |
| 429 | 429 | |
| 430 | + MODINFO | |
| 430 | 431 | ELF_DETAILS |
| 431 | 432 | |
| 432 | 433 | DISCARDS |
| @@ -48,6 +48,8 @@ s16 __apicid_to_node[MAX_LOCAL_APIC] = { · 47 unmodified lines | ||
| 48 | 48 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE |
| 49 | 49 | }; |
| 50 | 50 | |
| 51 | +nodemask_t numa_phys_nodes_parsed __initdata; | |
| 52 | + | |
| 51 | 53 | int numa_cpu_node(int cpu) |
| 52 | 54 | { |
| 53 | 55 | u32 apicid = early_per_cpu(x86_cpu_to_apicid, cpu); |
| @@ -57,6 +59,11 @@ int numa_cpu_node(int cpu) · 3 unmodified lines | ||
| 57 | 59 | return NUMA_NO_NODE; |
| 58 | 60 | } |
| 59 | 61 | |
| 62 | +int __init num_phys_nodes(void) | |
| 63 | +{ | |
| 64 | + return bitmap_weight(numa_phys_nodes_parsed.bits, MAX_NUMNODES); | |
| 65 | +} | |
| 66 | + | |
| 60 | 67 | cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; |
| 61 | 68 | EXPORT_SYMBOL(node_to_cpumask_map); |
| 62 | 69 | |
| @@ -210,6 +217,7 @@ static int __init dummy_numa_init(void) · 147 unmodified lines | ||
| 210 | 217 | 0LLU, PFN_PHYS(max_pfn) - 1); |
| 211 | 218 | |
| 212 | 219 | node_set(0, numa_nodes_parsed); |
| 220 | + node_set(0, numa_phys_nodes_parsed); | |
| 213 | 221 | numa_add_memblk(0, 0, PFN_PHYS(max_pfn)); |
| 214 | 222 | |
| 215 | 223 | return 0; |
| @@ -57,6 +57,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) · 56 unmodified lines | ||
| 57 | 57 | } |
| 58 | 58 | set_apicid_to_node(apic_id, node); |
| 59 | 59 | node_set(node, numa_nodes_parsed); |
| 60 | + node_set(node, numa_phys_nodes_parsed); | |
| 60 | 61 | pr_debug("SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", pxm, apic_id, node); |
| 61 | 62 | } |
| 62 | 63 | |
| @@ -97,6 +98,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) · 34 unmodified lines | ||
| 97 | 98 | |
| 98 | 99 | set_apicid_to_node(apic_id, node); |
| 99 | 100 | node_set(node, numa_nodes_parsed); |
| 101 | + node_set(node, numa_phys_nodes_parsed); | |
| 100 | 102 | pr_debug("SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", pxm, apic_id, node); |
| 101 | 103 | } |
| 102 | 104 | |
| @@ -836,7 +836,7 @@ static void __init __efi_enter_virtual_mode(void) · 835 unmodified lines | ||
| 836 | 836 | } |
| 837 | 837 | |
| 838 | 838 | efi_check_for_embedded_firmwares(); |
| 839 | − efi_free_boot_services(); | |
| 839 | + efi_unmap_boot_services(); | |
| 840 | 840 | |
| 841 | 841 | if (!efi_is_mixed()) |
| 842 | 842 | efi_native_runtime_setup(); |
| @@ -341,7 +341,7 @@ void __init efi_reserve_boot_services(void) · 340 unmodified lines | ||
| 341 | 341 | |
| 342 | 342 | /* |
| 343 | 343 | * Because the following memblock_reserve() is paired |
| 344 | − * with memblock_free_late() for this region in | |
| 344 | + * with free_reserved_area() for this region in | |
| 345 | 345 | * efi_free_boot_services(), we must be extremely |
| 346 | 346 | * careful not to reserve, and subsequently free, |
| 347 | 347 | * critical regions of memory (like the kernel image) or |
| @@ -404,17 +404,33 @@ static void __init efi_unmap_pages(efi_memory_desc_t *md) · 56 unmodified lines | ||
| 404 | 404 | pr_err("Failed to unmap VA mapping for 0x%llx\n", va); |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | −void __init efi_free_boot_services(void) | |
| 407 | +struct efi_freeable_range { | |
| 408 | + u64 start; | |
| 409 | + u64 end; | |
| 410 | +}; | |
| 411 | + | |
| 412 | +static struct efi_freeable_range *ranges_to_free; | |
| 413 | + | |
| 414 | +void __init efi_unmap_boot_services(void) | |
| 408 | 415 | { |
| 409 | 416 | struct efi_memory_map_data data = { 0 }; |
| 410 | 417 | efi_memory_desc_t *md; |
| 411 | 418 | int num_entries = 0; |
| 419 | + int idx = 0; | |
| 420 | + size_t sz; | |
| 412 | 421 | void *new, *new_md; |
| 413 | 422 | |
| 414 | 423 | /* Keep all regions for /sys/kernel/debug/efi */ |
| 415 | 424 | if (efi_enabled(EFI_DBG)) |
| 416 | 425 | return; |
| 417 | 426 | |
| 427 | + sz = sizeof(*ranges_to_free) * efi.memmap.nr_map + 1; | |
| 428 | + ranges_to_free = kzalloc(sz, GFP_KERNEL); | |
| 429 | + if (!ranges_to_free) { | |
| 430 | + pr_err("Failed to allocate storage for freeable EFI regions\n"); | |
| 431 | + return; | |
| 432 | + } | |
| 433 | + | |
| 418 | 434 | for_each_efi_memory_desc(md) { |
| 419 | 435 | unsigned long long start = md->phys_addr; |
| 420 | 436 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
| @@ -471,7 +487,15 @@ void __init efi_free_boot_services(void) · 50 unmodified lines | ||
| 471 | 487 | start = SZ_1M; |
| 472 | 488 | } |
| 473 | 489 | |
| 474 | − memblock_free_late(start, size); | |
| 490 | + /* | |
| 491 | + * With CONFIG_DEFERRED_STRUCT_PAGE_INIT parts of the memory | |
| 492 | + * map are still not initialized and we can't reliably free | |
| 493 | + * memory here. | |
| 494 | + * Queue the ranges to free at a later point. | |
| 495 | + */ | |
| 496 | + ranges_to_free[idx].start = start; | |
| 497 | + ranges_to_free[idx].end = start + size; | |
| 498 | + idx++; | |
| 475 | 499 | } |
| 476 | 500 | |
| 477 | 501 | if (!num_entries) |
| @@ -512,6 +536,31 @@ void __init efi_free_boot_services(void) · 34 unmodified lines | ||
| 512 | 536 | } |
| 513 | 537 | } |
| 514 | 538 | |
| 539 | +static int __init efi_free_boot_services(void) | |
| 540 | +{ | |
| 541 | + struct efi_freeable_range *range = ranges_to_free; | |
| 542 | + unsigned long freed = 0; | |
| 543 | + | |
| 544 | + if (!ranges_to_free) | |
| 545 | + return 0; | |
| 546 | + | |
| 547 | + while (range->start) { | |
| 548 | + void *start = phys_to_virt(range->start); | |
| 549 | + void *end = phys_to_virt(range->end); | |
| 550 | + | |
| 551 | + free_reserved_area(start, end, -1, NULL); | |
| 552 | + freed += (end - start); | |
| 553 | + range++; | |
| 554 | + } | |
| 555 | + kfree(ranges_to_free); | |
| 556 | + | |
| 557 | + if (freed) | |
| 558 | + pr_info("Freeing EFI boot services memory: %ldK\n", freed / SZ_1K); | |
| 559 | + | |
| 560 | + return 0; | |
| 561 | +} | |
| 562 | +arch_initcall(efi_free_boot_services); | |
| 563 | + | |
| 515 | 564 | /* |
| 516 | 565 | * A number of config table entries get remapped to virtual addresses |
| 517 | 566 | * after entering EFI virtual mode. However, the kexec kernel requires |
| @@ -25,11 +25,6 @@ struct hvm_start_info __initdata pvh_start_info; · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | const unsigned int __initconst pvh_start_info_sz = sizeof(pvh_start_info); |
| 27 | 27 | |
| 28 | −static u64 __init pvh_get_root_pointer(void) | |
| 29 | −{ | |
| 30 | − return pvh_start_info.rsdp_paddr; | |
| 31 | −} | |
| 32 | − | |
| 33 | 28 | /* |
| 34 | 29 | * Xen guests are able to obtain the memory map from the hypervisor via the |
| 35 | 30 | * HYPERVISOR_memory_op hypercall. |
| @@ -95,7 +90,7 @@ static void __init init_pvh_bootparams(bool xen_guest) · 59 unmodified lines | ||
| 95 | 90 | pvh_bootparams.hdr.version = (2 << 8) | 12; |
| 96 | 91 | pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0; |
| 97 | 92 | |
| 98 | − x86_init.acpi.get_root_pointer = pvh_get_root_pointer; | |
| 93 | + pvh_bootparams.acpi_rsdp_addr = pvh_start_info.rsdp_paddr; | |
| 99 | 94 | } |
| 100 | 95 | |
| 101 | 96 | /* |
| @@ -392,7 +392,7 @@ static void __init xen_init_capabilities(void) · 391 unmodified lines | ||
| 392 | 392 | |
| 393 | 393 | /* |
| 394 | 394 | * Xen PV would need some work to support PCID: CR3 handling as well |
| 395 | − * as xen_flush_tlb_others() would need updating. | |
| 395 | + * as xen_flush_tlb_multi() would need updating. | |
| 396 | 396 | */ |
| 397 | 397 | setup_clear_cpu_cap(X86_FEATURE_PCID); |
| 398 | 398 | |
| @@ -105,6 +105,9 @@ pte_t xen_make_pte_init(pteval_t pte); · 104 unmodified lines | ||
| 105 | 105 | static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; |
| 106 | 106 | #endif |
| 107 | 107 | |
| 108 | +static pud_t level3_ident_pgt[PTRS_PER_PUD] __page_aligned_bss; | |
| 109 | +static pmd_t level2_ident_pgt[PTRS_PER_PMD] __page_aligned_bss; | |
| 110 | + | |
| 108 | 111 | /* |
| 109 | 112 | * Protects atomic reservation decrease/increase against concurrent increases. |
| 110 | 113 | * Also protects non-atomic updates of current_pages and balloon lists. |
| @@ -1777,6 +1780,12 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) · 1666 unmodified lines | ||
| 1777 | 1780 | /* Zap identity mapping */ |
| 1778 | 1781 | init_top_pgt[0] = __pgd(0); |
| 1779 | 1782 | |
| 1783 | + init_top_pgt[pgd_index(__PAGE_OFFSET_BASE_L4)].pgd = | |
| 1784 | + __pa_symbol(level3_ident_pgt) + _KERNPG_TABLE_NOENC; | |
| 1785 | + init_top_pgt[pgd_index(__START_KERNEL_map)].pgd = | |
| 1786 | + __pa_symbol(level3_kernel_pgt) + _PAGE_TABLE_NOENC; | |
| 1787 | + level3_ident_pgt[0].pud = __pa_symbol(level2_ident_pgt) + _KERNPG_TABLE_NOENC; | |
| 1788 | + | |
| 1780 | 1789 | /* Pre-constructed entries are in pfn, so convert to mfn */ |
| 1781 | 1790 | /* L4[273] -> level3_ident_pgt */ |
| 1782 | 1791 | /* L4[511] -> level3_kernel_pgt */ |
| @@ -398,8 +398,7 @@ static struct bio *bio_copy_kern(struct request *rq, void *data, unsigned int le · 397 unmodified lines | ||
| 398 | 398 | if (op_is_write(op)) |
| 399 | 399 | memcpy(page_address(page), p, bytes); |
| 400 | 400 | |
| 401 | − if (bio_add_page(bio, page, bytes, 0) < bytes) | |
| 402 | − break; | |
| 401 | + __bio_add_page(bio, page, bytes, 0); | |
| 403 | 402 | |
| 404 | 403 | len -= bytes; |
| 405 | 404 | p += bytes; |
| @@ -4793,38 +4793,45 @@ static void blk_mq_update_queue_map(struct blk_mq_tag_set *set) · 4792 unmodified lines | ||
| 4793 | 4793 | } |
| 4794 | 4794 | } |
| 4795 | 4795 | |
| 4796 | −static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set, | |
| 4797 | − int new_nr_hw_queues) | |
| 4796 | +static struct blk_mq_tags **blk_mq_prealloc_tag_set_tags( | |
| 4797 | + struct blk_mq_tag_set *set, | |
| 4798 | + int new_nr_hw_queues) | |
| 4798 | 4799 | { |
| 4799 | 4800 | struct blk_mq_tags **new_tags; |
| 4800 | 4801 | int i; |
| 4801 | 4802 | |
| 4802 | 4803 | if (set->nr_hw_queues >= new_nr_hw_queues) |
| 4803 | − goto done; | |
| 4804 | + return NULL; | |
| 4804 | 4805 | |
| 4805 | 4806 | new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *), |
| 4806 | 4807 | GFP_KERNEL, set->numa_node); |
| 4807 | 4808 | if (!new_tags) |
| 4808 | − return -ENOMEM; | |
| 4809 | + return ERR_PTR(-ENOMEM); | |
| 4809 | 4810 | |
| 4810 | 4811 | if (set->tags) |
| 4811 | 4812 | memcpy(new_tags, set->tags, set->nr_hw_queues * |
| 4812 | 4813 | sizeof(*set->tags)); |
| 4813 | − kfree(set->tags); | |
| 4814 | − set->tags = new_tags; | |
| 4815 | 4814 | |
| 4816 | 4815 | for (i = set->nr_hw_queues; i < new_nr_hw_queues; i++) { |
| 4817 | − if (!__blk_mq_alloc_map_and_rqs(set, i)) { | |
| 4818 | − while (--i >= set->nr_hw_queues) | |
| 4819 | − __blk_mq_free_map_and_rqs(set, i); | |
| 4820 | − return -ENOMEM; | |
| 4816 | + if (blk_mq_is_shared_tags(set->flags)) { | |
| 4817 | + new_tags[i] = set->shared_tags; | |
| 4818 | + } else { | |
| 4819 | + new_tags[i] = blk_mq_alloc_map_and_rqs(set, i, | |
| 4820 | + set->queue_depth); | |
| 4821 | + if (!new_tags[i]) | |
| 4822 | + goto out_unwind; | |
| 4821 | 4823 | } |
| 4822 | 4824 | cond_resched(); |
| 4823 | 4825 | } |
| 4824 | 4826 | |
| 4825 | −done: | |
| 4826 | − set->nr_hw_queues = new_nr_hw_queues; | |
| 4827 | − return 0; | |
| 4827 | + return new_tags; | |
| 4828 | +out_unwind: | |
| 4829 | + while (--i >= set->nr_hw_queues) { | |
| 4830 | + if (!blk_mq_is_shared_tags(set->flags)) | |
| 4831 | + blk_mq_free_map_and_rqs(set, new_tags[i], i); | |
| 4832 | + } | |
| 4833 | + kfree(new_tags); | |
| 4834 | + return ERR_PTR(-ENOMEM); | |
| 4828 | 4835 | } |
| 4829 | 4836 | |
| 4830 | 4837 | /* |
| @@ -5113,6 +5120,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, · 282 unmodified lines | ||
| 5113 | 5120 | unsigned int memflags; |
| 5114 | 5121 | int i; |
| 5115 | 5122 | struct xarray elv_tbl; |
| 5123 | + struct blk_mq_tags **new_tags; | |
| 5116 | 5124 | bool queues_frozen = false; |
| 5117 | 5125 | |
| 5118 | 5126 | lockdep_assert_held(&set->tag_list_lock); |
| @@ -5147,11 +5155,18 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, · 28 unmodified lines | ||
| 5147 | 5155 | if (blk_mq_elv_switch_none(q, &elv_tbl)) |
| 5148 | 5156 | goto switch_back; |
| 5149 | 5157 | |
| 5158 | + new_tags = blk_mq_prealloc_tag_set_tags(set, nr_hw_queues); | |
| 5159 | + if (IS_ERR(new_tags)) | |
| 5160 | + goto switch_back; | |
| 5161 | + | |
| 5150 | 5162 | list_for_each_entry(q, &set->tag_list, tag_set_list) |
| 5151 | 5163 | blk_mq_freeze_queue_nomemsave(q); |
| 5152 | 5164 | queues_frozen = true; |
| 5153 | − if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0) | |
| 5154 | − goto switch_back; | |
| 5165 | + if (new_tags) { | |
| 5166 | + kfree(set->tags); | |
| 5167 | + set->tags = new_tags; | |
| 5168 | + } | |
| 5169 | + set->nr_hw_queues = nr_hw_queues; | |
| 5155 | 5170 | |
| 5156 | 5171 | fallback: |
| 5157 | 5172 | blk_mq_update_queue_map(set); |
| @@ -78,8 +78,14 @@ queue_requests_store(struct gendisk *disk, const char *page, size_t count) · 77 unmodified lines | ||
| 78 | 78 | /* |
| 79 | 79 | * Serialize updating nr_requests with concurrent queue_requests_store() |
| 80 | 80 | * and switching elevator. |
| 81 | + * | |
| 82 | + * Use trylock to avoid circular lock dependency with kernfs active | |
| 83 | + * reference during concurrent disk deletion: | |
| 84 | + * update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del) | |
| 85 | + * kn->active -> update_nr_hwq_lock (via this sysfs write path) | |
| 81 | 86 | */ |
| 82 | − down_write(&set->update_nr_hwq_lock); | |
| 87 | + if (!down_write_trylock(&set->update_nr_hwq_lock)) | |
| 88 | + return -EBUSY; | |
| 83 | 89 | |
| 84 | 90 | if (nr == q->nr_requests) |
| 85 | 91 | goto unlock; |
| @@ -807,7 +807,16 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf, · 806 unmodified lines | ||
| 807 | 807 | elv_iosched_load_module(ctx.name); |
| 808 | 808 | ctx.type = elevator_find_get(ctx.name); |
| 809 | 809 | |
| 810 | − down_read(&set->update_nr_hwq_lock); | |
| 810 | + /* | |
| 811 | + * Use trylock to avoid circular lock dependency with kernfs active | |
| 812 | + * reference during concurrent disk deletion: | |
| 813 | + * update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del) | |
| 814 | + * kn->active -> update_nr_hwq_lock (via this sysfs write path) | |
| 815 | + */ | |
| 816 | + if (!down_read_trylock(&set->update_nr_hwq_lock)) { | |
| 817 | + ret = -EBUSY; | |
| 818 | + goto out; | |
| 819 | + } | |
| 811 | 820 | if (!blk_queue_no_elv_switch(q)) { |
| 812 | 821 | ret = elevator_change(q, &ctx); |
| 813 | 822 | if (!ret) |
| @@ -817,6 +826,7 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf, · 3 unmodified lines | ||
| 817 | 826 | } |
| 818 | 827 | up_read(&set->update_nr_hwq_lock); |
| 819 | 828 | |
| 829 | +out: | |
| 820 | 830 | if (ctx.type) |
| 821 | 831 | elevator_put(ctx.type); |
| 822 | 832 | return ret; |
| @@ -876,8 +876,6 @@ config CRYPTO_BLAKE2B · 875 unmodified lines | ||
| 876 | 876 | - blake2b-384 |
| 877 | 877 | - blake2b-512 |
| 878 | 878 | |
| 879 | − Used by the btrfs filesystem. | |
| 880 | − | |
| 881 | 879 | See https://blake2.net for further information. |
| 882 | 880 | |
| 883 | 881 | config CRYPTO_CMAC |
| @@ -965,7 +963,6 @@ config CRYPTO_SHA256 · 81 unmodified lines | ||
| 965 | 963 | 10118-3), including HMAC support. |
| 966 | 964 | |
| 967 | 965 | This is required for IPsec AH (XFRM_AH) and IPsec ESP (XFRM_ESP). |
| 968 | − Used by the btrfs filesystem, Ceph, NFS, and SMB. | |
| 969 | 966 | |
| 970 | 967 | config CRYPTO_SHA512 |
| 971 | 968 | tristate "SHA-384 and SHA-512" |
| @@ -1039,8 +1036,6 @@ config CRYPTO_XXHASH · 67 unmodified lines | ||
| 1039 | 1036 | |
| 1040 | 1037 | Extremely fast, working at speeds close to RAM limits. |
| 1041 | 1038 | |
| 1042 | − Used by the btrfs filesystem. | |
| 1043 | − | |
| 1044 | 1039 | endmenu |
| 1045 | 1040 | |
| 1046 | 1041 | menu "CRCs (cyclic redundancy checks)" |
| @@ -1058,8 +1053,6 @@ config CRYPTO_CRC32C · 11 unmodified lines | ||
| 1058 | 1053 | on Communications, Vol. 41, No. 6, June 1993, selected for use with |
| 1059 | 1054 | iSCSI. |
| 1060 | 1055 | |
| 1061 | − Used by btrfs, ext4, jbd2, NVMeoF/TCP, and iSCSI. | |
| 1062 | − | |
| 1063 | 1056 | config CRYPTO_CRC32 |
| 1064 | 1057 | tristate "CRC32" |
| 1065 | 1058 | select CRYPTO_HASH |
| @@ -1067,8 +1060,6 @@ config CRYPTO_CRC32 · 1 unmodified line | ||
| 1067 | 1060 | help |
| 1068 | 1061 | CRC32 CRC algorithm (IEEE 802.3) |
| 1069 | 1062 | |
| 1070 | − Used by RoCEv2 and f2fs. | |
| 1071 | − | |
| 1072 | 1063 | endmenu |
| 1073 | 1064 | |
| 1074 | 1065 | menu "Compression" |
| @@ -4132,7 +4132,7 @@ static const struct alg_test_desc alg_test_descs[] = { · 4131 unmodified lines | ||
| 4132 | 4132 | .fips_allowed = 1, |
| 4133 | 4133 | }, { |
| 4134 | 4134 | .alg = "authenc(hmac(sha224),cbc(aes))", |
| 4135 | − .generic_driver = "authenc(hmac-sha224-lib,cbc(aes-generic))", | |
| 4135 | + .generic_driver = "authenc(hmac-sha224-lib,cbc(aes-lib))", | |
| 4136 | 4136 | .test = alg_test_aead, |
| 4137 | 4137 | .suite = { |
| 4138 | 4138 | .aead = __VECS(hmac_sha224_aes_cbc_tv_temp) |
| @@ -4194,7 +4194,7 @@ static const struct alg_test_desc alg_test_descs[] = { · 55 unmodified lines | ||
| 4194 | 4194 | .fips_allowed = 1, |
| 4195 | 4195 | }, { |
| 4196 | 4196 | .alg = "authenc(hmac(sha384),cbc(aes))", |
| 4197 | − .generic_driver = "authenc(hmac-sha384-lib,cbc(aes-generic))", | |
| 4197 | + .generic_driver = "authenc(hmac-sha384-lib,cbc(aes-lib))", | |
| 4198 | 4198 | .test = alg_test_aead, |
| 4199 | 4199 | .suite = { |
| 4200 | 4200 | .aead = __VECS(hmac_sha384_aes_cbc_tv_temp) |
| @@ -186,13 +186,13 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size) · 185 unmodified lines | ||
| 186 | 186 | cmd_abo = job->cmd_bo; |
| 187 | 187 | |
| 188 | 188 | if (unlikely(job->job_timeout)) { |
| 189 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_TIMEOUT); | |
| 189 | + amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_TIMEOUT); | |
| 190 | 190 | ret = -EINVAL; |
| 191 | 191 | goto out; |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | if (unlikely(!data) || unlikely(size != sizeof(u32))) { |
| 195 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT); | |
| 195 | + amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ABORT); | |
| 196 | 196 | ret = -EINVAL; |
| 197 | 197 | goto out; |
| 198 | 198 | } |
| @@ -202,7 +202,7 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size) · 3 unmodified lines | ||
| 202 | 202 | if (status == AIE2_STATUS_SUCCESS) |
| 203 | 203 | amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED); |
| 204 | 204 | else |
| 205 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR); | |
| 205 | + amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ERROR); | |
| 206 | 206 | |
| 207 | 207 | out: |
| 208 | 208 | aie2_sched_notify(job); |
| @@ -244,13 +244,13 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size) · 35 unmodified lines | ||
| 244 | 244 | cmd_abo = job->cmd_bo; |
| 245 | 245 | |
| 246 | 246 | if (unlikely(job->job_timeout)) { |
| 247 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_TIMEOUT); | |
| 247 | + amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_TIMEOUT); | |
| 248 | 248 | ret = -EINVAL; |
| 249 | 249 | goto out; |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 252 | if (unlikely(!data) || unlikely(size != sizeof(u32) * 3)) { |
| 253 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT); | |
| 253 | + amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ABORT); | |
| 254 | 254 | ret = -EINVAL; |
| 255 | 255 | goto out; |
| 256 | 256 | } |
| @@ -270,19 +270,12 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size) · 13 unmodified lines | ||
| 270 | 270 | fail_cmd_idx, fail_cmd_status); |
| 271 | 271 | |
| 272 | 272 | if (fail_cmd_status == AIE2_STATUS_SUCCESS) { |
| 273 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT); | |
| 273 | + amdxdna_cmd_set_error(cmd_abo, job, fail_cmd_idx, ERT_CMD_STATE_ABORT); | |
| 274 | 274 | ret = -EINVAL; |
| 275 | − goto out; | |
| 275 | + } else { | |
| 276 | + amdxdna_cmd_set_error(cmd_abo, job, fail_cmd_idx, ERT_CMD_STATE_ERROR); | |
| 276 | 277 | } |
| 277 | − amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR); | |
| 278 | 278 | |
| 279 | − if (amdxdna_cmd_get_op(cmd_abo) == ERT_CMD_CHAIN) { | |
| 280 | − struct amdxdna_cmd_chain *cc = amdxdna_cmd_get_payload(cmd_abo, NULL); | |
| 281 | − | |
| 282 | − cc->error_index = fail_cmd_idx; | |
| 283 | − if (cc->error_index >= cc->command_count) | |
| 284 | − cc->error_index = 0; | |
| 285 | − } | |
| 286 | 279 | out: |
| 287 | 280 | aie2_sched_notify(job); |
| 288 | 281 | return ret; |
| @@ -40,11 +40,8 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev, · 39 unmodified lines | ||
| 40 | 40 | return -ENODEV; |
| 41 | 41 | |
| 42 | 42 | ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg); |
| 43 | − if (ret == -ETIME) { | |
| 44 | − xdna_mailbox_stop_channel(ndev->mgmt_chann); | |
| 45 | − xdna_mailbox_destroy_channel(ndev->mgmt_chann); | |
| 46 | − ndev->mgmt_chann = NULL; | |
| 47 | − } | |
| 43 | + if (ret == -ETIME) | |
| 44 | + aie2_destroy_mgmt_chann(ndev); | |
| 48 | 45 | |
| 49 | 46 | if (!ret && *hdl->status != AIE2_STATUS_SUCCESS) { |
| 50 | 47 | XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x", |
| @@ -296,13 +293,20 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct · 245 unmodified lines | ||
| 296 | 293 | } |
| 297 | 294 | |
| 298 | 295 | intr_reg = i2x.mb_head_ptr_reg + 4; |
| 299 | − hwctx->priv->mbox_chann = xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x, | |
| 300 | − intr_reg, ret); | |
| 296 | + hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox); | |
| 301 | 297 | if (!hwctx->priv->mbox_chann) { |
| 302 | 298 | XDNA_ERR(xdna, "Not able to create channel"); |
| 303 | 299 | ret = -EINVAL; |
| 304 | 300 | goto del_ctx_req; |
| 305 | 301 | } |
| 302 | + | |
| 303 | + ret = xdna_mailbox_start_channel(hwctx->priv->mbox_chann, &x2i, &i2x, | |
| 304 | + intr_reg, ret); | |
| 305 | + if (ret) { | |
| 306 | + XDNA_ERR(xdna, "Not able to create channel"); | |
| 307 | + ret = -EINVAL; | |
| 308 | + goto free_channel; | |
| 309 | + } | |
| 306 | 310 | ndev->hwctx_num++; |
| 307 | 311 | |
| 308 | 312 | XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, resp.msix_id); |
| @@ -310,6 +314,8 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct · 1 unmodified line | ||
| 310 | 314 | |
| 311 | 315 | return 0; |
| 312 | 316 | |
| 317 | +free_channel: | |
| 318 | + xdna_mailbox_free_channel(hwctx->priv->mbox_chann); | |
| 313 | 319 | del_ctx_req: |
| 314 | 320 | aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); |
| 315 | 321 | return ret; |
| @@ -325,7 +331,7 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc · 9 unmodified lines | ||
| 325 | 331 | |
| 326 | 332 | xdna_mailbox_stop_channel(hwctx->priv->mbox_chann); |
| 327 | 333 | ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); |
| 328 | − xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann); | |
| 334 | + xdna_mailbox_free_channel(hwctx->priv->mbox_chann); | |
| 329 | 335 | XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id); |
| 330 | 336 | hwctx->priv->mbox_chann = NULL; |
| 331 | 337 | hwctx->fw_ctx_id = -1; |
| @@ -914,6 +920,20 @@ void aie2_msg_init(struct amdxdna_dev_hdl *ndev) · 582 unmodified lines | ||
| 914 | 920 | ndev->exec_msg_ops = &legacy_exec_message_ops; |
| 915 | 921 | } |
| 916 | 922 | |
| 923 | +void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev) | |
| 924 | +{ | |
| 925 | + struct amdxdna_dev *xdna = ndev->xdna; | |
| 926 | + | |
| 927 | + drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); | |
| 928 | + | |
| 929 | + if (!ndev->mgmt_chann) | |
| 930 | + return; | |
| 931 | + | |
| 932 | + xdna_mailbox_stop_channel(ndev->mgmt_chann); | |
| 933 | + xdna_mailbox_free_channel(ndev->mgmt_chann); | |
| 934 | + ndev->mgmt_chann = NULL; | |
| 935 | +} | |
| 936 | + | |
| 917 | 937 | static inline struct amdxdna_gem_obj * |
| 918 | 938 | aie2_cmdlist_get_cmd_buf(struct amdxdna_sched_job *job) |
| 919 | 939 | { |
| @@ -331,9 +331,7 @@ static void aie2_hw_stop(struct amdxdna_dev *xdna) · 330 unmodified lines | ||
| 331 | 331 | |
| 332 | 332 | aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL); |
| 333 | 333 | aie2_mgmt_fw_fini(ndev); |
| 334 | − xdna_mailbox_stop_channel(ndev->mgmt_chann); | |
| 335 | − xdna_mailbox_destroy_channel(ndev->mgmt_chann); | |
| 336 | − ndev->mgmt_chann = NULL; | |
| 334 | + aie2_destroy_mgmt_chann(ndev); | |
| 337 | 335 | drmm_kfree(&xdna->ddev, ndev->mbox); |
| 338 | 336 | ndev->mbox = NULL; |
| 339 | 337 | aie2_psp_stop(ndev->psp_hdl); |
| @@ -364,10 +362,29 @@ static int aie2_hw_start(struct amdxdna_dev *xdna) · 24 unmodified lines | ||
| 364 | 362 | } |
| 365 | 363 | pci_set_master(pdev); |
| 366 | 364 | |
| 365 | + mbox_res.ringbuf_base = ndev->sram_base; | |
| 366 | + mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar); | |
| 367 | + mbox_res.mbox_base = ndev->mbox_base; | |
| 368 | + mbox_res.mbox_size = MBOX_SIZE(ndev); | |
| 369 | + mbox_res.name = "xdna_mailbox"; | |
| 370 | + ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res); | |
| 371 | + if (!ndev->mbox) { | |
| 372 | + XDNA_ERR(xdna, "failed to create mailbox device"); | |
| 373 | + ret = -ENODEV; | |
| 374 | + goto disable_dev; | |
| 375 | + } | |
| 376 | + | |
| 377 | + ndev->mgmt_chann = xdna_mailbox_alloc_channel(ndev->mbox); | |
| 378 | + if (!ndev->mgmt_chann) { | |
| 379 | + XDNA_ERR(xdna, "failed to alloc channel"); | |
| 380 | + ret = -ENODEV; | |
| 381 | + goto disable_dev; | |
| 382 | + } | |
| 383 | + | |
| 367 | 384 | ret = aie2_smu_init(ndev); |
| 368 | 385 | if (ret) { |
| 369 | 386 | XDNA_ERR(xdna, "failed to init smu, ret %d", ret); |
| 370 | − goto disable_dev; | |
| 387 | + goto free_channel; | |
| 371 | 388 | } |
| 372 | 389 | |
| 373 | 390 | ret = aie2_psp_start(ndev->psp_hdl); |
| @@ -382,18 +399,6 @@ static int aie2_hw_start(struct amdxdna_dev *xdna) · 8 unmodified lines | ||
| 382 | 399 | goto stop_psp; |
| 383 | 400 | } |
| 384 | 401 | |
| 385 | − mbox_res.ringbuf_base = ndev->sram_base; | |
| 386 | − mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar); | |
| 387 | − mbox_res.mbox_base = ndev->mbox_base; | |
| 388 | − mbox_res.mbox_size = MBOX_SIZE(ndev); | |
| 389 | − mbox_res.name = "xdna_mailbox"; | |
| 390 | − ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res); | |
| 391 | − if (!ndev->mbox) { | |
| 392 | − XDNA_ERR(xdna, "failed to create mailbox device"); | |
| 393 | − ret = -ENODEV; | |
| 394 | − goto stop_psp; | |
| 395 | − } | |
| 396 | − | |
| 397 | 402 | mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx); |
| 398 | 403 | if (mgmt_mb_irq < 0) { |
| 399 | 404 | ret = mgmt_mb_irq; |
| @@ -402,13 +407,13 @@ static int aie2_hw_start(struct amdxdna_dev *xdna) · 2 unmodified lines | ||
| 402 | 407 | } |
| 403 | 408 | |
| 404 | 409 | xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4; |
| 405 | − ndev->mgmt_chann = xdna_mailbox_create_channel(ndev->mbox, | |
| 406 | − &ndev->mgmt_x2i, | |
| 407 | − &ndev->mgmt_i2x, | |
| 408 | − xdna_mailbox_intr_reg, | |
| 409 | − mgmt_mb_irq); | |
| 410 | − if (!ndev->mgmt_chann) { | |
| 411 | − XDNA_ERR(xdna, "failed to create management mailbox channel"); | |
| 410 | + ret = xdna_mailbox_start_channel(ndev->mgmt_chann, | |
| 411 | + &ndev->mgmt_x2i, | |
| 412 | + &ndev->mgmt_i2x, | |
| 413 | + xdna_mailbox_intr_reg, | |
| 414 | + mgmt_mb_irq); | |
| 415 | + if (ret) { | |
| 416 | + XDNA_ERR(xdna, "failed to start management mailbox channel"); | |
| 412 | 417 | ret = -EINVAL; |
| 413 | 418 | goto stop_psp; |
| 414 | 419 | } |
| @@ -416,38 +421,41 @@ static int aie2_hw_start(struct amdxdna_dev *xdna) · 1 unmodified line | ||
| 416 | 421 | ret = aie2_mgmt_fw_init(ndev); |
| 417 | 422 | if (ret) { |
| 418 | 423 | XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret); |
| 419 | − goto destroy_mgmt_chann; | |
| 424 | + goto stop_fw; | |
| 420 | 425 | } |
| 421 | 426 | |
| 422 | 427 | ret = aie2_pm_init(ndev); |
| 423 | 428 | if (ret) { |
| 424 | 429 | XDNA_ERR(xdna, "failed to init pm, ret %d", ret); |
| 425 | − goto destroy_mgmt_chann; | |
| 430 | + goto stop_fw; | |
| 426 | 431 | } |
| 427 | 432 | |
| 428 | 433 | ret = aie2_mgmt_fw_query(ndev); |
| 429 | 434 | if (ret) { |
| 430 | 435 | XDNA_ERR(xdna, "failed to query fw, ret %d", ret); |
| 431 | − goto destroy_mgmt_chann; | |
| 436 | + goto stop_fw; | |
| 432 | 437 | } |
| 433 | 438 | |
| 434 | 439 | ret = aie2_error_async_events_alloc(ndev); |
| 435 | 440 | if (ret) { |
| 436 | 441 | XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret); |
| 437 | − goto destroy_mgmt_chann; | |
| 442 | + goto stop_fw; | |
| 438 | 443 | } |
| 439 | 444 | |
| 440 | 445 | ndev->dev_status = AIE2_DEV_START; |
| 441 | 446 | |
| 442 | 447 | return 0; |
| 443 | 448 | |
| 444 | −destroy_mgmt_chann: | |
| 449 | +stop_fw: | |
| 450 | + aie2_suspend_fw(ndev); | |
| 445 | 451 | xdna_mailbox_stop_channel(ndev->mgmt_chann); |
| 446 | − xdna_mailbox_destroy_channel(ndev->mgmt_chann); | |
| 447 | 452 | stop_psp: |
| 448 | 453 | aie2_psp_stop(ndev->psp_hdl); |
| 449 | 454 | fini_smu: |
| 450 | 455 | aie2_smu_fini(ndev); |
| 456 | +free_channel: | |
| 457 | + xdna_mailbox_free_channel(ndev->mgmt_chann); | |
| 458 | + ndev->mgmt_chann = NULL; | |
| 451 | 459 | disable_dev: |
| 452 | 460 | pci_disable_device(pdev); |
| 453 | 461 | |
| @@ -331,6 +331,7 @@ int aie2_get_array_async_error(struct amdxdna_dev_hdl *ndev, · 330 unmodified lines | ||
| 331 | 331 | |
| 332 | 332 | /* aie2_message.c */ |
| 333 | 333 | void aie2_msg_init(struct amdxdna_dev_hdl *ndev); |
| 334 | +void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev); | |
| 334 | 335 | int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev); |
| 335 | 336 | int aie2_resume_fw(struct amdxdna_dev_hdl *ndev); |
| 336 | 337 | int aie2_set_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 value); |
| @@ -135,6 +135,33 @@ u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo) · 134 unmodified lines | ||
| 135 | 135 | return INVALID_CU_IDX; |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | +int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo, | |
| 139 | + struct amdxdna_sched_job *job, u32 cmd_idx, | |
| 140 | + enum ert_cmd_state error_state) | |
| 141 | +{ | |
| 142 | + struct amdxdna_client *client = job->hwctx->client; | |
| 143 | + struct amdxdna_cmd *cmd = abo->mem.kva; | |
| 144 | + struct amdxdna_cmd_chain *cc = NULL; | |
| 145 | + | |
| 146 | + cmd->header &= ~AMDXDNA_CMD_STATE; | |
| 147 | + cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state); | |
| 148 | + | |
| 149 | + if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) { | |
| 150 | + cc = amdxdna_cmd_get_payload(abo, NULL); | |
| 151 | + cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0; | |
| 152 | + abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD); | |
| 153 | + if (!abo) | |
| 154 | + return -EINVAL; | |
| 155 | + cmd = abo->mem.kva; | |
| 156 | + } | |
| 157 | + | |
| 158 | + memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd)); | |
| 159 | + if (cc) | |
| 160 | + amdxdna_gem_put_obj(abo); | |
| 161 | + | |
| 162 | + return 0; | |
| 163 | +} | |
| 164 | + | |
| 138 | 165 | /* |
| 139 | 166 | * This should be called in close() and remove(). DO NOT call in other syscalls. |
| 140 | 167 | * This guarantee that when hwctx and resources will be released, if user |
| @@ -167,6 +167,9 @@ amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo) · 166 unmodified lines | ||
| 167 | 167 | |
| 168 | 168 | void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size); |
| 169 | 169 | u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo); |
| 170 | +int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo, | |
| 171 | + struct amdxdna_sched_job *job, u32 cmd_idx, | |
| 172 | + enum ert_cmd_state error_state); | |
| 170 | 173 | |
| 171 | 174 | void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job); |
| 172 | 175 | void amdxdna_hwctx_remove_all(struct amdxdna_client *client); |
| @@ -460,26 +460,49 @@ msg_id_failed: · 459 unmodified lines | ||
| 460 | 460 | return ret; |
| 461 | 461 | } |
| 462 | 462 | |
| 463 | −struct mailbox_channel * | |
| 464 | −xdna_mailbox_create_channel(struct mailbox *mb, | |
| 465 | − const struct xdna_mailbox_chann_res *x2i, | |
| 466 | − const struct xdna_mailbox_chann_res *i2x, | |
| 467 | − u32 iohub_int_addr, | |
| 468 | − int mb_irq) | |
| 463 | +struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb) | |
| 469 | 464 | { |
| 470 | 465 | struct mailbox_channel *mb_chann; |
| 471 | − int ret; | |
| 472 | − | |
| 473 | − if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) { | |
| 474 | − pr_err("Ring buf size must be power of 2"); | |
| 475 | − return NULL; | |
| 476 | − } | |
| 477 | 466 | |
| 478 | 467 | mb_chann = kzalloc_obj(*mb_chann); |
| 479 | 468 | if (!mb_chann) |
| 480 | 469 | return NULL; |
| 481 | 470 | |
| 471 | + INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker); | |
| 472 | + mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME); | |
| 473 | + if (!mb_chann->work_q) { | |
| 474 | + MB_ERR(mb_chann, "Create workqueue failed"); | |
| 475 | + goto free_chann; | |
| 476 | + } | |
| 482 | 477 | mb_chann->mb = mb; |
| 478 | + | |
| 479 | + return mb_chann; | |
| 480 | + | |
| 481 | +free_chann: | |
| 482 | + kfree(mb_chann); | |
| 483 | + return NULL; | |
| 484 | +} | |
| 485 | + | |
| 486 | +void xdna_mailbox_free_channel(struct mailbox_channel *mb_chann) | |
| 487 | +{ | |
| 488 | + destroy_workqueue(mb_chann->work_q); | |
| 489 | + kfree(mb_chann); | |
| 490 | +} | |
| 491 | + | |
| 492 | +int | |
| 493 | +xdna_mailbox_start_channel(struct mailbox_channel *mb_chann, | |
| 494 | + const struct xdna_mailbox_chann_res *x2i, | |
| 495 | + const struct xdna_mailbox_chann_res *i2x, | |
| 496 | + u32 iohub_int_addr, | |
| 497 | + int mb_irq) | |
| 498 | +{ | |
| 499 | + int ret; | |
| 500 | + | |
| 501 | + if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) { | |
| 502 | + pr_err("Ring buf size must be power of 2"); | |
| 503 | + return -EINVAL; | |
| 504 | + } | |
| 505 | + | |
| 483 | 506 | mb_chann->msix_irq = mb_irq; |
| 484 | 507 | mb_chann->iohub_int_addr = iohub_int_addr; |
| 485 | 508 | memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i)); |
| @@ -489,61 +512,37 @@ xdna_mailbox_create_channel(struct mailbox *mb, · 3 unmodified lines | ||
| 489 | 512 | mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I); |
| 490 | 513 | mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X); |
| 491 | 514 | |
| 492 | − INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker); | |
| 493 | − mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME); | |
| 494 | − if (!mb_chann->work_q) { | |
| 495 | − MB_ERR(mb_chann, "Create workqueue failed"); | |
| 496 | − goto free_and_out; | |
| 497 | − } | |
| 498 | − | |
| 499 | 515 | /* Everything look good. Time to enable irq handler */ |
| 500 | 516 | ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, mb_chann); |
| 501 | 517 | if (ret) { |
| 502 | 518 | MB_ERR(mb_chann, "Failed to request irq %d ret %d", mb_irq, ret); |
| 503 | − goto destroy_wq; | |
| 519 | + return ret; | |
| 504 | 520 | } |
| 505 | 521 | |
| 506 | 522 | mb_chann->bad_state = false; |
| 507 | 523 | mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0); |
| 508 | 524 | |
| 509 | − MB_DBG(mb_chann, "Mailbox channel created (irq: %d)", mb_chann->msix_irq); | |
| 510 | − return mb_chann; | |
| 511 | − | |
| 512 | −destroy_wq: | |
| 513 | − destroy_workqueue(mb_chann->work_q); | |
| 514 | −free_and_out: | |
| 515 | − kfree(mb_chann); | |
| 516 | − return NULL; | |
| 525 | + MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", mb_chann->msix_irq); | |
| 526 | + return 0; | |
| 517 | 527 | } |
| 518 | 528 | |
| 519 | −int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann) | |
| 529 | +void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann) | |
| 520 | 530 | { |
| 521 | 531 | struct mailbox_msg *mb_msg; |
| 522 | 532 | unsigned long msg_id; |
| 523 | 533 | |
| 524 | − MB_DBG(mb_chann, "IRQ disabled and RX work cancelled"); | |
| 534 | + /* Disable an irq and wait. This might sleep. */ | |
| 525 | 535 | free_irq(mb_chann->msix_irq, mb_chann); |
| 526 | − destroy_workqueue(mb_chann->work_q); | |
| 527 | − /* We can clean up and release resources */ | |
| 528 | 536 | |
| 537 | + /* Cancel RX work and wait for it to finish */ | |
| 538 | + drain_workqueue(mb_chann->work_q); | |
| 539 | + | |
| 540 | + /* We can clean up and release resources */ | |
| 529 | 541 | xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg) |
| 530 | 542 | mailbox_release_msg(mb_chann, mb_msg); |
| 531 | − | |
| 532 | 543 | xa_destroy(&mb_chann->chan_xa); |
| 533 | 544 | |
| 534 | − MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", mb_chann->msix_irq); | |
| 535 | − kfree(mb_chann); | |
| 536 | − return 0; | |
| 537 | −} | |
| 538 | − | |
| 539 | −void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann) | |
| 540 | −{ | |
| 541 | − /* Disable an irq and wait. This might sleep. */ | |
| 542 | − disable_irq(mb_chann->msix_irq); | |
| 543 | − | |
| 544 | − /* Cancel RX work and wait for it to finish */ | |
| 545 | − cancel_work_sync(&mb_chann->rx_work); | |
| 546 | − MB_DBG(mb_chann, "IRQ disabled and RX work cancelled"); | |
| 545 | + MB_DBG(mb_chann, "Mailbox channel stopped, irq: %d", mb_chann->msix_irq); | |
| 547 | 546 | } |
| 548 | 547 | |
| 549 | 548 | struct mailbox *xdnam_mailbox_create(struct drm_device *ddev, |
| @@ -74,9 +74,16 @@ struct mailbox *xdnam_mailbox_create(struct drm_device *ddev, · 73 unmodified lines | ||
| 74 | 74 | const struct xdna_mailbox_res *res); |
| 75 | 75 | |
| 76 | 76 | /* |
| 77 | − * xdna_mailbox_create_channel() -- Create a mailbox channel instance | |
| 77 | + * xdna_mailbox_alloc_channel() -- alloc a mailbox channel | |
| 78 | 78 | * |
| 79 | − * @mailbox: the handle return from xdna_mailbox_create() | |
| 79 | + * @mb: mailbox handle | |
| 80 | + */ | |
| 81 | +struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb); | |
| 82 | + | |
| 83 | +/* | |
| 84 | + * xdna_mailbox_start_channel() -- start a mailbox channel instance | |
| 85 | + * | |
| 86 | + * @mb_chann: the handle return from xdna_mailbox_alloc_channel() | |
| 80 | 87 | * @x2i: host to firmware mailbox resources |
| 81 | 88 | * @i2x: firmware to host mailbox resources |
| 82 | 89 | * @xdna_mailbox_intr_reg: register addr of MSI-X interrupt |
| @@ -84,28 +91,24 @@ struct mailbox *xdnam_mailbox_create(struct drm_device *ddev, · 1 unmodified line | ||
| 84 | 91 | * |
| 85 | 92 | * Return: If success, return a handle of mailbox channel. Otherwise, return NULL. |
| 86 | 93 | */ |
| 87 | −struct mailbox_channel * | |
| 88 | −xdna_mailbox_create_channel(struct mailbox *mailbox, | |
| 89 | − const struct xdna_mailbox_chann_res *x2i, | |
| 90 | − const struct xdna_mailbox_chann_res *i2x, | |
| 91 | − u32 xdna_mailbox_intr_reg, | |
| 92 | − int mb_irq); | |
| 94 | +int | |
| 95 | +xdna_mailbox_start_channel(struct mailbox_channel *mb_chann, | |
| 96 | + const struct xdna_mailbox_chann_res *x2i, | |
| 97 | + const struct xdna_mailbox_chann_res *i2x, | |
| 98 | + u32 xdna_mailbox_intr_reg, | |
| 99 | + int mb_irq); | |
| 93 | 100 | |
| 94 | 101 | /* |
| 95 | − * xdna_mailbox_destroy_channel() -- destroy mailbox channel | |
| 102 | + * xdna_mailbox_free_channel() -- free mailbox channel | |
| 96 | 103 | * |
| 97 | 104 | * @mailbox_chann: the handle return from xdna_mailbox_create_channel() |
| 98 | − * | |
| 99 | − * Return: if success, return 0. otherwise return error code | |
| 100 | 105 | */ |
| 101 | −int xdna_mailbox_destroy_channel(struct mailbox_channel *mailbox_chann); | |
| 106 | +void xdna_mailbox_free_channel(struct mailbox_channel *mailbox_chann); | |
| 102 | 107 | |
| 103 | 108 | /* |
| 104 | 109 | * xdna_mailbox_stop_channel() -- stop mailbox channel |
| 105 | 110 | * |
| 106 | 111 | * @mailbox_chann: the handle return from xdna_mailbox_create_channel() |
| 107 | − * | |
| 108 | − * Return: if success, return 0. otherwise return error code | |
| 109 | 112 | */ |
| 110 | 113 | void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann); |
| 111 | 114 | |
| @@ -67,7 +67,7 @@ const struct dpm_clk_freq npu1_dpm_clk_table[] = { · 66 unmodified lines | ||
| 67 | 67 | |
| 68 | 68 | static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = { |
| 69 | 69 | { .major = 5, .min_minor = 7 }, |
| 70 | − { .features = BIT_U64(AIE2_NPU_COMMAND), .min_minor = 8 }, | |
| 70 | + { .features = BIT_U64(AIE2_NPU_COMMAND), .major = 5, .min_minor = 8 }, | |
| 71 | 71 | { 0 } |
| 72 | 72 | }; |
| 73 | 73 | |
| @@ -245,11 +245,14 @@ static int calc_sizes(struct drm_device *ddev, · 244 unmodified lines | ||
| 245 | 245 | ((st->ifm.stride_kernel >> 1) & 0x1) + 1; |
| 246 | 246 | u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) + |
| 247 | 247 | (st->ifm.stride_kernel & 0x1) + 1; |
| 248 | − u32 ifm_height = st->ofm.height[2] * stride_y + | |
| 248 | + s32 ifm_height = st->ofm.height[2] * stride_y + | |
| 249 | 249 | st->ifm.height[2] - (st->ifm.pad_top + st->ifm.pad_bottom); |
| 250 | − u32 ifm_width = st->ofm.width * stride_x + | |
| 250 | + s32 ifm_width = st->ofm.width * stride_x + | |
| 251 | 251 | st->ifm.width - (st->ifm.pad_left + st->ifm.pad_right); |
| 252 | 252 | |
| 253 | + if (ifm_height < 0 || ifm_width < 0) | |
| 254 | + return -EINVAL; | |
| 255 | + | |
| 253 | 256 | len = feat_matrix_length(info, &st->ifm, ifm_width, |
| 254 | 257 | ifm_height, st->ifm.depth); |
| 255 | 258 | dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n", |
| @@ -417,7 +420,10 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, · 161 unmodified lines | ||
| 417 | 420 | return ret; |
| 418 | 421 | break; |
| 419 | 422 | case NPU_OP_ELEMENTWISE: |
| 420 | − use_ifm2 = !((st.ifm2.broadcast == 8) || (param == 5) || | |
| 423 | + use_scale = ethosu_is_u65(edev) ? | |
| 424 | + (st.ifm2.broadcast & 0x80) : | |
| 425 | + (st.ifm2.broadcast == 8); | |
| 426 | + use_ifm2 = !(use_scale || (param == 5) || | |
| 421 | 427 | (param == 6) || (param == 7) || (param == 0x24)); |
| 422 | 428 | use_ifm = st.ifm.broadcast != 8; |
| 423 | 429 | ret = calc_sizes_elemwise(ddev, info, cmd, &st, use_ifm, use_ifm2); |
| @@ -143,23 +143,29 @@ out: · 142 unmodified lines | ||
| 143 | 143 | return ret; |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | +static void ethosu_job_err_cleanup(struct ethosu_job *job) | |
| 147 | +{ | |
| 148 | + unsigned int i; | |
| 149 | + | |
| 150 | + for (i = 0; i < job->region_cnt; i++) | |
| 151 | + drm_gem_object_put(job->region_bo[i]); | |
| 152 | + | |
| 153 | + drm_gem_object_put(job->cmd_bo); | |
| 154 | + | |
| 155 | + kfree(job); | |
| 156 | +} | |
| 157 | + | |
| 146 | 158 | static void ethosu_job_cleanup(struct kref *ref) |
| 147 | 159 | { |
| 148 | 160 | struct ethosu_job *job = container_of(ref, struct ethosu_job, |
| 149 | 161 | refcount); |
| 150 | − unsigned int i; | |
| 151 | 162 | |
| 152 | 163 | pm_runtime_put_autosuspend(job->dev->base.dev); |
| 153 | 164 | |
| 154 | 165 | dma_fence_put(job->done_fence); |
| 155 | 166 | dma_fence_put(job->inference_done_fence); |
| 156 | 167 | |
| 157 | − for (i = 0; i < job->region_cnt; i++) | |
| 158 | − drm_gem_object_put(job->region_bo[i]); | |
| 159 | − | |
| 160 | − drm_gem_object_put(job->cmd_bo); | |
| 161 | − | |
| 162 | − kfree(job); | |
| 168 | + ethosu_job_err_cleanup(job); | |
| 163 | 169 | } |
| 164 | 170 | |
| 165 | 171 | static void ethosu_job_put(struct ethosu_job *job) |
| @@ -454,12 +460,16 @@ static int ethosu_ioctl_submit_job(struct drm_device *dev, struct drm_file *file · 288 unmodified lines | ||
| 454 | 460 | } |
| 455 | 461 | } |
| 456 | 462 | ret = ethosu_job_push(ejob); |
| 463 | + if (!ret) { | |
| 464 | + ethosu_job_put(ejob); | |
| 465 | + return 0; | |
| 466 | + } | |
| 457 | 467 | |
| 458 | 468 | out_cleanup_job: |
| 459 | 469 | if (ret) |
| 460 | 470 | drm_sched_job_cleanup(&ejob->base); |
| 461 | 471 | out_put_job: |
| 462 | − ethosu_job_put(ejob); | |
| 472 | + ethosu_job_err_cleanup(ejob); | |
| 463 | 473 | |
| 464 | 474 | return ret; |
| 465 | 475 | } |
| @@ -379,8 +379,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { · 378 unmodified lines | ||
| 379 | 379 | |
| 380 | 380 | {{"_CPC", METHOD_0ARGS, |
| 381 | 381 | METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */ |
| 382 | − PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, | |
| 383 | − 0, 0, 0), | |
| 382 | + PACKAGE_INFO(ACPI_PTYPE1_VAR, | |
| 383 | + ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | | |
| 384 | + ACPI_RTYPE_PACKAGE, 0, 0, 0, 0), | |
| 384 | 385 | |
| 385 | 386 | {{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */ |
| 386 | 387 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, |
| @@ -1456,15 +1456,6 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) · 1455 unmodified lines | ||
| 1456 | 1456 | if (!adev || !acpi_match_device_ids(adev, special_pm_ids)) |
| 1457 | 1457 | return 0; |
| 1458 | 1458 | |
| 1459 | − /* | |
| 1460 | − * Skip devices whose ACPI companions don't support power management and | |
| 1461 | − * don't have a wakeup GPE. | |
| 1462 | − */ | |
| 1463 | − if (!acpi_device_power_manageable(adev) && !acpi_device_can_wakeup(adev)) { | |
| 1464 | − dev_dbg(dev, "No ACPI power management or wakeup GPE\n"); | |
| 1465 | − return 0; | |
| 1466 | − } | |
| 1467 | − | |
| 1468 | 1459 | /* |
| 1469 | 1460 | * Only attach the power domain to the first device if the |
| 1470 | 1461 | * companion is shared by multiple. This is to prevent doing power |
| @@ -4189,6 +4189,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = { · 4188 unmodified lines | ||
| 4189 | 4189 | ATA_QUIRK_FIRMWARE_WARN }, |
| 4190 | 4190 | |
| 4191 | 4191 | /* Seagate disks with LPM issues */ |
| 4192 | + { "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM }, | |
| 4192 | 4193 | { "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM }, |
| 4193 | 4194 | |
| 4194 | 4195 | /* drives which fail FPDMA_AA activation (some may freeze afterwards) |
| @@ -4231,6 +4232,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = { · 36 unmodified lines | ||
| 4231 | 4232 | /* Devices that do not need bridging limits applied */ |
| 4232 | 4233 | { "MTRON MSP-SATA*", NULL, ATA_QUIRK_BRIDGE_OK }, |
| 4233 | 4234 | { "BUFFALO HD-QSU2/R5", NULL, ATA_QUIRK_BRIDGE_OK }, |
| 4235 | + { "QEMU HARDDISK", "2.5+", ATA_QUIRK_BRIDGE_OK }, | |
| 4234 | 4236 | |
| 4235 | 4237 | /* Devices which aren't very happy with higher link speeds */ |
| 4236 | 4238 | { "WD My Book", NULL, ATA_QUIRK_1_5_GBPS }, |
| @@ -647,7 +647,7 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, · 646 unmodified lines | ||
| 647 | 647 | break; |
| 648 | 648 | } |
| 649 | 649 | |
| 650 | − if (qc == ap->deferred_qc) { | |
| 650 | + if (i < ATA_MAX_QUEUE && qc == ap->deferred_qc) { | |
| 651 | 651 | /* |
| 652 | 652 | * This is a deferred command that timed out while |
| 653 | 653 | * waiting for the command queue to drain. Since the qc |
| @@ -659,6 +659,7 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, · 5 unmodified lines | ||
| 659 | 659 | */ |
| 660 | 660 | WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE); |
| 661 | 661 | ap->deferred_qc = NULL; |
| 662 | + cancel_work(&ap->deferred_qc_work); | |
| 662 | 663 | set_host_byte(scmd, DID_TIME_OUT); |
| 663 | 664 | scsi_eh_finish_cmd(scmd, &ap->eh_done_q); |
| 664 | 665 | } else if (i < ATA_MAX_QUEUE) { |
| @@ -1699,6 +1699,7 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap) · 1698 unmodified lines | ||
| 1699 | 1699 | |
| 1700 | 1700 | scmd = qc->scsicmd; |
| 1701 | 1701 | ap->deferred_qc = NULL; |
| 1702 | + cancel_work(&ap->deferred_qc_work); | |
| 1702 | 1703 | ata_qc_free(qc); |
| 1703 | 1704 | scmd->result = (DID_SOFT_ERROR << 16); |
| 1704 | 1705 | scsi_done(scmd); |
| @@ -179,19 +179,10 @@ void device_release_driver_internal(struct device *dev, const struct device_driv · 178 unmodified lines | ||
| 179 | 179 | void driver_detach(const struct device_driver *drv); |
| 180 | 180 | void driver_deferred_probe_del(struct device *dev); |
| 181 | 181 | void device_set_deferred_probe_reason(const struct device *dev, struct va_format *vaf); |
| 182 | −static inline int driver_match_device_locked(const struct device_driver *drv, | |
| 183 | − struct device *dev) | |
| 184 | −{ | |
| 185 | − device_lock_assert(dev); | |
| 186 | − | |
| 187 | − return drv->bus->match ? drv->bus->match(dev, drv) : 1; | |
| 188 | −} | |
| 189 | − | |
| 190 | 182 | static inline int driver_match_device(const struct device_driver *drv, |
| 191 | 183 | struct device *dev) |
| 192 | 184 | { |
| 193 | − guard(device)(dev); | |
| 194 | − return driver_match_device_locked(drv, dev); | |
| 185 | + return drv->bus->match ? drv->bus->match(dev, drv) : 1; | |
| 195 | 186 | } |
| 196 | 187 | |
| 197 | 188 | static inline void dev_sync_state(struct device *dev) |
| @@ -928,7 +928,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data) · 927 unmodified lines | ||
| 928 | 928 | bool async_allowed; |
| 929 | 929 | int ret; |
| 930 | 930 | |
| 931 | − ret = driver_match_device_locked(drv, dev); | |
| 931 | + ret = driver_match_device(drv, dev); | |
| 932 | 932 | if (ret == 0) { |
| 933 | 933 | /* no match */ |
| 934 | 934 | return 0; |
| @@ -52,9 +52,10 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data, · 51 unmodified lines | ||
| 52 | 52 | rng->priv = 0; |
| 53 | 53 | } else { |
| 54 | 54 | work_data = kmalloc_obj(*work_data, GFP_ATOMIC); |
| 55 | − if (!work_data) | |
| 55 | + if (!work_data) { | |
| 56 | + atomic_dec(&i2c_priv->tfm_count); | |
| 56 | 57 | return -ENOMEM; |
| 57 | − | |
| 58 | + } | |
| 58 | 59 | work_data->ctx = i2c_priv; |
| 59 | 60 | work_data->client = i2c_priv->client; |
| 60 | 61 | |
| @@ -378,9 +378,9 @@ void sev_tsm_init_locked(struct sev_device *sev, void *tio_status_page) · 377 unmodified lines | ||
| 378 | 378 | return; |
| 379 | 379 | |
| 380 | 380 | error_exit: |
| 381 | − kfree(t); | |
| 382 | 381 | pr_err("Failed to enable SEV-TIO: ret=%d en=%d initdone=%d SEV=%d\n", |
| 383 | 382 | ret, t->tio_en, t->tio_init_done, boot_cpu_has(X86_FEATURE_SEV)); |
| 383 | + kfree(t); | |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | 386 | void sev_tsm_uninit(struct sev_device *sev) |
| @@ -1105,15 +1105,12 @@ struct page *snp_alloc_hv_fixed_pages(unsigned int num_2mb_pages) · 1104 unmodified lines | ||
| 1105 | 1105 | { |
| 1106 | 1106 | struct psp_device *psp_master = psp_get_master_device(); |
| 1107 | 1107 | struct snp_hv_fixed_pages_entry *entry; |
| 1108 | − struct sev_device *sev; | |
| 1109 | 1108 | unsigned int order; |
| 1110 | 1109 | struct page *page; |
| 1111 | 1110 | |
| 1112 | − if (!psp_master || !psp_master->sev_data) | |
| 1111 | + if (!psp_master) | |
| 1113 | 1112 | return NULL; |
| 1114 | 1113 | |
| 1115 | − sev = psp_master->sev_data; | |
| 1116 | − | |
| 1117 | 1114 | order = get_order(PMD_SIZE * num_2mb_pages); |
| 1118 | 1115 | |
| 1119 | 1116 | /* |
| @@ -1126,7 +1123,8 @@ struct page *snp_alloc_hv_fixed_pages(unsigned int num_2mb_pages) · 6 unmodified lines | ||
| 1126 | 1123 | * This API uses SNP_INIT_EX to transition allocated pages to HV_Fixed |
| 1127 | 1124 | * page state, fail if SNP is already initialized. |
| 1128 | 1125 | */ |
| 1129 | − if (sev->snp_initialized) | |
| 1126 | + if (psp_master->sev_data && | |
| 1127 | + ((struct sev_device *)psp_master->sev_data)->snp_initialized) | |
| 1130 | 1128 | return NULL; |
| 1131 | 1129 | |
| 1132 | 1130 | /* Re-use freed pages that match the request */ |
| @@ -1162,7 +1160,7 @@ void snp_free_hv_fixed_pages(struct page *page) · 29 unmodified lines | ||
| 1162 | 1160 | struct psp_device *psp_master = psp_get_master_device(); |
| 1163 | 1161 | struct snp_hv_fixed_pages_entry *entry, *nentry; |
| 1164 | 1162 | |
| 1165 | − if (!psp_master || !psp_master->sev_data) | |
| 1163 | + if (!psp_master) | |
| 1166 | 1164 | return; |
| 1167 | 1165 | |
| 1168 | 1166 | /* |
| @@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj; · 84 unmodified lines | ||
| 85 | 85 | * as an alternative to ordinary EFI variables, due to platform-dependent |
| 86 | 86 | * limitations. The memory occupied by this table is marked as reserved. |
| 87 | 87 | * |
| 88 | − * This routine must be called before efi_free_boot_services() in order | |
| 88 | + * This routine must be called before efi_unmap_boot_services() in order | |
| 89 | 89 | * to guarantee that it can mark the table as reserved. |
| 90 | 90 | * |
| 91 | 91 | * Implicit inputs: |
| @@ -47,7 +47,7 @@ subdir-ccflags-$(CONFIG_DRM_AMDGPU_WERROR) += -Werror · 46 unmodified lines | ||
| 47 | 47 | amdgpu-y := amdgpu_drv.o |
| 48 | 48 | |
| 49 | 49 | # add KMS driver |
| 50 | −amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ | |
| 50 | +amdgpu-y += amdgpu_device.o amdgpu_reg_access.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ | |
| 51 | 51 | amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ |
| 52 | 52 | atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ |
| 53 | 53 | amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ |
| @@ -81,6 +81,7 @@ · 80 unmodified lines | ||
| 81 | 81 | #include "amdgpu_sdma.h" |
| 82 | 82 | #include "amdgpu_lsdma.h" |
| 83 | 83 | #include "amdgpu_nbio.h" |
| 84 | +#include "amdgpu_reg_access.h" | |
| 84 | 85 | #include "amdgpu_hdp.h" |
| 85 | 86 | #include "amdgpu_dm.h" |
| 86 | 87 | #include "amdgpu_virt.h" |
| @@ -217,9 +218,7 @@ extern struct amdgpu_watchdog_timer amdgpu_watchdog_timer; · 130 unmodified lines | ||
| 217 | 218 | extern int amdgpu_async_gfx_ring; |
| 218 | 219 | extern int amdgpu_mcbp; |
| 219 | 220 | extern int amdgpu_discovery; |
| 220 | −extern int amdgpu_mes; | |
| 221 | 221 | extern int amdgpu_mes_log_enable; |
| 222 | −extern int amdgpu_mes_kiq; | |
| 223 | 222 | extern int amdgpu_uni_mes; |
| 224 | 223 | extern int amdgpu_noretry; |
| 225 | 224 | extern int amdgpu_force_asic_type; |
| @@ -680,21 +679,6 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device); · 454 unmodified lines | ||
| 680 | 679 | /* |
| 681 | 680 | * Core structure, functions and helpers. |
| 682 | 681 | */ |
| 683 | −typedef uint32_t (*amdgpu_rreg_t)(struct amdgpu_device*, uint32_t); | |
| 684 | −typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t); | |
| 685 | − | |
| 686 | −typedef uint32_t (*amdgpu_rreg_ext_t)(struct amdgpu_device*, uint64_t); | |
| 687 | −typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device*, uint64_t, uint32_t); | |
| 688 | − | |
| 689 | −typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device*, uint32_t); | |
| 690 | −typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t); | |
| 691 | − | |
| 692 | −typedef uint64_t (*amdgpu_rreg64_ext_t)(struct amdgpu_device*, uint64_t); | |
| 693 | −typedef void (*amdgpu_wreg64_ext_t)(struct amdgpu_device*, uint64_t, uint64_t); | |
| 694 | − | |
| 695 | −typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t); | |
| 696 | −typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t); | |
| 697 | − | |
| 698 | 682 | struct amdgpu_mmio_remap { |
| 699 | 683 | u32 reg_offset; |
| 700 | 684 | resource_size_t bus_addr; |
| @@ -791,6 +775,12 @@ struct amd_powerplay { · 90 unmodified lines | ||
| 791 | 775 | (rid == 0x01) || \ |
| 792 | 776 | (rid == 0x10)))) |
| 793 | 777 | |
| 778 | +enum amdgpu_mqd_update_flag { | |
| 779 | + AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE = 1, | |
| 780 | + AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE = 2, | |
| 781 | + AMDGPU_UPDATE_FLAG_IS_GWS = 4, /* quirk for gfx9 IP */ | |
| 782 | +}; | |
| 783 | + | |
| 794 | 784 | struct amdgpu_mqd_prop { |
| 795 | 785 | uint64_t mqd_gpu_addr; |
| 796 | 786 | uint64_t hqd_base_gpu_addr; |
| @@ -811,6 +801,10 @@ struct amdgpu_mqd_prop { · 14 unmodified lines | ||
| 811 | 801 | uint64_t fence_address; |
| 812 | 802 | bool tmz_queue; |
| 813 | 803 | bool kernel_queue; |
| 804 | + uint32_t *cu_mask; | |
| 805 | + uint32_t cu_mask_count; | |
| 806 | + uint32_t cu_flags; | |
| 807 | + bool is_user_cu_masked; | |
| 814 | 808 | }; |
| 815 | 809 | |
| 816 | 810 | struct amdgpu_mqd { |
| @@ -906,42 +900,8 @@ struct amdgpu_device { · 89 unmodified lines | ||
| 906 | 900 | /* protects concurrent MM_INDEX/DATA based register access */ |
| 907 | 901 | spinlock_t mmio_idx_lock; |
| 908 | 902 | struct amdgpu_mmio_remap rmmio_remap; |
| 909 | − /* protects concurrent SMC based register access */ | |
| 910 | − spinlock_t smc_idx_lock; | |
| 911 | − amdgpu_rreg_t smc_rreg; | |
| 912 | − amdgpu_wreg_t smc_wreg; | |
| 913 | − /* protects concurrent PCIE register access */ | |
| 914 | − spinlock_t pcie_idx_lock; | |
| 915 | − amdgpu_rreg_t pcie_rreg; | |
| 916 | − amdgpu_wreg_t pcie_wreg; | |
| 917 | − amdgpu_rreg_t pciep_rreg; | |
| 918 | − amdgpu_wreg_t pciep_wreg; | |
| 919 | − amdgpu_rreg_ext_t pcie_rreg_ext; | |
| 920 | − amdgpu_wreg_ext_t pcie_wreg_ext; | |
| 921 | − amdgpu_rreg64_t pcie_rreg64; | |
| 922 | − amdgpu_wreg64_t pcie_wreg64; | |
| 923 | − amdgpu_rreg64_ext_t pcie_rreg64_ext; | |
| 924 | − amdgpu_wreg64_ext_t pcie_wreg64_ext; | |
| 925 | − /* protects concurrent UVD register access */ | |
| 926 | − spinlock_t uvd_ctx_idx_lock; | |
| 927 | − amdgpu_rreg_t uvd_ctx_rreg; | |
| 928 | − amdgpu_wreg_t uvd_ctx_wreg; | |
| 929 | − /* protects concurrent DIDT register access */ | |
| 930 | − spinlock_t didt_idx_lock; | |
| 931 | − amdgpu_rreg_t didt_rreg; | |
| 932 | − amdgpu_wreg_t didt_wreg; | |
| 933 | − /* protects concurrent gc_cac register access */ | |
| 934 | − spinlock_t gc_cac_idx_lock; | |
| 935 | − amdgpu_rreg_t gc_cac_rreg; | |
| 936 | − amdgpu_wreg_t gc_cac_wreg; | |
| 937 | − /* protects concurrent se_cac register access */ | |
| 938 | − spinlock_t se_cac_idx_lock; | |
| 939 | − amdgpu_rreg_t se_cac_rreg; | |
| 940 | − amdgpu_wreg_t se_cac_wreg; | |
| 941 | − /* protects concurrent ENDPOINT (audio) register access */ | |
| 942 | − spinlock_t audio_endpt_idx_lock; | |
| 943 | − amdgpu_block_rreg_t audio_endpt_rreg; | |
| 944 | − amdgpu_block_wreg_t audio_endpt_wreg; | |
| 903 | + /* Indirect register access blocks */ | |
| 904 | + struct amdgpu_reg_access reg; | |
| 945 | 905 | struct amdgpu_doorbell doorbell; |
| 946 | 906 | |
| 947 | 907 | /* clock/pll info */ |
| @@ -1297,42 +1257,6 @@ size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos, · 349 unmodified lines | ||
| 1297 | 1257 | |
| 1298 | 1258 | void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, |
| 1299 | 1259 | void *buf, size_t size, bool write); |
| 1300 | −uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev, | |
| 1301 | − uint32_t inst, uint32_t reg_addr, char reg_name[], | |
| 1302 | − uint32_t expected_value, uint32_t mask); | |
| 1303 | −uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, | |
| 1304 | − uint32_t reg, uint32_t acc_flags); | |
| 1305 | −u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev, | |
| 1306 | − u64 reg_addr); | |
| 1307 | −uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev, | |
| 1308 | − uint32_t reg, uint32_t acc_flags, | |
| 1309 | − uint32_t xcc_id); | |
| 1310 | −void amdgpu_device_wreg(struct amdgpu_device *adev, | |
| 1311 | − uint32_t reg, uint32_t v, | |
| 1312 | − uint32_t acc_flags); | |
| 1313 | −void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev, | |
| 1314 | − u64 reg_addr, u32 reg_data); | |
| 1315 | −void amdgpu_device_xcc_wreg(struct amdgpu_device *adev, | |
| 1316 | − uint32_t reg, uint32_t v, | |
| 1317 | − uint32_t acc_flags, | |
| 1318 | − uint32_t xcc_id); | |
| 1319 | −void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, | |
| 1320 | − uint32_t reg, uint32_t v, uint32_t xcc_id); | |
| 1321 | −void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value); | |
| 1322 | −uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset); | |
| 1323 | − | |
| 1324 | −u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, | |
| 1325 | − u32 reg_addr); | |
| 1326 | −u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, | |
| 1327 | − u32 reg_addr); | |
| 1328 | −u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev, | |
| 1329 | − u64 reg_addr); | |
| 1330 | −void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, | |
| 1331 | − u32 reg_addr, u32 reg_data); | |
| 1332 | −void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, | |
| 1333 | − u32 reg_addr, u64 reg_data); | |
| 1334 | −void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev, | |
| 1335 | − u64 reg_addr, u64 reg_data); | |
| 1336 | 1260 | u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev); |
| 1337 | 1261 | bool amdgpu_device_asic_has_dc_support(struct pci_dev *pdev, |
| 1338 | 1262 | enum amd_asic_type asic_type); |
| @@ -1372,28 +1296,30 @@ int emu_soc_asic_init(struct amdgpu_device *adev); · 33 unmodified lines | ||
| 1372 | 1296 | #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) |
| 1373 | 1297 | #define RREG32_XCC(reg, inst) amdgpu_device_xcc_rreg(adev, (reg), 0, inst) |
| 1374 | 1298 | #define WREG32_XCC(reg, v, inst) amdgpu_device_xcc_wreg(adev, (reg), (v), 0, inst) |
| 1375 | −#define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg)) | |
| 1376 | −#define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v)) | |
| 1377 | −#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg)) | |
| 1378 | −#define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v)) | |
| 1379 | −#define RREG32_PCIE_EXT(reg) adev->pcie_rreg_ext(adev, (reg)) | |
| 1380 | −#define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v)) | |
| 1381 | −#define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg)) | |
| 1382 | −#define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v)) | |
| 1383 | −#define RREG64_PCIE_EXT(reg) adev->pcie_rreg64_ext(adev, (reg)) | |
| 1384 | −#define WREG64_PCIE_EXT(reg, v) adev->pcie_wreg64_ext(adev, (reg), (v)) | |
| 1385 | −#define RREG32_SMC(reg) adev->smc_rreg(adev, (reg)) | |
| 1386 | −#define WREG32_SMC(reg, v) adev->smc_wreg(adev, (reg), (v)) | |
| 1387 | −#define RREG32_UVD_CTX(reg) adev->uvd_ctx_rreg(adev, (reg)) | |
| 1388 | −#define WREG32_UVD_CTX(reg, v) adev->uvd_ctx_wreg(adev, (reg), (v)) | |
| 1389 | −#define RREG32_DIDT(reg) adev->didt_rreg(adev, (reg)) | |
| 1390 | −#define WREG32_DIDT(reg, v) adev->didt_wreg(adev, (reg), (v)) | |
| 1391 | −#define RREG32_GC_CAC(reg) adev->gc_cac_rreg(adev, (reg)) | |
| 1392 | −#define WREG32_GC_CAC(reg, v) adev->gc_cac_wreg(adev, (reg), (v)) | |
| 1393 | −#define RREG32_SE_CAC(reg) adev->se_cac_rreg(adev, (reg)) | |
| 1394 | −#define WREG32_SE_CAC(reg, v) adev->se_cac_wreg(adev, (reg), (v)) | |
| 1395 | −#define RREG32_AUDIO_ENDPT(block, reg) adev->audio_endpt_rreg(adev, (block), (reg)) | |
| 1396 | −#define WREG32_AUDIO_ENDPT(block, reg, v) adev->audio_endpt_wreg(adev, (block), (reg), (v)) | |
| 1299 | +#define RREG32_PCIE(reg) amdgpu_reg_pcie_rd32(adev, (reg)) | |
| 1300 | +#define WREG32_PCIE(reg, v) amdgpu_reg_pcie_wr32(adev, (reg), (v)) | |
| 1301 | +#define RREG32_PCIE_PORT(reg) amdgpu_reg_pciep_rd32(adev, (reg)) | |
| 1302 | +#define WREG32_PCIE_PORT(reg, v) amdgpu_reg_pciep_wr32(adev, (reg), (v)) | |
| 1303 | +#define RREG32_PCIE_EXT(reg) amdgpu_reg_pcie_ext_rd32(adev, (reg)) | |
| 1304 | +#define WREG32_PCIE_EXT(reg, v) amdgpu_reg_pcie_ext_wr32(adev, (reg), (v)) | |
| 1305 | +#define RREG64_PCIE(reg) amdgpu_reg_pcie_rd64(adev, (reg)) | |
| 1306 | +#define WREG64_PCIE(reg, v) amdgpu_reg_pcie_wr64(adev, (reg), (v)) | |
| 1307 | +#define RREG64_PCIE_EXT(reg) amdgpu_reg_pcie_ext_rd64(adev, (reg)) | |
| 1308 | +#define WREG64_PCIE_EXT(reg, v) amdgpu_reg_pcie_ext_wr64(adev, (reg), (v)) | |
| 1309 | +#define RREG32_SMC(reg) amdgpu_reg_smc_rd32(adev, (reg)) | |
| 1310 | +#define WREG32_SMC(reg, v) amdgpu_reg_smc_wr32(adev, (reg), (v)) | |
| 1311 | +#define RREG32_UVD_CTX(reg) amdgpu_reg_uvd_ctx_rd32(adev, (reg)) | |
| 1312 | +#define WREG32_UVD_CTX(reg, v) amdgpu_reg_uvd_ctx_wr32(adev, (reg), (v)) | |
| 1313 | +#define RREG32_DIDT(reg) amdgpu_reg_didt_rd32(adev, (reg)) | |
| 1314 | +#define WREG32_DIDT(reg, v) amdgpu_reg_didt_wr32(adev, (reg), (v)) | |
| 1315 | +#define RREG32_GC_CAC(reg) amdgpu_reg_gc_cac_rd32(adev, (reg)) | |
| 1316 | +#define WREG32_GC_CAC(reg, v) amdgpu_reg_gc_cac_wr32(adev, (reg), (v)) | |
| 1317 | +#define RREG32_SE_CAC(reg) amdgpu_reg_se_cac_rd32(adev, (reg)) | |
| 1318 | +#define WREG32_SE_CAC(reg, v) amdgpu_reg_se_cac_wr32(adev, (reg), (v)) | |
| 1319 | +#define RREG32_AUDIO_ENDPT(block, reg) \ | |
| 1320 | + amdgpu_reg_audio_endpt_rd32(adev, (block), (reg)) | |
| 1321 | +#define WREG32_AUDIO_ENDPT(block, reg, v) \ | |
| 1322 | + amdgpu_reg_audio_endpt_wr32(adev, (block), (reg), (v)) | |
| 1397 | 1323 | #define WREG32_P(reg, val, mask) \ |
| 1398 | 1324 | do { \ |
| 1399 | 1325 | uint32_t tmp_ = RREG32(reg); \ |
| @@ -1523,10 +1449,6 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev, · 123 unmodified lines | ||
| 1523 | 1449 | struct amdgpu_ring *ring); |
| 1524 | 1450 | |
| 1525 | 1451 | void amdgpu_device_halt(struct amdgpu_device *adev); |
| 1526 | −u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev, | |
| 1527 | − u32 reg); | |
| 1528 | −void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, | |
| 1529 | − u32 reg, u32 v); | |
| 1530 | 1452 | struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev); |
| 1531 | 1453 | struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, |
| 1532 | 1454 | struct dma_fence *gang); |
| @@ -1536,6 +1458,8 @@ struct dma_fence *amdgpu_device_enforce_isolation(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 1536 | 1458 | bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev); |
| 1537 | 1459 | ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring); |
| 1538 | 1460 | ssize_t amdgpu_show_reset_mask(char *buf, uint32_t supported_reset); |
| 1461 | +void amdgpu_sdma_set_vm_pte_scheds(struct amdgpu_device *adev, | |
| 1462 | + const struct amdgpu_vm_pte_funcs *vm_pte_funcs); | |
| 1539 | 1463 | |
| 1540 | 1464 | /* atpx handler */ |
| 1541 | 1465 | #if defined(CONFIG_VGA_SWITCHEROO) |
| @@ -1439,7 +1439,10 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, · 1438 unmodified lines | ||
| 1439 | 1439 | *process_info = info; |
| 1440 | 1440 | } |
| 1441 | 1441 | |
| 1442 | − vm->process_info = *process_info; | |
| 1442 | + if (cmpxchg(&vm->process_info, NULL, *process_info) != NULL) { | |
| 1443 | + ret = -EINVAL; | |
| 1444 | + goto already_acquired; | |
| 1445 | + } | |
| 1443 | 1446 | |
| 1444 | 1447 | /* Validate page directory and attach eviction fence */ |
| 1445 | 1448 | ret = amdgpu_bo_reserve(vm->root.bo, true); |
| @@ -1479,6 +1482,7 @@ validate_pd_fail: · 33 unmodified lines | ||
| 1479 | 1482 | amdgpu_bo_unreserve(vm->root.bo); |
| 1480 | 1483 | reserve_pd_fail: |
| 1481 | 1484 | vm->process_info = NULL; |
| 1485 | +already_acquired: | |
| 1482 | 1486 | if (info) { |
| 1483 | 1487 | dma_fence_put(&info->eviction_fence->base); |
| 1484 | 1488 | *process_info = NULL; |
| @@ -35,6 +35,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, · 34 unmodified lines | ||
| 35 | 35 | struct dma_fence *fence; |
| 36 | 36 | int i, r; |
| 37 | 37 | |
| 38 | + mutex_lock(&adev->mman.default_entity.lock); | |
| 38 | 39 | stime = ktime_get(); |
| 39 | 40 | for (i = 0; i < n; i++) { |
| 40 | 41 | r = amdgpu_copy_buffer(adev, &adev->mman.default_entity, |
| @@ -49,6 +50,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, · 8 unmodified lines | ||
| 49 | 50 | } |
| 50 | 51 | |
| 51 | 52 | exit_do_move: |
| 53 | + mutex_unlock(&adev->mman.default_entity.lock); | |
| 52 | 54 | etime = ktime_get(); |
| 53 | 55 | *time_ms = ktime_ms_delta(etime, stime); |
| 54 | 56 | |
| @@ -84,13 +84,6 @@ static int amdgpu_cs_job_idx(struct amdgpu_cs_parser *p, · 83 unmodified lines | ||
| 84 | 84 | if (r) |
| 85 | 85 | return r; |
| 86 | 86 | |
| 87 | − /* | |
| 88 | − * Abort if there is no run queue associated with this entity. | |
| 89 | − * Possibly because of disabled HW IP. | |
| 90 | − */ | |
| 91 | − if (entity->rq == NULL) | |
| 92 | − return -EINVAL; | |
| 93 | − | |
| 94 | 87 | /* Check if we can add this IB to some existing job */ |
| 95 | 88 | for (i = 0; i < p->gang_size; ++i) |
| 96 | 89 | if (p->entities[i] == entity) |
| @@ -231,13 +231,19 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, · 230 unmodified lines | ||
| 231 | 231 | } else { |
| 232 | 232 | struct amdgpu_fpriv *fpriv; |
| 233 | 233 | |
| 234 | − fpriv = container_of(ctx->ctx_mgr, struct amdgpu_fpriv, ctx_mgr); | |
| 234 | + /* TODO: Stop using fpriv here, we only need the xcp_id. */ | |
| 235 | + fpriv = container_of(ctx->mgr, struct amdgpu_fpriv, ctx_mgr); | |
| 235 | 236 | r = amdgpu_xcp_select_scheds(adev, hw_ip, hw_prio, fpriv, |
| 236 | 237 | &num_scheds, &scheds); |
| 237 | 238 | if (r) |
| 238 | 239 | goto error_free_entity; |
| 239 | 240 | } |
| 240 | 241 | |
| 242 | + if (num_scheds == 0) { | |
| 243 | + r = -EINVAL; | |
| 244 | + goto error_free_entity; | |
| 245 | + } | |
| 246 | + | |
| 241 | 247 | /* disable load balance if the hw engine retains context among dependent jobs */ |
| 242 | 248 | if (hw_ip == AMDGPU_HW_IP_VCN_ENC || |
| 243 | 249 | hw_ip == AMDGPU_HW_IP_VCN_DEC || |
| @@ -348,7 +354,6 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority, · 104 unmodified lines | ||
| 348 | 354 | else |
| 349 | 355 | ctx->stable_pstate = current_stable_pstate; |
| 350 | 356 | |
| 351 | − ctx->ctx_mgr = &(fpriv->ctx_mgr); | |
| 352 | 357 | return 0; |
| 353 | 358 | } |
| 354 | 359 | |
| @@ -44,20 +44,19 @@ struct amdgpu_ctx_entity { · 43 unmodified lines | ||
| 44 | 44 | |
| 45 | 45 | struct amdgpu_ctx { |
| 46 | 46 | struct kref refcount; |
| 47 | − struct amdgpu_ctx_mgr *mgr; | |
| 47 | + spinlock_t ring_lock; | |
| 48 | 48 | unsigned reset_counter; |
| 49 | 49 | unsigned reset_counter_query; |
| 50 | − uint64_t generation; | |
| 51 | − spinlock_t ring_lock; | |
| 52 | − struct amdgpu_ctx_entity *entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM]; | |
| 53 | − bool preamble_presented; | |
| 54 | 50 | int32_t init_priority; |
| 55 | 51 | int32_t override_priority; |
| 52 | + uint32_t stable_pstate; | |
| 56 | 53 | atomic_t guilty; |
| 54 | + bool preamble_presented; | |
| 55 | + uint64_t generation; | |
| 57 | 56 | unsigned long ras_counter_ce; |
| 58 | 57 | unsigned long ras_counter_ue; |
| 59 | − uint32_t stable_pstate; | |
| 60 | − struct amdgpu_ctx_mgr *ctx_mgr; | |
| 58 | + struct amdgpu_ctx_mgr *mgr; | |
| 59 | + struct amdgpu_ctx_entity *entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM]; | |
| 61 | 60 | }; |
| 62 | 61 | |
| 63 | 62 | struct amdgpu_ctx_mgr { |
| @@ -638,7 +638,7 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, · 637 unmodified lines | ||
| 638 | 638 | if (size & 0x3 || *pos & 0x3) |
| 639 | 639 | return -EINVAL; |
| 640 | 640 | |
| 641 | − if (!adev->didt_rreg) | |
| 641 | + if (!adev->reg.didt.rreg) | |
| 642 | 642 | return -EOPNOTSUPP; |
| 643 | 643 | |
| 644 | 644 | r = pm_runtime_get_sync(adev_to_drm(adev)->dev); |
| @@ -696,7 +696,7 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user · 51 unmodified lines | ||
| 696 | 696 | if (size & 0x3 || *pos & 0x3) |
| 697 | 697 | return -EINVAL; |
| 698 | 698 | |
| 699 | − if (!adev->didt_wreg) | |
| 699 | + if (!adev->reg.didt.wreg) | |
| 700 | 700 | return -EOPNOTSUPP; |
| 701 | 701 | |
| 702 | 702 | r = pm_runtime_get_sync(adev_to_drm(adev)->dev); |
| @@ -752,7 +752,7 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, · 49 unmodified lines | ||
| 752 | 752 | ssize_t result = 0; |
| 753 | 753 | int r; |
| 754 | 754 | |
| 755 | − if (!adev->smc_rreg) | |
| 755 | + if (!adev->reg.smc.rreg) | |
| 756 | 756 | return -EOPNOTSUPP; |
| 757 | 757 | |
| 758 | 758 | if (size & 0x3 || *pos & 0x3) |
| @@ -810,7 +810,7 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * · 51 unmodified lines | ||
| 810 | 810 | ssize_t result = 0; |
| 811 | 811 | int r; |
| 812 | 812 | |
| 813 | − if (!adev->smc_wreg) | |
| 813 | + if (!adev->reg.smc.wreg) | |
| 814 | 814 | return -EOPNOTSUPP; |
| 815 | 815 | |
| 816 | 816 | if (size & 0x3 || *pos & 0x3) |
| @@ -846,558 +846,6 @@ bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev) · 845 unmodified lines | ||
| 846 | 846 | return false; |
| 847 | 847 | } |
| 848 | 848 | |
| 849 | −/** | |
| 850 | − * amdgpu_device_rreg - read a memory mapped IO or indirect register | |
| 851 | − * | |
| 852 | − * @adev: amdgpu_device pointer | |
| 853 | − * @reg: dword aligned register offset | |
| 854 | − * @acc_flags: access flags which require special behavior | |
| 855 | − * | |
| 856 | − * Returns the 32 bit value from the offset specified. | |
| 857 | − */ | |
| 858 | −uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, | |
| 859 | − uint32_t reg, uint32_t acc_flags) | |
| 860 | −{ | |
| 861 | − uint32_t ret; | |
| 862 | − | |
| 863 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 864 | − return 0; | |
| 865 | − | |
| 866 | − if ((reg * 4) < adev->rmmio_size) { | |
| 867 | − if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 868 | − amdgpu_sriov_runtime(adev) && | |
| 869 | − down_read_trylock(&adev->reset_domain->sem)) { | |
| 870 | − ret = amdgpu_kiq_rreg(adev, reg, 0); | |
| 871 | − up_read(&adev->reset_domain->sem); | |
| 872 | − } else { | |
| 873 | − ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 874 | − } | |
| 875 | − } else { | |
| 876 | − ret = adev->pcie_rreg(adev, reg * 4); | |
| 877 | − } | |
| 878 | − | |
| 879 | − trace_amdgpu_device_rreg(adev->pdev->device, reg, ret); | |
| 880 | − | |
| 881 | − return ret; | |
| 882 | −} | |
| 883 | − | |
| 884 | −/* | |
| 885 | − * MMIO register read with bytes helper functions | |
| 886 | − * @offset:bytes offset from MMIO start | |
| 887 | − */ | |
| 888 | − | |
| 889 | −/** | |
| 890 | − * amdgpu_mm_rreg8 - read a memory mapped IO register | |
| 891 | − * | |
| 892 | − * @adev: amdgpu_device pointer | |
| 893 | − * @offset: byte aligned register offset | |
| 894 | − * | |
| 895 | − * Returns the 8 bit value from the offset specified. | |
| 896 | − */ | |
| 897 | −uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) | |
| 898 | −{ | |
| 899 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 900 | − return 0; | |
| 901 | − | |
| 902 | − if (offset < adev->rmmio_size) | |
| 903 | − return (readb(adev->rmmio + offset)); | |
| 904 | − BUG(); | |
| 905 | −} | |
| 906 | − | |
| 907 | − | |
| 908 | −/** | |
| 909 | − * amdgpu_device_xcc_rreg - read a memory mapped IO or indirect register with specific XCC | |
| 910 | − * | |
| 911 | − * @adev: amdgpu_device pointer | |
| 912 | − * @reg: dword aligned register offset | |
| 913 | − * @acc_flags: access flags which require special behavior | |
| 914 | − * @xcc_id: xcc accelerated compute core id | |
| 915 | − * | |
| 916 | − * Returns the 32 bit value from the offset specified. | |
| 917 | − */ | |
| 918 | −uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev, | |
| 919 | − uint32_t reg, uint32_t acc_flags, | |
| 920 | − uint32_t xcc_id) | |
| 921 | −{ | |
| 922 | − uint32_t ret, rlcg_flag; | |
| 923 | − | |
| 924 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 925 | − return 0; | |
| 926 | − | |
| 927 | − if ((reg * 4) < adev->rmmio_size) { | |
| 928 | − if (amdgpu_sriov_vf(adev) && | |
| 929 | − !amdgpu_sriov_runtime(adev) && | |
| 930 | − adev->gfx.rlc.rlcg_reg_access_supported && | |
| 931 | − amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, | |
| 932 | − GC_HWIP, false, | |
| 933 | − &rlcg_flag)) { | |
| 934 | − ret = amdgpu_virt_rlcg_reg_rw(adev, reg, 0, rlcg_flag, GET_INST(GC, xcc_id)); | |
| 935 | − } else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 936 | − amdgpu_sriov_runtime(adev) && | |
| 937 | − down_read_trylock(&adev->reset_domain->sem)) { | |
| 938 | − ret = amdgpu_kiq_rreg(adev, reg, xcc_id); | |
| 939 | − up_read(&adev->reset_domain->sem); | |
| 940 | − } else { | |
| 941 | − ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 942 | − } | |
| 943 | − } else { | |
| 944 | − ret = adev->pcie_rreg(adev, reg * 4); | |
| 945 | − } | |
| 946 | − | |
| 947 | − return ret; | |
| 948 | −} | |
| 949 | − | |
| 950 | −/* | |
| 951 | − * MMIO register write with bytes helper functions | |
| 952 | − * @offset:bytes offset from MMIO start | |
| 953 | − * @value: the value want to be written to the register | |
| 954 | − */ | |
| 955 | − | |
| 956 | −/** | |
| 957 | − * amdgpu_mm_wreg8 - read a memory mapped IO register | |
| 958 | − * | |
| 959 | − * @adev: amdgpu_device pointer | |
| 960 | − * @offset: byte aligned register offset | |
| 961 | − * @value: 8 bit value to write | |
| 962 | − * | |
| 963 | − * Writes the value specified to the offset specified. | |
| 964 | − */ | |
| 965 | −void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) | |
| 966 | −{ | |
| 967 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 968 | − return; | |
| 969 | − | |
| 970 | − if (offset < adev->rmmio_size) | |
| 971 | − writeb(value, adev->rmmio + offset); | |
| 972 | − else | |
| 973 | − BUG(); | |
| 974 | −} | |
| 975 | − | |
| 976 | −/** | |
| 977 | − * amdgpu_device_wreg - write to a memory mapped IO or indirect register | |
| 978 | − * | |
| 979 | − * @adev: amdgpu_device pointer | |
| 980 | − * @reg: dword aligned register offset | |
| 981 | − * @v: 32 bit value to write to the register | |
| 982 | − * @acc_flags: access flags which require special behavior | |
| 983 | − * | |
| 984 | − * Writes the value specified to the offset specified. | |
| 985 | − */ | |
| 986 | −void amdgpu_device_wreg(struct amdgpu_device *adev, | |
| 987 | − uint32_t reg, uint32_t v, | |
| 988 | − uint32_t acc_flags) | |
| 989 | −{ | |
| 990 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 991 | − return; | |
| 992 | − | |
| 993 | − if ((reg * 4) < adev->rmmio_size) { | |
| 994 | − if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 995 | − amdgpu_sriov_runtime(adev) && | |
| 996 | − down_read_trylock(&adev->reset_domain->sem)) { | |
| 997 | − amdgpu_kiq_wreg(adev, reg, v, 0); | |
| 998 | − up_read(&adev->reset_domain->sem); | |
| 999 | − } else { | |
| 1000 | − writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 1001 | − } | |
| 1002 | − } else { | |
| 1003 | − adev->pcie_wreg(adev, reg * 4, v); | |
| 1004 | − } | |
| 1005 | − | |
| 1006 | − trace_amdgpu_device_wreg(adev->pdev->device, reg, v); | |
| 1007 | −} | |
| 1008 | − | |
| 1009 | −/** | |
| 1010 | − * amdgpu_mm_wreg_mmio_rlc - write register either with direct/indirect mmio or with RLC path if in range | |
| 1011 | − * | |
| 1012 | − * @adev: amdgpu_device pointer | |
| 1013 | − * @reg: mmio/rlc register | |
| 1014 | − * @v: value to write | |
| 1015 | − * @xcc_id: xcc accelerated compute core id | |
| 1016 | − * | |
| 1017 | − * this function is invoked only for the debugfs register access | |
| 1018 | − */ | |
| 1019 | −void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, | |
| 1020 | − uint32_t reg, uint32_t v, | |
| 1021 | − uint32_t xcc_id) | |
| 1022 | −{ | |
| 1023 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 1024 | − return; | |
| 1025 | − | |
| 1026 | − if (amdgpu_sriov_fullaccess(adev) && | |
| 1027 | − adev->gfx.rlc.funcs && | |
| 1028 | − adev->gfx.rlc.funcs->is_rlcg_access_range) { | |
| 1029 | − if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg)) | |
| 1030 | − return amdgpu_sriov_wreg(adev, reg, v, 0, 0, xcc_id); | |
| 1031 | − } else if ((reg * 4) >= adev->rmmio_size) { | |
| 1032 | − adev->pcie_wreg(adev, reg * 4, v); | |
| 1033 | − } else { | |
| 1034 | − writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 1035 | − } | |
| 1036 | −} | |
| 1037 | − | |
| 1038 | −/** | |
| 1039 | − * amdgpu_device_xcc_wreg - write to a memory mapped IO or indirect register with specific XCC | |
| 1040 | − * | |
| 1041 | − * @adev: amdgpu_device pointer | |
| 1042 | − * @reg: dword aligned register offset | |
| 1043 | − * @v: 32 bit value to write to the register | |
| 1044 | − * @acc_flags: access flags which require special behavior | |
| 1045 | − * @xcc_id: xcc accelerated compute core id | |
| 1046 | − * | |
| 1047 | − * Writes the value specified to the offset specified. | |
| 1048 | − */ | |
| 1049 | −void amdgpu_device_xcc_wreg(struct amdgpu_device *adev, | |
| 1050 | − uint32_t reg, uint32_t v, | |
| 1051 | − uint32_t acc_flags, uint32_t xcc_id) | |
| 1052 | −{ | |
| 1053 | − uint32_t rlcg_flag; | |
| 1054 | − | |
| 1055 | − if (amdgpu_device_skip_hw_access(adev)) | |
| 1056 | − return; | |
| 1057 | − | |
| 1058 | − if ((reg * 4) < adev->rmmio_size) { | |
| 1059 | − if (amdgpu_sriov_vf(adev) && | |
| 1060 | − !amdgpu_sriov_runtime(adev) && | |
| 1061 | − adev->gfx.rlc.rlcg_reg_access_supported && | |
| 1062 | − amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, | |
| 1063 | − GC_HWIP, true, | |
| 1064 | − &rlcg_flag)) { | |
| 1065 | − amdgpu_virt_rlcg_reg_rw(adev, reg, v, rlcg_flag, GET_INST(GC, xcc_id)); | |
| 1066 | − } else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 1067 | − amdgpu_sriov_runtime(adev) && | |
| 1068 | − down_read_trylock(&adev->reset_domain->sem)) { | |
| 1069 | − amdgpu_kiq_wreg(adev, reg, v, xcc_id); | |
| 1070 | − up_read(&adev->reset_domain->sem); | |
| 1071 | − } else { | |
| 1072 | − writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 1073 | − } | |
| 1074 | − } else { | |
| 1075 | − adev->pcie_wreg(adev, reg * 4, v); | |
| 1076 | − } | |
| 1077 | −} | |
| 1078 | − | |
| 1079 | −/** | |
| 1080 | − * amdgpu_device_indirect_rreg - read an indirect register | |
| 1081 | − * | |
| 1082 | − * @adev: amdgpu_device pointer | |
| 1083 | − * @reg_addr: indirect register address to read from | |
| 1084 | − * | |
| 1085 | − * Returns the value of indirect register @reg_addr | |
| 1086 | − */ | |
| 1087 | −u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, | |
| 1088 | − u32 reg_addr) | |
| 1089 | −{ | |
| 1090 | − unsigned long flags, pcie_index, pcie_data; | |
| 1091 | − void __iomem *pcie_index_offset; | |
| 1092 | − void __iomem *pcie_data_offset; | |
| 1093 | − u32 r; | |
| 1094 | − | |
| 1095 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1096 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1097 | − | |
| 1098 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1099 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1100 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1101 | − | |
| 1102 | − writel(reg_addr, pcie_index_offset); | |
| 1103 | − readl(pcie_index_offset); | |
| 1104 | − r = readl(pcie_data_offset); | |
| 1105 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1106 | − | |
| 1107 | − return r; | |
| 1108 | −} | |
| 1109 | − | |
| 1110 | −u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev, | |
| 1111 | − u64 reg_addr) | |
| 1112 | −{ | |
| 1113 | − unsigned long flags, pcie_index, pcie_index_hi, pcie_data; | |
| 1114 | − u32 r; | |
| 1115 | − void __iomem *pcie_index_offset; | |
| 1116 | − void __iomem *pcie_index_hi_offset; | |
| 1117 | − void __iomem *pcie_data_offset; | |
| 1118 | − | |
| 1119 | − if (unlikely(!adev->nbio.funcs)) { | |
| 1120 | − pcie_index = AMDGPU_PCIE_INDEX_FALLBACK; | |
| 1121 | − pcie_data = AMDGPU_PCIE_DATA_FALLBACK; | |
| 1122 | − } else { | |
| 1123 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1124 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1125 | − } | |
| 1126 | − | |
| 1127 | − if (reg_addr >> 32) { | |
| 1128 | − if (unlikely(!adev->nbio.funcs)) | |
| 1129 | − pcie_index_hi = AMDGPU_PCIE_INDEX_HI_FALLBACK; | |
| 1130 | − else | |
| 1131 | − pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 1132 | − } else { | |
| 1133 | − pcie_index_hi = 0; | |
| 1134 | − } | |
| 1135 | − | |
| 1136 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1137 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1138 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1139 | − if (pcie_index_hi != 0) | |
| 1140 | − pcie_index_hi_offset = (void __iomem *)adev->rmmio + | |
| 1141 | − pcie_index_hi * 4; | |
| 1142 | − | |
| 1143 | − writel(reg_addr, pcie_index_offset); | |
| 1144 | − readl(pcie_index_offset); | |
| 1145 | − if (pcie_index_hi != 0) { | |
| 1146 | − writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 1147 | − readl(pcie_index_hi_offset); | |
| 1148 | − } | |
| 1149 | − r = readl(pcie_data_offset); | |
| 1150 | − | |
| 1151 | − /* clear the high bits */ | |
| 1152 | − if (pcie_index_hi != 0) { | |
| 1153 | − writel(0, pcie_index_hi_offset); | |
| 1154 | − readl(pcie_index_hi_offset); | |
| 1155 | − } | |
| 1156 | − | |
| 1157 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1158 | − | |
| 1159 | − return r; | |
| 1160 | −} | |
| 1161 | − | |
| 1162 | −/** | |
| 1163 | − * amdgpu_device_indirect_rreg64 - read a 64bits indirect register | |
| 1164 | − * | |
| 1165 | − * @adev: amdgpu_device pointer | |
| 1166 | − * @reg_addr: indirect register address to read from | |
| 1167 | − * | |
| 1168 | − * Returns the value of indirect register @reg_addr | |
| 1169 | − */ | |
| 1170 | −u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, | |
| 1171 | − u32 reg_addr) | |
| 1172 | −{ | |
| 1173 | − unsigned long flags, pcie_index, pcie_data; | |
| 1174 | − void __iomem *pcie_index_offset; | |
| 1175 | − void __iomem *pcie_data_offset; | |
| 1176 | − u64 r; | |
| 1177 | − | |
| 1178 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1179 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1180 | − | |
| 1181 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1182 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1183 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1184 | − | |
| 1185 | − /* read low 32 bits */ | |
| 1186 | − writel(reg_addr, pcie_index_offset); | |
| 1187 | − readl(pcie_index_offset); | |
| 1188 | − r = readl(pcie_data_offset); | |
| 1189 | − /* read high 32 bits */ | |
| 1190 | − writel(reg_addr + 4, pcie_index_offset); | |
| 1191 | − readl(pcie_index_offset); | |
| 1192 | − r |= ((u64)readl(pcie_data_offset) << 32); | |
| 1193 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1194 | − | |
| 1195 | − return r; | |
| 1196 | −} | |
| 1197 | − | |
| 1198 | −u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev, | |
| 1199 | − u64 reg_addr) | |
| 1200 | −{ | |
| 1201 | − unsigned long flags, pcie_index, pcie_data; | |
| 1202 | − unsigned long pcie_index_hi = 0; | |
| 1203 | − void __iomem *pcie_index_offset; | |
| 1204 | − void __iomem *pcie_index_hi_offset; | |
| 1205 | − void __iomem *pcie_data_offset; | |
| 1206 | − u64 r; | |
| 1207 | − | |
| 1208 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1209 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1210 | − if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset)) | |
| 1211 | − pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 1212 | − | |
| 1213 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1214 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1215 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1216 | − if (pcie_index_hi != 0) | |
| 1217 | − pcie_index_hi_offset = (void __iomem *)adev->rmmio + | |
| 1218 | − pcie_index_hi * 4; | |
| 1219 | − | |
| 1220 | − /* read low 32 bits */ | |
| 1221 | − writel(reg_addr, pcie_index_offset); | |
| 1222 | − readl(pcie_index_offset); | |
| 1223 | − if (pcie_index_hi != 0) { | |
| 1224 | − writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 1225 | − readl(pcie_index_hi_offset); | |
| 1226 | − } | |
| 1227 | − r = readl(pcie_data_offset); | |
| 1228 | − /* read high 32 bits */ | |
| 1229 | − writel(reg_addr + 4, pcie_index_offset); | |
| 1230 | − readl(pcie_index_offset); | |
| 1231 | − if (pcie_index_hi != 0) { | |
| 1232 | − writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 1233 | − readl(pcie_index_hi_offset); | |
| 1234 | − } | |
| 1235 | − r |= ((u64)readl(pcie_data_offset) << 32); | |
| 1236 | − | |
| 1237 | − /* clear the high bits */ | |
| 1238 | − if (pcie_index_hi != 0) { | |
| 1239 | − writel(0, pcie_index_hi_offset); | |
| 1240 | − readl(pcie_index_hi_offset); | |
| 1241 | − } | |
| 1242 | − | |
| 1243 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1244 | − | |
| 1245 | − return r; | |
| 1246 | −} | |
| 1247 | − | |
| 1248 | −/** | |
| 1249 | − * amdgpu_device_indirect_wreg - write an indirect register address | |
| 1250 | − * | |
| 1251 | − * @adev: amdgpu_device pointer | |
| 1252 | − * @reg_addr: indirect register offset | |
| 1253 | − * @reg_data: indirect register data | |
| 1254 | − * | |
| 1255 | − */ | |
| 1256 | −void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, | |
| 1257 | − u32 reg_addr, u32 reg_data) | |
| 1258 | −{ | |
| 1259 | − unsigned long flags, pcie_index, pcie_data; | |
| 1260 | − void __iomem *pcie_index_offset; | |
| 1261 | − void __iomem *pcie_data_offset; | |
| 1262 | − | |
| 1263 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1264 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1265 | − | |
| 1266 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1267 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1268 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1269 | − | |
| 1270 | − writel(reg_addr, pcie_index_offset); | |
| 1271 | − readl(pcie_index_offset); | |
| 1272 | − writel(reg_data, pcie_data_offset); | |
| 1273 | − readl(pcie_data_offset); | |
| 1274 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1275 | −} | |
| 1276 | − | |
| 1277 | −void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev, | |
| 1278 | − u64 reg_addr, u32 reg_data) | |
| 1279 | −{ | |
| 1280 | − unsigned long flags, pcie_index, pcie_index_hi, pcie_data; | |
| 1281 | − void __iomem *pcie_index_offset; | |
| 1282 | − void __iomem *pcie_index_hi_offset; | |
| 1283 | − void __iomem *pcie_data_offset; | |
| 1284 | − | |
| 1285 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1286 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1287 | − if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset)) | |
| 1288 | − pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 1289 | − else | |
| 1290 | − pcie_index_hi = 0; | |
| 1291 | − | |
| 1292 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1293 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1294 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1295 | − if (pcie_index_hi != 0) | |
| 1296 | − pcie_index_hi_offset = (void __iomem *)adev->rmmio + | |
| 1297 | − pcie_index_hi * 4; | |
| 1298 | − | |
| 1299 | − writel(reg_addr, pcie_index_offset); | |
| 1300 | − readl(pcie_index_offset); | |
| 1301 | − if (pcie_index_hi != 0) { | |
| 1302 | − writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 1303 | − readl(pcie_index_hi_offset); | |
| 1304 | − } | |
| 1305 | − writel(reg_data, pcie_data_offset); | |
| 1306 | − readl(pcie_data_offset); | |
| 1307 | − | |
| 1308 | − /* clear the high bits */ | |
| 1309 | − if (pcie_index_hi != 0) { | |
| 1310 | − writel(0, pcie_index_hi_offset); | |
| 1311 | − readl(pcie_index_hi_offset); | |
| 1312 | − } | |
| 1313 | − | |
| 1314 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1315 | −} | |
| 1316 | − | |
| 1317 | −/** | |
| 1318 | − * amdgpu_device_indirect_wreg64 - write a 64bits indirect register address | |
| 1319 | − * | |
| 1320 | − * @adev: amdgpu_device pointer | |
| 1321 | − * @reg_addr: indirect register offset | |
| 1322 | − * @reg_data: indirect register data | |
| 1323 | − * | |
| 1324 | − */ | |
| 1325 | −void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, | |
| 1326 | − u32 reg_addr, u64 reg_data) | |
| 1327 | −{ | |
| 1328 | − unsigned long flags, pcie_index, pcie_data; | |
| 1329 | − void __iomem *pcie_index_offset; | |
| 1330 | − void __iomem *pcie_data_offset; | |
| 1331 | − | |
| 1332 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1333 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1334 | − | |
| 1335 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1336 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1337 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1338 | − | |
| 1339 | − /* write low 32 bits */ | |
| 1340 | − writel(reg_addr, pcie_index_offset); | |
| 1341 | − readl(pcie_index_offset); | |
| 1342 | − writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset); | |
| 1343 | − readl(pcie_data_offset); | |
| 1344 | − /* write high 32 bits */ | |
| 1345 | − writel(reg_addr + 4, pcie_index_offset); | |
| 1346 | − readl(pcie_index_offset); | |
| 1347 | − writel((u32)(reg_data >> 32), pcie_data_offset); | |
| 1348 | − readl(pcie_data_offset); | |
| 1349 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1350 | −} | |
| 1351 | − | |
| 1352 | −void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev, | |
| 1353 | − u64 reg_addr, u64 reg_data) | |
| 1354 | −{ | |
| 1355 | − unsigned long flags, pcie_index, pcie_data; | |
| 1356 | − unsigned long pcie_index_hi = 0; | |
| 1357 | − void __iomem *pcie_index_offset; | |
| 1358 | − void __iomem *pcie_index_hi_offset; | |
| 1359 | − void __iomem *pcie_data_offset; | |
| 1360 | − | |
| 1361 | − pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 1362 | − pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 1363 | − if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset)) | |
| 1364 | − pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 1365 | − | |
| 1366 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1367 | − pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 1368 | − pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 1369 | − if (pcie_index_hi != 0) | |
| 1370 | − pcie_index_hi_offset = (void __iomem *)adev->rmmio + | |
| 1371 | − pcie_index_hi * 4; | |
| 1372 | − | |
| 1373 | − /* write low 32 bits */ | |
| 1374 | − writel(reg_addr, pcie_index_offset); | |
| 1375 | − readl(pcie_index_offset); | |
| 1376 | − if (pcie_index_hi != 0) { | |
| 1377 | − writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 1378 | − readl(pcie_index_hi_offset); | |
| 1379 | − } | |
| 1380 | − writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset); | |
| 1381 | − readl(pcie_data_offset); | |
| 1382 | − /* write high 32 bits */ | |
| 1383 | − writel(reg_addr + 4, pcie_index_offset); | |
| 1384 | − readl(pcie_index_offset); | |
| 1385 | − if (pcie_index_hi != 0) { | |
| 1386 | − writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 1387 | − readl(pcie_index_hi_offset); | |
| 1388 | − } | |
| 1389 | − writel((u32)(reg_data >> 32), pcie_data_offset); | |
| 1390 | − readl(pcie_data_offset); | |
| 1391 | − | |
| 1392 | − /* clear the high bits */ | |
| 1393 | − if (pcie_index_hi != 0) { | |
| 1394 | − writel(0, pcie_index_hi_offset); | |
| 1395 | − readl(pcie_index_hi_offset); | |
| 1396 | − } | |
| 1397 | − | |
| 1398 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1399 | −} | |
| 1400 | − | |
| 1401 | 849 | /** |
| 1402 | 850 | * amdgpu_device_get_rev_id - query device rev_id |
| 1403 | 851 | * |
| @@ -1410,149 +858,6 @@ u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev) · 6 unmodified lines | ||
| 1410 | 858 | return adev->nbio.funcs->get_rev_id(adev); |
| 1411 | 859 | } |
| 1412 | 860 | |
| 1413 | −/** | |
| 1414 | − * amdgpu_invalid_rreg - dummy reg read function | |
| 1415 | − * | |
| 1416 | − * @adev: amdgpu_device pointer | |
| 1417 | − * @reg: offset of register | |
| 1418 | − * | |
| 1419 | − * Dummy register read function. Used for register blocks | |
| 1420 | − * that certain asics don't have (all asics). | |
| 1421 | − * Returns the value in the register. | |
| 1422 | − */ | |
| 1423 | −static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg) | |
| 1424 | −{ | |
| 1425 | − dev_err(adev->dev, "Invalid callback to read register 0x%04X\n", reg); | |
| 1426 | − BUG(); | |
| 1427 | − return 0; | |
| 1428 | −} | |
| 1429 | − | |
| 1430 | −static uint32_t amdgpu_invalid_rreg_ext(struct amdgpu_device *adev, uint64_t reg) | |
| 1431 | −{ | |
| 1432 | − dev_err(adev->dev, "Invalid callback to read register 0x%llX\n", reg); | |
| 1433 | − BUG(); | |
| 1434 | − return 0; | |
| 1435 | −} | |
| 1436 | − | |
| 1437 | −/** | |
| 1438 | − * amdgpu_invalid_wreg - dummy reg write function | |
| 1439 | − * | |
| 1440 | − * @adev: amdgpu_device pointer | |
| 1441 | − * @reg: offset of register | |
| 1442 | − * @v: value to write to the register | |
| 1443 | − * | |
| 1444 | − * Dummy register read function. Used for register blocks | |
| 1445 | − * that certain asics don't have (all asics). | |
| 1446 | − */ | |
| 1447 | −static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) | |
| 1448 | −{ | |
| 1449 | − dev_err(adev->dev, | |
| 1450 | − "Invalid callback to write register 0x%04X with 0x%08X\n", reg, | |
| 1451 | − v); | |
| 1452 | − BUG(); | |
| 1453 | −} | |
| 1454 | − | |
| 1455 | −static void amdgpu_invalid_wreg_ext(struct amdgpu_device *adev, uint64_t reg, uint32_t v) | |
| 1456 | −{ | |
| 1457 | − dev_err(adev->dev, | |
| 1458 | − "Invalid callback to write register 0x%llX with 0x%08X\n", reg, | |
| 1459 | − v); | |
| 1460 | − BUG(); | |
| 1461 | −} | |
| 1462 | − | |
| 1463 | −/** | |
| 1464 | − * amdgpu_invalid_rreg64 - dummy 64 bit reg read function | |
| 1465 | − * | |
| 1466 | − * @adev: amdgpu_device pointer | |
| 1467 | − * @reg: offset of register | |
| 1468 | − * | |
| 1469 | − * Dummy register read function. Used for register blocks | |
| 1470 | − * that certain asics don't have (all asics). | |
| 1471 | − * Returns the value in the register. | |
| 1472 | − */ | |
| 1473 | −static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg) | |
| 1474 | −{ | |
| 1475 | − dev_err(adev->dev, "Invalid callback to read 64 bit register 0x%04X\n", | |
| 1476 | − reg); | |
| 1477 | − BUG(); | |
| 1478 | − return 0; | |
| 1479 | −} | |
| 1480 | − | |
| 1481 | −static uint64_t amdgpu_invalid_rreg64_ext(struct amdgpu_device *adev, uint64_t reg) | |
| 1482 | −{ | |
| 1483 | − dev_err(adev->dev, "Invalid callback to read register 0x%llX\n", reg); | |
| 1484 | − BUG(); | |
| 1485 | − return 0; | |
| 1486 | −} | |
| 1487 | − | |
| 1488 | −/** | |
| 1489 | − * amdgpu_invalid_wreg64 - dummy reg write function | |
| 1490 | − * | |
| 1491 | − * @adev: amdgpu_device pointer | |
| 1492 | − * @reg: offset of register | |
| 1493 | − * @v: value to write to the register | |
| 1494 | − * | |
| 1495 | − * Dummy register read function. Used for register blocks | |
| 1496 | − * that certain asics don't have (all asics). | |
| 1497 | − */ | |
| 1498 | −static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint64_t v) | |
| 1499 | −{ | |
| 1500 | − dev_err(adev->dev, | |
| 1501 | − "Invalid callback to write 64 bit register 0x%04X with 0x%08llX\n", | |
| 1502 | − reg, v); | |
| 1503 | − BUG(); | |
| 1504 | −} | |
| 1505 | − | |
| 1506 | −static void amdgpu_invalid_wreg64_ext(struct amdgpu_device *adev, uint64_t reg, uint64_t v) | |
| 1507 | −{ | |
| 1508 | − dev_err(adev->dev, | |
| 1509 | − "Invalid callback to write 64 bit register 0x%llX with 0x%08llX\n", | |
| 1510 | − reg, v); | |
| 1511 | − BUG(); | |
| 1512 | −} | |
| 1513 | − | |
| 1514 | −/** | |
| 1515 | − * amdgpu_block_invalid_rreg - dummy reg read function | |
| 1516 | − * | |
| 1517 | − * @adev: amdgpu_device pointer | |
| 1518 | − * @block: offset of instance | |
| 1519 | − * @reg: offset of register | |
| 1520 | − * | |
| 1521 | − * Dummy register read function. Used for register blocks | |
| 1522 | − * that certain asics don't have (all asics). | |
| 1523 | − * Returns the value in the register. | |
| 1524 | − */ | |
| 1525 | −static uint32_t amdgpu_block_invalid_rreg(struct amdgpu_device *adev, | |
| 1526 | − uint32_t block, uint32_t reg) | |
| 1527 | −{ | |
| 1528 | − dev_err(adev->dev, | |
| 1529 | − "Invalid callback to read register 0x%04X in block 0x%04X\n", | |
| 1530 | − reg, block); | |
| 1531 | − BUG(); | |
| 1532 | − return 0; | |
| 1533 | −} | |
| 1534 | − | |
| 1535 | −/** | |
| 1536 | − * amdgpu_block_invalid_wreg - dummy reg write function | |
| 1537 | − * | |
| 1538 | − * @adev: amdgpu_device pointer | |
| 1539 | − * @block: offset of instance | |
| 1540 | − * @reg: offset of register | |
| 1541 | − * @v: value to write to the register | |
| 1542 | − * | |
| 1543 | − * Dummy register read function. Used for register blocks | |
| 1544 | − * that certain asics don't have (all asics). | |
| 1545 | − */ | |
| 1546 | −static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev, | |
| 1547 | − uint32_t block, | |
| 1548 | − uint32_t reg, uint32_t v) | |
| 1549 | −{ | |
| 1550 | − dev_err(adev->dev, | |
| 1551 | − "Invalid block callback to write register 0x%04X in block 0x%04X with 0x%08X\n", | |
| 1552 | − reg, block, v); | |
| 1553 | − BUG(); | |
| 1554 | −} | |
| 1555 | − | |
| 1556 | 861 | static uint32_t amdgpu_device_get_vbios_flags(struct amdgpu_device *adev) |
| 1557 | 862 | { |
| 1558 | 863 | if (hweight32(adev->aid_mask) && (adev->flags & AMD_IS_APU)) |
| @@ -3156,9 +2461,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) · 1597 unmodified lines | ||
| 3156 | 2461 | if (r) |
| 3157 | 2462 | goto init_failed; |
| 3158 | 2463 | |
| 3159 | − if (adev->mman.buffer_funcs_ring && | |
| 3160 | − adev->mman.buffer_funcs_ring->sched.ready) | |
| 3161 | − amdgpu_ttm_set_buffer_funcs_status(adev, true); | |
| 2464 | + amdgpu_ttm_set_buffer_funcs_status(adev, true); | |
| 3162 | 2465 | |
| 3163 | 2466 | /* Don't init kfd if whole hive need to be reset during init */ |
| 3164 | 2467 | if (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI) { |
| @@ -4047,8 +3350,7 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) · 882 unmodified lines | ||
| 4047 | 3350 | |
| 4048 | 3351 | r = amdgpu_device_ip_resume_phase2(adev); |
| 4049 | 3352 | |
| 4050 | − if (adev->mman.buffer_funcs_ring->sched.ready) | |
| 4051 | − amdgpu_ttm_set_buffer_funcs_status(adev, true); | |
| 3353 | + amdgpu_ttm_set_buffer_funcs_status(adev, true); | |
| 4052 | 3354 | |
| 4053 | 3355 | if (r) |
| 4054 | 3356 | return r; |
| @@ -4108,17 +3410,6 @@ bool amdgpu_device_asic_has_dc_support(struct pci_dev *pdev, · 53 unmodified lines | ||
| 4108 | 3410 | case CHIP_VERDE: |
| 4109 | 3411 | case CHIP_OLAND: |
| 4110 | 3412 | return amdgpu_dc != 0 && IS_ENABLED(CONFIG_DRM_AMD_DC_SI); |
| 4111 | − case CHIP_KAVERI: | |
| 4112 | − case CHIP_KABINI: | |
| 4113 | − case CHIP_MULLINS: | |
| 4114 | − /* | |
| 4115 | − * We have systems in the wild with these ASICs that require | |
| 4116 | − * TRAVIS and NUTMEG support which is not supported with DC. | |
| 4117 | − * | |
| 4118 | − * Fallback to the non-DC driver here by default so as not to | |
| 4119 | − * cause regressions. | |
| 4120 | − */ | |
| 4121 | − return amdgpu_dc > 0; | |
| 4122 | 3413 | default: |
| 4123 | 3414 | return amdgpu_dc != 0; |
| 4124 | 3415 | #else |
| @@ -4396,26 +3687,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 271 unmodified lines | ||
| 4396 | 3687 | adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS); |
| 4397 | 3688 | bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); |
| 4398 | 3689 | |
| 4399 | − adev->smc_rreg = &amdgpu_invalid_rreg; | |
| 4400 | − adev->smc_wreg = &amdgpu_invalid_wreg; | |
| 4401 | − adev->pcie_rreg = &amdgpu_invalid_rreg; | |
| 4402 | − adev->pcie_wreg = &amdgpu_invalid_wreg; | |
| 4403 | − adev->pcie_rreg_ext = &amdgpu_invalid_rreg_ext; | |
| 4404 | − adev->pcie_wreg_ext = &amdgpu_invalid_wreg_ext; | |
| 4405 | − adev->pciep_rreg = &amdgpu_invalid_rreg; | |
| 4406 | − adev->pciep_wreg = &amdgpu_invalid_wreg; | |
| 4407 | − adev->pcie_rreg64 = &amdgpu_invalid_rreg64; | |
| 4408 | − adev->pcie_wreg64 = &amdgpu_invalid_wreg64; | |
| 4409 | − adev->pcie_rreg64_ext = &amdgpu_invalid_rreg64_ext; | |
| 4410 | − adev->pcie_wreg64_ext = &amdgpu_invalid_wreg64_ext; | |
| 4411 | − adev->uvd_ctx_rreg = &amdgpu_invalid_rreg; | |
| 4412 | − adev->uvd_ctx_wreg = &amdgpu_invalid_wreg; | |
| 4413 | − adev->didt_rreg = &amdgpu_invalid_rreg; | |
| 4414 | − adev->didt_wreg = &amdgpu_invalid_wreg; | |
| 4415 | − adev->gc_cac_rreg = &amdgpu_invalid_rreg; | |
| 4416 | − adev->gc_cac_wreg = &amdgpu_invalid_wreg; | |
| 4417 | − adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg; | |
| 4418 | − adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg; | |
| 3690 | + amdgpu_reg_access_init(adev); | |
| 4419 | 3691 | |
| 4420 | 3692 | dev_info( |
| 4421 | 3693 | adev->dev, |
| @@ -4460,13 +3732,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 38 unmodified lines | ||
| 4460 | 3732 | return r; |
| 4461 | 3733 | |
| 4462 | 3734 | spin_lock_init(&adev->mmio_idx_lock); |
| 4463 | − spin_lock_init(&adev->smc_idx_lock); | |
| 4464 | − spin_lock_init(&adev->pcie_idx_lock); | |
| 4465 | − spin_lock_init(&adev->uvd_ctx_idx_lock); | |
| 4466 | − spin_lock_init(&adev->didt_idx_lock); | |
| 4467 | − spin_lock_init(&adev->gc_cac_idx_lock); | |
| 4468 | − spin_lock_init(&adev->se_cac_idx_lock); | |
| 4469 | − spin_lock_init(&adev->audio_endpt_idx_lock); | |
| 4470 | 3735 | spin_lock_init(&adev->mm_stats.lock); |
| 4471 | 3736 | spin_lock_init(&adev->virt.rlcg_reg_lock); |
| 4472 | 3737 | spin_lock_init(&adev->wb.lock); |
| @@ -5195,8 +4460,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients) · 722 unmodified lines | ||
| 5195 | 4460 | return 0; |
| 5196 | 4461 | |
| 5197 | 4462 | unwind_evict: |
| 5198 | − if (adev->mman.buffer_funcs_ring->sched.ready) | |
| 5199 | − amdgpu_ttm_set_buffer_funcs_status(adev, true); | |
| 4463 | + amdgpu_ttm_set_buffer_funcs_status(adev, true); | |
| 5200 | 4464 | amdgpu_fence_driver_hw_init(adev); |
| 5201 | 4465 | |
| 5202 | 4466 | unwind_userq: |
| @@ -5930,8 +5194,7 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context) · 727 unmodified lines | ||
| 5930 | 5194 | if (r) |
| 5931 | 5195 | goto out; |
| 5932 | 5196 | |
| 5933 | − if (tmp_adev->mman.buffer_funcs_ring->sched.ready) | |
| 5934 | − amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true); | |
| 5197 | + amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true); | |
| 5935 | 5198 | |
| 5936 | 5199 | r = amdgpu_device_ip_resume_phase3(tmp_adev); |
| 5937 | 5200 | if (r) |
| @@ -6309,7 +5572,7 @@ static void amdgpu_device_halt_activities(struct amdgpu_device *adev, · 371 unmodified lines | ||
| 6309 | 5572 | if (!amdgpu_ring_sched_ready(ring)) |
| 6310 | 5573 | continue; |
| 6311 | 5574 | |
| 6312 | − drm_sched_stop(&ring->sched, job ? &job->base : NULL); | |
| 5575 | + drm_sched_wqueue_stop(&ring->sched); | |
| 6313 | 5576 | |
| 6314 | 5577 | if (need_emergency_restart) |
| 6315 | 5578 | amdgpu_job_stop_all_jobs_on_sched(&ring->sched); |
| @@ -6393,7 +5656,7 @@ static int amdgpu_device_sched_resume(struct list_head *device_list, · 77 unmodified lines | ||
| 6393 | 5656 | if (!amdgpu_ring_sched_ready(ring)) |
| 6394 | 5657 | continue; |
| 6395 | 5658 | |
| 6396 | − drm_sched_start(&ring->sched, 0); | |
| 5659 | + drm_sched_wqueue_start(&ring->sched); | |
| 6397 | 5660 | } |
| 6398 | 5661 | |
| 6399 | 5662 | if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) |
| @@ -7376,39 +6639,6 @@ void amdgpu_device_halt(struct amdgpu_device *adev) · 976 unmodified lines | ||
| 7376 | 6639 | pci_wait_for_pending_transaction(pdev); |
| 7377 | 6640 | } |
| 7378 | 6641 | |
| 7379 | −u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev, | |
| 7380 | − u32 reg) | |
| 7381 | −{ | |
| 7382 | − unsigned long flags, address, data; | |
| 7383 | − u32 r; | |
| 7384 | − | |
| 7385 | − address = adev->nbio.funcs->get_pcie_port_index_offset(adev); | |
| 7386 | − data = adev->nbio.funcs->get_pcie_port_data_offset(adev); | |
| 7387 | − | |
| 7388 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 7389 | − WREG32(address, reg * 4); | |
| 7390 | − (void)RREG32(address); | |
| 7391 | − r = RREG32(data); | |
| 7392 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 7393 | − return r; | |
| 7394 | −} | |
| 7395 | − | |
| 7396 | −void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, | |
| 7397 | − u32 reg, u32 v) | |
| 7398 | −{ | |
| 7399 | − unsigned long flags, address, data; | |
| 7400 | − | |
| 7401 | − address = adev->nbio.funcs->get_pcie_port_index_offset(adev); | |
| 7402 | − data = adev->nbio.funcs->get_pcie_port_data_offset(adev); | |
| 7403 | − | |
| 7404 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 7405 | − WREG32(address, reg * 4); | |
| 7406 | − (void)RREG32(address); | |
| 7407 | − WREG32(data, v); | |
| 7408 | − (void)RREG32(data); | |
| 7409 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 7410 | −} | |
| 7411 | − | |
| 7412 | 6642 | /** |
| 7413 | 6643 | * amdgpu_device_get_gang - return a reference to the current gang |
| 7414 | 6644 | * @adev: amdgpu_device pointer |
| @@ -7591,36 +6821,6 @@ bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev) · 176 unmodified lines | ||
| 7591 | 6821 | } |
| 7592 | 6822 | } |
| 7593 | 6823 | |
| 7594 | −uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev, | |
| 7595 | − uint32_t inst, uint32_t reg_addr, char reg_name[], | |
| 7596 | − uint32_t expected_value, uint32_t mask) | |
| 7597 | −{ | |
| 7598 | − uint32_t ret = 0; | |
| 7599 | − uint32_t old_ = 0; | |
| 7600 | − uint32_t tmp_ = RREG32(reg_addr); | |
| 7601 | − uint32_t loop = adev->usec_timeout; | |
| 7602 | − | |
| 7603 | − while ((tmp_ & (mask)) != (expected_value)) { | |
| 7604 | − if (old_ != tmp_) { | |
| 7605 | − loop = adev->usec_timeout; | |
| 7606 | − old_ = tmp_; | |
| 7607 | − } else | |
| 7608 | − udelay(1); | |
| 7609 | − tmp_ = RREG32(reg_addr); | |
| 7610 | − loop--; | |
| 7611 | − if (!loop) { | |
| 7612 | − dev_warn( | |
| 7613 | − adev->dev, | |
| 7614 | − "Register(%d) [%s] failed to reach value 0x%08x != 0x%08xn", | |
| 7615 | − inst, reg_name, (uint32_t)expected_value, | |
| 7616 | − (uint32_t)(tmp_ & (mask))); | |
| 7617 | − ret = -ETIMEDOUT; | |
| 7618 | − break; | |
| 7619 | − } | |
| 7620 | − } | |
| 7621 | − return ret; | |
| 7622 | −} | |
| 7623 | − | |
| 7624 | 6824 | ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring) |
| 7625 | 6825 | { |
| 7626 | 6826 | ssize_t size = 0; |
| @@ -2298,6 +2298,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev) · 2297 unmodified lines | ||
| 2298 | 2298 | case IP_VERSION(3, 5, 1): |
| 2299 | 2299 | case IP_VERSION(3, 6, 0): |
| 2300 | 2300 | case IP_VERSION(4, 1, 0): |
| 2301 | + case IP_VERSION(4, 2, 0): | |
| 2301 | 2302 | /* TODO: Fix IP version. DC code expects version 4.0.1 */ |
| 2302 | 2303 | if (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(4, 1, 0)) |
| 2303 | 2304 | adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 0, 1); |
| @@ -223,9 +223,7 @@ uint amdgpu_dc_visual_confirm; · 222 unmodified lines | ||
| 223 | 223 | int amdgpu_async_gfx_ring = 1; |
| 224 | 224 | int amdgpu_mcbp = -1; |
| 225 | 225 | int amdgpu_discovery = -1; |
| 226 | −int amdgpu_mes; | |
| 227 | 226 | int amdgpu_mes_log_enable = 0; |
| 228 | −int amdgpu_mes_kiq; | |
| 229 | 227 | int amdgpu_uni_mes = 1; |
| 230 | 228 | int amdgpu_noretry = -1; |
| 231 | 229 | int amdgpu_force_asic_type = -1; |
| @@ -690,15 +688,6 @@ MODULE_PARM_DESC(discovery, · 458 unmodified lines | ||
| 690 | 688 | "Allow driver to discover hardware IPs from IP Discovery table at the top of VRAM"); |
| 691 | 689 | module_param_named(discovery, amdgpu_discovery, int, 0444); |
| 692 | 690 | |
| 693 | −/** | |
| 694 | − * DOC: mes (int) | |
| 695 | − * Enable Micro Engine Scheduler. This is a new hw scheduling engine for gfx, sdma, and compute. | |
| 696 | − * (0 = disabled (default), 1 = enabled) | |
| 697 | − */ | |
| 698 | −MODULE_PARM_DESC(mes, | |
| 699 | − "Enable Micro Engine Scheduler (0 = disabled (default), 1 = enabled)"); | |
| 700 | −module_param_named(mes, amdgpu_mes, int, 0444); | |
| 701 | − | |
| 702 | 691 | /** |
| 703 | 692 | * DOC: mes_log_enable (int) |
| 704 | 693 | * Enable Micro Engine Scheduler log. This is used to enable/disable MES internal log. |
| @@ -708,15 +697,6 @@ MODULE_PARM_DESC(mes_log_enable, · 3 unmodified lines | ||
| 708 | 697 | "Enable Micro Engine Scheduler log (0 = disabled (default), 1 = enabled)"); |
| 709 | 698 | module_param_named(mes_log_enable, amdgpu_mes_log_enable, int, 0444); |
| 710 | 699 | |
| 711 | −/** | |
| 712 | − * DOC: mes_kiq (int) | |
| 713 | − * Enable Micro Engine Scheduler KIQ. This is a new engine pipe for kiq. | |
| 714 | − * (0 = disabled (default), 1 = enabled) | |
| 715 | − */ | |
| 716 | −MODULE_PARM_DESC(mes_kiq, | |
| 717 | − "Enable Micro Engine Scheduler KIQ (0 = disabled (default), 1 = enabled)"); | |
| 718 | −module_param_named(mes_kiq, amdgpu_mes_kiq, int, 0444); | |
| 719 | − | |
| 720 | 700 | /** |
| 721 | 701 | * DOC: uni_mes (int) |
| 722 | 702 | * Enable Unified Micro Engine Scheduler. This is a new engine pipe for unified scheduler. |
| @@ -89,16 +89,6 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring) · 88 unmodified lines | ||
| 89 | 89 | return seq; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | −static void amdgpu_fence_save_fence_wptr_start(struct amdgpu_fence *af) | |
| 93 | −{ | |
| 94 | − af->fence_wptr_start = af->ring->wptr; | |
| 95 | −} | |
| 96 | − | |
| 97 | −static void amdgpu_fence_save_fence_wptr_end(struct amdgpu_fence *af) | |
| 98 | −{ | |
| 99 | − af->fence_wptr_end = af->ring->wptr; | |
| 100 | −} | |
| 101 | − | |
| 102 | 92 | /** |
| 103 | 93 | * amdgpu_fence_emit - emit a fence on the requested ring |
| 104 | 94 | * |
| @@ -107,16 +97,14 @@ static void amdgpu_fence_save_fence_wptr_end(struct amdgpu_fence *af) · 2 unmodified lines | ||
| 107 | 97 | * @flags: flags to pass into the subordinate .emit_fence() call |
| 108 | 98 | * |
| 109 | 99 | * Emits a fence command on the requested ring (all asics). |
| 110 | − * Returns 0 on success, -ENOMEM on failure. | |
| 111 | 100 | */ |
| 112 | −int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, | |
| 113 | − unsigned int flags) | |
| 101 | +void amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, | |
| 102 | + unsigned int flags) | |
| 114 | 103 | { |
| 115 | 104 | struct amdgpu_device *adev = ring->adev; |
| 116 | 105 | struct dma_fence *fence; |
| 117 | 106 | struct dma_fence __rcu **ptr; |
| 118 | 107 | uint32_t seq; |
| 119 | − int r; | |
| 120 | 108 | |
| 121 | 109 | fence = &af->base; |
| 122 | 110 | af->ring = ring; |
| @@ -126,11 +114,9 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, · 3 unmodified lines | ||
| 126 | 114 | &ring->fence_drv.lock, |
| 127 | 115 | adev->fence_context + ring->idx, seq); |
| 128 | 116 | |
| 129 | − amdgpu_fence_save_fence_wptr_start(af); | |
| 130 | 117 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, |
| 131 | 118 | seq, flags | AMDGPU_FENCE_FLAG_INT); |
| 132 | − amdgpu_fence_save_fence_wptr_end(af); | |
| 133 | − amdgpu_fence_save_wptr(af); | |
| 119 | + | |
| 134 | 120 | pm_runtime_get_noresume(adev_to_drm(adev)->dev); |
| 135 | 121 | ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; |
| 136 | 122 | if (unlikely(rcu_dereference_protected(*ptr, 1))) { |
| @@ -141,10 +127,13 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, · 4 unmodified lines | ||
| 141 | 127 | rcu_read_unlock(); |
| 142 | 128 | |
| 143 | 129 | if (old) { |
| 144 | − r = dma_fence_wait(old, false); | |
| 130 | + /* | |
| 131 | + * dma_fence_wait(old, false) is not interruptible. | |
| 132 | + * It will not return an error in this case. | |
| 133 | + * So we can safely ignore the return value. | |
| 134 | + */ | |
| 135 | + dma_fence_wait(old, false); | |
| 145 | 136 | dma_fence_put(old); |
| 146 | − if (r) | |
| 147 | − return r; | |
| 148 | 137 | } |
| 149 | 138 | } |
| 150 | 139 | |
| @@ -154,8 +143,6 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, · 3 unmodified lines | ||
| 154 | 143 | * emitting the fence would mess up the hardware ring buffer. |
| 155 | 144 | */ |
| 156 | 145 | rcu_assign_pointer(*ptr, dma_fence_get(fence)); |
| 157 | − | |
| 158 | − return 0; | |
| 159 | 146 | } |
| 160 | 147 | |
| 161 | 148 | /** |
| @@ -241,7 +228,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) · 79 unmodified lines | ||
| 241 | 228 | |
| 242 | 229 | do { |
| 243 | 230 | struct dma_fence *fence, **ptr; |
| 244 | − struct amdgpu_fence *am_fence; | |
| 245 | 231 | |
| 246 | 232 | ++last_seq; |
| 247 | 233 | last_seq &= drv->num_fences_mask; |
| @@ -254,12 +240,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) · 6 unmodified lines | ||
| 254 | 240 | if (!fence) |
| 255 | 241 | continue; |
| 256 | 242 | |
| 257 | − /* Save the wptr in the fence driver so we know what the last processed | |
| 258 | − * wptr was. This is required for re-emitting the ring state for | |
| 259 | − * queues that are reset but are not guilty and thus have no guilty fence. | |
| 260 | − */ | |
| 261 | − am_fence = container_of(fence, struct amdgpu_fence, base); | |
| 262 | − drv->signalled_wptr = am_fence->wptr; | |
| 263 | 243 | dma_fence_signal(fence); |
| 264 | 244 | dma_fence_put(fence); |
| 265 | 245 | pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); |
| @@ -708,25 +688,29 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring) · 442 unmodified lines | ||
| 708 | 688 | */ |
| 709 | 689 | |
| 710 | 690 | /** |
| 711 | − * amdgpu_fence_driver_update_timedout_fence_state - Update fence state and set errors | |
| 691 | + * amdgpu_ring_set_fence_errors_and_reemit - Set dma_fence errors and reemit | |
| 712 | 692 | * |
| 713 | − * @af: fence of the ring to update | |
| 693 | + * @ring: the ring to operate on | |
| 694 | + * @guilty_fence: fence of the ring to update | |
| 714 | 695 | * |
| 715 | 696 | */ |
| 716 | −void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af) | |
| 697 | +void amdgpu_ring_set_fence_errors_and_reemit(struct amdgpu_ring *ring, | |
| 698 | + struct amdgpu_fence *guilty_fence) | |
| 717 | 699 | { |
| 718 | 700 | struct dma_fence *unprocessed; |
| 719 | 701 | struct dma_fence __rcu **ptr; |
| 720 | 702 | struct amdgpu_fence *fence; |
| 721 | − struct amdgpu_ring *ring = af->ring; | |
| 722 | 703 | unsigned long flags; |
| 723 | 704 | u32 seq, last_seq; |
| 724 | − bool reemitted = false; | |
| 705 | + unsigned int i; | |
| 706 | + bool is_guilty_fence; | |
| 707 | + bool is_guilty_context; | |
| 725 | 708 | |
| 726 | 709 | last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; |
| 727 | 710 | seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask; |
| 728 | 711 | |
| 729 | − /* mark all fences from the guilty context with an error */ | |
| 712 | + ring->reemit = true; | |
| 713 | + amdgpu_ring_alloc(ring, ring->ring_backup_entries_to_copy); | |
| 730 | 714 | spin_lock_irqsave(&ring->fence_drv.lock, flags); |
| 731 | 715 | do { |
| 732 | 716 | last_seq++; |
| @@ -738,39 +722,45 @@ void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af) · 5 unmodified lines | ||
| 738 | 722 | |
| 739 | 723 | if (unprocessed && !dma_fence_is_signaled_locked(unprocessed)) { |
| 740 | 724 | fence = container_of(unprocessed, struct amdgpu_fence, base); |
| 725 | + is_guilty_fence = fence == guilty_fence; | |
| 726 | + is_guilty_context = fence->context == guilty_fence->context; | |
| 741 | 727 | |
| 742 | − if (fence->reemitted > 1) | |
| 743 | − reemitted = true; | |
| 744 | − else if (fence == af) | |
| 728 | + /* mark all fences from the guilty context with an error */ | |
| 729 | + if (is_guilty_fence) | |
| 745 | 730 | dma_fence_set_error(&fence->base, -ETIME); |
| 746 | − else if (fence->context == af->context) | |
| 731 | + else if (is_guilty_context) | |
| 747 | 732 | dma_fence_set_error(&fence->base, -ECANCELED); |
| 733 | + | |
| 734 | + /* reemit the packet stream and update wptrs */ | |
| 735 | + fence->ib_wptr = ring->wptr; | |
| 736 | + for (i = 0; i < fence->ib_dw_size; i++) { | |
| 737 | + /* Skip the IB(s) for the guilty context. */ | |
| 738 | + if (is_guilty_context && | |
| 739 | + i >= fence->skip_ib_dw_start_offset && | |
| 740 | + i < fence->skip_ib_dw_end_offset) | |
| 741 | + amdgpu_ring_write(ring, ring->funcs->nop); | |
| 742 | + else | |
| 743 | + amdgpu_ring_write(ring, | |
| 744 | + ring->ring_backup[fence->backup_idx + i]); | |
| 745 | + } | |
| 748 | 746 | } |
| 749 | 747 | rcu_read_unlock(); |
| 750 | 748 | } while (last_seq != seq); |
| 751 | 749 | spin_unlock_irqrestore(&ring->fence_drv.lock, flags); |
| 752 | − | |
| 753 | − if (reemitted) { | |
| 754 | − /* if we've already reemitted once then just cancel everything */ | |
| 755 | − amdgpu_fence_driver_force_completion(af->ring); | |
| 756 | − af->ring->ring_backup_entries_to_copy = 0; | |
| 757 | − } | |
| 758 | −} | |
| 759 | − | |
| 760 | −void amdgpu_fence_save_wptr(struct amdgpu_fence *af) | |
| 761 | −{ | |
| 762 | − af->wptr = af->ring->wptr; | |
| 750 | + amdgpu_ring_commit(ring); | |
| 751 | + ring->reemit = false; | |
| 763 | 752 | } |
| 764 | 753 | |
| 765 | 754 | static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring, |
| 766 | − u64 start_wptr, u64 end_wptr) | |
| 755 | + struct amdgpu_fence *af) | |
| 767 | 756 | { |
| 768 | − unsigned int first_idx = start_wptr & ring->buf_mask; | |
| 769 | − unsigned int last_idx = end_wptr & ring->buf_mask; | |
| 757 | + unsigned int first_idx = af->ib_wptr & ring->buf_mask; | |
| 758 | + unsigned int dw_size = af->ib_dw_size; | |
| 770 | 759 | unsigned int i; |
| 771 | 760 | |
| 761 | + af->backup_idx = ring->ring_backup_entries_to_copy; | |
| 772 | 762 | /* Backup the contents of the ring buffer. */ |
| 773 | − for (i = first_idx; i != last_idx; ++i, i &= ring->buf_mask) | |
| 763 | + for (i = first_idx; dw_size > 0; ++i, i &= ring->buf_mask, --dw_size) | |
| 774 | 764 | ring->ring_backup[ring->ring_backup_entries_to_copy++] = ring->ring[i]; |
| 775 | 765 | } |
| 776 | 766 | |
| @@ -780,12 +770,10 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring, · 3 unmodified lines | ||
| 780 | 770 | struct dma_fence *unprocessed; |
| 781 | 771 | struct dma_fence __rcu **ptr; |
| 782 | 772 | struct amdgpu_fence *fence; |
| 783 | − u64 wptr; | |
| 784 | 773 | u32 seq, last_seq; |
| 785 | 774 | |
| 786 | 775 | last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; |
| 787 | 776 | seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask; |
| 788 | − wptr = ring->fence_drv.signalled_wptr; | |
| 789 | 777 | ring->ring_backup_entries_to_copy = 0; |
| 790 | 778 | |
| 791 | 779 | do { |
| @@ -799,21 +787,7 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring, · 7 unmodified lines | ||
| 799 | 787 | if (unprocessed && !dma_fence_is_signaled(unprocessed)) { |
| 800 | 788 | fence = container_of(unprocessed, struct amdgpu_fence, base); |
| 801 | 789 | |
| 802 | − /* save everything if the ring is not guilty, otherwise | |
| 803 | − * just save the content from other contexts. | |
| 804 | − */ | |
| 805 | − if (!fence->reemitted && | |
| 806 | − (!guilty_fence || (fence->context != guilty_fence->context))) { | |
| 807 | − amdgpu_ring_backup_unprocessed_command(ring, wptr, | |
| 808 | − fence->wptr); | |
| 809 | − } else if (!fence->reemitted) { | |
| 810 | − /* always save the fence */ | |
| 811 | − amdgpu_ring_backup_unprocessed_command(ring, | |
| 812 | − fence->fence_wptr_start, | |
| 813 | − fence->fence_wptr_end); | |
| 814 | − } | |
| 815 | − wptr = fence->wptr; | |
| 816 | − fence->reemitted++; | |
| 790 | + amdgpu_ring_backup_unprocessed_command(ring, fence); | |
| 817 | 791 | } |
| 818 | 792 | rcu_read_unlock(); |
| 819 | 793 | } while (last_seq != seq); |
| @@ -503,6 +503,55 @@ void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id) · 502 unmodified lines | ||
| 503 | 503 | &ring->mqd_ptr); |
| 504 | 504 | } |
| 505 | 505 | |
| 506 | +void amdgpu_gfx_mqd_symmetrically_map_cu_mask(struct amdgpu_device *adev, const uint32_t *cu_mask, | |
| 507 | + uint32_t cu_mask_count, uint32_t *se_mask) | |
| 508 | +{ | |
| 509 | + struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info; | |
| 510 | + struct amdgpu_gfx_config *gfx_info = &adev->gfx.config; | |
| 511 | + uint32_t cu_per_sh[8][4] = {0}; | |
| 512 | + int i, se, sh, cu, cu_bitmap_sh_mul; | |
| 513 | + int xcc_inst = ffs(adev->gfx.xcc_mask) - 1; | |
| 514 | + bool wgp_mode_req = amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 0, 0); | |
| 515 | + int cu_inc = wgp_mode_req ? 2 : 1; | |
| 516 | + uint32_t en_mask = wgp_mode_req ? 0x3 : 0x1; | |
| 517 | + int num_xcc, inc, inst = 0; | |
| 518 | + | |
| 519 | + if (xcc_inst < 0) | |
| 520 | + xcc_inst = 0; | |
| 521 | + | |
| 522 | + num_xcc = hweight16(adev->gfx.xcc_mask); | |
| 523 | + if (!num_xcc) | |
| 524 | + num_xcc = 1; | |
| 525 | + | |
| 526 | + inc = cu_inc * num_xcc; | |
| 527 | + | |
| 528 | + cu_bitmap_sh_mul = 2; | |
| 529 | + | |
| 530 | + for (se = 0; se < gfx_info->max_shader_engines; se++) | |
| 531 | + for (sh = 0; sh < gfx_info->max_sh_per_se; sh++) | |
| 532 | + cu_per_sh[se][sh] = hweight32( | |
| 533 | + cu_info->bitmap[xcc_inst][se % 4][sh + (se / 4) * | |
| 534 | + cu_bitmap_sh_mul]); | |
| 535 | + | |
| 536 | + for (i = 0; i < gfx_info->max_shader_engines; i++) | |
| 537 | + se_mask[i] = 0; | |
| 538 | + | |
| 539 | + i = inst; | |
| 540 | + for (cu = 0; cu < 16; cu += cu_inc) { | |
| 541 | + for (sh = 0; sh < gfx_info->max_sh_per_se; sh++) { | |
| 542 | + for (se = 0; se < gfx_info->max_shader_engines; se++) { | |
| 543 | + if (cu_per_sh[se][sh] > cu) { | |
| 544 | + if ((i / 32) < cu_mask_count && (cu_mask[i / 32] & (1 << (i % 32)))) | |
| 545 | + se_mask[se] |= en_mask << (cu + sh * 16); | |
| 546 | + i += inc; | |
| 547 | + if (i >= cu_mask_count * 32) | |
| 548 | + return; | |
| 549 | + } | |
| 550 | + } | |
| 551 | + } | |
| 552 | + } | |
| 553 | +} | |
| 554 | + | |
| 506 | 555 | int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id) |
| 507 | 556 | { |
| 508 | 557 | struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id]; |
| @@ -583,6 +583,8 @@ int amdgpu_gfx_kiq_init(struct amdgpu_device *adev, · 582 unmodified lines | ||
| 583 | 583 | int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev, |
| 584 | 584 | unsigned mqd_size, int xcc_id); |
| 585 | 585 | void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id); |
| 586 | +void amdgpu_gfx_mqd_symmetrically_map_cu_mask(struct amdgpu_device *adev, const uint32_t *cu_mask, | |
| 587 | + uint32_t cu_mask_count, uint32_t *se_mask); | |
| 586 | 588 | int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id); |
| 587 | 589 | int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id); |
| 588 | 590 | int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id); |
| @@ -742,7 +742,7 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, · 741 unmodified lines | ||
| 742 | 742 | * translation. Avoid this by doing the invalidation from the SDMA |
| 743 | 743 | * itself at least for GART. |
| 744 | 744 | */ |
| 745 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 745 | + mutex_lock(&adev->mman.default_entity.lock); | |
| 746 | 746 | r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.default_entity.base, |
| 747 | 747 | AMDGPU_FENCE_OWNER_UNDEFINED, |
| 748 | 748 | 16 * 4, AMDGPU_IB_POOL_IMMEDIATE, |
| @@ -755,7 +755,7 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, · 6 unmodified lines | ||
| 755 | 755 | job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop; |
| 756 | 756 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
| 757 | 757 | fence = amdgpu_job_submit(job); |
| 758 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 758 | + mutex_unlock(&adev->mman.default_entity.lock); | |
| 759 | 759 | |
| 760 | 760 | dma_fence_wait(fence, false); |
| 761 | 761 | dma_fence_put(fence); |
| @@ -763,7 +763,7 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, · 1 unmodified line | ||
| 763 | 763 | return; |
| 764 | 764 | |
| 765 | 765 | error_alloc: |
| 766 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 766 | + mutex_unlock(&adev->mman.default_entity.lock); | |
| 767 | 767 | dev_err(adev->dev, "Error flushing GPU TLB using the SDMA (%d)!\n", r); |
| 768 | 768 | } |
| 769 | 769 | |
| @@ -324,17 +324,13 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) · 323 unmodified lines | ||
| 324 | 324 | { |
| 325 | 325 | struct amdgpu_gtt_mgr *mgr = &adev->mman.gtt_mgr; |
| 326 | 326 | struct ttm_resource_manager *man = &mgr->manager; |
| 327 | − uint64_t start, size; | |
| 328 | 327 | |
| 329 | 328 | man->use_tt = true; |
| 330 | 329 | man->func = &amdgpu_gtt_mgr_func; |
| 331 | 330 | |
| 332 | 331 | ttm_resource_manager_init(man, &adev->mman.bdev, gtt_size); |
| 333 | 332 | |
| 334 | − start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS; | |
| 335 | − start += amdgpu_vce_required_gart_pages(adev); | |
| 336 | − size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; | |
| 337 | − drm_mm_init(&mgr->mm, start, size); | |
| 333 | + drm_mm_init(&mgr->mm, 0, adev->gmc.gart_size >> PAGE_SHIFT); | |
| 338 | 334 | spin_lock_init(&mgr->lock); |
| 339 | 335 | |
| 340 | 336 | ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); |
| @@ -129,6 +129,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 128 unmodified lines | ||
| 129 | 129 | struct amdgpu_ib *ib = &ibs[0]; |
| 130 | 130 | struct dma_fence *tmp = NULL; |
| 131 | 131 | struct amdgpu_fence *af; |
| 132 | + struct amdgpu_fence *vm_af; | |
| 132 | 133 | bool need_ctx_switch; |
| 133 | 134 | struct amdgpu_vm *vm; |
| 134 | 135 | uint64_t fence_ctx; |
| @@ -215,25 +216,28 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 80 unmodified lines | ||
| 215 | 216 | dma_fence_put(tmp); |
| 216 | 217 | } |
| 217 | 218 | |
| 218 | − if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync) | |
| 219 | − ring->funcs->emit_mem_sync(ring); | |
| 219 | + if (job) { | |
| 220 | + vm_af = job->hw_vm_fence; | |
| 221 | + /* VM sequence */ | |
| 222 | + vm_af->ib_wptr = ring->wptr; | |
| 223 | + amdgpu_vm_flush(ring, job, need_pipe_sync); | |
| 224 | + vm_af->ib_dw_size = | |
| 225 | + amdgpu_ring_get_dw_distance(ring, vm_af->ib_wptr, ring->wptr); | |
| 226 | + } | |
| 220 | 227 | |
| 221 | − if (ring->funcs->emit_wave_limit && | |
| 222 | − ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH) | |
| 223 | − ring->funcs->emit_wave_limit(ring, true); | |
| 228 | + /* IB sequence */ | |
| 229 | + af->ib_wptr = ring->wptr; | |
| 230 | + amdgpu_ring_ib_begin(ring); | |
| 224 | 231 | |
| 225 | 232 | if (ring->funcs->insert_start) |
| 226 | 233 | ring->funcs->insert_start(ring); |
| 227 | 234 | |
| 228 | − if (job) { | |
| 229 | − r = amdgpu_vm_flush(ring, job, need_pipe_sync); | |
| 230 | − if (r) { | |
| 231 | − amdgpu_ring_undo(ring); | |
| 232 | − goto free_fence; | |
| 233 | − } | |
| 234 | − } | |
| 235 | + if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync) | |
| 236 | + ring->funcs->emit_mem_sync(ring); | |
| 235 | 237 | |
| 236 | − amdgpu_ring_ib_begin(ring); | |
| 238 | + if (ring->funcs->emit_wave_limit && | |
| 239 | + ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH) | |
| 240 | + ring->funcs->emit_wave_limit(ring, true); | |
| 237 | 241 | |
| 238 | 242 | if (ring->funcs->emit_gfx_shadow && adev->gfx.cp_gfx_shadow) |
| 239 | 243 | amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va, |
| @@ -243,6 +247,9 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 3 unmodified lines | ||
| 243 | 247 | cond_exec = amdgpu_ring_init_cond_exec(ring, |
| 244 | 248 | ring->cond_exe_gpu_addr); |
| 245 | 249 | |
| 250 | + /* Skip the IB for guilty contexts */ | |
| 251 | + af->skip_ib_dw_start_offset = | |
| 252 | + amdgpu_ring_get_dw_distance(ring, af->ib_wptr, ring->wptr); | |
| 246 | 253 | amdgpu_device_flush_hdp(adev, ring); |
| 247 | 254 | |
| 248 | 255 | if (need_ctx_switch) |
| @@ -281,6 +288,9 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 32 unmodified lines | ||
| 281 | 288 | amdgpu_ring_emit_frame_cntl(ring, false, secure); |
| 282 | 289 | |
| 283 | 290 | amdgpu_device_invalidate_hdp(adev, ring); |
| 291 | + /* Skip the IB for guilty contexts */ | |
| 292 | + af->skip_ib_dw_end_offset = | |
| 293 | + amdgpu_ring_get_dw_distance(ring, af->ib_wptr, ring->wptr); | |
| 284 | 294 | |
| 285 | 295 | if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE) |
| 286 | 296 | fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY; |
| @@ -297,14 +307,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 10 unmodified lines | ||
| 297 | 307 | amdgpu_ring_init_cond_exec(ring, ring->cond_exe_gpu_addr); |
| 298 | 308 | } |
| 299 | 309 | |
| 300 | − r = amdgpu_fence_emit(ring, af, fence_flags); | |
| 301 | − if (r) { | |
| 302 | − dev_err(adev->dev, "failed to emit fence (%d)\n", r); | |
| 303 | − if (job && job->vmid) | |
| 304 | − amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid); | |
| 305 | − amdgpu_ring_undo(ring); | |
| 306 | − goto free_fence; | |
| 307 | − } | |
| 310 | + amdgpu_fence_emit(ring, af, fence_flags); | |
| 308 | 311 | *f = &af->base; |
| 309 | 312 | /* get a ref for the job */ |
| 310 | 313 | if (job) |
| @@ -323,15 +326,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 12 unmodified lines | ||
| 323 | 326 | ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH) |
| 324 | 327 | ring->funcs->emit_wave_limit(ring, false); |
| 325 | 328 | |
| 326 | − /* Save the wptr associated with this fence. | |
| 327 | − * This must be last for resets to work properly | |
| 328 | − * as we need to save the wptr associated with this | |
| 329 | − * fence so we know what rings contents to backup | |
| 330 | − * after we reset the queue. | |
| 331 | − */ | |
| 332 | − amdgpu_fence_save_wptr(af); | |
| 333 | − | |
| 334 | 329 | amdgpu_ring_ib_end(ring); |
| 330 | + | |
| 331 | + af->ib_dw_size = amdgpu_ring_get_dw_distance(ring, af->ib_wptr, ring->wptr); | |
| 332 | + | |
| 335 | 333 | amdgpu_ring_commit(ring); |
| 336 | 334 | |
| 337 | 335 | return 0; |
| @@ -92,7 +92,6 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) · 91 unmodified lines | ||
| 92 | 92 | struct drm_wedge_task_info *info = NULL; |
| 93 | 93 | struct amdgpu_task_info *ti = NULL; |
| 94 | 94 | struct amdgpu_device *adev = ring->adev; |
| 95 | − enum drm_gpu_sched_stat status = DRM_GPU_SCHED_STAT_RESET; | |
| 96 | 95 | int idx, r; |
| 97 | 96 | |
| 98 | 97 | if (!drm_dev_enter(adev_to_drm(adev), &idx)) { |
| @@ -147,8 +146,6 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) · 48 unmodified lines | ||
| 147 | 146 | ring->sched.name); |
| 148 | 147 | drm_dev_wedged_event(adev_to_drm(adev), |
| 149 | 148 | DRM_WEDGE_RECOVERY_NONE, info); |
| 150 | − /* This is needed to add the job back to the pending list */ | |
| 151 | − status = DRM_GPU_SCHED_STAT_NO_HANG; | |
| 152 | 149 | goto exit; |
| 153 | 150 | } |
| 154 | 151 | dev_err(adev->dev, "Ring %s reset failed\n", ring->sched.name); |
| @@ -184,7 +181,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) · 29 unmodified lines | ||
| 184 | 181 | exit: |
| 185 | 182 | amdgpu_vm_put_task_info(ti); |
| 186 | 183 | drm_dev_exit(idx); |
| 187 | − return status; | |
| 184 | + /* This is needed to add the job back to the pending list */ | |
| 185 | + return DRM_GPU_SCHED_STAT_NO_HANG; | |
| 188 | 186 | } |
| 189 | 187 | |
| 190 | 188 | int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm, |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | * |
| 22 | 22 | * |
| 23 | 23 | */ |
| 24 | +#include "amdgpu_reg_access.h" | |
| 24 | 25 | #include <linux/debugfs.h> |
| 25 | 26 | #include <linux/list.h> |
| 26 | 27 | #include <linux/module.h> |
| @@ -42,6 +43,7 @@ · 15 unmodified lines | ||
| 42 | 43 | #include "amdgpu_reset.h" |
| 43 | 44 | #include "amdgpu_psp.h" |
| 44 | 45 | #include "amdgpu_ras_mgr.h" |
| 46 | +#include "amdgpu_virt_ras_cmd.h" | |
| 45 | 47 | |
| 46 | 48 | #ifdef CONFIG_X86_MCE_AMD |
| 47 | 49 | #include <asm/mce.h> |
| @@ -228,19 +230,30 @@ static int amdgpu_check_address_validity(struct amdgpu_device *adev, · 180 unmodified lines | ||
| 228 | 230 | return 0; |
| 229 | 231 | |
| 230 | 232 | if (amdgpu_sriov_vf(adev)) { |
| 231 | − if (amdgpu_virt_check_vf_critical_region(adev, address, &hit)) | |
| 232 | − return -EPERM; | |
| 233 | − return hit ? -EACCES : 0; | |
| 233 | + if (amdgpu_uniras_enabled(adev)) { | |
| 234 | + if (amdgpu_virt_ras_check_address_validity(adev, address, &hit)) | |
| 235 | + return -EPERM; | |
| 236 | + if (hit) | |
| 237 | + return -EACCES; | |
| 238 | + } else { | |
| 239 | + if (amdgpu_virt_check_vf_critical_region(adev, address, &hit)) | |
| 240 | + return -EPERM; | |
| 241 | + return hit ? -EACCES : 0; | |
| 242 | + } | |
| 234 | 243 | } |
| 235 | 244 | |
| 236 | 245 | if ((address >= adev->gmc.mc_vram_size) || |
| 237 | 246 | (address >= RAS_UMC_INJECT_ADDR_LIMIT)) |
| 238 | 247 | return -EFAULT; |
| 239 | 248 | |
| 240 | − if (amdgpu_uniras_enabled(adev)) | |
| 241 | − count = amdgpu_ras_mgr_lookup_bad_pages_in_a_row(adev, address, | |
| 242 | − page_pfns, ARRAY_SIZE(page_pfns)); | |
| 243 | − else | |
| 249 | + if (amdgpu_uniras_enabled(adev)) { | |
| 250 | + if (amdgpu_sriov_vf(adev)) | |
| 251 | + count = amdgpu_virt_ras_convert_retired_address(adev, address, | |
| 252 | + page_pfns, ARRAY_SIZE(page_pfns)); | |
| 253 | + else | |
| 254 | + count = amdgpu_ras_mgr_lookup_bad_pages_in_a_row(adev, address, | |
| 255 | + page_pfns, ARRAY_SIZE(page_pfns)); | |
| 256 | + } else | |
| 244 | 257 | count = amdgpu_umc_lookup_bad_pages_in_a_row(adev, |
| 245 | 258 | address, page_pfns, ARRAY_SIZE(page_pfns)); |
| 246 | 259 | |
| @@ -3118,9 +3131,11 @@ static int __amdgpu_ras_convert_rec_array_from_rom(struct amdgpu_device *adev, · 2871 unmodified lines | ||
| 3118 | 3131 | enum amdgpu_memory_partition nps) |
| 3119 | 3132 | { |
| 3120 | 3133 | int i = 0; |
| 3134 | + uint64_t chan_idx_v2; | |
| 3121 | 3135 | enum amdgpu_memory_partition save_nps; |
| 3122 | 3136 | |
| 3123 | 3137 | save_nps = (bps[0].retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; |
| 3138 | + chan_idx_v2 = bps[0].retired_page & UMC_CHANNEL_IDX_V2; | |
| 3124 | 3139 | |
| 3125 | 3140 | /*old asics just have pa in eeprom*/ |
| 3126 | 3141 | if (IP_VERSION_MAJ(amdgpu_ip_version(adev, UMC_HWIP, 0)) < 12) { |
| @@ -3132,7 +3147,7 @@ static int __amdgpu_ras_convert_rec_array_from_rom(struct amdgpu_device *adev, · 5 unmodified lines | ||
| 3132 | 3147 | for (i = 0; i < adev->umc.retire_unit; i++) |
| 3133 | 3148 | bps[i].retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); |
| 3134 | 3149 | |
| 3135 | − if (save_nps) { | |
| 3150 | + if (save_nps || chan_idx_v2) { | |
| 3136 | 3151 | if (save_nps == nps) { |
| 3137 | 3152 | if (amdgpu_umc_pages_in_a_row(adev, err_data, |
| 3138 | 3153 | bps[0].retired_page << AMDGPU_GPU_PAGE_SHIFT)) |
| @@ -3176,10 +3191,12 @@ static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev, · 37 unmodified lines | ||
| 3176 | 3191 | enum amdgpu_memory_partition nps) |
| 3177 | 3192 | { |
| 3178 | 3193 | int i = 0; |
| 3194 | + uint64_t chan_idx_v2; | |
| 3179 | 3195 | enum amdgpu_memory_partition save_nps; |
| 3180 | 3196 | |
| 3181 | 3197 | if (!amdgpu_ras_smu_eeprom_supported(adev)) { |
| 3182 | 3198 | save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; |
| 3199 | + chan_idx_v2 = bps->retired_page & UMC_CHANNEL_IDX_V2; | |
| 3183 | 3200 | bps->retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); |
| 3184 | 3201 | } else { |
| 3185 | 3202 | /* if pmfw manages eeprom, save_nps is not stored on eeprom, |
| @@ -3201,16 +3218,19 @@ static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev, · 15 unmodified lines | ||
| 3201 | 3218 | err_data->err_addr[i].mcumc_id = bps->mcumc_id; |
| 3202 | 3219 | } |
| 3203 | 3220 | } else { |
| 3204 | − if (bps->address) { | |
| 3221 | + if (save_nps || chan_idx_v2) { | |
| 3205 | 3222 | if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data)) |
| 3206 | 3223 | return -EINVAL; |
| 3207 | 3224 | } else { |
| 3208 | 3225 | /* for specific old eeprom data, mca address is not stored, |
| 3209 | 3226 | * calc it from pa |
| 3210 | 3227 | */ |
| 3211 | − if (amdgpu_umc_pa2mca(adev, bps->retired_page << AMDGPU_GPU_PAGE_SHIFT, | |
| 3212 | − &(bps->address), AMDGPU_NPS1_PARTITION_MODE)) | |
| 3213 | − return -EINVAL; | |
| 3228 | + if (bps->address == 0) | |
| 3229 | + if (amdgpu_umc_pa2mca(adev, | |
| 3230 | + bps->retired_page << AMDGPU_GPU_PAGE_SHIFT, | |
| 3231 | + &(bps->address), | |
| 3232 | + AMDGPU_NPS1_PARTITION_MODE)) | |
| 3233 | + return -EINVAL; | |
| 3214 | 3234 | |
| 3215 | 3235 | if (amdgpu_ras_mca2pa(adev, bps, err_data)) |
| 3216 | 3236 | return -EOPNOTSUPP; |
| @@ -5516,11 +5536,11 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev, · 2299 unmodified lines | ||
| 5516 | 5536 | * is changed. In such case, replace the aqua_vanjaram implementation |
| 5517 | 5537 | * with more common helper */ |
| 5518 | 5538 | reg_addr = (mmMP0_SMN_C2PMSG_92 << 2) + |
| 5519 | − aqua_vanjaram_encode_ext_smn_addressing(instance); | |
| 5539 | + amdgpu_reg_get_smn_base64(adev, MP0_HWIP, instance); | |
| 5520 | 5540 | fw_status = amdgpu_device_indirect_rreg_ext(adev, reg_addr); |
| 5521 | 5541 | |
| 5522 | 5542 | reg_addr = (mmMP0_SMN_C2PMSG_126 << 2) + |
| 5523 | − aqua_vanjaram_encode_ext_smn_addressing(instance); | |
| 5543 | + amdgpu_reg_get_smn_base64(adev, MP0_HWIP, instance); | |
| 5524 | 5544 | boot_error = amdgpu_device_indirect_rreg_ext(adev, reg_addr); |
| 5525 | 5545 | |
| 5526 | 5546 | socket_id = AMDGPU_RAS_GPU_ERR_SOCKET_ID(boot_error); |
| @@ -5586,7 +5606,7 @@ static bool amdgpu_ras_boot_error_detected(struct amdgpu_device *adev, · 59 unmodified lines | ||
| 5586 | 5606 | int retry_loop; |
| 5587 | 5607 | |
| 5588 | 5608 | reg_addr = (mmMP0_SMN_C2PMSG_92 << 2) + |
| 5589 | − aqua_vanjaram_encode_ext_smn_addressing(instance); | |
| 5609 | + amdgpu_reg_get_smn_base64(adev, MP0_HWIP, instance); | |
| 5590 | 5610 | |
| 5591 | 5611 | for (retry_loop = 0; retry_loop < AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT; retry_loop++) { |
| 5592 | 5612 | reg_data = amdgpu_device_indirect_rreg_ext(adev, reg_addr); |
| @@ -508,6 +508,9 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) · 507 unmodified lines | ||
| 508 | 508 | control->bad_channel_bitmap = 0; |
| 509 | 509 | amdgpu_dpm_send_hbm_bad_channel_flag(adev, control->bad_channel_bitmap); |
| 510 | 510 | con->update_channel_flag = false; |
| 511 | + /* there is no record on eeprom now, clear the counter */ | |
| 512 | + if (con->eh_data) | |
| 513 | + con->eh_data->count_saved = 0; | |
| 511 | 514 | |
| 512 | 515 | amdgpu_ras_debugfs_set_ret_size(control); |
| 513 | 516 | |
| @@ -0,0 +1,959 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +/* | |
| 3 | + * Copyright 2025 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#include <linux/delay.h> | |
| 25 | + | |
| 26 | +#include "amdgpu.h" | |
| 27 | +#include "amdgpu_reset.h" | |
| 28 | +#include "amdgpu_trace.h" | |
| 29 | +#include "amdgpu_virt.h" | |
| 30 | +#include "amdgpu_reg_access.h" | |
| 31 | + | |
| 32 | +#define AMDGPU_PCIE_INDEX_FALLBACK (0x38 >> 2) | |
| 33 | +#define AMDGPU_PCIE_INDEX_HI_FALLBACK (0x44 >> 2) | |
| 34 | +#define AMDGPU_PCIE_DATA_FALLBACK (0x3C >> 2) | |
| 35 | + | |
| 36 | +void amdgpu_reg_access_init(struct amdgpu_device *adev) | |
| 37 | +{ | |
| 38 | + spin_lock_init(&adev->reg.smc.lock); | |
| 39 | + adev->reg.smc.rreg = NULL; | |
| 40 | + adev->reg.smc.wreg = NULL; | |
| 41 | + | |
| 42 | + spin_lock_init(&adev->reg.uvd_ctx.lock); | |
| 43 | + adev->reg.uvd_ctx.rreg = NULL; | |
| 44 | + adev->reg.uvd_ctx.wreg = NULL; | |
| 45 | + | |
| 46 | + spin_lock_init(&adev->reg.didt.lock); | |
| 47 | + adev->reg.didt.rreg = NULL; | |
| 48 | + adev->reg.didt.wreg = NULL; | |
| 49 | + | |
| 50 | + spin_lock_init(&adev->reg.gc_cac.lock); | |
| 51 | + adev->reg.gc_cac.rreg = NULL; | |
| 52 | + adev->reg.gc_cac.wreg = NULL; | |
| 53 | + | |
| 54 | + spin_lock_init(&adev->reg.se_cac.lock); | |
| 55 | + adev->reg.se_cac.rreg = NULL; | |
| 56 | + adev->reg.se_cac.wreg = NULL; | |
| 57 | + | |
| 58 | + spin_lock_init(&adev->reg.audio_endpt.lock); | |
| 59 | + adev->reg.audio_endpt.rreg = NULL; | |
| 60 | + adev->reg.audio_endpt.wreg = NULL; | |
| 61 | + | |
| 62 | + spin_lock_init(&adev->reg.pcie.lock); | |
| 63 | + adev->reg.pcie.rreg = NULL; | |
| 64 | + adev->reg.pcie.wreg = NULL; | |
| 65 | + adev->reg.pcie.rreg_ext = NULL; | |
| 66 | + adev->reg.pcie.wreg_ext = NULL; | |
| 67 | + adev->reg.pcie.rreg64 = NULL; | |
| 68 | + adev->reg.pcie.wreg64 = NULL; | |
| 69 | + adev->reg.pcie.rreg64_ext = NULL; | |
| 70 | + adev->reg.pcie.wreg64_ext = NULL; | |
| 71 | + adev->reg.pcie.port_rreg = NULL; | |
| 72 | + adev->reg.pcie.port_wreg = NULL; | |
| 73 | +} | |
| 74 | + | |
| 75 | +uint32_t amdgpu_reg_smc_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 76 | +{ | |
| 77 | + if (!adev->reg.smc.rreg) { | |
| 78 | + dev_err_once(adev->dev, "SMC register read not supported\n"); | |
| 79 | + return 0; | |
| 80 | + } | |
| 81 | + return adev->reg.smc.rreg(adev, reg); | |
| 82 | +} | |
| 83 | + | |
| 84 | +void amdgpu_reg_smc_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v) | |
| 85 | +{ | |
| 86 | + if (!adev->reg.smc.wreg) { | |
| 87 | + dev_err_once(adev->dev, "SMC register write not supported\n"); | |
| 88 | + return; | |
| 89 | + } | |
| 90 | + adev->reg.smc.wreg(adev, reg, v); | |
| 91 | +} | |
| 92 | + | |
| 93 | +uint32_t amdgpu_reg_uvd_ctx_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 94 | +{ | |
| 95 | + if (!adev->reg.uvd_ctx.rreg) { | |
| 96 | + dev_err_once(adev->dev, | |
| 97 | + "UVD_CTX register read not supported\n"); | |
| 98 | + return 0; | |
| 99 | + } | |
| 100 | + return adev->reg.uvd_ctx.rreg(adev, reg); | |
| 101 | +} | |
| 102 | + | |
| 103 | +void amdgpu_reg_uvd_ctx_wr32(struct amdgpu_device *adev, uint32_t reg, | |
| 104 | + uint32_t v) | |
| 105 | +{ | |
| 106 | + if (!adev->reg.uvd_ctx.wreg) { | |
| 107 | + dev_err_once(adev->dev, | |
| 108 | + "UVD_CTX register write not supported\n"); | |
| 109 | + return; | |
| 110 | + } | |
| 111 | + adev->reg.uvd_ctx.wreg(adev, reg, v); | |
| 112 | +} | |
| 113 | + | |
| 114 | +uint32_t amdgpu_reg_didt_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 115 | +{ | |
| 116 | + if (!adev->reg.didt.rreg) { | |
| 117 | + dev_err_once(adev->dev, "DIDT register read not supported\n"); | |
| 118 | + return 0; | |
| 119 | + } | |
| 120 | + return adev->reg.didt.rreg(adev, reg); | |
| 121 | +} | |
| 122 | + | |
| 123 | +void amdgpu_reg_didt_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v) | |
| 124 | +{ | |
| 125 | + if (!adev->reg.didt.wreg) { | |
| 126 | + dev_err_once(adev->dev, "DIDT register write not supported\n"); | |
| 127 | + return; | |
| 128 | + } | |
| 129 | + adev->reg.didt.wreg(adev, reg, v); | |
| 130 | +} | |
| 131 | + | |
| 132 | +uint32_t amdgpu_reg_gc_cac_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 133 | +{ | |
| 134 | + if (!adev->reg.gc_cac.rreg) { | |
| 135 | + dev_err_once(adev->dev, "GC_CAC register read not supported\n"); | |
| 136 | + return 0; | |
| 137 | + } | |
| 138 | + return adev->reg.gc_cac.rreg(adev, reg); | |
| 139 | +} | |
| 140 | + | |
| 141 | +void amdgpu_reg_gc_cac_wr32(struct amdgpu_device *adev, uint32_t reg, | |
| 142 | + uint32_t v) | |
| 143 | +{ | |
| 144 | + if (!adev->reg.gc_cac.wreg) { | |
| 145 | + dev_err_once(adev->dev, | |
| 146 | + "GC_CAC register write not supported\n"); | |
| 147 | + return; | |
| 148 | + } | |
| 149 | + adev->reg.gc_cac.wreg(adev, reg, v); | |
| 150 | +} | |
| 151 | + | |
| 152 | +uint32_t amdgpu_reg_se_cac_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 153 | +{ | |
| 154 | + if (!adev->reg.se_cac.rreg) { | |
| 155 | + dev_err_once(adev->dev, "SE_CAC register read not supported\n"); | |
| 156 | + return 0; | |
| 157 | + } | |
| 158 | + return adev->reg.se_cac.rreg(adev, reg); | |
| 159 | +} | |
| 160 | + | |
| 161 | +void amdgpu_reg_se_cac_wr32(struct amdgpu_device *adev, uint32_t reg, | |
| 162 | + uint32_t v) | |
| 163 | +{ | |
| 164 | + if (!adev->reg.se_cac.wreg) { | |
| 165 | + dev_err_once(adev->dev, | |
| 166 | + "SE_CAC register write not supported\n"); | |
| 167 | + return; | |
| 168 | + } | |
| 169 | + adev->reg.se_cac.wreg(adev, reg, v); | |
| 170 | +} | |
| 171 | + | |
| 172 | +uint32_t amdgpu_reg_audio_endpt_rd32(struct amdgpu_device *adev, uint32_t block, | |
| 173 | + uint32_t reg) | |
| 174 | +{ | |
| 175 | + if (!adev->reg.audio_endpt.rreg) { | |
| 176 | + dev_err_once(adev->dev, | |
| 177 | + "AUDIO_ENDPT register read not supported\n"); | |
| 178 | + return 0; | |
| 179 | + } | |
| 180 | + return adev->reg.audio_endpt.rreg(adev, block, reg); | |
| 181 | +} | |
| 182 | + | |
| 183 | +void amdgpu_reg_audio_endpt_wr32(struct amdgpu_device *adev, uint32_t block, | |
| 184 | + uint32_t reg, uint32_t v) | |
| 185 | +{ | |
| 186 | + if (!adev->reg.audio_endpt.wreg) { | |
| 187 | + dev_err_once(adev->dev, | |
| 188 | + "AUDIO_ENDPT register write not supported\n"); | |
| 189 | + return; | |
| 190 | + } | |
| 191 | + adev->reg.audio_endpt.wreg(adev, block, reg, v); | |
| 192 | +} | |
| 193 | + | |
| 194 | +uint32_t amdgpu_reg_pcie_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 195 | +{ | |
| 196 | + if (!adev->reg.pcie.rreg) { | |
| 197 | + dev_err_once(adev->dev, "PCIE register read not supported\n"); | |
| 198 | + return 0; | |
| 199 | + } | |
| 200 | + return adev->reg.pcie.rreg(adev, reg); | |
| 201 | +} | |
| 202 | + | |
| 203 | +void amdgpu_reg_pcie_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v) | |
| 204 | +{ | |
| 205 | + if (!adev->reg.pcie.wreg) { | |
| 206 | + dev_err_once(adev->dev, "PCIE register write not supported\n"); | |
| 207 | + return; | |
| 208 | + } | |
| 209 | + adev->reg.pcie.wreg(adev, reg, v); | |
| 210 | +} | |
| 211 | + | |
| 212 | +uint32_t amdgpu_reg_pcie_ext_rd32(struct amdgpu_device *adev, uint64_t reg) | |
| 213 | +{ | |
| 214 | + if (!adev->reg.pcie.rreg_ext) { | |
| 215 | + dev_err_once(adev->dev, "PCIE EXT register read not supported\n"); | |
| 216 | + return 0; | |
| 217 | + } | |
| 218 | + return adev->reg.pcie.rreg_ext(adev, reg); | |
| 219 | +} | |
| 220 | + | |
| 221 | +void amdgpu_reg_pcie_ext_wr32(struct amdgpu_device *adev, uint64_t reg, | |
| 222 | + uint32_t v) | |
| 223 | +{ | |
| 224 | + if (!adev->reg.pcie.wreg_ext) { | |
| 225 | + dev_err_once(adev->dev, "PCIE EXT register write not supported\n"); | |
| 226 | + return; | |
| 227 | + } | |
| 228 | + adev->reg.pcie.wreg_ext(adev, reg, v); | |
| 229 | +} | |
| 230 | + | |
| 231 | +uint64_t amdgpu_reg_pcie_rd64(struct amdgpu_device *adev, uint32_t reg) | |
| 232 | +{ | |
| 233 | + if (!adev->reg.pcie.rreg64) { | |
| 234 | + dev_err_once(adev->dev, "PCIE 64-bit register read not supported\n"); | |
| 235 | + return 0; | |
| 236 | + } | |
| 237 | + return adev->reg.pcie.rreg64(adev, reg); | |
| 238 | +} | |
| 239 | + | |
| 240 | +void amdgpu_reg_pcie_wr64(struct amdgpu_device *adev, uint32_t reg, uint64_t v) | |
| 241 | +{ | |
| 242 | + if (!adev->reg.pcie.wreg64) { | |
| 243 | + dev_err_once(adev->dev, "PCIE 64-bit register write not supported\n"); | |
| 244 | + return; | |
| 245 | + } | |
| 246 | + adev->reg.pcie.wreg64(adev, reg, v); | |
| 247 | +} | |
| 248 | + | |
| 249 | +uint64_t amdgpu_reg_pcie_ext_rd64(struct amdgpu_device *adev, uint64_t reg) | |
| 250 | +{ | |
| 251 | + if (!adev->reg.pcie.rreg64_ext) { | |
| 252 | + dev_err_once(adev->dev, "PCIE EXT 64-bit register read not supported\n"); | |
| 253 | + return 0; | |
| 254 | + } | |
| 255 | + return adev->reg.pcie.rreg64_ext(adev, reg); | |
| 256 | +} | |
| 257 | + | |
| 258 | +void amdgpu_reg_pcie_ext_wr64(struct amdgpu_device *adev, uint64_t reg, | |
| 259 | + uint64_t v) | |
| 260 | +{ | |
| 261 | + if (!adev->reg.pcie.wreg64_ext) { | |
| 262 | + dev_err_once(adev->dev, "PCIE EXT 64-bit register write not supported\n"); | |
| 263 | + return; | |
| 264 | + } | |
| 265 | + adev->reg.pcie.wreg64_ext(adev, reg, v); | |
| 266 | +} | |
| 267 | + | |
| 268 | +uint32_t amdgpu_reg_pciep_rd32(struct amdgpu_device *adev, uint32_t reg) | |
| 269 | +{ | |
| 270 | + if (!adev->reg.pcie.port_rreg) { | |
| 271 | + dev_err_once(adev->dev, "PCIEP register read not supported\n"); | |
| 272 | + return 0; | |
| 273 | + } | |
| 274 | + return adev->reg.pcie.port_rreg(adev, reg); | |
| 275 | +} | |
| 276 | + | |
| 277 | +void amdgpu_reg_pciep_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v) | |
| 278 | +{ | |
| 279 | + if (!adev->reg.pcie.port_wreg) { | |
| 280 | + dev_err_once(adev->dev, "PCIEP register write not supported\n"); | |
| 281 | + return; | |
| 282 | + } | |
| 283 | + adev->reg.pcie.port_wreg(adev, reg, v); | |
| 284 | +} | |
| 285 | + | |
| 286 | +static int amdgpu_reg_get_smn_base_version(struct amdgpu_device *adev) | |
| 287 | +{ | |
| 288 | + struct pci_dev *pdev = adev->pdev; | |
| 289 | + int id; | |
| 290 | + | |
| 291 | + if (amdgpu_sriov_vf(adev)) | |
| 292 | + return -EOPNOTSUPP; | |
| 293 | + | |
| 294 | + id = (pdev->device >> 4) & 0xFFFF; | |
| 295 | + if (id == 0x74A || id == 0x74B || id == 0x75A || id == 0x75B) | |
| 296 | + return 1; | |
| 297 | + | |
| 298 | + return -EOPNOTSUPP; | |
| 299 | +} | |
| 300 | + | |
| 301 | +uint64_t amdgpu_reg_get_smn_base64(struct amdgpu_device *adev, | |
| 302 | + enum amd_hw_ip_block_type block, | |
| 303 | + int die_inst) | |
| 304 | +{ | |
| 305 | + if (!adev->reg.smn.get_smn_base) { | |
| 306 | + int version = amdgpu_reg_get_smn_base_version(adev); | |
| 307 | + switch (version) { | |
| 308 | + case 1: | |
| 309 | + return amdgpu_reg_smn_v1_0_get_base(adev, block, | |
| 310 | + die_inst); | |
| 311 | + default: | |
| 312 | + dev_err_once( | |
| 313 | + adev->dev, | |
| 314 | + "SMN base address query not supported for this device\n"); | |
| 315 | + return 0; | |
| 316 | + } | |
| 317 | + return 0; | |
| 318 | + } | |
| 319 | + return adev->reg.smn.get_smn_base(adev, block, die_inst); | |
| 320 | +} | |
| 321 | + | |
| 322 | +uint64_t amdgpu_reg_smn_v1_0_get_base(struct amdgpu_device *adev, | |
| 323 | + enum amd_hw_ip_block_type block, | |
| 324 | + int die_inst) | |
| 325 | +{ | |
| 326 | + uint64_t smn_base; | |
| 327 | + | |
| 328 | + if (die_inst == 0) | |
| 329 | + return 0; | |
| 330 | + | |
| 331 | + switch (block) { | |
| 332 | + case XGMI_HWIP: | |
| 333 | + case NBIO_HWIP: | |
| 334 | + case MP0_HWIP: | |
| 335 | + case UMC_HWIP: | |
| 336 | + case DF_HWIP: | |
| 337 | + smn_base = ((uint64_t)(die_inst & 0x3) << 32) | (1ULL << 34); | |
| 338 | + break; | |
| 339 | + default: | |
| 340 | + dev_warn_once( | |
| 341 | + adev->dev, | |
| 342 | + "SMN base address query not supported for this block %d\n", | |
| 343 | + block); | |
| 344 | + smn_base = 0; | |
| 345 | + break; | |
| 346 | + } | |
| 347 | + | |
| 348 | + return smn_base; | |
| 349 | +} | |
| 350 | + | |
| 351 | +/* | |
| 352 | + * register access helper functions. | |
| 353 | + */ | |
| 354 | + | |
| 355 | +/** | |
| 356 | + * amdgpu_device_rreg - read a memory mapped IO or indirect register | |
| 357 | + * | |
| 358 | + * @adev: amdgpu_device pointer | |
| 359 | + * @reg: dword aligned register offset | |
| 360 | + * @acc_flags: access flags which require special behavior | |
| 361 | + * | |
| 362 | + * Returns the 32 bit value from the offset specified. | |
| 363 | + */ | |
| 364 | +uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, uint32_t reg, | |
| 365 | + uint32_t acc_flags) | |
| 366 | +{ | |
| 367 | + uint32_t ret; | |
| 368 | + | |
| 369 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 370 | + return 0; | |
| 371 | + | |
| 372 | + if ((reg * 4) < adev->rmmio_size) { | |
| 373 | + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 374 | + amdgpu_sriov_runtime(adev) && | |
| 375 | + down_read_trylock(&adev->reset_domain->sem)) { | |
| 376 | + ret = amdgpu_kiq_rreg(adev, reg, 0); | |
| 377 | + up_read(&adev->reset_domain->sem); | |
| 378 | + } else { | |
| 379 | + ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 380 | + } | |
| 381 | + } else { | |
| 382 | + ret = amdgpu_reg_pcie_rd32(adev, reg * 4); | |
| 383 | + } | |
| 384 | + | |
| 385 | + trace_amdgpu_device_rreg(adev->pdev->device, reg, ret); | |
| 386 | + | |
| 387 | + return ret; | |
| 388 | +} | |
| 389 | + | |
| 390 | +/* | |
| 391 | + * MMIO register read with bytes helper functions | |
| 392 | + * @offset:bytes offset from MMIO start | |
| 393 | + */ | |
| 394 | + | |
| 395 | +/** | |
| 396 | + * amdgpu_mm_rreg8 - read a memory mapped IO register | |
| 397 | + * | |
| 398 | + * @adev: amdgpu_device pointer | |
| 399 | + * @offset: byte aligned register offset | |
| 400 | + * | |
| 401 | + * Returns the 8 bit value from the offset specified. | |
| 402 | + */ | |
| 403 | +uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) | |
| 404 | +{ | |
| 405 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 406 | + return 0; | |
| 407 | + | |
| 408 | + if (offset < adev->rmmio_size) | |
| 409 | + return (readb(adev->rmmio + offset)); | |
| 410 | + BUG(); | |
| 411 | +} | |
| 412 | + | |
| 413 | +/** | |
| 414 | + * amdgpu_device_xcc_rreg - read a memory mapped IO or indirect register with specific XCC | |
| 415 | + * | |
| 416 | + * @adev: amdgpu_device pointer | |
| 417 | + * @reg: dword aligned register offset | |
| 418 | + * @acc_flags: access flags which require special behavior | |
| 419 | + * @xcc_id: xcc accelerated compute core id | |
| 420 | + * | |
| 421 | + * Returns the 32 bit value from the offset specified. | |
| 422 | + */ | |
| 423 | +uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev, uint32_t reg, | |
| 424 | + uint32_t acc_flags, uint32_t xcc_id) | |
| 425 | +{ | |
| 426 | + uint32_t ret, rlcg_flag; | |
| 427 | + | |
| 428 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 429 | + return 0; | |
| 430 | + | |
| 431 | + if ((reg * 4) < adev->rmmio_size) { | |
| 432 | + if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_runtime(adev) && | |
| 433 | + adev->gfx.rlc.rlcg_reg_access_supported && | |
| 434 | + amdgpu_virt_get_rlcg_reg_access_flag( | |
| 435 | + adev, acc_flags, GC_HWIP, false, &rlcg_flag)) { | |
| 436 | + ret = amdgpu_virt_rlcg_reg_rw(adev, reg, 0, rlcg_flag, | |
| 437 | + GET_INST(GC, xcc_id)); | |
| 438 | + } else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 439 | + amdgpu_sriov_runtime(adev) && | |
| 440 | + down_read_trylock(&adev->reset_domain->sem)) { | |
| 441 | + ret = amdgpu_kiq_rreg(adev, reg, xcc_id); | |
| 442 | + up_read(&adev->reset_domain->sem); | |
| 443 | + } else { | |
| 444 | + ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 445 | + } | |
| 446 | + } else { | |
| 447 | + ret = amdgpu_reg_pcie_rd32(adev, reg * 4); | |
| 448 | + } | |
| 449 | + | |
| 450 | + return ret; | |
| 451 | +} | |
| 452 | + | |
| 453 | +/* | |
| 454 | + * MMIO register write with bytes helper functions | |
| 455 | + * @offset:bytes offset from MMIO start | |
| 456 | + * @value: the value want to be written to the register | |
| 457 | + */ | |
| 458 | + | |
| 459 | +/** | |
| 460 | + * amdgpu_mm_wreg8 - read a memory mapped IO register | |
| 461 | + * | |
| 462 | + * @adev: amdgpu_device pointer | |
| 463 | + * @offset: byte aligned register offset | |
| 464 | + * @value: 8 bit value to write | |
| 465 | + * | |
| 466 | + * Writes the value specified to the offset specified. | |
| 467 | + */ | |
| 468 | +void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) | |
| 469 | +{ | |
| 470 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 471 | + return; | |
| 472 | + | |
| 473 | + if (offset < adev->rmmio_size) | |
| 474 | + writeb(value, adev->rmmio + offset); | |
| 475 | + else | |
| 476 | + BUG(); | |
| 477 | +} | |
| 478 | + | |
| 479 | +/** | |
| 480 | + * amdgpu_device_wreg - write to a memory mapped IO or indirect register | |
| 481 | + * | |
| 482 | + * @adev: amdgpu_device pointer | |
| 483 | + * @reg: dword aligned register offset | |
| 484 | + * @v: 32 bit value to write to the register | |
| 485 | + * @acc_flags: access flags which require special behavior | |
| 486 | + * | |
| 487 | + * Writes the value specified to the offset specified. | |
| 488 | + */ | |
| 489 | +void amdgpu_device_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, | |
| 490 | + uint32_t acc_flags) | |
| 491 | +{ | |
| 492 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 493 | + return; | |
| 494 | + | |
| 495 | + if ((reg * 4) < adev->rmmio_size) { | |
| 496 | + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 497 | + amdgpu_sriov_runtime(adev) && | |
| 498 | + down_read_trylock(&adev->reset_domain->sem)) { | |
| 499 | + amdgpu_kiq_wreg(adev, reg, v, 0); | |
| 500 | + up_read(&adev->reset_domain->sem); | |
| 501 | + } else { | |
| 502 | + writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 503 | + } | |
| 504 | + } else { | |
| 505 | + amdgpu_reg_pcie_wr32(adev, reg * 4, v); | |
| 506 | + } | |
| 507 | + | |
| 508 | + trace_amdgpu_device_wreg(adev->pdev->device, reg, v); | |
| 509 | +} | |
| 510 | + | |
| 511 | +/** | |
| 512 | + * amdgpu_mm_wreg_mmio_rlc - write register either with direct/indirect mmio or with RLC path if in range | |
| 513 | + * | |
| 514 | + * @adev: amdgpu_device pointer | |
| 515 | + * @reg: mmio/rlc register | |
| 516 | + * @v: value to write | |
| 517 | + * @xcc_id: xcc accelerated compute core id | |
| 518 | + * | |
| 519 | + * this function is invoked only for the debugfs register access | |
| 520 | + */ | |
| 521 | +void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, | |
| 522 | + uint32_t v, uint32_t xcc_id) | |
| 523 | +{ | |
| 524 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 525 | + return; | |
| 526 | + | |
| 527 | + if (amdgpu_sriov_fullaccess(adev) && adev->gfx.rlc.funcs && | |
| 528 | + adev->gfx.rlc.funcs->is_rlcg_access_range) { | |
| 529 | + if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg)) | |
| 530 | + return amdgpu_sriov_wreg(adev, reg, v, 0, 0, xcc_id); | |
| 531 | + } else if ((reg * 4) >= adev->rmmio_size) { | |
| 532 | + amdgpu_reg_pcie_wr32(adev, reg * 4, v); | |
| 533 | + } else { | |
| 534 | + writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 535 | + } | |
| 536 | +} | |
| 537 | + | |
| 538 | +/** | |
| 539 | + * amdgpu_device_xcc_wreg - write to a memory mapped IO or indirect register with specific XCC | |
| 540 | + * | |
| 541 | + * @adev: amdgpu_device pointer | |
| 542 | + * @reg: dword aligned register offset | |
| 543 | + * @v: 32 bit value to write to the register | |
| 544 | + * @acc_flags: access flags which require special behavior | |
| 545 | + * @xcc_id: xcc accelerated compute core id | |
| 546 | + * | |
| 547 | + * Writes the value specified to the offset specified. | |
| 548 | + */ | |
| 549 | +void amdgpu_device_xcc_wreg(struct amdgpu_device *adev, uint32_t reg, | |
| 550 | + uint32_t v, uint32_t acc_flags, uint32_t xcc_id) | |
| 551 | +{ | |
| 552 | + uint32_t rlcg_flag; | |
| 553 | + | |
| 554 | + if (amdgpu_device_skip_hw_access(adev)) | |
| 555 | + return; | |
| 556 | + | |
| 557 | + if ((reg * 4) < adev->rmmio_size) { | |
| 558 | + if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_runtime(adev) && | |
| 559 | + adev->gfx.rlc.rlcg_reg_access_supported && | |
| 560 | + amdgpu_virt_get_rlcg_reg_access_flag( | |
| 561 | + adev, acc_flags, GC_HWIP, true, &rlcg_flag)) { | |
| 562 | + amdgpu_virt_rlcg_reg_rw(adev, reg, v, rlcg_flag, | |
| 563 | + GET_INST(GC, xcc_id)); | |
| 564 | + } else if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && | |
| 565 | + amdgpu_sriov_runtime(adev) && | |
| 566 | + down_read_trylock(&adev->reset_domain->sem)) { | |
| 567 | + amdgpu_kiq_wreg(adev, reg, v, xcc_id); | |
| 568 | + up_read(&adev->reset_domain->sem); | |
| 569 | + } else { | |
| 570 | + writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | |
| 571 | + } | |
| 572 | + } else { | |
| 573 | + amdgpu_reg_pcie_wr32(adev, reg * 4, v); | |
| 574 | + } | |
| 575 | +} | |
| 576 | + | |
| 577 | +/** | |
| 578 | + * amdgpu_device_indirect_rreg - read an indirect register | |
| 579 | + * | |
| 580 | + * @adev: amdgpu_device pointer | |
| 581 | + * @reg_addr: indirect register address to read from | |
| 582 | + * | |
| 583 | + * Returns the value of indirect register @reg_addr | |
| 584 | + */ | |
| 585 | +u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, u32 reg_addr) | |
| 586 | +{ | |
| 587 | + unsigned long flags, pcie_index, pcie_data; | |
| 588 | + void __iomem *pcie_index_offset; | |
| 589 | + void __iomem *pcie_data_offset; | |
| 590 | + u32 r; | |
| 591 | + | |
| 592 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 593 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 594 | + | |
| 595 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 596 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 597 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 598 | + | |
| 599 | + writel(reg_addr, pcie_index_offset); | |
| 600 | + readl(pcie_index_offset); | |
| 601 | + r = readl(pcie_data_offset); | |
| 602 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 603 | + | |
| 604 | + return r; | |
| 605 | +} | |
| 606 | + | |
| 607 | +u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev, u64 reg_addr) | |
| 608 | +{ | |
| 609 | + unsigned long flags, pcie_index, pcie_index_hi, pcie_data; | |
| 610 | + u32 r; | |
| 611 | + void __iomem *pcie_index_offset; | |
| 612 | + void __iomem *pcie_index_hi_offset; | |
| 613 | + void __iomem *pcie_data_offset; | |
| 614 | + | |
| 615 | + if (unlikely(!adev->nbio.funcs)) { | |
| 616 | + pcie_index = AMDGPU_PCIE_INDEX_FALLBACK; | |
| 617 | + pcie_data = AMDGPU_PCIE_DATA_FALLBACK; | |
| 618 | + } else { | |
| 619 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 620 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 621 | + } | |
| 622 | + | |
| 623 | + if (reg_addr >> 32) { | |
| 624 | + if (unlikely(!adev->nbio.funcs)) | |
| 625 | + pcie_index_hi = AMDGPU_PCIE_INDEX_HI_FALLBACK; | |
| 626 | + else | |
| 627 | + pcie_index_hi = | |
| 628 | + adev->nbio.funcs->get_pcie_index_hi_offset( | |
| 629 | + adev); | |
| 630 | + } else { | |
| 631 | + pcie_index_hi = 0; | |
| 632 | + } | |
| 633 | + | |
| 634 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 635 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 636 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 637 | + if (pcie_index_hi != 0) | |
| 638 | + pcie_index_hi_offset = | |
| 639 | + (void __iomem *)adev->rmmio + pcie_index_hi * 4; | |
| 640 | + | |
| 641 | + writel(reg_addr, pcie_index_offset); | |
| 642 | + readl(pcie_index_offset); | |
| 643 | + if (pcie_index_hi != 0) { | |
| 644 | + writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 645 | + readl(pcie_index_hi_offset); | |
| 646 | + } | |
| 647 | + r = readl(pcie_data_offset); | |
| 648 | + | |
| 649 | + /* clear the high bits */ | |
| 650 | + if (pcie_index_hi != 0) { | |
| 651 | + writel(0, pcie_index_hi_offset); | |
| 652 | + readl(pcie_index_hi_offset); | |
| 653 | + } | |
| 654 | + | |
| 655 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 656 | + | |
| 657 | + return r; | |
| 658 | +} | |
| 659 | + | |
| 660 | +/** | |
| 661 | + * amdgpu_device_indirect_rreg64 - read a 64bits indirect register | |
| 662 | + * | |
| 663 | + * @adev: amdgpu_device pointer | |
| 664 | + * @reg_addr: indirect register address to read from | |
| 665 | + * | |
| 666 | + * Returns the value of indirect register @reg_addr | |
| 667 | + */ | |
| 668 | +u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, u32 reg_addr) | |
| 669 | +{ | |
| 670 | + unsigned long flags, pcie_index, pcie_data; | |
| 671 | + void __iomem *pcie_index_offset; | |
| 672 | + void __iomem *pcie_data_offset; | |
| 673 | + u64 r; | |
| 674 | + | |
| 675 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 676 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 677 | + | |
| 678 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 679 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 680 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 681 | + | |
| 682 | + /* read low 32 bits */ | |
| 683 | + writel(reg_addr, pcie_index_offset); | |
| 684 | + readl(pcie_index_offset); | |
| 685 | + r = readl(pcie_data_offset); | |
| 686 | + /* read high 32 bits */ | |
| 687 | + writel(reg_addr + 4, pcie_index_offset); | |
| 688 | + readl(pcie_index_offset); | |
| 689 | + r |= ((u64)readl(pcie_data_offset) << 32); | |
| 690 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 691 | + | |
| 692 | + return r; | |
| 693 | +} | |
| 694 | + | |
| 695 | +u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev, u64 reg_addr) | |
| 696 | +{ | |
| 697 | + unsigned long flags, pcie_index, pcie_data; | |
| 698 | + unsigned long pcie_index_hi = 0; | |
| 699 | + void __iomem *pcie_index_offset; | |
| 700 | + void __iomem *pcie_index_hi_offset; | |
| 701 | + void __iomem *pcie_data_offset; | |
| 702 | + u64 r; | |
| 703 | + | |
| 704 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 705 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 706 | + if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset)) | |
| 707 | + pcie_index_hi = | |
| 708 | + adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 709 | + | |
| 710 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 711 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 712 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 713 | + if (pcie_index_hi != 0) | |
| 714 | + pcie_index_hi_offset = | |
| 715 | + (void __iomem *)adev->rmmio + pcie_index_hi * 4; | |
| 716 | + | |
| 717 | + /* read low 32 bits */ | |
| 718 | + writel(reg_addr, pcie_index_offset); | |
| 719 | + readl(pcie_index_offset); | |
| 720 | + if (pcie_index_hi != 0) { | |
| 721 | + writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 722 | + readl(pcie_index_hi_offset); | |
| 723 | + } | |
| 724 | + r = readl(pcie_data_offset); | |
| 725 | + /* read high 32 bits */ | |
| 726 | + writel(reg_addr + 4, pcie_index_offset); | |
| 727 | + readl(pcie_index_offset); | |
| 728 | + if (pcie_index_hi != 0) { | |
| 729 | + writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 730 | + readl(pcie_index_hi_offset); | |
| 731 | + } | |
| 732 | + r |= ((u64)readl(pcie_data_offset) << 32); | |
| 733 | + | |
| 734 | + /* clear the high bits */ | |
| 735 | + if (pcie_index_hi != 0) { | |
| 736 | + writel(0, pcie_index_hi_offset); | |
| 737 | + readl(pcie_index_hi_offset); | |
| 738 | + } | |
| 739 | + | |
| 740 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 741 | + | |
| 742 | + return r; | |
| 743 | +} | |
| 744 | + | |
| 745 | +/** | |
| 746 | + * amdgpu_device_indirect_wreg - write an indirect register address | |
| 747 | + * | |
| 748 | + * @adev: amdgpu_device pointer | |
| 749 | + * @reg_addr: indirect register offset | |
| 750 | + * @reg_data: indirect register data | |
| 751 | + * | |
| 752 | + */ | |
| 753 | +void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, u32 reg_addr, | |
| 754 | + u32 reg_data) | |
| 755 | +{ | |
| 756 | + unsigned long flags, pcie_index, pcie_data; | |
| 757 | + void __iomem *pcie_index_offset; | |
| 758 | + void __iomem *pcie_data_offset; | |
| 759 | + | |
| 760 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 761 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 762 | + | |
| 763 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 764 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 765 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 766 | + | |
| 767 | + writel(reg_addr, pcie_index_offset); | |
| 768 | + readl(pcie_index_offset); | |
| 769 | + writel(reg_data, pcie_data_offset); | |
| 770 | + readl(pcie_data_offset); | |
| 771 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 772 | +} | |
| 773 | + | |
| 774 | +void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev, u64 reg_addr, | |
| 775 | + u32 reg_data) | |
| 776 | +{ | |
| 777 | + unsigned long flags, pcie_index, pcie_index_hi, pcie_data; | |
| 778 | + void __iomem *pcie_index_offset; | |
| 779 | + void __iomem *pcie_index_hi_offset; | |
| 780 | + void __iomem *pcie_data_offset; | |
| 781 | + | |
| 782 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 783 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 784 | + if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset)) | |
| 785 | + pcie_index_hi = | |
| 786 | + adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 787 | + else | |
| 788 | + pcie_index_hi = 0; | |
| 789 | + | |
| 790 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 791 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 792 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 793 | + if (pcie_index_hi != 0) | |
| 794 | + pcie_index_hi_offset = | |
| 795 | + (void __iomem *)adev->rmmio + pcie_index_hi * 4; | |
| 796 | + | |
| 797 | + writel(reg_addr, pcie_index_offset); | |
| 798 | + readl(pcie_index_offset); | |
| 799 | + if (pcie_index_hi != 0) { | |
| 800 | + writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 801 | + readl(pcie_index_hi_offset); | |
| 802 | + } | |
| 803 | + writel(reg_data, pcie_data_offset); | |
| 804 | + readl(pcie_data_offset); | |
| 805 | + | |
| 806 | + /* clear the high bits */ | |
| 807 | + if (pcie_index_hi != 0) { | |
| 808 | + writel(0, pcie_index_hi_offset); | |
| 809 | + readl(pcie_index_hi_offset); | |
| 810 | + } | |
| 811 | + | |
| 812 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 813 | +} | |
| 814 | + | |
| 815 | +/** | |
| 816 | + * amdgpu_device_indirect_wreg64 - write a 64bits indirect register address | |
| 817 | + * | |
| 818 | + * @adev: amdgpu_device pointer | |
| 819 | + * @reg_addr: indirect register offset | |
| 820 | + * @reg_data: indirect register data | |
| 821 | + * | |
| 822 | + */ | |
| 823 | +void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, u32 reg_addr, | |
| 824 | + u64 reg_data) | |
| 825 | +{ | |
| 826 | + unsigned long flags, pcie_index, pcie_data; | |
| 827 | + void __iomem *pcie_index_offset; | |
| 828 | + void __iomem *pcie_data_offset; | |
| 829 | + | |
| 830 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 831 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 832 | + | |
| 833 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 834 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 835 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 836 | + | |
| 837 | + /* write low 32 bits */ | |
| 838 | + writel(reg_addr, pcie_index_offset); | |
| 839 | + readl(pcie_index_offset); | |
| 840 | + writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset); | |
| 841 | + readl(pcie_data_offset); | |
| 842 | + /* write high 32 bits */ | |
| 843 | + writel(reg_addr + 4, pcie_index_offset); | |
| 844 | + readl(pcie_index_offset); | |
| 845 | + writel((u32)(reg_data >> 32), pcie_data_offset); | |
| 846 | + readl(pcie_data_offset); | |
| 847 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 848 | +} | |
| 849 | + | |
| 850 | +void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev, u64 reg_addr, | |
| 851 | + u64 reg_data) | |
| 852 | +{ | |
| 853 | + unsigned long flags, pcie_index, pcie_data; | |
| 854 | + unsigned long pcie_index_hi = 0; | |
| 855 | + void __iomem *pcie_index_offset; | |
| 856 | + void __iomem *pcie_index_hi_offset; | |
| 857 | + void __iomem *pcie_data_offset; | |
| 858 | + | |
| 859 | + pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev); | |
| 860 | + pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev); | |
| 861 | + if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset)) | |
| 862 | + pcie_index_hi = | |
| 863 | + adev->nbio.funcs->get_pcie_index_hi_offset(adev); | |
| 864 | + | |
| 865 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 866 | + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; | |
| 867 | + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; | |
| 868 | + if (pcie_index_hi != 0) | |
| 869 | + pcie_index_hi_offset = | |
| 870 | + (void __iomem *)adev->rmmio + pcie_index_hi * 4; | |
| 871 | + | |
| 872 | + /* write low 32 bits */ | |
| 873 | + writel(reg_addr, pcie_index_offset); | |
| 874 | + readl(pcie_index_offset); | |
| 875 | + if (pcie_index_hi != 0) { | |
| 876 | + writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 877 | + readl(pcie_index_hi_offset); | |
| 878 | + } | |
| 879 | + writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset); | |
| 880 | + readl(pcie_data_offset); | |
| 881 | + /* write high 32 bits */ | |
| 882 | + writel(reg_addr + 4, pcie_index_offset); | |
| 883 | + readl(pcie_index_offset); | |
| 884 | + if (pcie_index_hi != 0) { | |
| 885 | + writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset); | |
| 886 | + readl(pcie_index_hi_offset); | |
| 887 | + } | |
| 888 | + writel((u32)(reg_data >> 32), pcie_data_offset); | |
| 889 | + readl(pcie_data_offset); | |
| 890 | + | |
| 891 | + /* clear the high bits */ | |
| 892 | + if (pcie_index_hi != 0) { | |
| 893 | + writel(0, pcie_index_hi_offset); | |
| 894 | + readl(pcie_index_hi_offset); | |
| 895 | + } | |
| 896 | + | |
| 897 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 898 | +} | |
| 899 | + | |
| 900 | +u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev, u32 reg) | |
| 901 | +{ | |
| 902 | + unsigned long flags, address, data; | |
| 903 | + u32 r; | |
| 904 | + | |
| 905 | + address = adev->nbio.funcs->get_pcie_port_index_offset(adev); | |
| 906 | + data = adev->nbio.funcs->get_pcie_port_data_offset(adev); | |
| 907 | + | |
| 908 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 909 | + WREG32(address, reg * 4); | |
| 910 | + (void)RREG32(address); | |
| 911 | + r = RREG32(data); | |
| 912 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 913 | + return r; | |
| 914 | +} | |
| 915 | + | |
| 916 | +void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, u32 reg, u32 v) | |
| 917 | +{ | |
| 918 | + unsigned long flags, address, data; | |
| 919 | + | |
| 920 | + address = adev->nbio.funcs->get_pcie_port_index_offset(adev); | |
| 921 | + data = adev->nbio.funcs->get_pcie_port_data_offset(adev); | |
| 922 | + | |
| 923 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 924 | + WREG32(address, reg * 4); | |
| 925 | + (void)RREG32(address); | |
| 926 | + WREG32(data, v); | |
| 927 | + (void)RREG32(data); | |
| 928 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 929 | +} | |
| 930 | + | |
| 931 | +uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev, uint32_t inst, | |
| 932 | + uint32_t reg_addr, char reg_name[], | |
| 933 | + uint32_t expected_value, uint32_t mask) | |
| 934 | +{ | |
| 935 | + uint32_t ret = 0; | |
| 936 | + uint32_t old_ = 0; | |
| 937 | + uint32_t tmp_ = RREG32(reg_addr); | |
| 938 | + uint32_t loop = adev->usec_timeout; | |
| 939 | + | |
| 940 | + while ((tmp_ & (mask)) != (expected_value)) { | |
| 941 | + if (old_ != tmp_) { | |
| 942 | + loop = adev->usec_timeout; | |
| 943 | + old_ = tmp_; | |
| 944 | + } else | |
| 945 | + udelay(1); | |
| 946 | + tmp_ = RREG32(reg_addr); | |
| 947 | + loop--; | |
| 948 | + if (!loop) { | |
| 949 | + dev_warn( | |
| 950 | + adev->dev, | |
| 951 | + "Register(%d) [%s] failed to reach value 0x%08x != 0x%08xn", | |
| 952 | + inst, reg_name, (uint32_t)expected_value, | |
| 953 | + (uint32_t)(tmp_ & (mask))); | |
| 954 | + ret = -ETIMEDOUT; | |
| 955 | + break; | |
| 956 | + } | |
| 957 | + } | |
| 958 | + return ret; | |
| 959 | +} | |
| @@ -0,0 +1,163 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2025 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#ifndef __AMDGPU_REG_ACCESS_H__ | |
| 25 | +#define __AMDGPU_REG_ACCESS_H__ | |
| 26 | + | |
| 27 | +#include <linux/types.h> | |
| 28 | +#include <linux/spinlock.h> | |
| 29 | + | |
| 30 | +#include "amdgpu_ip.h" | |
| 31 | + | |
| 32 | +struct amdgpu_device; | |
| 33 | + | |
| 34 | +typedef uint32_t (*amdgpu_rreg_t)(struct amdgpu_device *, uint32_t); | |
| 35 | +typedef void (*amdgpu_wreg_t)(struct amdgpu_device *, uint32_t, uint32_t); | |
| 36 | +typedef uint32_t (*amdgpu_rreg_ext_t)(struct amdgpu_device *, uint64_t); | |
| 37 | +typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device *, uint64_t, uint32_t); | |
| 38 | +typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device *, uint32_t); | |
| 39 | +typedef void (*amdgpu_wreg64_t)(struct amdgpu_device *, uint32_t, uint64_t); | |
| 40 | +typedef uint64_t (*amdgpu_rreg64_ext_t)(struct amdgpu_device *, uint64_t); | |
| 41 | +typedef void (*amdgpu_wreg64_ext_t)(struct amdgpu_device *, uint64_t, uint64_t); | |
| 42 | + | |
| 43 | +typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device *, uint32_t, | |
| 44 | + uint32_t); | |
| 45 | +typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device *, uint32_t, uint32_t, | |
| 46 | + uint32_t); | |
| 47 | +typedef uint64_t (*amdgpu_reg_get_smn_base64_t)(struct amdgpu_device *adev, | |
| 48 | + enum amd_hw_ip_block_type block, | |
| 49 | + int die_inst); | |
| 50 | + | |
| 51 | +struct amdgpu_reg_ind { | |
| 52 | + spinlock_t lock; | |
| 53 | + amdgpu_rreg_t rreg; | |
| 54 | + amdgpu_wreg_t wreg; | |
| 55 | +}; | |
| 56 | + | |
| 57 | +struct amdgpu_reg_ind_blk { | |
| 58 | + spinlock_t lock; | |
| 59 | + amdgpu_block_rreg_t rreg; | |
| 60 | + amdgpu_block_wreg_t wreg; | |
| 61 | +}; | |
| 62 | + | |
| 63 | +struct amdgpu_reg_pcie_ind { | |
| 64 | + spinlock_t lock; | |
| 65 | + amdgpu_rreg_t rreg; | |
| 66 | + amdgpu_wreg_t wreg; | |
| 67 | + amdgpu_rreg_ext_t rreg_ext; | |
| 68 | + amdgpu_wreg_ext_t wreg_ext; | |
| 69 | + amdgpu_rreg64_t rreg64; | |
| 70 | + amdgpu_wreg64_t wreg64; | |
| 71 | + amdgpu_rreg64_ext_t rreg64_ext; | |
| 72 | + amdgpu_wreg64_ext_t wreg64_ext; | |
| 73 | + amdgpu_rreg_t port_rreg; | |
| 74 | + amdgpu_wreg_t port_wreg; | |
| 75 | +}; | |
| 76 | + | |
| 77 | +struct amdgpu_reg_smn_ext { | |
| 78 | + amdgpu_reg_get_smn_base64_t get_smn_base; | |
| 79 | +}; | |
| 80 | + | |
| 81 | +struct amdgpu_reg_access { | |
| 82 | + struct amdgpu_reg_ind smc; | |
| 83 | + struct amdgpu_reg_ind uvd_ctx; | |
| 84 | + struct amdgpu_reg_ind didt; | |
| 85 | + struct amdgpu_reg_ind gc_cac; | |
| 86 | + struct amdgpu_reg_ind se_cac; | |
| 87 | + struct amdgpu_reg_ind_blk audio_endpt; | |
| 88 | + struct amdgpu_reg_pcie_ind pcie; | |
| 89 | + struct amdgpu_reg_smn_ext smn; | |
| 90 | +}; | |
| 91 | + | |
| 92 | +void amdgpu_reg_access_init(struct amdgpu_device *adev); | |
| 93 | +uint32_t amdgpu_reg_smc_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 94 | +void amdgpu_reg_smc_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v); | |
| 95 | +uint32_t amdgpu_reg_uvd_ctx_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 96 | +void amdgpu_reg_uvd_ctx_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v); | |
| 97 | +uint32_t amdgpu_reg_didt_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 98 | +void amdgpu_reg_didt_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v); | |
| 99 | +uint32_t amdgpu_reg_gc_cac_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 100 | +void amdgpu_reg_gc_cac_wr32(struct amdgpu_device *adev, uint32_t reg, | |
| 101 | + uint32_t v); | |
| 102 | +uint32_t amdgpu_reg_se_cac_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 103 | +void amdgpu_reg_se_cac_wr32(struct amdgpu_device *adev, uint32_t reg, | |
| 104 | + uint32_t v); | |
| 105 | +uint32_t amdgpu_reg_audio_endpt_rd32(struct amdgpu_device *adev, uint32_t block, | |
| 106 | + uint32_t reg); | |
| 107 | +void amdgpu_reg_audio_endpt_wr32(struct amdgpu_device *adev, uint32_t block, | |
| 108 | + uint32_t reg, uint32_t v); | |
| 109 | +uint32_t amdgpu_reg_pcie_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 110 | +void amdgpu_reg_pcie_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v); | |
| 111 | +uint32_t amdgpu_reg_pcie_ext_rd32(struct amdgpu_device *adev, uint64_t reg); | |
| 112 | +void amdgpu_reg_pcie_ext_wr32(struct amdgpu_device *adev, uint64_t reg, | |
| 113 | + uint32_t v); | |
| 114 | +uint64_t amdgpu_reg_pcie_rd64(struct amdgpu_device *adev, uint32_t reg); | |
| 115 | +void amdgpu_reg_pcie_wr64(struct amdgpu_device *adev, uint32_t reg, uint64_t v); | |
| 116 | +uint64_t amdgpu_reg_pcie_ext_rd64(struct amdgpu_device *adev, uint64_t reg); | |
| 117 | +void amdgpu_reg_pcie_ext_wr64(struct amdgpu_device *adev, uint64_t reg, | |
| 118 | + uint64_t v); | |
| 119 | +uint32_t amdgpu_reg_pciep_rd32(struct amdgpu_device *adev, uint32_t reg); | |
| 120 | +void amdgpu_reg_pciep_wr32(struct amdgpu_device *adev, uint32_t reg, | |
| 121 | + uint32_t v); | |
| 122 | +uint64_t amdgpu_reg_get_smn_base64(struct amdgpu_device *adev, | |
| 123 | + enum amd_hw_ip_block_type block, | |
| 124 | + int die_inst); | |
| 125 | +uint64_t amdgpu_reg_smn_v1_0_get_base(struct amdgpu_device *adev, | |
| 126 | + enum amd_hw_ip_block_type block, | |
| 127 | + int die_inst); | |
| 128 | + | |
| 129 | +uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, uint32_t reg, | |
| 130 | + uint32_t acc_flags); | |
| 131 | +uint32_t amdgpu_device_xcc_rreg(struct amdgpu_device *adev, uint32_t reg, | |
| 132 | + uint32_t acc_flags, uint32_t xcc_id); | |
| 133 | +void amdgpu_device_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, | |
| 134 | + uint32_t acc_flags); | |
| 135 | +void amdgpu_device_xcc_wreg(struct amdgpu_device *adev, uint32_t reg, | |
| 136 | + uint32_t v, uint32_t acc_flags, uint32_t xcc_id); | |
| 137 | +void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, | |
| 138 | + uint32_t v, uint32_t xcc_id); | |
| 139 | +void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, | |
| 140 | + uint8_t value); | |
| 141 | +uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset); | |
| 142 | + | |
| 143 | +u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, u32 reg_addr); | |
| 144 | +u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev, u64 reg_addr); | |
| 145 | +u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, u32 reg_addr); | |
| 146 | +u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev, u64 reg_addr); | |
| 147 | +void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, u32 reg_addr, | |
| 148 | + u32 reg_data); | |
| 149 | +void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev, u64 reg_addr, | |
| 150 | + u32 reg_data); | |
| 151 | +void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, u32 reg_addr, | |
| 152 | + u64 reg_data); | |
| 153 | +void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev, u64 reg_addr, | |
| 154 | + u64 reg_data); | |
| 155 | + | |
| 156 | +u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev, u32 reg); | |
| 157 | +void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, u32 reg, u32 v); | |
| 158 | + | |
| 159 | +uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev, uint32_t inst, | |
| 160 | + uint32_t reg_addr, char reg_name[], | |
| 161 | + uint32_t expected_value, uint32_t mask); | |
| 162 | + | |
| 163 | +#endif /* __AMDGPU_REG_ACCESS_H__ */ | |
| @@ -90,10 +90,13 @@ int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned int ndw) · 89 unmodified lines | ||
| 90 | 90 | ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask; |
| 91 | 91 | |
| 92 | 92 | /* Make sure we aren't trying to allocate more space |
| 93 | − * than the maximum for one submission | |
| 93 | + * than the maximum for one submission. Skip for reemit | |
| 94 | + * since we may be reemitting several submissions. | |
| 94 | 95 | */ |
| 95 | − if (WARN_ON_ONCE(ndw > ring->max_dw)) | |
| 96 | − return -ENOMEM; | |
| 96 | + if (!ring->reemit) { | |
| 97 | + if (WARN_ON_ONCE(ndw > ring->max_dw)) | |
| 98 | + return -ENOMEM; | |
| 99 | + } | |
| 97 | 100 | |
| 98 | 101 | ring->count_dw = ndw; |
| 99 | 102 | ring->wptr_old = ring->wptr; |
| @@ -104,29 +107,6 @@ int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned int ndw) · 4 unmodified lines | ||
| 104 | 107 | return 0; |
| 105 | 108 | } |
| 106 | 109 | |
| 107 | −/** | |
| 108 | − * amdgpu_ring_alloc_reemit - allocate space on the ring buffer for reemit | |
| 109 | − * | |
| 110 | − * @ring: amdgpu_ring structure holding ring information | |
| 111 | − * @ndw: number of dwords to allocate in the ring buffer | |
| 112 | − * | |
| 113 | − * Allocate @ndw dwords in the ring buffer (all asics). | |
| 114 | − * doesn't check the max_dw limit as we may be reemitting | |
| 115 | − * several submissions. | |
| 116 | − */ | |
| 117 | −static void amdgpu_ring_alloc_reemit(struct amdgpu_ring *ring, unsigned int ndw) | |
| 118 | −{ | |
| 119 | − /* Align requested size with padding so unlock_commit can | |
| 120 | − * pad safely */ | |
| 121 | − ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask; | |
| 122 | − | |
| 123 | − ring->count_dw = ndw; | |
| 124 | − ring->wptr_old = ring->wptr; | |
| 125 | − | |
| 126 | − if (ring->funcs->begin_use) | |
| 127 | − ring->funcs->begin_use(ring); | |
| 128 | −} | |
| 129 | − | |
| 130 | 110 | /** |
| 131 | 111 | * amdgpu_ring_insert_nop - insert NOP packets |
| 132 | 112 | * |
| @@ -875,7 +855,6 @@ void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring, · 742 unmodified lines | ||
| 875 | 855 | int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring, |
| 876 | 856 | struct amdgpu_fence *guilty_fence) |
| 877 | 857 | { |
| 878 | − unsigned int i; | |
| 879 | 858 | int r; |
| 880 | 859 | |
| 881 | 860 | /* verify that the ring is functional */ |
| @@ -883,16 +862,9 @@ int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring, · 1 unmodified line | ||
| 883 | 862 | if (r) |
| 884 | 863 | return r; |
| 885 | 864 | |
| 886 | − /* set an error on all fences from the context */ | |
| 887 | − if (guilty_fence) | |
| 888 | − amdgpu_fence_driver_update_timedout_fence_state(guilty_fence); | |
| 889 | − /* Re-emit the non-guilty commands */ | |
| 890 | − if (ring->ring_backup_entries_to_copy) { | |
| 891 | − amdgpu_ring_alloc_reemit(ring, ring->ring_backup_entries_to_copy); | |
| 892 | − for (i = 0; i < ring->ring_backup_entries_to_copy; i++) | |
| 893 | − amdgpu_ring_write(ring, ring->ring_backup[i]); | |
| 894 | − amdgpu_ring_commit(ring); | |
| 895 | − } | |
| 865 | + /* set an error on all fences from the context and reemit */ | |
| 866 | + amdgpu_ring_set_fence_errors_and_reemit(ring, guilty_fence); | |
| 867 | + | |
| 896 | 868 | return 0; |
| 897 | 869 | } |
| 898 | 870 | |
| @@ -121,7 +121,6 @@ struct amdgpu_fence_driver { · 120 unmodified lines | ||
| 121 | 121 | /* sync_seq is protected by ring emission lock */ |
| 122 | 122 | uint32_t sync_seq; |
| 123 | 123 | atomic_t last_seq; |
| 124 | − u64 signalled_wptr; | |
| 125 | 124 | bool initialized; |
| 126 | 125 | struct amdgpu_irq_src *irq_src; |
| 127 | 126 | unsigned irq_type; |
| @@ -146,23 +145,23 @@ struct amdgpu_fence { · 18 unmodified lines | ||
| 146 | 145 | struct amdgpu_ring *ring; |
| 147 | 146 | ktime_t start_timestamp; |
| 148 | 147 | |
| 149 | − /* wptr for the total submission for resets */ | |
| 150 | − u64 wptr; | |
| 148 | + /* location and size of the IB */ | |
| 149 | + u64 ib_wptr; | |
| 150 | + unsigned int ib_dw_size; | |
| 151 | + unsigned int skip_ib_dw_start_offset; | |
| 152 | + unsigned int skip_ib_dw_end_offset; | |
| 151 | 153 | /* fence context for resets */ |
| 152 | 154 | u64 context; |
| 153 | − /* has this fence been reemitted */ | |
| 154 | − unsigned int reemitted; | |
| 155 | − /* wptr for the fence for the submission */ | |
| 156 | − u64 fence_wptr_start; | |
| 157 | − u64 fence_wptr_end; | |
| 155 | + /* idx for ring backups */ | |
| 156 | + unsigned int backup_idx; | |
| 158 | 157 | }; |
| 159 | 158 | |
| 160 | 159 | extern const struct drm_sched_backend_ops amdgpu_sched_ops; |
| 161 | 160 | |
| 162 | 161 | void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error); |
| 163 | 162 | void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); |
| 164 | −void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af); | |
| 165 | −void amdgpu_fence_save_wptr(struct amdgpu_fence *af); | |
| 163 | +void amdgpu_ring_set_fence_errors_and_reemit(struct amdgpu_ring *ring, | |
| 164 | + struct amdgpu_fence *guilty_fence); | |
| 166 | 165 | |
| 167 | 166 | int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring); |
| 168 | 167 | int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, |
| @@ -172,8 +171,8 @@ void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev); · 3 unmodified lines | ||
| 172 | 171 | void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev); |
| 173 | 172 | int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev); |
| 174 | 173 | void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev); |
| 175 | −int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, | |
| 176 | − unsigned int flags); | |
| 174 | +void amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, | |
| 175 | + unsigned int flags); | |
| 177 | 176 | int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s, |
| 178 | 177 | uint32_t timeout); |
| 179 | 178 | bool amdgpu_fence_process(struct amdgpu_ring *ring); |
| @@ -313,6 +312,7 @@ struct amdgpu_ring { · 133 unmodified lines | ||
| 313 | 312 | /* backups for resets */ |
| 314 | 313 | uint32_t *ring_backup; |
| 315 | 314 | unsigned int ring_backup_entries_to_copy; |
| 315 | + bool reemit; | |
| 316 | 316 | unsigned rptr_offs; |
| 317 | 317 | u64 rptr_gpu_addr; |
| 318 | 318 | u32 *rptr_cpu_addr; |
| @@ -522,6 +522,17 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, · 203 unmodified lines | ||
| 522 | 522 | ring->count_dw -= count_dw; |
| 523 | 523 | } |
| 524 | 524 | |
| 525 | +static inline unsigned int amdgpu_ring_get_dw_distance(struct amdgpu_ring *ring, | |
| 526 | + u64 start_wptr, u64 end_wptr) | |
| 527 | +{ | |
| 528 | + unsigned int start = start_wptr & ring->buf_mask; | |
| 529 | + unsigned int end = end_wptr & ring->buf_mask; | |
| 530 | + | |
| 531 | + if (end < start) | |
| 532 | + end += ring->ring_size >> 2; | |
| 533 | + return end - start; | |
| 534 | +} | |
| 535 | + | |
| 525 | 536 | /** |
| 526 | 537 | * amdgpu_ring_patch_cond_exec - patch dw count of conditional execute |
| 527 | 538 | * @ring: amdgpu_ring structure |
| @@ -532,18 +543,13 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, · 4 unmodified lines | ||
| 532 | 543 | static inline void amdgpu_ring_patch_cond_exec(struct amdgpu_ring *ring, |
| 533 | 544 | unsigned int offset) |
| 534 | 545 | { |
| 535 | − unsigned cur; | |
| 536 | − | |
| 537 | 546 | if (!ring->funcs->init_cond_exec) |
| 538 | 547 | return; |
| 539 | 548 | |
| 540 | 549 | WARN_ON(offset > ring->buf_mask); |
| 541 | 550 | WARN_ON(ring->ring[offset] != 0); |
| 542 | 551 | |
| 543 | − cur = (ring->wptr - 1) & ring->buf_mask; | |
| 544 | − if (cur < offset) | |
| 545 | − cur += ring->ring_size >> 2; | |
| 546 | − ring->ring[offset] = cur - offset; | |
| 552 | + ring->ring[offset] = amdgpu_ring_get_dw_distance(ring, offset, ring->wptr - 1); | |
| 547 | 553 | } |
| 548 | 554 | |
| 549 | 555 | int amdgpu_ring_test_helper(struct amdgpu_ring *ring); |
| @@ -163,7 +163,8 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, · 162 unmodified lines | ||
| 163 | 163 | } |
| 164 | 164 | |
| 165 | 165 | static struct dma_fence * |
| 166 | −amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_job *job, u32 num_dw) | |
| 166 | +amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_ttm_buffer_entity *entity, | |
| 167 | + struct amdgpu_job *job, u32 num_dw) | |
| 167 | 168 | { |
| 168 | 169 | struct amdgpu_ring *ring; |
| 169 | 170 | |
| @@ -171,6 +172,8 @@ amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_job *job, u32 nu · 1 unmodified line | ||
| 171 | 172 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
| 172 | 173 | WARN_ON(job->ibs[0].length_dw > num_dw); |
| 173 | 174 | |
| 175 | + lockdep_assert_held(&entity->lock); | |
| 176 | + | |
| 174 | 177 | return amdgpu_job_submit(job); |
| 175 | 178 | } |
| 176 | 179 | |
| @@ -228,9 +231,7 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, · 51 unmodified lines | ||
| 228 | 231 | |
| 229 | 232 | *size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset); |
| 230 | 233 | |
| 231 | − *addr = adev->gmc.gart_start; | |
| 232 | − *addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE * | |
| 233 | − AMDGPU_GPU_PAGE_SIZE; | |
| 234 | + *addr = amdgpu_compute_gart_address(&adev->gmc, entity, window); | |
| 234 | 235 | *addr += offset; |
| 235 | 236 | |
| 236 | 237 | num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); |
| @@ -248,7 +249,7 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, · 11 unmodified lines | ||
| 248 | 249 | src_addr += job->ibs[0].gpu_addr; |
| 249 | 250 | |
| 250 | 251 | dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); |
| 251 | − dst_addr += window * AMDGPU_GTT_MAX_TRANSFER_SIZE * 8; | |
| 252 | + dst_addr += (entity->gart_window_offs[window] >> AMDGPU_GPU_PAGE_SHIFT) * 8; | |
| 252 | 253 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, |
| 253 | 254 | dst_addr, num_bytes, 0); |
| 254 | 255 | |
| @@ -269,7 +270,7 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, · 14 unmodified lines | ||
| 269 | 270 | amdgpu_gart_map_vram_range(adev, pa, 0, num_pages, flags, cpu_addr); |
| 270 | 271 | } |
| 271 | 272 | |
| 272 | − dma_fence_put(amdgpu_ttm_job_submit(adev, job, num_dw)); | |
| 273 | + dma_fence_put(amdgpu_ttm_job_submit(adev, entity, job, num_dw)); | |
| 273 | 274 | return 0; |
| 274 | 275 | } |
| 275 | 276 | |
| @@ -313,7 +314,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, · 37 unmodified lines | ||
| 313 | 314 | amdgpu_res_first(src->mem, src->offset, size, &src_mm); |
| 314 | 315 | amdgpu_res_first(dst->mem, dst->offset, size, &dst_mm); |
| 315 | 316 | |
| 316 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 317 | + mutex_lock(&entity->lock); | |
| 317 | 318 | while (src_mm.remaining) { |
| 318 | 319 | uint64_t from, to, cur_size, tiling_flags; |
| 319 | 320 | uint32_t num_type, data_format, max_com, write_compress_disable; |
| @@ -368,7 +369,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, · 48 unmodified lines | ||
| 368 | 369 | amdgpu_res_next(&dst_mm, cur_size); |
| 369 | 370 | } |
| 370 | 371 | error: |
| 371 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 372 | + mutex_unlock(&entity->lock); | |
| 372 | 373 | *f = fence; |
| 373 | 374 | return r; |
| 374 | 375 | } |
| @@ -1580,7 +1581,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, · 1205 unmodified lines | ||
| 1580 | 1581 | if (r) |
| 1581 | 1582 | goto out; |
| 1582 | 1583 | |
| 1583 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 1584 | + mutex_lock(&adev->mman.default_entity.lock); | |
| 1584 | 1585 | amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm); |
| 1585 | 1586 | src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + |
| 1586 | 1587 | src_mm.start; |
| @@ -1591,8 +1592,8 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, · 4 unmodified lines | ||
| 1591 | 1592 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, |
| 1592 | 1593 | PAGE_SIZE, 0); |
| 1593 | 1594 | |
| 1594 | − fence = amdgpu_ttm_job_submit(adev, job, num_dw); | |
| 1595 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 1595 | + fence = amdgpu_ttm_job_submit(adev, &adev->mman.default_entity, job, num_dw); | |
| 1596 | + mutex_unlock(&adev->mman.default_entity.lock); | |
| 1596 | 1597 | |
| 1597 | 1598 | if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout)) |
| 1598 | 1599 | r = -ETIMEDOUT; |
| @@ -1908,7 +1909,7 @@ static void amdgpu_ttm_pools_fini(struct amdgpu_device *adev) · 309 unmodified lines | ||
| 1908 | 1909 | } |
| 1909 | 1910 | |
| 1910 | 1911 | /** |
| 1911 | − * amdgpu_ttm_mmio_remap_bo_init - Allocate the singleton MMIO_REMAP BO | |
| 1912 | + * amdgpu_ttm_alloc_mmio_remap_bo - Allocate the singleton MMIO_REMAP BO | |
| 1912 | 1913 | * @adev: amdgpu device |
| 1913 | 1914 | * |
| 1914 | 1915 | * Allocates a global BO with backing AMDGPU_PL_MMIO_REMAP when the |
| @@ -2013,6 +2014,50 @@ static void amdgpu_ttm_free_mmio_remap_bo(struct amdgpu_device *adev) · 98 unmodified lines | ||
| 2013 | 2014 | adev->rmmio_remap.bo = NULL; |
| 2014 | 2015 | } |
| 2015 | 2016 | |
| 2017 | +static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr, | |
| 2018 | + struct amdgpu_ttm_buffer_entity *entity, | |
| 2019 | + enum drm_sched_priority prio, | |
| 2020 | + struct drm_gpu_scheduler **scheds, | |
| 2021 | + int num_schedulers, | |
| 2022 | + u32 num_gart_windows) | |
| 2023 | +{ | |
| 2024 | + int i, r, num_pages; | |
| 2025 | + | |
| 2026 | + r = drm_sched_entity_init(&entity->base, prio, scheds, num_schedulers, NULL); | |
| 2027 | + if (r) | |
| 2028 | + return r; | |
| 2029 | + | |
| 2030 | + mutex_init(&entity->lock); | |
| 2031 | + | |
| 2032 | + if (ARRAY_SIZE(entity->gart_window_offs) < num_gart_windows) | |
| 2033 | + return -EINVAL; | |
| 2034 | + if (num_gart_windows == 0) | |
| 2035 | + return 0; | |
| 2036 | + | |
| 2037 | + num_pages = num_gart_windows * AMDGPU_GTT_MAX_TRANSFER_SIZE; | |
| 2038 | + r = amdgpu_gtt_mgr_alloc_entries(mgr, &entity->gart_node, num_pages, | |
| 2039 | + DRM_MM_INSERT_BEST); | |
| 2040 | + if (r) { | |
| 2041 | + drm_sched_entity_destroy(&entity->base); | |
| 2042 | + return r; | |
| 2043 | + } | |
| 2044 | + | |
| 2045 | + for (i = 0; i < num_gart_windows; i++) { | |
| 2046 | + entity->gart_window_offs[i] = | |
| 2047 | + amdgpu_gtt_node_to_byte_offset(&entity->gart_node) + | |
| 2048 | + i * AMDGPU_GTT_MAX_TRANSFER_SIZE * PAGE_SIZE; | |
| 2049 | + } | |
| 2050 | + | |
| 2051 | + return 0; | |
| 2052 | +} | |
| 2053 | + | |
| 2054 | +static void amdgpu_ttm_buffer_entity_fini(struct amdgpu_gtt_mgr *mgr, | |
| 2055 | + struct amdgpu_ttm_buffer_entity *entity) | |
| 2056 | +{ | |
| 2057 | + amdgpu_gtt_mgr_free_entries(mgr, &entity->gart_node); | |
| 2058 | + drm_sched_entity_destroy(&entity->base); | |
| 2059 | +} | |
| 2060 | + | |
| 2016 | 2061 | /* |
| 2017 | 2062 | * amdgpu_ttm_init - Init the memory management (ttm) as well as various |
| 2018 | 2063 | * gtt/vram related fields. |
| @@ -2027,8 +2072,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) · 8 unmodified lines | ||
| 2027 | 2072 | uint64_t gtt_size; |
| 2028 | 2073 | int r; |
| 2029 | 2074 | |
| 2030 | − mutex_init(&adev->mman.gtt_window_lock); | |
| 2031 | − | |
| 2032 | 2075 | dma_set_max_seg_size(adev->dev, UINT_MAX); |
| 2033 | 2076 | /* No others user of address space so set it to 0 */ |
| 2034 | 2077 | r = ttm_device_init(&adev->mman.bdev, &amdgpu_bo_driver, adev->dev, |
| @@ -2313,42 +2356,49 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) · 278 unmodified lines | ||
| 2313 | 2356 | struct amdgpu_ring *ring; |
| 2314 | 2357 | struct drm_gpu_scheduler *sched; |
| 2315 | 2358 | |
| 2359 | + if (!adev->mman.buffer_funcs_ring || !adev->mman.buffer_funcs_ring->sched.ready) { | |
| 2360 | + dev_warn(adev->dev, "Not enabling DMA transfers for in kernel use"); | |
| 2361 | + return; | |
| 2362 | + } | |
| 2363 | + | |
| 2316 | 2364 | ring = adev->mman.buffer_funcs_ring; |
| 2317 | 2365 | sched = &ring->sched; |
| 2318 | − r = drm_sched_entity_init(&adev->mman.default_entity.base, | |
| 2319 | − DRM_SCHED_PRIORITY_KERNEL, &sched, | |
| 2320 | − 1, NULL); | |
| 2321 | − if (r) { | |
| 2366 | + r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, | |
| 2367 | + &adev->mman.default_entity, | |
| 2368 | + DRM_SCHED_PRIORITY_KERNEL, | |
| 2369 | + &sched, 1, 0); | |
| 2370 | + if (r < 0) { | |
| 2322 | 2371 | dev_err(adev->dev, |
| 2323 | − "Failed setting up TTM BO move entity (%d)\n", | |
| 2324 | − r); | |
| 2372 | + "Failed setting up TTM entity (%d)\n", r); | |
| 2325 | 2373 | return; |
| 2326 | 2374 | } |
| 2327 | 2375 | |
| 2328 | − r = drm_sched_entity_init(&adev->mman.clear_entity.base, | |
| 2329 | − DRM_SCHED_PRIORITY_NORMAL, &sched, | |
| 2330 | − 1, NULL); | |
| 2331 | − if (r) { | |
| 2376 | + r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, | |
| 2377 | + &adev->mman.clear_entity, | |
| 2378 | + DRM_SCHED_PRIORITY_NORMAL, | |
| 2379 | + &sched, 1, 1); | |
| 2380 | + if (r < 0) { | |
| 2332 | 2381 | dev_err(adev->dev, |
| 2333 | − "Failed setting up TTM BO clear entity (%d)\n", | |
| 2334 | − r); | |
| 2335 | − goto error_free_entity; | |
| 2382 | + "Failed setting up TTM BO clear entity (%d)\n", r); | |
| 2383 | + goto error_free_default_entity; | |
| 2336 | 2384 | } |
| 2337 | 2385 | |
| 2338 | − r = drm_sched_entity_init(&adev->mman.move_entity.base, | |
| 2339 | − DRM_SCHED_PRIORITY_NORMAL, &sched, | |
| 2340 | − 1, NULL); | |
| 2341 | − if (r) { | |
| 2386 | + r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, | |
| 2387 | + &adev->mman.move_entity, | |
| 2388 | + DRM_SCHED_PRIORITY_NORMAL, | |
| 2389 | + &sched, 1, 2); | |
| 2390 | + if (r < 0) { | |
| 2342 | 2391 | dev_err(adev->dev, |
| 2343 | − "Failed setting up TTM BO move entity (%d)\n", | |
| 2344 | − r); | |
| 2345 | − drm_sched_entity_destroy(&adev->mman.clear_entity.base); | |
| 2346 | − goto error_free_entity; | |
| 2392 | + "Failed setting up TTM BO move entity (%d)\n", r); | |
| 2393 | + goto error_free_clear_entity; | |
| 2347 | 2394 | } |
| 2348 | 2395 | } else { |
| 2349 | − drm_sched_entity_destroy(&adev->mman.default_entity.base); | |
| 2350 | − drm_sched_entity_destroy(&adev->mman.clear_entity.base); | |
| 2351 | − drm_sched_entity_destroy(&adev->mman.move_entity.base); | |
| 2396 | + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, | |
| 2397 | + &adev->mman.default_entity); | |
| 2398 | + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, | |
| 2399 | + &adev->mman.clear_entity); | |
| 2400 | + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, | |
| 2401 | + &adev->mman.move_entity); | |
| 2352 | 2402 | /* Drop all the old fences since re-creating the scheduler entities |
| 2353 | 2403 | * will allocate new contexts. |
| 2354 | 2404 | */ |
| @@ -2365,8 +2415,12 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) · 10 unmodified lines | ||
| 2365 | 2415 | |
| 2366 | 2416 | return; |
| 2367 | 2417 | |
| 2368 | −error_free_entity: | |
| 2369 | − drm_sched_entity_destroy(&adev->mman.default_entity.base); | |
| 2418 | +error_free_clear_entity: | |
| 2419 | + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, | |
| 2420 | + &adev->mman.clear_entity); | |
| 2421 | +error_free_default_entity: | |
| 2422 | + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, | |
| 2423 | + &adev->mman.default_entity); | |
| 2370 | 2424 | } |
| 2371 | 2425 | |
| 2372 | 2426 | static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev, |
| @@ -2440,7 +2494,7 @@ int amdgpu_copy_buffer(struct amdgpu_device *adev, · 67 unmodified lines | ||
| 2440 | 2494 | byte_count -= cur_size_in_bytes; |
| 2441 | 2495 | } |
| 2442 | 2496 | |
| 2443 | − *fence = amdgpu_ttm_job_submit(adev, job, num_dw); | |
| 2497 | + *fence = amdgpu_ttm_job_submit(adev, entity, job, num_dw); | |
| 2444 | 2498 | |
| 2445 | 2499 | return 0; |
| 2446 | 2500 | |
| @@ -2483,7 +2537,7 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_device *adev, · 36 unmodified lines | ||
| 2483 | 2537 | byte_count -= cur_size; |
| 2484 | 2538 | } |
| 2485 | 2539 | |
| 2486 | − *fence = amdgpu_ttm_job_submit(adev, job, num_dw); | |
| 2540 | + *fence = amdgpu_ttm_job_submit(adev, entity, job, num_dw); | |
| 2487 | 2541 | return 0; |
| 2488 | 2542 | } |
| 2489 | 2543 | |
| @@ -2503,6 +2557,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 13 unmodified lines | ||
| 2503 | 2557 | struct dma_fence **fence) |
| 2504 | 2558 | { |
| 2505 | 2559 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
| 2560 | + struct amdgpu_ttm_buffer_entity *entity; | |
| 2506 | 2561 | struct amdgpu_res_cursor cursor; |
| 2507 | 2562 | u64 addr; |
| 2508 | 2563 | int r = 0; |
| @@ -2513,11 +2568,12 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 4 unmodified lines | ||
| 2513 | 2568 | if (!fence) |
| 2514 | 2569 | return -EINVAL; |
| 2515 | 2570 | |
| 2571 | + entity = &adev->mman.clear_entity; | |
| 2516 | 2572 | *fence = dma_fence_get_stub(); |
| 2517 | 2573 | |
| 2518 | 2574 | amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); |
| 2519 | 2575 | |
| 2520 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 2576 | + mutex_lock(&entity->lock); | |
| 2521 | 2577 | while (cursor.remaining) { |
| 2522 | 2578 | struct dma_fence *next = NULL; |
| 2523 | 2579 | u64 size; |
| @@ -2530,13 +2586,12 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 6 unmodified lines | ||
| 2530 | 2586 | /* Never clear more than 256MiB at once to avoid timeouts */ |
| 2531 | 2587 | size = min(cursor.size, 256ULL << 20); |
| 2532 | 2588 | |
| 2533 | − r = amdgpu_ttm_map_buffer(&adev->mman.clear_entity, | |
| 2534 | − &bo->tbo, bo->tbo.resource, &cursor, | |
| 2535 | − 1, false, &size, &addr); | |
| 2589 | + r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &cursor, | |
| 2590 | + 0, false, &size, &addr); | |
| 2536 | 2591 | if (r) |
| 2537 | 2592 | goto err; |
| 2538 | 2593 | |
| 2539 | − r = amdgpu_ttm_fill_mem(adev, &adev->mman.clear_entity, 0, addr, size, resv, | |
| 2594 | + r = amdgpu_ttm_fill_mem(adev, entity, 0, addr, size, resv, | |
| 2540 | 2595 | &next, true, |
| 2541 | 2596 | AMDGPU_KERNEL_JOB_ID_TTM_CLEAR_BUFFER); |
| 2542 | 2597 | if (r) |
| @@ -2548,7 +2603,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 5 unmodified lines | ||
| 2548 | 2603 | amdgpu_res_next(&cursor, size); |
| 2549 | 2604 | } |
| 2550 | 2605 | err: |
| 2551 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 2606 | + mutex_unlock(&entity->lock); | |
| 2552 | 2607 | |
| 2553 | 2608 | return r; |
| 2554 | 2609 | } |
| @@ -2573,7 +2628,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, · 18 unmodified lines | ||
| 2573 | 2628 | |
| 2574 | 2629 | amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst); |
| 2575 | 2630 | |
| 2576 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 2631 | + mutex_lock(&entity->lock); | |
| 2577 | 2632 | while (dst.remaining) { |
| 2578 | 2633 | struct dma_fence *next; |
| 2579 | 2634 | uint64_t cur_size, to; |
| @@ -2582,7 +2637,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, · 2 unmodified lines | ||
| 2582 | 2637 | cur_size = min(dst.size, 256ULL << 20); |
| 2583 | 2638 | |
| 2584 | 2639 | r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &dst, |
| 2585 | − 1, false, &cur_size, &to); | |
| 2640 | + 0, false, &cur_size, &to); | |
| 2586 | 2641 | if (r) |
| 2587 | 2642 | goto error; |
| 2588 | 2643 | |
| @@ -2598,7 +2653,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, · 9 unmodified lines | ||
| 2598 | 2653 | amdgpu_res_next(&dst, cur_size); |
| 2599 | 2654 | } |
| 2600 | 2655 | error: |
| 2601 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 2656 | + mutex_unlock(&entity->lock); | |
| 2602 | 2657 | if (f) |
| 2603 | 2658 | *f = dma_fence_get(fence); |
| 2604 | 2659 | dma_fence_put(fence); |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <drm/ttm/ttm_placement.h> |
| 30 | 30 | #include "amdgpu_vram_mgr.h" |
| 31 | 31 | #include "amdgpu_hmm.h" |
| 32 | +#include "amdgpu_gmc.h" | |
| 32 | 33 | |
| 33 | 34 | #define AMDGPU_PL_GDS (TTM_PL_PRIV + 0) |
| 34 | 35 | #define AMDGPU_PL_GWS (TTM_PL_PRIV + 1) |
| @@ -38,8 +39,7 @@ · 3 unmodified lines | ||
| 38 | 39 | #define AMDGPU_PL_MMIO_REMAP (TTM_PL_PRIV + 5) |
| 39 | 40 | #define __AMDGPU_PL_NUM (TTM_PL_PRIV + 6) |
| 40 | 41 | |
| 41 | −#define AMDGPU_GTT_MAX_TRANSFER_SIZE 512 | |
| 42 | −#define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2 | |
| 42 | +#define AMDGPU_GTT_MAX_TRANSFER_SIZE 1024 | |
| 43 | 43 | |
| 44 | 44 | extern const struct attribute_group amdgpu_vram_mgr_attr_group; |
| 45 | 45 | extern const struct attribute_group amdgpu_gtt_mgr_attr_group; |
| @@ -54,6 +54,9 @@ struct amdgpu_gtt_mgr { · 8 unmodified lines | ||
| 54 | 54 | |
| 55 | 55 | struct amdgpu_ttm_buffer_entity { |
| 56 | 56 | struct drm_sched_entity base; |
| 57 | + struct mutex lock; | |
| 58 | + struct drm_mm_node gart_node; | |
| 59 | + u64 gart_window_offs[2]; | |
| 57 | 60 | }; |
| 58 | 61 | |
| 59 | 62 | struct amdgpu_mman { |
| @@ -67,8 +70,7 @@ struct amdgpu_mman { · 7 unmodified lines | ||
| 67 | 70 | struct amdgpu_ring *buffer_funcs_ring; |
| 68 | 71 | bool buffer_funcs_enabled; |
| 69 | 72 | |
| 70 | − struct mutex gtt_window_lock; | |
| 71 | − | |
| 73 | + /* @default_entity: for workarounds, has no gart windows */ | |
| 72 | 74 | struct amdgpu_ttm_buffer_entity default_entity; |
| 73 | 75 | struct amdgpu_ttm_buffer_entity clear_entity; |
| 74 | 76 | struct amdgpu_ttm_buffer_entity move_entity; |
| @@ -205,6 +207,27 @@ static inline int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, · 130 unmodified lines | ||
| 205 | 207 | } |
| 206 | 208 | #endif |
| 207 | 209 | |
| 210 | +/** | |
| 211 | + * amdgpu_compute_gart_address() - Returns GART address of an entity's window | |
| 212 | + * @gmc: The &struct amdgpu_gmc instance to use | |
| 213 | + * @entity: The &struct amdgpu_ttm_buffer_entity owning the GART window | |
| 214 | + * @index: The window to use (must be 0 or 1) | |
| 215 | + */ | |
| 216 | +static inline u64 amdgpu_compute_gart_address(struct amdgpu_gmc *gmc, | |
| 217 | + struct amdgpu_ttm_buffer_entity *entity, | |
| 218 | + int index) | |
| 219 | +{ | |
| 220 | + return gmc->gart_start + entity->gart_window_offs[index]; | |
| 221 | +} | |
| 222 | + | |
| 223 | +/** | |
| 224 | + * amdgpu_gtt_node_to_byte_offset() - Returns a byte offset of a gtt node | |
| 225 | + */ | |
| 226 | +static inline u64 amdgpu_gtt_node_to_byte_offset(const struct drm_mm_node *gtt_node) | |
| 227 | +{ | |
| 228 | + return gtt_node->start * (u64)PAGE_SIZE; | |
| 229 | +} | |
| 230 | + | |
| 208 | 231 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct amdgpu_hmm_range *range); |
| 209 | 232 | int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo, |
| 210 | 233 | uint64_t *user_addr); |
| @@ -446,8 +446,7 @@ static int amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue) · 445 unmodified lines | ||
| 446 | 446 | return ret; |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | −static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue, | |
| 450 | − int queue_id) | |
| 449 | +static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue) | |
| 451 | 450 | { |
| 452 | 451 | struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr; |
| 453 | 452 | struct amdgpu_device *adev = uq_mgr->adev; |
| @@ -461,7 +460,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue, · 7 unmodified lines | ||
| 461 | 460 | uq_funcs->mqd_destroy(queue); |
| 462 | 461 | amdgpu_userq_fence_driver_free(queue); |
| 463 | 462 | /* Use interrupt-safe locking since IRQ handlers may access these XArrays */ |
| 464 | − xa_erase_irq(&uq_mgr->userq_xa, (unsigned long)queue_id); | |
| 465 | 463 | xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index); |
| 466 | 464 | queue->userq_mgr = NULL; |
| 467 | 465 | list_del(&queue->userq_va_list); |
| @@ -470,12 +468,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue, · 2 unmodified lines | ||
| 470 | 468 | up_read(&adev->reset_domain->sem); |
| 471 | 469 | } |
| 472 | 470 | |
| 473 | −static struct amdgpu_usermode_queue * | |
| 474 | −amdgpu_userq_find(struct amdgpu_userq_mgr *uq_mgr, int qid) | |
| 475 | −{ | |
| 476 | − return xa_load(&uq_mgr->userq_xa, qid); | |
| 477 | −} | |
| 478 | − | |
| 479 | 471 | void |
| 480 | 472 | amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr, |
| 481 | 473 | struct amdgpu_eviction_fence_mgr *evf_mgr) |
| @@ -625,22 +617,13 @@ unref_bo: · 143 unmodified lines | ||
| 625 | 617 | } |
| 626 | 618 | |
| 627 | 619 | static int |
| 628 | −amdgpu_userq_destroy(struct drm_file *filp, int queue_id) | |
| 620 | +amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue) | |
| 629 | 621 | { |
| 630 | − struct amdgpu_fpriv *fpriv = filp->driver_priv; | |
| 631 | − struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr; | |
| 632 | 622 | struct amdgpu_device *adev = uq_mgr->adev; |
| 633 | − struct amdgpu_usermode_queue *queue; | |
| 634 | 623 | int r = 0; |
| 635 | 624 | |
| 636 | 625 | cancel_delayed_work_sync(&uq_mgr->resume_work); |
| 637 | 626 | mutex_lock(&uq_mgr->userq_mutex); |
| 638 | − queue = amdgpu_userq_find(uq_mgr, queue_id); | |
| 639 | − if (!queue) { | |
| 640 | − drm_dbg_driver(adev_to_drm(uq_mgr->adev), "Invalid queue id to destroy\n"); | |
| 641 | − mutex_unlock(&uq_mgr->userq_mutex); | |
| 642 | − return -EINVAL; | |
| 643 | − } | |
| 644 | 627 | amdgpu_userq_wait_for_last_fence(queue); |
| 645 | 628 | /* Cancel any pending hang detection work and cleanup */ |
| 646 | 629 | if (queue->hang_detect_fence) { |
| @@ -672,7 +655,7 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id) · 25 unmodified lines | ||
| 672 | 655 | drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n"); |
| 673 | 656 | queue->state = AMDGPU_USERQ_STATE_HUNG; |
| 674 | 657 | } |
| 675 | − amdgpu_userq_cleanup(queue, queue_id); | |
| 658 | + amdgpu_userq_cleanup(queue); | |
| 676 | 659 | mutex_unlock(&uq_mgr->userq_mutex); |
| 677 | 660 | |
| 678 | 661 | pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); |
| @@ -680,6 +663,37 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id) · 1 unmodified line | ||
| 680 | 663 | return r; |
| 681 | 664 | } |
| 682 | 665 | |
| 666 | +static void amdgpu_userq_kref_destroy(struct kref *kref) | |
| 667 | +{ | |
| 668 | + int r; | |
| 669 | + struct amdgpu_usermode_queue *queue = | |
| 670 | + container_of(kref, struct amdgpu_usermode_queue, refcount); | |
| 671 | + struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr; | |
| 672 | + | |
| 673 | + r = amdgpu_userq_destroy(uq_mgr, queue); | |
| 674 | + if (r) | |
| 675 | + drm_file_err(uq_mgr->file, "Failed to destroy usermode queue %d\n", r); | |
| 676 | +} | |
| 677 | + | |
| 678 | +struct amdgpu_usermode_queue *amdgpu_userq_get(struct amdgpu_userq_mgr *uq_mgr, u32 qid) | |
| 679 | +{ | |
| 680 | + struct amdgpu_usermode_queue *queue; | |
| 681 | + | |
| 682 | + xa_lock(&uq_mgr->userq_xa); | |
| 683 | + queue = xa_load(&uq_mgr->userq_xa, qid); | |
| 684 | + if (queue) | |
| 685 | + kref_get(&queue->refcount); | |
| 686 | + xa_unlock(&uq_mgr->userq_xa); | |
| 687 | + | |
| 688 | + return queue; | |
| 689 | +} | |
| 690 | + | |
| 691 | +void amdgpu_userq_put(struct amdgpu_usermode_queue *queue) | |
| 692 | +{ | |
| 693 | + if (queue) | |
| 694 | + kref_put(&queue->refcount, amdgpu_userq_kref_destroy); | |
| 695 | +} | |
| 696 | + | |
| 683 | 697 | static int amdgpu_userq_priority_permit(struct drm_file *filp, |
| 684 | 698 | int priority) |
| 685 | 699 | { |
| @@ -834,6 +848,9 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args) · 148 unmodified lines | ||
| 834 | 848 | goto unlock; |
| 835 | 849 | } |
| 836 | 850 | |
| 851 | + /* drop this refcount during queue destroy */ | |
| 852 | + kref_init(&queue->refcount); | |
| 853 | + | |
| 837 | 854 | /* Wait for mode-1 reset to complete */ |
| 838 | 855 | down_read(&adev->reset_domain->sem); |
| 839 | 856 | r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL)); |
| @@ -985,7 +1002,9 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data, · 145 unmodified lines | ||
| 985 | 1002 | struct drm_file *filp) |
| 986 | 1003 | { |
| 987 | 1004 | union drm_amdgpu_userq *args = data; |
| 988 | − int r; | |
| 1005 | + struct amdgpu_fpriv *fpriv = filp->driver_priv; | |
| 1006 | + struct amdgpu_usermode_queue *queue; | |
| 1007 | + int r = 0; | |
| 989 | 1008 | |
| 990 | 1009 | if (!amdgpu_userq_enabled(dev)) |
| 991 | 1010 | return -ENOTSUPP; |
| @@ -1000,11 +1019,16 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data, · 8 unmodified lines | ||
| 1000 | 1019 | drm_file_err(filp, "Failed to create usermode queue\n"); |
| 1001 | 1020 | break; |
| 1002 | 1021 | |
| 1003 | − case AMDGPU_USERQ_OP_FREE: | |
| 1004 | − r = amdgpu_userq_destroy(filp, args->in.queue_id); | |
| 1005 | − if (r) | |
| 1006 | − drm_file_err(filp, "Failed to destroy usermode queue\n"); | |
| 1022 | + case AMDGPU_USERQ_OP_FREE: { | |
| 1023 | + xa_lock(&fpriv->userq_mgr.userq_xa); | |
| 1024 | + queue = __xa_erase(&fpriv->userq_mgr.userq_xa, args->in.queue_id); | |
| 1025 | + xa_unlock(&fpriv->userq_mgr.userq_xa); | |
| 1026 | + if (!queue) | |
| 1027 | + return -ENOENT; | |
| 1028 | + | |
| 1029 | + amdgpu_userq_put(queue); | |
| 1007 | 1030 | break; |
| 1031 | + } | |
| 1008 | 1032 | |
| 1009 | 1033 | default: |
| 1010 | 1034 | drm_dbg_driver(dev, "Invalid user queue op specified: %d\n", args->in.op); |
| @@ -1023,16 +1047,23 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr) · 12 unmodified lines | ||
| 1023 | 1047 | |
| 1024 | 1048 | /* Resume all the queues for this process */ |
| 1025 | 1049 | xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { |
| 1050 | + queue = amdgpu_userq_get(uq_mgr, queue_id); | |
| 1051 | + if (!queue) | |
| 1052 | + continue; | |
| 1053 | + | |
| 1026 | 1054 | if (!amdgpu_userq_buffer_vas_mapped(queue)) { |
| 1027 | 1055 | drm_file_err(uq_mgr->file, |
| 1028 | 1056 | "trying restore queue without va mapping\n"); |
| 1029 | 1057 | queue->state = AMDGPU_USERQ_STATE_INVALID_VA; |
| 1058 | + amdgpu_userq_put(queue); | |
| 1030 | 1059 | continue; |
| 1031 | 1060 | } |
| 1032 | 1061 | |
| 1033 | 1062 | r = amdgpu_userq_restore_helper(queue); |
| 1034 | 1063 | if (r) |
| 1035 | 1064 | ret = r; |
| 1065 | + | |
| 1066 | + amdgpu_userq_put(queue); | |
| 1036 | 1067 | } |
| 1037 | 1068 | |
| 1038 | 1069 | if (ret) |
| @@ -1266,9 +1297,13 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr) · 227 unmodified lines | ||
| 1266 | 1297 | amdgpu_userq_detect_and_reset_queues(uq_mgr); |
| 1267 | 1298 | /* Try to unmap all the queues in this process ctx */ |
| 1268 | 1299 | xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { |
| 1300 | + queue = amdgpu_userq_get(uq_mgr, queue_id); | |
| 1301 | + if (!queue) | |
| 1302 | + continue; | |
| 1269 | 1303 | r = amdgpu_userq_preempt_helper(queue); |
| 1270 | 1304 | if (r) |
| 1271 | 1305 | ret = r; |
| 1306 | + amdgpu_userq_put(queue); | |
| 1272 | 1307 | } |
| 1273 | 1308 | |
| 1274 | 1309 | if (ret) |
| @@ -1301,16 +1336,24 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr) · 26 unmodified lines | ||
| 1301 | 1336 | int ret; |
| 1302 | 1337 | |
| 1303 | 1338 | xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { |
| 1339 | + queue = amdgpu_userq_get(uq_mgr, queue_id); | |
| 1340 | + if (!queue) | |
| 1341 | + continue; | |
| 1342 | + | |
| 1304 | 1343 | struct dma_fence *f = queue->last_fence; |
| 1305 | 1344 | |
| 1306 | − if (!f || dma_fence_is_signaled(f)) | |
| 1345 | + if (!f || dma_fence_is_signaled(f)) { | |
| 1346 | + amdgpu_userq_put(queue); | |
| 1307 | 1347 | continue; |
| 1348 | + } | |
| 1308 | 1349 | ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100)); |
| 1309 | 1350 | if (ret <= 0) { |
| 1310 | 1351 | drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n", |
| 1311 | 1352 | f->context, f->seqno); |
| 1353 | + amdgpu_userq_put(queue); | |
| 1312 | 1354 | return -ETIMEDOUT; |
| 1313 | 1355 | } |
| 1356 | + amdgpu_userq_put(queue); | |
| 1314 | 1357 | } |
| 1315 | 1358 | |
| 1316 | 1359 | return 0; |
| @@ -1361,20 +1404,23 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *f · 44 unmodified lines | ||
| 1361 | 1404 | void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr) |
| 1362 | 1405 | { |
| 1363 | 1406 | struct amdgpu_usermode_queue *queue; |
| 1364 | − unsigned long queue_id; | |
| 1407 | + unsigned long queue_id = 0; | |
| 1408 | + | |
| 1409 | + for (;;) { | |
| 1410 | + xa_lock(&userq_mgr->userq_xa); | |
| 1411 | + queue = xa_find(&userq_mgr->userq_xa, &queue_id, ULONG_MAX, | |
| 1412 | + XA_PRESENT); | |
| 1413 | + if (queue) | |
| 1414 | + __xa_erase(&userq_mgr->userq_xa, queue_id); | |
| 1415 | + xa_unlock(&userq_mgr->userq_xa); | |
| 1365 | 1416 | |
| 1366 | − cancel_delayed_work_sync(&userq_mgr->resume_work); | |
| 1417 | + if (!queue) | |
| 1418 | + break; | |
| 1367 | 1419 | |
| 1368 | − mutex_lock(&userq_mgr->userq_mutex); | |
| 1369 | − amdgpu_userq_detect_and_reset_queues(userq_mgr); | |
| 1370 | − xa_for_each(&userq_mgr->userq_xa, queue_id, queue) { | |
| 1371 | − amdgpu_userq_wait_for_last_fence(queue); | |
| 1372 | − amdgpu_userq_unmap_helper(queue); | |
| 1373 | − amdgpu_userq_cleanup(queue, queue_id); | |
| 1420 | + amdgpu_userq_put(queue); | |
| 1374 | 1421 | } |
| 1375 | 1422 | |
| 1376 | 1423 | xa_destroy(&userq_mgr->userq_xa); |
| 1377 | − mutex_unlock(&userq_mgr->userq_mutex); | |
| 1378 | 1424 | mutex_destroy(&userq_mgr->userq_mutex); |
| 1379 | 1425 | } |
| 1380 | 1426 | |
| @@ -74,6 +74,7 @@ struct amdgpu_usermode_queue { · 73 unmodified lines | ||
| 74 | 74 | struct dentry *debugfs_queue; |
| 75 | 75 | struct delayed_work hang_detect_work; |
| 76 | 76 | struct dma_fence *hang_detect_fence; |
| 77 | + struct kref refcount; | |
| 77 | 78 | |
| 78 | 79 | struct list_head userq_va_list; |
| 79 | 80 | }; |
| @@ -81,6 +82,8 @@ struct amdgpu_usermode_queue { · 1 unmodified line | ||
| 81 | 82 | struct amdgpu_userq_funcs { |
| 82 | 83 | int (*mqd_create)(struct amdgpu_usermode_queue *queue, |
| 83 | 84 | struct drm_amdgpu_userq_in *args); |
| 85 | + int (*mqd_update)(struct amdgpu_usermode_queue *queue, | |
| 86 | + struct drm_amdgpu_userq_in *args); | |
| 84 | 87 | void (*mqd_destroy)(struct amdgpu_usermode_queue *uq); |
| 85 | 88 | int (*unmap)(struct amdgpu_usermode_queue *queue); |
| 86 | 89 | int (*map)(struct amdgpu_usermode_queue *queue); |
| @@ -112,6 +115,9 @@ struct amdgpu_db_info { · 25 unmodified lines | ||
| 112 | 115 | struct amdgpu_userq_obj *db_obj; |
| 113 | 116 | }; |
| 114 | 117 | |
| 118 | +struct amdgpu_usermode_queue *amdgpu_userq_get(struct amdgpu_userq_mgr *uq_mgr, u32 qid); | |
| 119 | +void amdgpu_userq_put(struct amdgpu_usermode_queue *queue); | |
| 120 | + | |
| 115 | 121 | int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); |
| 116 | 122 | |
| 117 | 123 | int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv, |
| @@ -461,33 +461,31 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data, · 460 unmodified lines | ||
| 461 | 461 | struct drm_file *filp) |
| 462 | 462 | { |
| 463 | 463 | struct amdgpu_device *adev = drm_to_adev(dev); |
| 464 | + struct drm_amdgpu_userq_signal *args = data; | |
| 465 | + const unsigned int num_write_bo_handles = args->num_bo_write_handles; | |
| 466 | + const unsigned int num_read_bo_handles = args->num_bo_read_handles; | |
| 464 | 467 | struct amdgpu_fpriv *fpriv = filp->driver_priv; |
| 465 | 468 | struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr; |
| 466 | − struct drm_amdgpu_userq_signal *args = data; | |
| 467 | − struct drm_gem_object **gobj_write = NULL; | |
| 468 | − struct drm_gem_object **gobj_read = NULL; | |
| 469 | − struct amdgpu_usermode_queue *queue; | |
| 469 | + struct drm_gem_object **gobj_write, **gobj_read; | |
| 470 | + u32 *syncobj_handles, num_syncobj_handles; | |
| 470 | 471 | struct amdgpu_userq_fence *userq_fence; |
| 472 | + struct amdgpu_usermode_queue *queue = NULL; | |
| 471 | 473 | struct drm_syncobj **syncobj = NULL; |
| 472 | − u32 *bo_handles_write, num_write_bo_handles; | |
| 473 | − u32 *syncobj_handles, num_syncobj_handles; | |
| 474 | − u32 *bo_handles_read, num_read_bo_handles; | |
| 475 | − int r, i, entry, rentry, wentry; | |
| 476 | 474 | struct dma_fence *fence; |
| 477 | 475 | struct drm_exec exec; |
| 476 | + int r, i, entry; | |
| 478 | 477 | u64 wptr; |
| 479 | 478 | |
| 480 | 479 | if (!amdgpu_userq_enabled(dev)) |
| 481 | 480 | return -ENOTSUPP; |
| 482 | 481 | |
| 483 | − if (args->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES || | |
| 484 | − args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || | |
| 482 | + if (args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || | |
| 485 | 483 | args->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES) |
| 486 | 484 | return -EINVAL; |
| 487 | 485 | |
| 488 | 486 | num_syncobj_handles = args->num_syncobj_handles; |
| 489 | − syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles), | |
| 490 | − size_mul(sizeof(u32), num_syncobj_handles)); | |
| 487 | + syncobj_handles = memdup_array_user(u64_to_user_ptr(args->syncobj_handles), | |
| 488 | + num_syncobj_handles, sizeof(u32)); | |
| 491 | 489 | if (IS_ERR(syncobj_handles)) |
| 492 | 490 | return PTR_ERR(syncobj_handles); |
| 493 | 491 | |
| @@ -506,54 +504,22 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data, · 12 unmodified lines | ||
| 506 | 504 | } |
| 507 | 505 | } |
| 508 | 506 | |
| 509 | − num_read_bo_handles = args->num_bo_read_handles; | |
| 510 | − bo_handles_read = memdup_user(u64_to_user_ptr(args->bo_read_handles), | |
| 511 | − sizeof(u32) * num_read_bo_handles); | |
| 512 | − if (IS_ERR(bo_handles_read)) { | |
| 513 | − r = PTR_ERR(bo_handles_read); | |
| 507 | + r = drm_gem_objects_lookup(filp, | |
| 508 | + u64_to_user_ptr(args->bo_read_handles), | |
| 509 | + num_read_bo_handles, | |
| 510 | + &gobj_read); | |
| 511 | + if (r) | |
| 514 | 512 | goto free_syncobj; |
| 515 | − } | |
| 516 | 513 | |
| 517 | − /* Array of pointers to the GEM read objects */ | |
| 518 | − gobj_read = kmalloc_array(num_read_bo_handles, sizeof(*gobj_read), GFP_KERNEL); | |
| 519 | − if (!gobj_read) { | |
| 520 | − r = -ENOMEM; | |
| 521 | − goto free_bo_handles_read; | |
| 522 | − } | |
| 523 | − | |
| 524 | − for (rentry = 0; rentry < num_read_bo_handles; rentry++) { | |
| 525 | − gobj_read[rentry] = drm_gem_object_lookup(filp, bo_handles_read[rentry]); | |
| 526 | − if (!gobj_read[rentry]) { | |
| 527 | − r = -ENOENT; | |
| 528 | − goto put_gobj_read; | |
| 529 | − } | |
| 530 | − } | |
| 531 | − | |
| 532 | − num_write_bo_handles = args->num_bo_write_handles; | |
| 533 | − bo_handles_write = memdup_user(u64_to_user_ptr(args->bo_write_handles), | |
| 534 | − sizeof(u32) * num_write_bo_handles); | |
| 535 | − if (IS_ERR(bo_handles_write)) { | |
| 536 | − r = PTR_ERR(bo_handles_write); | |
| 514 | + r = drm_gem_objects_lookup(filp, | |
| 515 | + u64_to_user_ptr(args->bo_write_handles), | |
| 516 | + num_write_bo_handles, | |
| 517 | + &gobj_write); | |
| 518 | + if (r) | |
| 537 | 519 | goto put_gobj_read; |
| 538 | − } | |
| 539 | − | |
| 540 | − /* Array of pointers to the GEM write objects */ | |
| 541 | − gobj_write = kmalloc_array(num_write_bo_handles, sizeof(*gobj_write), GFP_KERNEL); | |
| 542 | − if (!gobj_write) { | |
| 543 | − r = -ENOMEM; | |
| 544 | − goto free_bo_handles_write; | |
| 545 | − } | |
| 546 | − | |
| 547 | − for (wentry = 0; wentry < num_write_bo_handles; wentry++) { | |
| 548 | − gobj_write[wentry] = drm_gem_object_lookup(filp, bo_handles_write[wentry]); | |
| 549 | − if (!gobj_write[wentry]) { | |
| 550 | − r = -ENOENT; | |
| 551 | − goto put_gobj_write; | |
| 552 | − } | |
| 553 | − } | |
| 554 | 520 | |
| 555 | 521 | /* Retrieve the user queue */ |
| 556 | − queue = xa_load(&userq_mgr->userq_xa, args->queue_id); | |
| 522 | + queue = amdgpu_userq_get(userq_mgr, args->queue_id); | |
| 557 | 523 | if (!queue) { |
| 558 | 524 | r = -ENOENT; |
| 559 | 525 | goto put_gobj_write; |
| @@ -629,17 +595,13 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data, · 69 unmodified lines | ||
| 629 | 595 | exec_fini: |
| 630 | 596 | drm_exec_fini(&exec); |
| 631 | 597 | put_gobj_write: |
| 632 | − while (wentry-- > 0) | |
| 633 | − drm_gem_object_put(gobj_write[wentry]); | |
| 598 | + for (i = 0; i < num_write_bo_handles; i++) | |
| 599 | + drm_gem_object_put(gobj_write[i]); | |
| 634 | 600 | kfree(gobj_write); |
| 635 | −free_bo_handles_write: | |
| 636 | − kfree(bo_handles_write); | |
| 637 | 601 | put_gobj_read: |
| 638 | − while (rentry-- > 0) | |
| 639 | − drm_gem_object_put(gobj_read[rentry]); | |
| 602 | + for (i = 0; i < num_read_bo_handles; i++) | |
| 603 | + drm_gem_object_put(gobj_read[i]); | |
| 640 | 604 | kfree(gobj_read); |
| 641 | −free_bo_handles_read: | |
| 642 | − kfree(bo_handles_read); | |
| 643 | 605 | free_syncobj: |
| 644 | 606 | while (entry-- > 0) |
| 645 | 607 | if (syncobj[entry]) |
| @@ -648,98 +610,73 @@ free_syncobj: · 2 unmodified lines | ||
| 648 | 610 | free_syncobj_handles: |
| 649 | 611 | kfree(syncobj_handles); |
| 650 | 612 | |
| 613 | + if (queue) | |
| 614 | + amdgpu_userq_put(queue); | |
| 615 | + | |
| 651 | 616 | return r; |
| 652 | 617 | } |
| 653 | 618 | |
| 654 | 619 | int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, |
| 655 | 620 | struct drm_file *filp) |
| 656 | 621 | { |
| 657 | − u32 *syncobj_handles, *timeline_points, *timeline_handles, *bo_handles_read, *bo_handles_write; | |
| 658 | − u32 num_syncobj, num_read_bo_handles, num_write_bo_handles; | |
| 659 | − struct drm_amdgpu_userq_fence_info *fence_info = NULL; | |
| 660 | 622 | struct drm_amdgpu_userq_wait *wait_info = data; |
| 623 | + const unsigned int num_write_bo_handles = wait_info->num_bo_write_handles; | |
| 624 | + const unsigned int num_read_bo_handles = wait_info->num_bo_read_handles; | |
| 625 | + struct drm_amdgpu_userq_fence_info *fence_info = NULL; | |
| 661 | 626 | struct amdgpu_fpriv *fpriv = filp->driver_priv; |
| 662 | 627 | struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr; |
| 663 | − struct amdgpu_usermode_queue *waitq; | |
| 664 | − struct drm_gem_object **gobj_write; | |
| 665 | − struct drm_gem_object **gobj_read; | |
| 628 | + struct drm_gem_object **gobj_write, **gobj_read; | |
| 629 | + u32 *timeline_points, *timeline_handles; | |
| 630 | + struct amdgpu_usermode_queue *waitq = NULL; | |
| 631 | + u32 *syncobj_handles, num_syncobj; | |
| 666 | 632 | struct dma_fence **fences = NULL; |
| 667 | 633 | u16 num_points, num_fences = 0; |
| 668 | − int r, i, rentry, wentry, cnt; | |
| 669 | 634 | struct drm_exec exec; |
| 635 | + int r, i, cnt; | |
| 670 | 636 | |
| 671 | 637 | if (!amdgpu_userq_enabled(dev)) |
| 672 | 638 | return -ENOTSUPP; |
| 673 | 639 | |
| 674 | − if (wait_info->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES || | |
| 675 | − wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || | |
| 640 | + if (wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || | |
| 676 | 641 | wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES) |
| 677 | 642 | return -EINVAL; |
| 678 | 643 | |
| 679 | − num_read_bo_handles = wait_info->num_bo_read_handles; | |
| 680 | − bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles), | |
| 681 | − size_mul(sizeof(u32), num_read_bo_handles)); | |
| 682 | − if (IS_ERR(bo_handles_read)) | |
| 683 | − return PTR_ERR(bo_handles_read); | |
| 684 | − | |
| 685 | − num_write_bo_handles = wait_info->num_bo_write_handles; | |
| 686 | − bo_handles_write = memdup_user(u64_to_user_ptr(wait_info->bo_write_handles), | |
| 687 | − size_mul(sizeof(u32), num_write_bo_handles)); | |
| 688 | − if (IS_ERR(bo_handles_write)) { | |
| 689 | − r = PTR_ERR(bo_handles_write); | |
| 690 | − goto free_bo_handles_read; | |
| 691 | − } | |
| 692 | − | |
| 693 | 644 | num_syncobj = wait_info->num_syncobj_handles; |
| 694 | − syncobj_handles = memdup_user(u64_to_user_ptr(wait_info->syncobj_handles), | |
| 695 | − size_mul(sizeof(u32), num_syncobj)); | |
| 696 | − if (IS_ERR(syncobj_handles)) { | |
| 697 | − r = PTR_ERR(syncobj_handles); | |
| 698 | − goto free_bo_handles_write; | |
| 699 | − } | |
| 645 | + syncobj_handles = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_handles), | |
| 646 | + num_syncobj, sizeof(u32)); | |
| 647 | + if (IS_ERR(syncobj_handles)) | |
| 648 | + return PTR_ERR(syncobj_handles); | |
| 649 | + | |
| 700 | 650 | |
| 701 | 651 | num_points = wait_info->num_syncobj_timeline_handles; |
| 702 | − timeline_handles = memdup_user(u64_to_user_ptr(wait_info->syncobj_timeline_handles), | |
| 703 | − sizeof(u32) * num_points); | |
| 652 | + timeline_handles = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_handles), | |
| 653 | + num_points, sizeof(u32)); | |
| 704 | 654 | if (IS_ERR(timeline_handles)) { |
| 705 | 655 | r = PTR_ERR(timeline_handles); |
| 706 | 656 | goto free_syncobj_handles; |
| 707 | 657 | } |
| 708 | 658 | |
| 709 | − timeline_points = memdup_user(u64_to_user_ptr(wait_info->syncobj_timeline_points), | |
| 710 | − sizeof(u32) * num_points); | |
| 659 | + timeline_points = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_points), | |
| 660 | + num_points, sizeof(u32)); | |
| 661 | + | |
| 711 | 662 | if (IS_ERR(timeline_points)) { |
| 712 | 663 | r = PTR_ERR(timeline_points); |
| 713 | 664 | goto free_timeline_handles; |
| 714 | 665 | } |
| 715 | 666 | |
| 716 | − gobj_read = kmalloc_array(num_read_bo_handles, sizeof(*gobj_read), GFP_KERNEL); | |
| 717 | − if (!gobj_read) { | |
| 718 | − r = -ENOMEM; | |
| 667 | + r = drm_gem_objects_lookup(filp, | |
| 668 | + u64_to_user_ptr(wait_info->bo_read_handles), | |
| 669 | + num_read_bo_handles, | |
| 670 | + &gobj_read); | |
| 671 | + if (r) | |
| 719 | 672 | goto free_timeline_points; |
| 720 | − } | |
| 721 | − | |
| 722 | − for (rentry = 0; rentry < num_read_bo_handles; rentry++) { | |
| 723 | − gobj_read[rentry] = drm_gem_object_lookup(filp, bo_handles_read[rentry]); | |
| 724 | − if (!gobj_read[rentry]) { | |
| 725 | − r = -ENOENT; | |
| 726 | − goto put_gobj_read; | |
| 727 | − } | |
| 728 | − } | |
| 729 | 673 | |
| 730 | − gobj_write = kmalloc_array(num_write_bo_handles, sizeof(*gobj_write), GFP_KERNEL); | |
| 731 | − if (!gobj_write) { | |
| 732 | − r = -ENOMEM; | |
| 674 | + r = drm_gem_objects_lookup(filp, | |
| 675 | + u64_to_user_ptr(wait_info->bo_write_handles), | |
| 676 | + num_write_bo_handles, | |
| 677 | + &gobj_write); | |
| 678 | + if (r) | |
| 733 | 679 | goto put_gobj_read; |
| 734 | − } | |
| 735 | − | |
| 736 | − for (wentry = 0; wentry < num_write_bo_handles; wentry++) { | |
| 737 | − gobj_write[wentry] = drm_gem_object_lookup(filp, bo_handles_write[wentry]); | |
| 738 | − if (!gobj_write[wentry]) { | |
| 739 | − r = -ENOENT; | |
| 740 | − goto put_gobj_write; | |
| 741 | − } | |
| 742 | − } | |
| 743 | 680 | |
| 744 | 681 | drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, |
| 745 | 682 | (num_read_bo_handles + num_write_bo_handles)); |
| @@ -926,7 +863,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, · 180 unmodified lines | ||
| 926 | 863 | */ |
| 927 | 864 | num_fences = dma_fence_dedup_array(fences, num_fences); |
| 928 | 865 | |
| 929 | − waitq = xa_load(&userq_mgr->userq_xa, wait_info->waitq_id); | |
| 866 | + waitq = amdgpu_userq_get(userq_mgr, wait_info->waitq_id); | |
| 930 | 867 | if (!waitq) { |
| 931 | 868 | r = -EINVAL; |
| 932 | 869 | goto free_fences; |
| @@ -983,43 +920,25 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, · 50 unmodified lines | ||
| 983 | 920 | r = -EFAULT; |
| 984 | 921 | goto free_fences; |
| 985 | 922 | } |
| 986 | − | |
| 987 | − kfree(fences); | |
| 988 | − kfree(fence_info); | |
| 989 | 923 | } |
| 990 | 924 | |
| 991 | − drm_exec_fini(&exec); | |
| 992 | − for (i = 0; i < num_read_bo_handles; i++) | |
| 993 | − drm_gem_object_put(gobj_read[i]); | |
| 994 | − kfree(gobj_read); | |
| 995 | − | |
| 996 | − for (i = 0; i < num_write_bo_handles; i++) | |
| 997 | − drm_gem_object_put(gobj_write[i]); | |
| 998 | − kfree(gobj_write); | |
| 999 | − | |
| 1000 | − kfree(timeline_points); | |
| 1001 | − kfree(timeline_handles); | |
| 1002 | − kfree(syncobj_handles); | |
| 1003 | − kfree(bo_handles_write); | |
| 1004 | − kfree(bo_handles_read); | |
| 1005 | − | |
| 1006 | − return 0; | |
| 1007 | − | |
| 1008 | 925 | free_fences: |
| 1009 | − while (num_fences-- > 0) | |
| 1010 | − dma_fence_put(fences[num_fences]); | |
| 1011 | − kfree(fences); | |
| 926 | + if (fences) { | |
| 927 | + while (num_fences-- > 0) | |
| 928 | + dma_fence_put(fences[num_fences]); | |
| 929 | + kfree(fences); | |
| 930 | + } | |
| 1012 | 931 | free_fence_info: |
| 1013 | 932 | kfree(fence_info); |
| 1014 | 933 | exec_fini: |
| 1015 | 934 | drm_exec_fini(&exec); |
| 1016 | 935 | put_gobj_write: |
| 1017 | − while (wentry-- > 0) | |
| 1018 | − drm_gem_object_put(gobj_write[wentry]); | |
| 936 | + for (i = 0; i < num_write_bo_handles; i++) | |
| 937 | + drm_gem_object_put(gobj_write[i]); | |
| 1019 | 938 | kfree(gobj_write); |
| 1020 | 939 | put_gobj_read: |
| 1021 | − while (rentry-- > 0) | |
| 1022 | − drm_gem_object_put(gobj_read[rentry]); | |
| 940 | + for (i = 0; i < num_read_bo_handles; i++) | |
| 941 | + drm_gem_object_put(gobj_read[i]); | |
| 1023 | 942 | kfree(gobj_read); |
| 1024 | 943 | free_timeline_points: |
| 1025 | 944 | kfree(timeline_points); |
| @@ -1027,10 +946,9 @@ free_timeline_handles: · 1 unmodified line | ||
| 1027 | 946 | kfree(timeline_handles); |
| 1028 | 947 | free_syncobj_handles: |
| 1029 | 948 | kfree(syncobj_handles); |
| 1030 | −free_bo_handles_write: | |
| 1031 | − kfree(bo_handles_write); | |
| 1032 | −free_bo_handles_read: | |
| 1033 | − kfree(bo_handles_read); | |
| 949 | + | |
| 950 | + if (waitq) | |
| 951 | + amdgpu_userq_put(waitq); | |
| 1034 | 952 | |
| 1035 | 953 | return r; |
| 1036 | 954 | } |
| @@ -450,24 +450,6 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp) · 449 unmodified lines | ||
| 450 | 450 | } |
| 451 | 451 | } |
| 452 | 452 | |
| 453 | −/** | |
| 454 | − * amdgpu_vce_required_gart_pages() - gets number of GART pages required by VCE | |
| 455 | − * | |
| 456 | − * @adev: amdgpu_device pointer | |
| 457 | − * | |
| 458 | − * Returns how many GART pages we need before GTT for the VCE IP block. | |
| 459 | − * For VCE1, see vce_v1_0_ensure_vcpu_bo_32bit_addr for details. | |
| 460 | − * For VCE2+, this is not needed so return zero. | |
| 461 | − */ | |
| 462 | −u32 amdgpu_vce_required_gart_pages(struct amdgpu_device *adev) | |
| 463 | −{ | |
| 464 | − /* VCE IP block not added yet, so can't use amdgpu_ip_version */ | |
| 465 | − if (adev->family == AMDGPU_FAMILY_SI) | |
| 466 | − return 512; | |
| 467 | − | |
| 468 | − return 0; | |
| 469 | −} | |
| 470 | − | |
| 471 | 453 | /** |
| 472 | 454 | * amdgpu_vce_get_create_msg - generate a VCE create msg |
| 473 | 455 | * |
| @@ -52,6 +52,7 @@ struct amdgpu_vce { · 51 unmodified lines | ||
| 52 | 52 | uint32_t srbm_soft_reset; |
| 53 | 53 | unsigned num_rings; |
| 54 | 54 | uint32_t keyselect; |
| 55 | + struct drm_mm_node gart_node; | |
| 55 | 56 | }; |
| 56 | 57 | |
| 57 | 58 | int amdgpu_vce_early_init(struct amdgpu_device *adev); |
| @@ -61,7 +62,6 @@ int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring) · 3 unmodified lines | ||
| 61 | 62 | int amdgpu_vce_suspend(struct amdgpu_device *adev); |
| 62 | 63 | int amdgpu_vce_resume(struct amdgpu_device *adev); |
| 63 | 64 | void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp); |
| 64 | −u32 amdgpu_vce_required_gart_pages(struct amdgpu_device *adev); | |
| 65 | 65 | int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, struct amdgpu_job *job, |
| 66 | 66 | struct amdgpu_ib *ib); |
| 67 | 67 | int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, |
| @@ -764,12 +764,9 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring, · 763 unmodified lines | ||
| 764 | 764 | * @need_pipe_sync: is pipe sync needed |
| 765 | 765 | * |
| 766 | 766 | * Emit a VM flush when it is necessary. |
| 767 | − * | |
| 768 | − * Returns: | |
| 769 | − * 0 on success, errno otherwise. | |
| 770 | 767 | */ |
| 771 | −int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, | |
| 772 | − bool need_pipe_sync) | |
| 768 | +void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, | |
| 769 | + bool need_pipe_sync) | |
| 773 | 770 | { |
| 774 | 771 | struct amdgpu_device *adev = ring->adev; |
| 775 | 772 | struct amdgpu_isolation *isolation = &adev->isolation[ring->xcp_id]; |
| @@ -783,8 +780,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, · 7 unmodified lines | ||
| 783 | 780 | bool cleaner_shader_needed = false; |
| 784 | 781 | bool pasid_mapping_needed = false; |
| 785 | 782 | struct dma_fence *fence = NULL; |
| 786 | − unsigned int patch; | |
| 787 | − int r; | |
| 783 | + unsigned int patch = 0; | |
| 788 | 784 | |
| 789 | 785 | if (amdgpu_vmid_had_gpu_reset(adev, id)) { |
| 790 | 786 | gds_switch_needed = true; |
| @@ -812,9 +808,20 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, · 21 unmodified lines | ||
| 812 | 808 | |
| 813 | 809 | if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync && |
| 814 | 810 | !cleaner_shader_needed) |
| 815 | − return 0; | |
| 811 | + return; | |
| 816 | 812 | |
| 817 | 813 | amdgpu_ring_ib_begin(ring); |
| 814 | + | |
| 815 | + /* There is no matching insert_end for this on purpose for the vm flush. | |
| 816 | + * The IB portion of the submission has both. Having multiple | |
| 817 | + * insert_start sequences is ok, but you can only have one insert_end | |
| 818 | + * per submission based on the way VCN FW works. For JPEG | |
| 819 | + * you can as many insert_start and insert_end sequences as you like as | |
| 820 | + * long as the rest of the packets come between start and end sequences. | |
| 821 | + */ | |
| 822 | + if (ring->funcs->insert_start) | |
| 823 | + ring->funcs->insert_start(ring); | |
| 824 | + | |
| 818 | 825 | if (ring->funcs->init_cond_exec) |
| 819 | 826 | patch = amdgpu_ring_init_cond_exec(ring, |
| 820 | 827 | ring->cond_exe_gpu_addr); |
| @@ -845,9 +852,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, · 24 unmodified lines | ||
| 845 | 852 | } |
| 846 | 853 | |
| 847 | 854 | if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) { |
| 848 | − r = amdgpu_fence_emit(ring, job->hw_vm_fence, 0); | |
| 849 | − if (r) | |
| 850 | − return r; | |
| 855 | + amdgpu_fence_emit(ring, job->hw_vm_fence, 0); | |
| 851 | 856 | fence = &job->hw_vm_fence->base; |
| 852 | 857 | /* get a ref for the job */ |
| 853 | 858 | dma_fence_get(fence); |
| @@ -892,7 +897,6 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, · 38 unmodified lines | ||
| 892 | 897 | } |
| 893 | 898 | |
| 894 | 899 | amdgpu_ring_ib_end(ring); |
| 895 | − return 0; | |
| 896 | 900 | } |
| 897 | 901 | |
| 898 | 902 | /** |
| @@ -3210,3 +3214,20 @@ void amdgpu_vm_print_task_info(struct amdgpu_device *adev, · 2311 unmodified lines | ||
| 3210 | 3214 | task_info->process_name, task_info->tgid, |
| 3211 | 3215 | task_info->task.comm, task_info->task.pid); |
| 3212 | 3216 | } |
| 3217 | + | |
| 3218 | +void amdgpu_sdma_set_vm_pte_scheds(struct amdgpu_device *adev, | |
| 3219 | + const struct amdgpu_vm_pte_funcs *vm_pte_funcs) | |
| 3220 | +{ | |
| 3221 | + struct drm_gpu_scheduler *sched; | |
| 3222 | + int i; | |
| 3223 | + | |
| 3224 | + for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 3225 | + if (adev->sdma.has_page_queue) | |
| 3226 | + sched = &adev->sdma.instance[i].page.sched; | |
| 3227 | + else | |
| 3228 | + sched = &adev->sdma.instance[i].ring.sched; | |
| 3229 | + adev->vm_manager.vm_pte_scheds[i] = sched; | |
| 3230 | + } | |
| 3231 | + adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 3232 | + adev->vm_manager.vm_pte_funcs = vm_pte_funcs; | |
| 3233 | +} | |
| @@ -513,7 +513,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 512 unmodified lines | ||
| 513 | 513 | struct ww_acquire_ctx *ticket, |
| 514 | 514 | int (*callback)(void *p, struct amdgpu_bo *bo), |
| 515 | 515 | void *param); |
| 516 | −int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync); | |
| 516 | +void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync); | |
| 517 | 517 | int amdgpu_vm_update_pdes(struct amdgpu_device *adev, |
| 518 | 518 | struct amdgpu_vm *vm, bool immediate); |
| 519 | 519 | int amdgpu_vm_clear_freed(struct amdgpu_device *adev, |
| @@ -338,7 +338,7 @@ static u32 xgmi_v6_4_get_link_status(struct amdgpu_device *adev, int global_link · 337 unmodified lines | ||
| 338 | 338 | if (!(adev->aid_mask & BIT(i))) |
| 339 | 339 | return U32_MAX; |
| 340 | 340 | |
| 341 | − addr += adev->asic_funcs->encode_ext_smn_addressing(i); | |
| 341 | + addr += amdgpu_reg_get_smn_base64(adev, XGMI_HWIP, i); | |
| 342 | 342 | |
| 343 | 343 | return RREG32_PCIE_EXT(addr); |
| 344 | 344 | } |
| @@ -347,6 +347,9 @@ int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num) · 2 unmodified lines | ||
| 347 | 347 | { |
| 348 | 348 | u32 xgmi_state_reg_val; |
| 349 | 349 | |
| 350 | + if (amdgpu_sriov_vf(adev)) | |
| 351 | + return AMDGPU_XGMI_LINK_NA; | |
| 352 | + | |
| 350 | 353 | if (adev->gmc.xgmi.num_physical_nodes <= 1) |
| 351 | 354 | return -EINVAL; |
| 352 | 355 | |
| @@ -1290,7 +1293,10 @@ static void amdgpu_xgmi_legacy_reset_ras_error_count(struct amdgpu_device *adev) · 937 unmodified lines | ||
| 1290 | 1293 | |
| 1291 | 1294 | static void __xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst, u64 mca_base) |
| 1292 | 1295 | { |
| 1293 | − WREG64_MCA(xgmi_inst, mca_base, ACA_REG_IDX_STATUS, 0ULL); | |
| 1296 | + uint64_t smn_base = | |
| 1297 | + amdgpu_reg_get_smn_base64(adev, XGMI_HWIP, xgmi_inst); | |
| 1298 | + | |
| 1299 | + WREG64_MCA(smn_base, mca_base, ACA_REG_IDX_STATUS, 0ULL); | |
| 1294 | 1300 | } |
| 1295 | 1301 | |
| 1296 | 1302 | static void xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst) |
| @@ -1500,6 +1506,7 @@ static void __xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, struct a · 203 unmodified lines | ||
| 1500 | 1506 | u64 mca_base, struct ras_err_data *err_data) |
| 1501 | 1507 | { |
| 1502 | 1508 | int xgmi_inst = mcm_info->die_id; |
| 1509 | + uint64_t smn_base; | |
| 1503 | 1510 | u64 status = 0; |
| 1504 | 1511 | |
| 1505 | 1512 | status = RREG64_MCA(xgmi_inst, mca_base, ACA_REG_IDX_STATUS); |
| @@ -1516,8 +1523,8 @@ static void __xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, struct a · 10 unmodified lines | ||
| 1516 | 1523 | default: |
| 1517 | 1524 | break; |
| 1518 | 1525 | } |
| 1519 | − | |
| 1520 | − WREG64_MCA(xgmi_inst, mca_base, ACA_REG_IDX_STATUS, 0ULL); | |
| 1526 | + smn_base = amdgpu_reg_get_smn_base64(adev, XGMI_HWIP, xgmi_inst); | |
| 1527 | + WREG64_MCA(smn_base, mca_base, ACA_REG_IDX_STATUS, 0ULL); | |
| 1521 | 1528 | } |
| 1522 | 1529 | |
| 1523 | 1530 | static void xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, int xgmi_inst, struct ras_err_data *err_data) |
| @@ -470,14 +470,23 @@ struct amd_sriov_ras_chk_criti { · 469 unmodified lines | ||
| 470 | 470 | uint32_t hit; |
| 471 | 471 | }; |
| 472 | 472 | |
| 473 | +union amd_sriov_ras_host_push { | |
| 474 | + struct amd_sriov_ras_telemetry_error_count error_count; | |
| 475 | + struct amd_sriov_ras_cper_dump cper_dump; | |
| 476 | + struct amd_sriov_ras_chk_criti chk_criti; | |
| 477 | +}; | |
| 478 | + | |
| 479 | +#define AMD_SRIOV_UNIRAS_BLOCKS_BUF_SIZE 4096 | |
| 480 | +#define AMD_SRIOV_UNIRAS_CMD_MAX_SIZE (4096 * 13) | |
| 481 | +struct amd_sriov_uniras_shared_mem { | |
| 482 | + uint8_t blocks_ecc_buf[AMD_SRIOV_UNIRAS_BLOCKS_BUF_SIZE]; | |
| 483 | + uint8_t cmd_buf[AMD_SRIOV_UNIRAS_CMD_MAX_SIZE]; | |
| 484 | +}; | |
| 485 | + | |
| 473 | 486 | struct amdsriov_ras_telemetry { |
| 474 | 487 | struct amd_sriov_ras_telemetry_header header; |
| 475 | − | |
| 476 | − union { | |
| 477 | − struct amd_sriov_ras_telemetry_error_count error_count; | |
| 478 | − struct amd_sriov_ras_cper_dump cper_dump; | |
| 479 | − struct amd_sriov_ras_chk_criti chk_criti; | |
| 480 | − } body; | |
| 488 | + union amd_sriov_ras_host_push body; | |
| 489 | + struct amd_sriov_uniras_shared_mem uniras_shared_mem; | |
| 481 | 490 | }; |
| 482 | 491 | |
| 483 | 492 | /* version data stored in MAILBOX_MSGBUF_RCV_DW1 for future expansion */ |
| @@ -510,6 +519,10 @@ _Static_assert(AMD_SRIOV_MSG_RESERVE_UCODE % 4 == 0, · 26 unmodified lines | ||
| 510 | 519 | _Static_assert(AMD_SRIOV_MSG_RESERVE_UCODE > AMD_SRIOV_UCODE_ID__MAX, |
| 511 | 520 | "AMD_SRIOV_MSG_RESERVE_UCODE must be bigger than AMD_SRIOV_UCODE_ID__MAX"); |
| 512 | 521 | |
| 522 | +_Static_assert( | |
| 523 | + sizeof(struct amdsriov_ras_telemetry) <= AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1 << 10, | |
| 524 | +"amdsriov_ras_telemetry must be " stringification(AMD_SRIOV_MSG_RAS_TELEMETRY_SIZE_KB_V1) " KB"); | |
| 525 | + | |
| 513 | 526 | #undef _stringification |
| 514 | 527 | #undef stringification |
| 515 | 528 | #endif |
| @@ -58,25 +58,6 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev) · 57 unmodified lines | ||
| 58 | 58 | adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | −/* Fixed pattern for smn addressing on different AIDs: | |
| 62 | − * bit[34]: indicate cross AID access | |
| 63 | − * bit[33:32]: indicate target AID id | |
| 64 | − * AID id range is 0 ~ 3 as maximum AID number is 4. | |
| 65 | − */ | |
| 66 | −u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id) | |
| 67 | −{ | |
| 68 | − u64 ext_offset; | |
| 69 | − | |
| 70 | − /* local routing and bit[34:32] will be zeros */ | |
| 71 | − if (ext_id == 0) | |
| 72 | − return 0; | |
| 73 | − | |
| 74 | − /* Initiated from host, accessing to all non-zero aids are cross traffic */ | |
| 75 | − ext_offset = ((u64)(ext_id & 0x3) << 32) | (1ULL << 34); | |
| 76 | − | |
| 77 | − return ext_offset; | |
| 78 | −} | |
| 79 | − | |
| 80 | 61 | static enum amdgpu_gfx_partition |
| 81 | 62 | __aqua_vanjaram_calc_xcp_mode(struct amdgpu_xcp_mgr *xcp_mgr) |
| 82 | 63 | { |
| @@ -590,7 +571,7 @@ static void aqua_read_smn_ext(struct amdgpu_device *adev, · 507 unmodified lines | ||
| 590 | 571 | uint64_t smn_addr, int i) |
| 591 | 572 | { |
| 592 | 573 | regdata->addr = |
| 593 | − smn_addr + adev->asic_funcs->encode_ext_smn_addressing(i); | |
| 574 | + smn_addr + amdgpu_reg_get_smn_base64(adev, XGMI_HWIP, i); | |
| 594 | 575 | regdata->value = RREG32_PCIE_EXT(regdata->addr); |
| 595 | 576 | } |
| 596 | 577 | |
| @@ -1462,8 +1462,6 @@ static void atom_get_vbios_pn(struct atom_context *ctx) · 1461 unmodified lines | ||
| 1462 | 1462 | |
| 1463 | 1463 | ctx->vbios_pn[count] = 0; |
| 1464 | 1464 | } |
| 1465 | − | |
| 1466 | − drm_info(ctx->card->dev, "ATOM BIOS: %s\n", ctx->vbios_pn); | |
| 1467 | 1465 | } |
| 1468 | 1466 | |
| 1469 | 1467 | static void atom_get_vbios_version(struct atom_context *ctx) |
| @@ -1520,6 +1518,30 @@ static void atom_get_vbios_build(struct atom_context *ctx) · 50 unmodified lines | ||
| 1520 | 1518 | strscpy(ctx->build_num, str, len); |
| 1521 | 1519 | } |
| 1522 | 1520 | |
| 1521 | +static inline void atom_print_vbios_info(struct atom_context *ctx) | |
| 1522 | +{ | |
| 1523 | + char vbios_info[256]; | |
| 1524 | + int off = 0; | |
| 1525 | + | |
| 1526 | + if (ctx->vbios_pn[0]) | |
| 1527 | + off += scnprintf(vbios_info + off, sizeof(vbios_info) - off, | |
| 1528 | + "%s", ctx->vbios_pn); | |
| 1529 | + if (ctx->build_num[0]) | |
| 1530 | + off += scnprintf(vbios_info + off, sizeof(vbios_info) - off, | |
| 1531 | + "%sbuild: %s", off ? ", " : "", | |
| 1532 | + ctx->build_num); | |
| 1533 | + if (ctx->vbios_ver_str[0]) | |
| 1534 | + off += scnprintf(vbios_info + off, sizeof(vbios_info) - off, | |
| 1535 | + "%sver: %s", off ? ", " : "", | |
| 1536 | + ctx->vbios_ver_str); | |
| 1537 | + if (ctx->date[0]) | |
| 1538 | + off += scnprintf(vbios_info + off, sizeof(vbios_info) - off, | |
| 1539 | + "%s%.10s", off ? ", " : "", | |
| 1540 | + ctx->date); | |
| 1541 | + if (off) | |
| 1542 | + drm_info(ctx->card->dev, "ATOM BIOS: %s\n", vbios_info); | |
| 1543 | +} | |
| 1544 | + | |
| 1523 | 1545 | struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) |
| 1524 | 1546 | { |
| 1525 | 1547 | int base; |
| @@ -1582,6 +1604,8 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) · 56 unmodified lines | ||
| 1582 | 1604 | atom_get_vbios_version(ctx); |
| 1583 | 1605 | atom_get_vbios_build(ctx); |
| 1584 | 1606 | |
| 1607 | + atom_print_vbios_info(ctx); | |
| 1608 | + | |
| 1585 | 1609 | return ctx; |
| 1586 | 1610 | } |
| 1587 | 1611 | |
| @@ -154,11 +154,11 @@ static u32 cik_pcie_rreg(struct amdgpu_device *adev, u32 reg) · 153 unmodified lines | ||
| 154 | 154 | unsigned long flags; |
| 155 | 155 | u32 r; |
| 156 | 156 | |
| 157 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 157 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 158 | 158 | WREG32(mmPCIE_INDEX, reg); |
| 159 | 159 | (void)RREG32(mmPCIE_INDEX); |
| 160 | 160 | r = RREG32(mmPCIE_DATA); |
| 161 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 161 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 162 | 162 | return r; |
| 163 | 163 | } |
| 164 | 164 | |
| @@ -166,12 +166,12 @@ static void cik_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 166 | 166 | { |
| 167 | 167 | unsigned long flags; |
| 168 | 168 | |
| 169 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 169 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 170 | 170 | WREG32(mmPCIE_INDEX, reg); |
| 171 | 171 | (void)RREG32(mmPCIE_INDEX); |
| 172 | 172 | WREG32(mmPCIE_DATA, v); |
| 173 | 173 | (void)RREG32(mmPCIE_DATA); |
| 174 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 174 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | static u32 cik_smc_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -179,10 +179,10 @@ static u32 cik_smc_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 179 | 179 | unsigned long flags; |
| 180 | 180 | u32 r; |
| 181 | 181 | |
| 182 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 182 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 183 | 183 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 184 | 184 | r = RREG32(mmSMC_IND_DATA_0); |
| 185 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 185 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 186 | 186 | return r; |
| 187 | 187 | } |
| 188 | 188 | |
| @@ -190,10 +190,10 @@ static void cik_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 190 | 190 | { |
| 191 | 191 | unsigned long flags; |
| 192 | 192 | |
| 193 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 193 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 194 | 194 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 195 | 195 | WREG32(mmSMC_IND_DATA_0, (v)); |
| 196 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 196 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | static u32 cik_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -201,10 +201,10 @@ static u32 cik_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 201 | 201 | unsigned long flags; |
| 202 | 202 | u32 r; |
| 203 | 203 | |
| 204 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 204 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 205 | 205 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 206 | 206 | r = RREG32(mmUVD_CTX_DATA); |
| 207 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 207 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 208 | 208 | return r; |
| 209 | 209 | } |
| 210 | 210 | |
| @@ -212,10 +212,10 @@ static void cik_uvd_ctx_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 212 | 212 | { |
| 213 | 213 | unsigned long flags; |
| 214 | 214 | |
| 215 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 215 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 216 | 216 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 217 | 217 | WREG32(mmUVD_CTX_DATA, (v)); |
| 218 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 218 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | 221 | static u32 cik_didt_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -223,10 +223,10 @@ static u32 cik_didt_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 223 | 223 | unsigned long flags; |
| 224 | 224 | u32 r; |
| 225 | 225 | |
| 226 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 226 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 227 | 227 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 228 | 228 | r = RREG32(mmDIDT_IND_DATA); |
| 229 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 229 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 230 | 230 | return r; |
| 231 | 231 | } |
| 232 | 232 | |
| @@ -234,10 +234,10 @@ static void cik_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 234 | 234 | { |
| 235 | 235 | unsigned long flags; |
| 236 | 236 | |
| 237 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 237 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 238 | 238 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 239 | 239 | WREG32(mmDIDT_IND_DATA, (v)); |
| 240 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 240 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | 243 | static const u32 bonaire_golden_spm_registers[] = |
| @@ -1027,7 +1027,7 @@ static bool cik_read_bios_from_rom(struct amdgpu_device *adev, · 783 unmodified lines | ||
| 1027 | 1027 | dw_ptr = (u32 *)bios; |
| 1028 | 1028 | length_dw = ALIGN(length_bytes, 4) / 4; |
| 1029 | 1029 | /* take the smc lock since we are using the smc index */ |
| 1030 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 1030 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 1031 | 1031 | /* set rom index to 0 */ |
| 1032 | 1032 | WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX); |
| 1033 | 1033 | WREG32(mmSMC_IND_DATA_0, 0); |
| @@ -1035,7 +1035,7 @@ static bool cik_read_bios_from_rom(struct amdgpu_device *adev, · 1 unmodified line | ||
| 1035 | 1035 | WREG32(mmSMC_IND_INDEX_0, ixROM_DATA); |
| 1036 | 1036 | for (i = 0; i < length_dw; i++) |
| 1037 | 1037 | dw_ptr[i] = RREG32(mmSMC_IND_DATA_0); |
| 1038 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 1038 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 1039 | 1039 | |
| 1040 | 1040 | return true; |
| 1041 | 1041 | } |
| @@ -1984,14 +1984,14 @@ static int cik_common_early_init(struct amdgpu_ip_block *ip_block) · 942 unmodified lines | ||
| 1984 | 1984 | { |
| 1985 | 1985 | struct amdgpu_device *adev = ip_block->adev; |
| 1986 | 1986 | |
| 1987 | − adev->smc_rreg = &cik_smc_rreg; | |
| 1988 | − adev->smc_wreg = &cik_smc_wreg; | |
| 1989 | − adev->pcie_rreg = &cik_pcie_rreg; | |
| 1990 | − adev->pcie_wreg = &cik_pcie_wreg; | |
| 1991 | − adev->uvd_ctx_rreg = &cik_uvd_ctx_rreg; | |
| 1992 | − adev->uvd_ctx_wreg = &cik_uvd_ctx_wreg; | |
| 1993 | − adev->didt_rreg = &cik_didt_rreg; | |
| 1994 | − adev->didt_wreg = &cik_didt_wreg; | |
| 1987 | + adev->reg.smc.rreg = cik_smc_rreg; | |
| 1988 | + adev->reg.smc.wreg = cik_smc_wreg; | |
| 1989 | + adev->reg.pcie.rreg = &cik_pcie_rreg; | |
| 1990 | + adev->reg.pcie.wreg = &cik_pcie_wreg; | |
| 1991 | + adev->reg.uvd_ctx.rreg = &cik_uvd_ctx_rreg; | |
| 1992 | + adev->reg.uvd_ctx.wreg = &cik_uvd_ctx_wreg; | |
| 1993 | + adev->reg.didt.rreg = &cik_didt_rreg; | |
| 1994 | + adev->reg.didt.wreg = &cik_didt_wreg; | |
| 1995 | 1995 | |
| 1996 | 1996 | adev->asic_funcs = &cik_asic_funcs; |
| 1997 | 1997 | |
| @@ -53,7 +53,6 @@ static const u32 sdma_offsets[SDMA_MAX_INSTANCE] = · 52 unmodified lines | ||
| 53 | 53 | static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev); |
| 54 | 54 | static void cik_sdma_set_irq_funcs(struct amdgpu_device *adev); |
| 55 | 55 | static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev); |
| 56 | −static void cik_sdma_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 57 | 56 | static int cik_sdma_soft_reset(struct amdgpu_ip_block *ip_block); |
| 58 | 57 | |
| 59 | 58 | u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev); |
| @@ -919,6 +918,14 @@ static void cik_enable_sdma_mgls(struct amdgpu_device *adev, · 859 unmodified lines | ||
| 919 | 918 | } |
| 920 | 919 | } |
| 921 | 920 | |
| 921 | +static const struct amdgpu_vm_pte_funcs cik_sdma_vm_pte_funcs = { | |
| 922 | + .copy_pte_num_dw = 7, | |
| 923 | + .copy_pte = cik_sdma_vm_copy_pte, | |
| 924 | + | |
| 925 | + .write_pte = cik_sdma_vm_write_pte, | |
| 926 | + .set_pte_pde = cik_sdma_vm_set_pte_pde, | |
| 927 | +}; | |
| 928 | + | |
| 922 | 929 | static int cik_sdma_early_init(struct amdgpu_ip_block *ip_block) |
| 923 | 930 | { |
| 924 | 931 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -933,7 +940,7 @@ static int cik_sdma_early_init(struct amdgpu_ip_block *ip_block) · 8 unmodified lines | ||
| 933 | 940 | cik_sdma_set_ring_funcs(adev); |
| 934 | 941 | cik_sdma_set_irq_funcs(adev); |
| 935 | 942 | cik_sdma_set_buffer_funcs(adev); |
| 936 | − cik_sdma_set_vm_pte_funcs(adev); | |
| 943 | + amdgpu_sdma_set_vm_pte_scheds(adev, &cik_sdma_vm_pte_funcs); | |
| 937 | 944 | |
| 938 | 945 | return 0; |
| 939 | 946 | } |
| @@ -1337,26 +1344,6 @@ static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev) · 397 unmodified lines | ||
| 1337 | 1344 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 1338 | 1345 | } |
| 1339 | 1346 | |
| 1340 | −static const struct amdgpu_vm_pte_funcs cik_sdma_vm_pte_funcs = { | |
| 1341 | − .copy_pte_num_dw = 7, | |
| 1342 | − .copy_pte = cik_sdma_vm_copy_pte, | |
| 1343 | − | |
| 1344 | − .write_pte = cik_sdma_vm_write_pte, | |
| 1345 | − .set_pte_pde = cik_sdma_vm_set_pte_pde, | |
| 1346 | −}; | |
| 1347 | − | |
| 1348 | −static void cik_sdma_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 1349 | −{ | |
| 1350 | − unsigned i; | |
| 1351 | − | |
| 1352 | − adev->vm_manager.vm_pte_funcs = &cik_sdma_vm_pte_funcs; | |
| 1353 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 1354 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 1355 | − &adev->sdma.instance[i].ring.sched; | |
| 1356 | − } | |
| 1357 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 1358 | −} | |
| 1359 | − | |
| 1360 | 1347 | const struct amdgpu_ip_block_version cik_sdma_ip_block = |
| 1361 | 1348 | { |
| 1362 | 1349 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| @@ -175,10 +175,10 @@ static u32 dce_v10_0_audio_endpt_rreg(struct amdgpu_device *adev, · 174 unmodified lines | ||
| 175 | 175 | unsigned long flags; |
| 176 | 176 | u32 r; |
| 177 | 177 | |
| 178 | − spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags); | |
| 178 | + spin_lock_irqsave(&adev->reg.audio_endpt.lock, flags); | |
| 179 | 179 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 180 | 180 | r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset); |
| 181 | − spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags); | |
| 181 | + spin_unlock_irqrestore(&adev->reg.audio_endpt.lock, flags); | |
| 182 | 182 | |
| 183 | 183 | return r; |
| 184 | 184 | } |
| @@ -188,10 +188,10 @@ static void dce_v10_0_audio_endpt_wreg(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 188 | 188 | { |
| 189 | 189 | unsigned long flags; |
| 190 | 190 | |
| 191 | − spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags); | |
| 191 | + spin_lock_irqsave(&adev->reg.audio_endpt.lock, flags); | |
| 192 | 192 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 193 | 193 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset, v); |
| 194 | − spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags); | |
| 194 | + spin_unlock_irqrestore(&adev->reg.audio_endpt.lock, flags); | |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) |
| @@ -2750,8 +2750,8 @@ static int dce_v10_0_early_init(struct amdgpu_ip_block *ip_block) · 2552 unmodified lines | ||
| 2750 | 2750 | { |
| 2751 | 2751 | struct amdgpu_device *adev = ip_block->adev; |
| 2752 | 2752 | |
| 2753 | − adev->audio_endpt_rreg = &dce_v10_0_audio_endpt_rreg; | |
| 2754 | − adev->audio_endpt_wreg = &dce_v10_0_audio_endpt_wreg; | |
| 2753 | + adev->reg.audio_endpt.rreg = &dce_v10_0_audio_endpt_rreg; | |
| 2754 | + adev->reg.audio_endpt.wreg = &dce_v10_0_audio_endpt_wreg; | |
| 2755 | 2755 | |
| 2756 | 2756 | dce_v10_0_set_display_funcs(adev); |
| 2757 | 2757 | |
| @@ -138,10 +138,10 @@ static u32 dce_v6_0_audio_endpt_rreg(struct amdgpu_device *adev, · 137 unmodified lines | ||
| 138 | 138 | unsigned long flags; |
| 139 | 139 | u32 r; |
| 140 | 140 | |
| 141 | − spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags); | |
| 141 | + spin_lock_irqsave(&adev->reg.audio_endpt.lock, flags); | |
| 142 | 142 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 143 | 143 | r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset); |
| 144 | − spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags); | |
| 144 | + spin_unlock_irqrestore(&adev->reg.audio_endpt.lock, flags); | |
| 145 | 145 | |
| 146 | 146 | return r; |
| 147 | 147 | } |
| @@ -151,11 +151,11 @@ static void dce_v6_0_audio_endpt_wreg(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 151 | 151 | { |
| 152 | 152 | unsigned long flags; |
| 153 | 153 | |
| 154 | − spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags); | |
| 154 | + spin_lock_irqsave(&adev->reg.audio_endpt.lock, flags); | |
| 155 | 155 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, |
| 156 | 156 | reg | AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_WRITE_EN_MASK); |
| 157 | 157 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset, v); |
| 158 | − spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags); | |
| 158 | + spin_unlock_irqrestore(&adev->reg.audio_endpt.lock, flags); | |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | 161 | static u32 dce_v6_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) |
| @@ -2697,8 +2697,8 @@ static int dce_v6_0_early_init(struct amdgpu_ip_block *ip_block) · 2535 unmodified lines | ||
| 2697 | 2697 | { |
| 2698 | 2698 | struct amdgpu_device *adev = ip_block->adev; |
| 2699 | 2699 | |
| 2700 | − adev->audio_endpt_rreg = &dce_v6_0_audio_endpt_rreg; | |
| 2701 | − adev->audio_endpt_wreg = &dce_v6_0_audio_endpt_wreg; | |
| 2700 | + adev->reg.audio_endpt.rreg = &dce_v6_0_audio_endpt_rreg; | |
| 2701 | + adev->reg.audio_endpt.wreg = &dce_v6_0_audio_endpt_wreg; | |
| 2702 | 2702 | |
| 2703 | 2703 | dce_v6_0_set_display_funcs(adev); |
| 2704 | 2704 | |
| @@ -126,10 +126,10 @@ static u32 dce_v8_0_audio_endpt_rreg(struct amdgpu_device *adev, · 125 unmodified lines | ||
| 126 | 126 | unsigned long flags; |
| 127 | 127 | u32 r; |
| 128 | 128 | |
| 129 | − spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags); | |
| 129 | + spin_lock_irqsave(&adev->reg.audio_endpt.lock, flags); | |
| 130 | 130 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 131 | 131 | r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset); |
| 132 | − spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags); | |
| 132 | + spin_unlock_irqrestore(&adev->reg.audio_endpt.lock, flags); | |
| 133 | 133 | |
| 134 | 134 | return r; |
| 135 | 135 | } |
| @@ -139,10 +139,10 @@ static void dce_v8_0_audio_endpt_wreg(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 139 | 139 | { |
| 140 | 140 | unsigned long flags; |
| 141 | 141 | |
| 142 | − spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags); | |
| 142 | + spin_lock_irqsave(&adev->reg.audio_endpt.lock, flags); | |
| 143 | 143 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 144 | 144 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset, v); |
| 145 | − spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags); | |
| 145 | + spin_unlock_irqrestore(&adev->reg.audio_endpt.lock, flags); | |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) |
| @@ -2655,8 +2655,8 @@ static int dce_v8_0_early_init(struct amdgpu_ip_block *ip_block) · 2506 unmodified lines | ||
| 2655 | 2655 | { |
| 2656 | 2656 | struct amdgpu_device *adev = ip_block->adev; |
| 2657 | 2657 | |
| 2658 | − adev->audio_endpt_rreg = &dce_v8_0_audio_endpt_rreg; | |
| 2659 | − adev->audio_endpt_wreg = &dce_v8_0_audio_endpt_wreg; | |
| 2658 | + adev->reg.audio_endpt.rreg = &dce_v8_0_audio_endpt_rreg; | |
| 2659 | + adev->reg.audio_endpt.wreg = &dce_v8_0_audio_endpt_wreg; | |
| 2660 | 2660 | |
| 2661 | 2661 | dce_v8_0_set_display_funcs(adev); |
| 2662 | 2662 | |
| @@ -51,7 +51,7 @@ static uint64_t df_v3_6_get_fica(struct amdgpu_device *adev, · 50 unmodified lines | ||
| 51 | 51 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 52 | 52 | data = adev->nbio.funcs->get_pcie_data_offset(adev); |
| 53 | 53 | |
| 54 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 54 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 55 | 55 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3); |
| 56 | 56 | WREG32(data, ficaa_val); |
| 57 | 57 | |
| @@ -61,7 +61,7 @@ static uint64_t df_v3_6_get_fica(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 61 | 61 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3); |
| 62 | 62 | ficadh_val = RREG32(data); |
| 63 | 63 | |
| 64 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 64 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 65 | 65 | |
| 66 | 66 | return (((ficadh_val & 0xFFFFFFFFFFFFFFFF) << 32) | ficadl_val); |
| 67 | 67 | } |
| @@ -74,7 +74,7 @@ static void df_v3_6_set_fica(struct amdgpu_device *adev, uint32_t ficaa_val, · 6 unmodified lines | ||
| 74 | 74 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 75 | 75 | data = adev->nbio.funcs->get_pcie_data_offset(adev); |
| 76 | 76 | |
| 77 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 77 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 78 | 78 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3); |
| 79 | 79 | WREG32(data, ficaa_val); |
| 80 | 80 | |
| @@ -84,7 +84,7 @@ static void df_v3_6_set_fica(struct amdgpu_device *adev, uint32_t ficaa_val, · 3 unmodified lines | ||
| 84 | 84 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3); |
| 85 | 85 | WREG32(data, ficadh_val); |
| 86 | 86 | |
| 87 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 87 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | /* |
| @@ -102,12 +102,12 @@ static void df_v3_6_perfmon_rreg(struct amdgpu_device *adev, · 11 unmodified lines | ||
| 102 | 102 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 103 | 103 | data = adev->nbio.funcs->get_pcie_data_offset(adev); |
| 104 | 104 | |
| 105 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 105 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 106 | 106 | WREG32(address, lo_addr); |
| 107 | 107 | *lo_val = RREG32(data); |
| 108 | 108 | WREG32(address, hi_addr); |
| 109 | 109 | *hi_val = RREG32(data); |
| 110 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 110 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | /* |
| @@ -124,12 +124,12 @@ static void df_v3_6_perfmon_wreg(struct amdgpu_device *adev, uint32_t lo_addr, · 10 unmodified lines | ||
| 124 | 124 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 125 | 125 | data = adev->nbio.funcs->get_pcie_data_offset(adev); |
| 126 | 126 | |
| 127 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 127 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 128 | 128 | WREG32(address, lo_addr); |
| 129 | 129 | WREG32(data, lo_val); |
| 130 | 130 | WREG32(address, hi_addr); |
| 131 | 131 | WREG32(data, hi_val); |
| 132 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 132 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | /* same as perfmon_wreg but return status on write value check */ |
| @@ -143,7 +143,7 @@ static int df_v3_6_perfmon_arm_with_status(struct amdgpu_device *adev, · 7 unmodified lines | ||
| 143 | 143 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 144 | 144 | data = adev->nbio.funcs->get_pcie_data_offset(adev); |
| 145 | 145 | |
| 146 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 146 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 147 | 147 | WREG32(address, lo_addr); |
| 148 | 148 | WREG32(data, lo_val); |
| 149 | 149 | WREG32(address, hi_addr); |
| @@ -153,7 +153,7 @@ static int df_v3_6_perfmon_arm_with_status(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 153 | 153 | lo_val_rb = RREG32(data); |
| 154 | 154 | WREG32(address, hi_addr); |
| 155 | 155 | hi_val_rb = RREG32(data); |
| 156 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 156 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 157 | 157 | |
| 158 | 158 | if (!(lo_val == lo_val_rb && hi_val == hi_val_rb)) |
| 159 | 159 | return -EBUSY; |
| @@ -4238,6 +4238,37 @@ static int gfx_v11_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev) · 4237 unmodified lines | ||
| 4238 | 4238 | return gfx_v11_0_cp_gfx_start(adev); |
| 4239 | 4239 | } |
| 4240 | 4240 | |
| 4241 | +static void gfx_v11_0_compute_mqd_set_cu_mask(struct amdgpu_device *adev, | |
| 4242 | + struct v11_compute_mqd *mqd, | |
| 4243 | + struct amdgpu_mqd_prop *prop) | |
| 4244 | +{ | |
| 4245 | + uint32_t se_mask[8] = {0}; | |
| 4246 | + uint32_t wa_mask; | |
| 4247 | + bool has_wa_flag = prop->cu_flags & (AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE | | |
| 4248 | + AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE); | |
| 4249 | + | |
| 4250 | + if (!has_wa_flag && (!prop->cu_mask || !prop->cu_mask_count)) | |
| 4251 | + return; | |
| 4252 | + | |
| 4253 | + if (has_wa_flag) { | |
| 4254 | + wa_mask = (prop->cu_flags & AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE) ? | |
| 4255 | + 0xffff : 0xffffffff; | |
| 4256 | + mqd->compute_static_thread_mgmt_se0 = wa_mask; | |
| 4257 | + mqd->compute_static_thread_mgmt_se1 = wa_mask; | |
| 4258 | + mqd->compute_static_thread_mgmt_se2 = wa_mask; | |
| 4259 | + mqd->compute_static_thread_mgmt_se3 = wa_mask; | |
| 4260 | + return; | |
| 4261 | + } | |
| 4262 | + | |
| 4263 | + amdgpu_gfx_mqd_symmetrically_map_cu_mask(adev, prop->cu_mask, | |
| 4264 | + prop->cu_mask_count, se_mask); | |
| 4265 | + | |
| 4266 | + mqd->compute_static_thread_mgmt_se0 = se_mask[0]; | |
| 4267 | + mqd->compute_static_thread_mgmt_se1 = se_mask[1]; | |
| 4268 | + mqd->compute_static_thread_mgmt_se2 = se_mask[2]; | |
| 4269 | + mqd->compute_static_thread_mgmt_se3 = se_mask[3]; | |
| 4270 | +} | |
| 4271 | + | |
| 4241 | 4272 | static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, |
| 4242 | 4273 | struct amdgpu_mqd_prop *prop) |
| 4243 | 4274 | { |
| @@ -4372,6 +4403,8 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, · 128 unmodified lines | ||
| 4372 | 4403 | /* set UQ fenceaddress */ |
| 4373 | 4404 | mqd->fence_address_lo = lower_32_bits(prop->fence_address); |
| 4374 | 4405 | mqd->fence_address_hi = upper_32_bits(prop->fence_address); |
| 4406 | + /* set CU mask */ | |
| 4407 | + gfx_v11_0_compute_mqd_set_cu_mask(adev, mqd, prop); | |
| 4375 | 4408 | |
| 4376 | 4409 | return 0; |
| 4377 | 4410 | } |
| @@ -3109,6 +3109,37 @@ static int gfx_v12_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev) · 3108 unmodified lines | ||
| 3109 | 3109 | return gfx_v12_0_cp_gfx_start(adev); |
| 3110 | 3110 | } |
| 3111 | 3111 | |
| 3112 | +static void gfx_v12_0_compute_mqd_set_cu_mask(struct amdgpu_device *adev, | |
| 3113 | + struct v12_compute_mqd *mqd, | |
| 3114 | + struct amdgpu_mqd_prop *prop) | |
| 3115 | +{ | |
| 3116 | + uint32_t se_mask[8] = {0}; | |
| 3117 | + uint32_t wa_mask; | |
| 3118 | + bool has_wa_flag = prop->cu_flags & (AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE | | |
| 3119 | + AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE); | |
| 3120 | + | |
| 3121 | + if (!has_wa_flag && (!prop->cu_mask || !prop->cu_mask_count)) | |
| 3122 | + return; | |
| 3123 | + | |
| 3124 | + if (has_wa_flag) { | |
| 3125 | + wa_mask = (prop->cu_flags & AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE) ? | |
| 3126 | + 0xffff : 0xffffffff; | |
| 3127 | + mqd->compute_static_thread_mgmt_se0 = wa_mask; | |
| 3128 | + mqd->compute_static_thread_mgmt_se1 = wa_mask; | |
| 3129 | + mqd->compute_static_thread_mgmt_se2 = wa_mask; | |
| 3130 | + mqd->compute_static_thread_mgmt_se3 = wa_mask; | |
| 3131 | + return; | |
| 3132 | + } | |
| 3133 | + | |
| 3134 | + amdgpu_gfx_mqd_symmetrically_map_cu_mask(adev, prop->cu_mask, | |
| 3135 | + prop->cu_mask_count, se_mask); | |
| 3136 | + | |
| 3137 | + mqd->compute_static_thread_mgmt_se0 = se_mask[0]; | |
| 3138 | + mqd->compute_static_thread_mgmt_se1 = se_mask[1]; | |
| 3139 | + mqd->compute_static_thread_mgmt_se2 = se_mask[2]; | |
| 3140 | + mqd->compute_static_thread_mgmt_se3 = se_mask[3]; | |
| 3141 | +} | |
| 3142 | + | |
| 3112 | 3143 | static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, |
| 3113 | 3144 | struct amdgpu_mqd_prop *prop) |
| 3114 | 3145 | { |
| @@ -3242,6 +3273,8 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, · 127 unmodified lines | ||
| 3242 | 3273 | /* set UQ fenceaddress */ |
| 3243 | 3274 | mqd->fence_address_lo = lower_32_bits(prop->fence_address); |
| 3244 | 3275 | mqd->fence_address_hi = upper_32_bits(prop->fence_address); |
| 3276 | + /* set CU mask */ | |
| 3277 | + gfx_v12_0_compute_mqd_set_cu_mask(adev, mqd, prop); | |
| 3245 | 3278 | |
| 3246 | 3279 | return 0; |
| 3247 | 3280 | } |
| @@ -1405,7 +1405,7 @@ static void gfx_v12_1_xcc_init_compute_vmid(struct amdgpu_device *adev, · 1404 unmodified lines | ||
| 1405 | 1405 | /* |
| 1406 | 1406 | * Configure apertures: |
| 1407 | 1407 | * LDS: 0x20000000'00000000 - 0x20000001'00000000 (4GB) |
| 1408 | − * Scratch: 0x10000000'00000000 - 0x10000001'00000000 (4GB) | |
| 1408 | + * Scratch: 0x10000000'00000000 - 0x11ffffff'ffffffff (128PB 57-bit) | |
| 1409 | 1409 | */ |
| 1410 | 1410 | sh_mem_bases = REG_SET_FIELD(0, SH_MEM_BASES, PRIVATE_BASE, |
| 1411 | 1411 | (adev->gmc.private_aperture_start >> 58)); |
| @@ -654,9 +654,15 @@ static int gmc_v12_0_early_init(struct amdgpu_ip_block *ip_block) · 653 unmodified lines | ||
| 654 | 654 | adev->gmc.shared_aperture_start = 0x2000000000000000ULL; |
| 655 | 655 | adev->gmc.shared_aperture_end = |
| 656 | 656 | adev->gmc.shared_aperture_start + (4ULL << 30) - 1; |
| 657 | + | |
| 657 | 658 | adev->gmc.private_aperture_start = 0x1000000000000000ULL; |
| 658 | − adev->gmc.private_aperture_end = | |
| 659 | − adev->gmc.private_aperture_start + (4ULL << 30) - 1; | |
| 659 | + if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0)) | |
| 660 | + adev->gmc.private_aperture_end = | |
| 661 | + adev->gmc.private_aperture_start + (1ULL << 57) - 1; | |
| 662 | + else | |
| 663 | + adev->gmc.private_aperture_end = | |
| 664 | + adev->gmc.private_aperture_start + (4ULL << 30) - 1; | |
| 665 | + | |
| 660 | 666 | adev->gmc.noretry_flags = AMDGPU_VM_NORETRY_FLAGS_TF; |
| 661 | 667 | |
| 662 | 668 | return 0; |
| @@ -345,9 +345,7 @@ static void gmc_v12_1_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, · 344 unmodified lines | ||
| 345 | 345 | return; |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 349 | 348 | gmc_v12_1_flush_vm_hub(adev, vmid, vmhub, 0); |
| 350 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 351 | 349 | return; |
| 352 | 350 | } |
| 353 | 351 | |
| @@ -283,10 +283,10 @@ static u32 nv_didt_rreg(struct amdgpu_device *adev, u32 reg) · 282 unmodified lines | ||
| 283 | 283 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 284 | 284 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); |
| 285 | 285 | |
| 286 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 286 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 287 | 287 | WREG32(address, (reg)); |
| 288 | 288 | r = RREG32(data); |
| 289 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 289 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 290 | 290 | return r; |
| 291 | 291 | } |
| 292 | 292 | |
| @@ -297,10 +297,10 @@ static void nv_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 4 unmodified lines | ||
| 297 | 297 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 298 | 298 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); |
| 299 | 299 | |
| 300 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 300 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 301 | 301 | WREG32(address, (reg)); |
| 302 | 302 | WREG32(data, (v)); |
| 303 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 303 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | 306 | static u32 nv_get_config_memsize(struct amdgpu_device *adev) |
| @@ -635,21 +635,15 @@ static int nv_common_early_init(struct amdgpu_ip_block *ip_block) · 328 unmodified lines | ||
| 635 | 635 | struct amdgpu_device *adev = ip_block->adev; |
| 636 | 636 | |
| 637 | 637 | adev->nbio.funcs->set_reg_remap(adev); |
| 638 | − adev->smc_rreg = NULL; | |
| 639 | − adev->smc_wreg = NULL; | |
| 640 | − adev->pcie_rreg = &amdgpu_device_indirect_rreg; | |
| 641 | − adev->pcie_wreg = &amdgpu_device_indirect_wreg; | |
| 642 | − adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | |
| 643 | − adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | |
| 644 | − adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | |
| 645 | − adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | |
| 646 | − | |
| 647 | − /* TODO: will add them during VCN v2 implementation */ | |
| 648 | − adev->uvd_ctx_rreg = NULL; | |
| 649 | − adev->uvd_ctx_wreg = NULL; | |
| 650 | − | |
| 651 | − adev->didt_rreg = &nv_didt_rreg; | |
| 652 | − adev->didt_wreg = &nv_didt_wreg; | |
| 638 | + adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; | |
| 639 | + adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; | |
| 640 | + adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; | |
| 641 | + adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; | |
| 642 | + adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; | |
| 643 | + adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; | |
| 644 | + | |
| 645 | + adev->reg.didt.rreg = &nv_didt_rreg; | |
| 646 | + adev->reg.didt.wreg = &nv_didt_wreg; | |
| 653 | 647 | |
| 654 | 648 | adev->asic_funcs = &nv_asic_funcs; |
| 655 | 649 | |
| @@ -166,7 +166,7 @@ static void psp_v13_0_bootloader_print_status(struct psp_context *psp, · 165 unmodified lines | ||
| 166 | 166 | bl_status_reg = |
| 167 | 167 | (SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_92) |
| 168 | 168 | << 2) + |
| 169 | − adev->asic_funcs->encode_ext_smn_addressing(i); | |
| 169 | + amdgpu_reg_get_smn_base64(adev, MP0_HWIP, i); | |
| 170 | 170 | at += snprintf(bl_status_msg + at, |
| 171 | 171 | PSP13_BL_STATUS_SIZE - at, |
| 172 | 172 | " status(%02i): 0x%08x", i, |
| @@ -69,12 +69,12 @@ static int psp_v15_0_0_ring_stop(struct psp_context *psp, · 68 unmodified lines | ||
| 69 | 69 | 0x80000000, 0x80000000, false); |
| 70 | 70 | } else { |
| 71 | 71 | /* Write the ring destroy command*/ |
| 72 | − WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64, | |
| 72 | + WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64, | |
| 73 | 73 | GFX_CTRL_CMD_ID_DESTROY_RINGS); |
| 74 | 74 | /* there might be handshake issue with hardware which needs delay */ |
| 75 | 75 | mdelay(20); |
| 76 | 76 | /* Wait for response flag (bit 31) */ |
| 77 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64), | |
| 77 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64), | |
| 78 | 78 | 0x80000000, 0x80000000, false); |
| 79 | 79 | } |
| 80 | 80 | |
| @@ -116,7 +116,7 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp, · 35 unmodified lines | ||
| 116 | 116 | |
| 117 | 117 | } else { |
| 118 | 118 | /* Wait for sOS ready for ring creation */ |
| 119 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64), | |
| 119 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64), | |
| 120 | 120 | 0x80000000, 0x80000000, false); |
| 121 | 121 | if (ret) { |
| 122 | 122 | DRM_ERROR("Failed to wait for trust OS ready for ring creation\n"); |
| @@ -125,23 +125,23 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp, · 2 unmodified lines | ||
| 125 | 125 | |
| 126 | 126 | /* Write low address of the ring to C2PMSG_69 */ |
| 127 | 127 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); |
| 128 | − WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_69, psp_ring_reg); | |
| 128 | + WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_69, psp_ring_reg); | |
| 129 | 129 | /* Write high address of the ring to C2PMSG_70 */ |
| 130 | 130 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); |
| 131 | − WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_70, psp_ring_reg); | |
| 131 | + WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_70, psp_ring_reg); | |
| 132 | 132 | /* Write size of ring to C2PMSG_71 */ |
| 133 | 133 | psp_ring_reg = ring->ring_size; |
| 134 | − WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_71, psp_ring_reg); | |
| 134 | + WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_71, psp_ring_reg); | |
| 135 | 135 | /* Write the ring initialization command to C2PMSG_64 */ |
| 136 | 136 | psp_ring_reg = ring_type; |
| 137 | 137 | psp_ring_reg = psp_ring_reg << 16; |
| 138 | − WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64, psp_ring_reg); | |
| 138 | + WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64, psp_ring_reg); | |
| 139 | 139 | |
| 140 | 140 | /* there might be handshake issue with hardware which needs delay */ |
| 141 | 141 | mdelay(20); |
| 142 | 142 | |
| 143 | 143 | /* Wait for response flag (bit 31) in C2PMSG_64 */ |
| 144 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64), | |
| 144 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64), | |
| 145 | 145 | 0x80000000, 0x8000FFFF, false); |
| 146 | 146 | } |
| 147 | 147 | |
| @@ -174,7 +174,7 @@ static uint32_t psp_v15_0_0_ring_get_wptr(struct psp_context *psp) · 26 unmodified lines | ||
| 174 | 174 | if (amdgpu_sriov_vf(adev)) |
| 175 | 175 | data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102); |
| 176 | 176 | else |
| 177 | − data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67); | |
| 177 | + data = RREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67); | |
| 178 | 178 | |
| 179 | 179 | return data; |
| 180 | 180 | } |
| @@ -188,7 +188,7 @@ static void psp_v15_0_0_ring_set_wptr(struct psp_context *psp, uint32_t value) · 7 unmodified lines | ||
| 188 | 188 | WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101, |
| 189 | 189 | GFX_CTRL_CMD_ID_CONSUME_CMD); |
| 190 | 190 | } else |
| 191 | − WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67, value); | |
| 191 | + WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67, value); | |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | static const struct psp_funcs psp_v15_0_0_funcs = { |
| @@ -51,7 +51,6 @@ · 50 unmodified lines | ||
| 51 | 51 | |
| 52 | 52 | static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev); |
| 53 | 53 | static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev); |
| 54 | −static void sdma_v2_4_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 55 | 54 | static void sdma_v2_4_set_irq_funcs(struct amdgpu_device *adev); |
| 56 | 55 | |
| 57 | 56 | MODULE_FIRMWARE("amdgpu/topaz_sdma.bin"); |
| @@ -809,6 +808,14 @@ static void sdma_v2_4_ring_emit_wreg(struct amdgpu_ring *ring, · 751 unmodified lines | ||
| 809 | 808 | amdgpu_ring_write(ring, val); |
| 810 | 809 | } |
| 811 | 810 | |
| 811 | +static const struct amdgpu_vm_pte_funcs sdma_v2_4_vm_pte_funcs = { | |
| 812 | + .copy_pte_num_dw = 7, | |
| 813 | + .copy_pte = sdma_v2_4_vm_copy_pte, | |
| 814 | + | |
| 815 | + .write_pte = sdma_v2_4_vm_write_pte, | |
| 816 | + .set_pte_pde = sdma_v2_4_vm_set_pte_pde, | |
| 817 | +}; | |
| 818 | + | |
| 812 | 819 | static int sdma_v2_4_early_init(struct amdgpu_ip_block *ip_block) |
| 813 | 820 | { |
| 814 | 821 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -822,7 +829,7 @@ static int sdma_v2_4_early_init(struct amdgpu_ip_block *ip_block) · 7 unmodified lines | ||
| 822 | 829 | |
| 823 | 830 | sdma_v2_4_set_ring_funcs(adev); |
| 824 | 831 | sdma_v2_4_set_buffer_funcs(adev); |
| 825 | − sdma_v2_4_set_vm_pte_funcs(adev); | |
| 832 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v2_4_vm_pte_funcs); | |
| 826 | 833 | sdma_v2_4_set_irq_funcs(adev); |
| 827 | 834 | |
| 828 | 835 | return 0; |
| @@ -1232,26 +1239,6 @@ static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev) · 403 unmodified lines | ||
| 1232 | 1239 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 1233 | 1240 | } |
| 1234 | 1241 | |
| 1235 | −static const struct amdgpu_vm_pte_funcs sdma_v2_4_vm_pte_funcs = { | |
| 1236 | − .copy_pte_num_dw = 7, | |
| 1237 | − .copy_pte = sdma_v2_4_vm_copy_pte, | |
| 1238 | − | |
| 1239 | − .write_pte = sdma_v2_4_vm_write_pte, | |
| 1240 | − .set_pte_pde = sdma_v2_4_vm_set_pte_pde, | |
| 1241 | −}; | |
| 1242 | − | |
| 1243 | −static void sdma_v2_4_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 1244 | −{ | |
| 1245 | − unsigned i; | |
| 1246 | − | |
| 1247 | − adev->vm_manager.vm_pte_funcs = &sdma_v2_4_vm_pte_funcs; | |
| 1248 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 1249 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 1250 | − &adev->sdma.instance[i].ring.sched; | |
| 1251 | − } | |
| 1252 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 1253 | −} | |
| 1254 | − | |
| 1255 | 1242 | const struct amdgpu_ip_block_version sdma_v2_4_ip_block = { |
| 1256 | 1243 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1257 | 1244 | .major = 2, |
| @@ -51,7 +51,6 @@ · 50 unmodified lines | ||
| 51 | 51 | |
| 52 | 52 | static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev); |
| 53 | 53 | static void sdma_v3_0_set_buffer_funcs(struct amdgpu_device *adev); |
| 54 | −static void sdma_v3_0_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 55 | 54 | static void sdma_v3_0_set_irq_funcs(struct amdgpu_device *adev); |
| 56 | 55 | |
| 57 | 56 | MODULE_FIRMWARE("amdgpu/tonga_sdma.bin"); |
| @@ -1082,6 +1081,14 @@ static void sdma_v3_0_ring_emit_wreg(struct amdgpu_ring *ring, · 1024 unmodified lines | ||
| 1082 | 1081 | amdgpu_ring_write(ring, val); |
| 1083 | 1082 | } |
| 1084 | 1083 | |
| 1084 | +static const struct amdgpu_vm_pte_funcs sdma_v3_0_vm_pte_funcs = { | |
| 1085 | + .copy_pte_num_dw = 7, | |
| 1086 | + .copy_pte = sdma_v3_0_vm_copy_pte, | |
| 1087 | + | |
| 1088 | + .write_pte = sdma_v3_0_vm_write_pte, | |
| 1089 | + .set_pte_pde = sdma_v3_0_vm_set_pte_pde, | |
| 1090 | +}; | |
| 1091 | + | |
| 1085 | 1092 | static int sdma_v3_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1086 | 1093 | { |
| 1087 | 1094 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1102,7 +1109,7 @@ static int sdma_v3_0_early_init(struct amdgpu_ip_block *ip_block) · 14 unmodified lines | ||
| 1102 | 1109 | |
| 1103 | 1110 | sdma_v3_0_set_ring_funcs(adev); |
| 1104 | 1111 | sdma_v3_0_set_buffer_funcs(adev); |
| 1105 | − sdma_v3_0_set_vm_pte_funcs(adev); | |
| 1112 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v3_0_vm_pte_funcs); | |
| 1106 | 1113 | sdma_v3_0_set_irq_funcs(adev); |
| 1107 | 1114 | |
| 1108 | 1115 | return 0; |
| @@ -1674,26 +1681,6 @@ static void sdma_v3_0_set_buffer_funcs(struct amdgpu_device *adev) · 565 unmodified lines | ||
| 1674 | 1681 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 1675 | 1682 | } |
| 1676 | 1683 | |
| 1677 | −static const struct amdgpu_vm_pte_funcs sdma_v3_0_vm_pte_funcs = { | |
| 1678 | − .copy_pte_num_dw = 7, | |
| 1679 | − .copy_pte = sdma_v3_0_vm_copy_pte, | |
| 1680 | − | |
| 1681 | − .write_pte = sdma_v3_0_vm_write_pte, | |
| 1682 | − .set_pte_pde = sdma_v3_0_vm_set_pte_pde, | |
| 1683 | −}; | |
| 1684 | − | |
| 1685 | −static void sdma_v3_0_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 1686 | −{ | |
| 1687 | − unsigned i; | |
| 1688 | − | |
| 1689 | − adev->vm_manager.vm_pte_funcs = &sdma_v3_0_vm_pte_funcs; | |
| 1690 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 1691 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 1692 | − &adev->sdma.instance[i].ring.sched; | |
| 1693 | − } | |
| 1694 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 1695 | −} | |
| 1696 | − | |
| 1697 | 1684 | const struct amdgpu_ip_block_version sdma_v3_0_ip_block = |
| 1698 | 1685 | { |
| 1699 | 1686 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| @@ -129,7 +129,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_4_0[] = { · 128 unmodified lines | ||
| 129 | 129 | |
| 130 | 130 | static void sdma_v4_0_set_ring_funcs(struct amdgpu_device *adev); |
| 131 | 131 | static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev); |
| 132 | −static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 133 | 132 | static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev); |
| 134 | 133 | static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev); |
| 135 | 134 | |
| @@ -1751,6 +1750,14 @@ static bool sdma_v4_0_fw_support_paging_queue(struct amdgpu_device *adev) · 1615 unmodified lines | ||
| 1751 | 1750 | } |
| 1752 | 1751 | } |
| 1753 | 1752 | |
| 1753 | +static const struct amdgpu_vm_pte_funcs sdma_v4_0_vm_pte_funcs = { | |
| 1754 | + .copy_pte_num_dw = 7, | |
| 1755 | + .copy_pte = sdma_v4_0_vm_copy_pte, | |
| 1756 | + | |
| 1757 | + .write_pte = sdma_v4_0_vm_write_pte, | |
| 1758 | + .set_pte_pde = sdma_v4_0_vm_set_pte_pde, | |
| 1759 | +}; | |
| 1760 | + | |
| 1754 | 1761 | static int sdma_v4_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1755 | 1762 | { |
| 1756 | 1763 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1769,7 +1776,7 @@ static int sdma_v4_0_early_init(struct amdgpu_ip_block *ip_block) · 12 unmodified lines | ||
| 1769 | 1776 | |
| 1770 | 1777 | sdma_v4_0_set_ring_funcs(adev); |
| 1771 | 1778 | sdma_v4_0_set_buffer_funcs(adev); |
| 1772 | − sdma_v4_0_set_vm_pte_funcs(adev); | |
| 1779 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v4_0_vm_pte_funcs); | |
| 1773 | 1780 | sdma_v4_0_set_irq_funcs(adev); |
| 1774 | 1781 | sdma_v4_0_set_ras_funcs(adev); |
| 1775 | 1782 | |
| @@ -2597,48 +2604,37 @@ static void sdma_v4_0_emit_fill_buffer(struct amdgpu_ib *ib, · 821 unmodified lines | ||
| 2597 | 2604 | } |
| 2598 | 2605 | |
| 2599 | 2606 | static const struct amdgpu_buffer_funcs sdma_v4_0_buffer_funcs = { |
| 2600 | − .copy_max_bytes = 0x400000, | |
| 2607 | + .copy_max_bytes = 1 << 22, | |
| 2601 | 2608 | .copy_num_dw = 7, |
| 2602 | 2609 | .emit_copy_buffer = sdma_v4_0_emit_copy_buffer, |
| 2603 | 2610 | |
| 2604 | − .fill_max_bytes = 0x400000, | |
| 2611 | + .fill_max_bytes = 1 << 22, | |
| 2612 | + .fill_num_dw = 5, | |
| 2613 | + .emit_fill_buffer = sdma_v4_0_emit_fill_buffer, | |
| 2614 | +}; | |
| 2615 | + | |
| 2616 | +static const struct amdgpu_buffer_funcs sdma_v4_4_buffer_funcs = { | |
| 2617 | + .copy_max_bytes = 1 << 30, | |
| 2618 | + .copy_num_dw = 7, | |
| 2619 | + .emit_copy_buffer = sdma_v4_0_emit_copy_buffer, | |
| 2620 | + | |
| 2621 | + .fill_max_bytes = 1 << 30, | |
| 2605 | 2622 | .fill_num_dw = 5, |
| 2606 | 2623 | .emit_fill_buffer = sdma_v4_0_emit_fill_buffer, |
| 2607 | 2624 | }; |
| 2608 | 2625 | |
| 2609 | 2626 | static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev) |
| 2610 | 2627 | { |
| 2611 | − adev->mman.buffer_funcs = &sdma_v4_0_buffer_funcs; | |
| 2628 | + if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) >= IP_VERSION(4, 4, 0)) | |
| 2629 | + adev->mman.buffer_funcs = &sdma_v4_4_buffer_funcs; | |
| 2630 | + else | |
| 2631 | + adev->mman.buffer_funcs = &sdma_v4_0_buffer_funcs; | |
| 2612 | 2632 | if (adev->sdma.has_page_queue) |
| 2613 | 2633 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].page; |
| 2614 | 2634 | else |
| 2615 | 2635 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 2616 | 2636 | } |
| 2617 | 2637 | |
| 2618 | −static const struct amdgpu_vm_pte_funcs sdma_v4_0_vm_pte_funcs = { | |
| 2619 | − .copy_pte_num_dw = 7, | |
| 2620 | − .copy_pte = sdma_v4_0_vm_copy_pte, | |
| 2621 | − | |
| 2622 | − .write_pte = sdma_v4_0_vm_write_pte, | |
| 2623 | − .set_pte_pde = sdma_v4_0_vm_set_pte_pde, | |
| 2624 | −}; | |
| 2625 | − | |
| 2626 | −static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 2627 | −{ | |
| 2628 | − struct drm_gpu_scheduler *sched; | |
| 2629 | − unsigned i; | |
| 2630 | − | |
| 2631 | − adev->vm_manager.vm_pte_funcs = &sdma_v4_0_vm_pte_funcs; | |
| 2632 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 2633 | − if (adev->sdma.has_page_queue) | |
| 2634 | − sched = &adev->sdma.instance[i].page.sched; | |
| 2635 | − else | |
| 2636 | − sched = &adev->sdma.instance[i].ring.sched; | |
| 2637 | − adev->vm_manager.vm_pte_scheds[i] = sched; | |
| 2638 | − } | |
| 2639 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 2640 | −} | |
| 2641 | − | |
| 2642 | 2638 | static void sdma_v4_0_get_ras_error_count(uint32_t value, |
| 2643 | 2639 | uint32_t instance, |
| 2644 | 2640 | uint32_t *sec_count) |
| @@ -104,7 +104,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_4_4_2[] = { · 103 unmodified lines | ||
| 104 | 104 | |
| 105 | 105 | static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev); |
| 106 | 106 | static void sdma_v4_4_2_set_buffer_funcs(struct amdgpu_device *adev); |
| 107 | −static void sdma_v4_4_2_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 108 | 107 | static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev); |
| 109 | 108 | static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev); |
| 110 | 109 | static void sdma_v4_4_2_update_reset_mask(struct amdgpu_device *adev); |
| @@ -1347,6 +1346,14 @@ static const struct amdgpu_sdma_funcs sdma_v4_4_2_sdma_funcs = { · 1236 unmodified lines | ||
| 1347 | 1346 | .soft_reset_kernel_queue = &sdma_v4_4_2_soft_reset_engine, |
| 1348 | 1347 | }; |
| 1349 | 1348 | |
| 1349 | +static const struct amdgpu_vm_pte_funcs sdma_v4_4_2_vm_pte_funcs = { | |
| 1350 | + .copy_pte_num_dw = 7, | |
| 1351 | + .copy_pte = sdma_v4_4_2_vm_copy_pte, | |
| 1352 | + | |
| 1353 | + .write_pte = sdma_v4_4_2_vm_write_pte, | |
| 1354 | + .set_pte_pde = sdma_v4_4_2_vm_set_pte_pde, | |
| 1355 | +}; | |
| 1356 | + | |
| 1350 | 1357 | static int sdma_v4_4_2_early_init(struct amdgpu_ip_block *ip_block) |
| 1351 | 1358 | { |
| 1352 | 1359 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1362,7 +1369,7 @@ static int sdma_v4_4_2_early_init(struct amdgpu_ip_block *ip_block) · 9 unmodified lines | ||
| 1362 | 1369 | |
| 1363 | 1370 | sdma_v4_4_2_set_ring_funcs(adev); |
| 1364 | 1371 | sdma_v4_4_2_set_buffer_funcs(adev); |
| 1365 | − sdma_v4_4_2_set_vm_pte_funcs(adev); | |
| 1372 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v4_4_2_vm_pte_funcs); | |
| 1366 | 1373 | sdma_v4_4_2_set_irq_funcs(adev); |
| 1367 | 1374 | sdma_v4_4_2_set_ras_funcs(adev); |
| 1368 | 1375 | return 0; |
| @@ -2298,11 +2305,11 @@ static void sdma_v4_4_2_emit_fill_buffer(struct amdgpu_ib *ib, · 929 unmodified lines | ||
| 2298 | 2305 | } |
| 2299 | 2306 | |
| 2300 | 2307 | static const struct amdgpu_buffer_funcs sdma_v4_4_2_buffer_funcs = { |
| 2301 | − .copy_max_bytes = 0x400000, | |
| 2308 | + .copy_max_bytes = 1 << 30, | |
| 2302 | 2309 | .copy_num_dw = 7, |
| 2303 | 2310 | .emit_copy_buffer = sdma_v4_4_2_emit_copy_buffer, |
| 2304 | 2311 | |
| 2305 | − .fill_max_bytes = 0x400000, | |
| 2312 | + .fill_max_bytes = 1 << 30, | |
| 2306 | 2313 | .fill_num_dw = 5, |
| 2307 | 2314 | .emit_fill_buffer = sdma_v4_4_2_emit_fill_buffer, |
| 2308 | 2315 | }; |
| @@ -2316,30 +2323,6 @@ static void sdma_v4_4_2_set_buffer_funcs(struct amdgpu_device *adev) · 7 unmodified lines | ||
| 2316 | 2323 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 2317 | 2324 | } |
| 2318 | 2325 | |
| 2319 | −static const struct amdgpu_vm_pte_funcs sdma_v4_4_2_vm_pte_funcs = { | |
| 2320 | − .copy_pte_num_dw = 7, | |
| 2321 | − .copy_pte = sdma_v4_4_2_vm_copy_pte, | |
| 2322 | − | |
| 2323 | − .write_pte = sdma_v4_4_2_vm_write_pte, | |
| 2324 | − .set_pte_pde = sdma_v4_4_2_vm_set_pte_pde, | |
| 2325 | −}; | |
| 2326 | − | |
| 2327 | −static void sdma_v4_4_2_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 2328 | −{ | |
| 2329 | − struct drm_gpu_scheduler *sched; | |
| 2330 | − unsigned i; | |
| 2331 | − | |
| 2332 | − adev->vm_manager.vm_pte_funcs = &sdma_v4_4_2_vm_pte_funcs; | |
| 2333 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 2334 | − if (adev->sdma.has_page_queue) | |
| 2335 | − sched = &adev->sdma.instance[i].page.sched; | |
| 2336 | − else | |
| 2337 | − sched = &adev->sdma.instance[i].ring.sched; | |
| 2338 | − adev->vm_manager.vm_pte_scheds[i] = sched; | |
| 2339 | − } | |
| 2340 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 2341 | −} | |
| 2342 | − | |
| 2343 | 2326 | /** |
| 2344 | 2327 | * sdma_v4_4_2_update_reset_mask - update reset mask for SDMA |
| 2345 | 2328 | * @adev: Pointer to the AMDGPU device structure |
| @@ -110,7 +110,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_5_0[] = { · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | static void sdma_v5_0_set_ring_funcs(struct amdgpu_device *adev); |
| 112 | 112 | static void sdma_v5_0_set_buffer_funcs(struct amdgpu_device *adev); |
| 113 | −static void sdma_v5_0_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 114 | 113 | static void sdma_v5_0_set_irq_funcs(struct amdgpu_device *adev); |
| 115 | 114 | static int sdma_v5_0_stop_queue(struct amdgpu_ring *ring); |
| 116 | 115 | static int sdma_v5_0_restore_queue(struct amdgpu_ring *ring); |
| @@ -1357,6 +1356,13 @@ static const struct amdgpu_sdma_funcs sdma_v5_0_sdma_funcs = { · 1240 unmodified lines | ||
| 1357 | 1356 | .soft_reset_kernel_queue = &sdma_v5_0_soft_reset_engine, |
| 1358 | 1357 | }; |
| 1359 | 1358 | |
| 1359 | +static const struct amdgpu_vm_pte_funcs sdma_v5_0_vm_pte_funcs = { | |
| 1360 | + .copy_pte_num_dw = 7, | |
| 1361 | + .copy_pte = sdma_v5_0_vm_copy_pte, | |
| 1362 | + .write_pte = sdma_v5_0_vm_write_pte, | |
| 1363 | + .set_pte_pde = sdma_v5_0_vm_set_pte_pde, | |
| 1364 | +}; | |
| 1365 | + | |
| 1360 | 1366 | static int sdma_v5_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1361 | 1367 | { |
| 1362 | 1368 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1368,7 +1374,7 @@ static int sdma_v5_0_early_init(struct amdgpu_ip_block *ip_block) · 5 unmodified lines | ||
| 1368 | 1374 | |
| 1369 | 1375 | sdma_v5_0_set_ring_funcs(adev); |
| 1370 | 1376 | sdma_v5_0_set_buffer_funcs(adev); |
| 1371 | − sdma_v5_0_set_vm_pte_funcs(adev); | |
| 1377 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v5_0_vm_pte_funcs); | |
| 1372 | 1378 | sdma_v5_0_set_irq_funcs(adev); |
| 1373 | 1379 | sdma_v5_0_set_mqd_funcs(adev); |
| 1374 | 1380 | |
| @@ -2052,27 +2058,6 @@ static void sdma_v5_0_set_buffer_funcs(struct amdgpu_device *adev) · 677 unmodified lines | ||
| 2052 | 2058 | } |
| 2053 | 2059 | } |
| 2054 | 2060 | |
| 2055 | −static const struct amdgpu_vm_pte_funcs sdma_v5_0_vm_pte_funcs = { | |
| 2056 | − .copy_pte_num_dw = 7, | |
| 2057 | − .copy_pte = sdma_v5_0_vm_copy_pte, | |
| 2058 | − .write_pte = sdma_v5_0_vm_write_pte, | |
| 2059 | − .set_pte_pde = sdma_v5_0_vm_set_pte_pde, | |
| 2060 | −}; | |
| 2061 | − | |
| 2062 | −static void sdma_v5_0_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 2063 | −{ | |
| 2064 | − unsigned i; | |
| 2065 | − | |
| 2066 | − if (adev->vm_manager.vm_pte_funcs == NULL) { | |
| 2067 | − adev->vm_manager.vm_pte_funcs = &sdma_v5_0_vm_pte_funcs; | |
| 2068 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 2069 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 2070 | − &adev->sdma.instance[i].ring.sched; | |
| 2071 | − } | |
| 2072 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 2073 | − } | |
| 2074 | −} | |
| 2075 | − | |
| 2076 | 2061 | const struct amdgpu_ip_block_version sdma_v5_0_ip_block = { |
| 2077 | 2062 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 2078 | 2063 | .major = 5, |
| @@ -111,7 +111,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_5_2[] = { · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | static void sdma_v5_2_set_ring_funcs(struct amdgpu_device *adev); |
| 113 | 113 | static void sdma_v5_2_set_buffer_funcs(struct amdgpu_device *adev); |
| 114 | −static void sdma_v5_2_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 115 | 114 | static void sdma_v5_2_set_irq_funcs(struct amdgpu_device *adev); |
| 116 | 115 | static int sdma_v5_2_stop_queue(struct amdgpu_ring *ring); |
| 117 | 116 | static int sdma_v5_2_restore_queue(struct amdgpu_ring *ring); |
| @@ -1248,6 +1247,13 @@ static void sdma_v5_2_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring, · 1130 unmodified lines | ||
| 1248 | 1247 | amdgpu_ring_emit_reg_wait(ring, reg1, mask, mask); |
| 1249 | 1248 | } |
| 1250 | 1249 | |
| 1250 | +static const struct amdgpu_vm_pte_funcs sdma_v5_2_vm_pte_funcs = { | |
| 1251 | + .copy_pte_num_dw = 7, | |
| 1252 | + .copy_pte = sdma_v5_2_vm_copy_pte, | |
| 1253 | + .write_pte = sdma_v5_2_vm_write_pte, | |
| 1254 | + .set_pte_pde = sdma_v5_2_vm_set_pte_pde, | |
| 1255 | +}; | |
| 1256 | + | |
| 1251 | 1257 | static int sdma_v5_2_early_init(struct amdgpu_ip_block *ip_block) |
| 1252 | 1258 | { |
| 1253 | 1259 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1259,7 +1265,7 @@ static int sdma_v5_2_early_init(struct amdgpu_ip_block *ip_block) · 5 unmodified lines | ||
| 1259 | 1265 | |
| 1260 | 1266 | sdma_v5_2_set_ring_funcs(adev); |
| 1261 | 1267 | sdma_v5_2_set_buffer_funcs(adev); |
| 1262 | − sdma_v5_2_set_vm_pte_funcs(adev); | |
| 1268 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v5_2_vm_pte_funcs); | |
| 1263 | 1269 | sdma_v5_2_set_irq_funcs(adev); |
| 1264 | 1270 | sdma_v5_2_set_mqd_funcs(adev); |
| 1265 | 1271 | |
| @@ -2039,11 +2045,11 @@ static void sdma_v5_2_emit_fill_buffer(struct amdgpu_ib *ib, · 773 unmodified lines | ||
| 2039 | 2045 | } |
| 2040 | 2046 | |
| 2041 | 2047 | static const struct amdgpu_buffer_funcs sdma_v5_2_buffer_funcs = { |
| 2042 | − .copy_max_bytes = 0x400000, | |
| 2048 | + .copy_max_bytes = 1 << 30, | |
| 2043 | 2049 | .copy_num_dw = 7, |
| 2044 | 2050 | .emit_copy_buffer = sdma_v5_2_emit_copy_buffer, |
| 2045 | 2051 | |
| 2046 | − .fill_max_bytes = 0x400000, | |
| 2052 | + .fill_max_bytes = 1 << 30, /* HW supports 1 << 30, but PAL uses 1 << 22 */ | |
| 2047 | 2053 | .fill_num_dw = 5, |
| 2048 | 2054 | .emit_fill_buffer = sdma_v5_2_emit_fill_buffer, |
| 2049 | 2055 | }; |
| @@ -2056,27 +2062,6 @@ static void sdma_v5_2_set_buffer_funcs(struct amdgpu_device *adev) · 6 unmodified lines | ||
| 2056 | 2062 | } |
| 2057 | 2063 | } |
| 2058 | 2064 | |
| 2059 | −static const struct amdgpu_vm_pte_funcs sdma_v5_2_vm_pte_funcs = { | |
| 2060 | − .copy_pte_num_dw = 7, | |
| 2061 | − .copy_pte = sdma_v5_2_vm_copy_pte, | |
| 2062 | − .write_pte = sdma_v5_2_vm_write_pte, | |
| 2063 | − .set_pte_pde = sdma_v5_2_vm_set_pte_pde, | |
| 2064 | −}; | |
| 2065 | − | |
| 2066 | −static void sdma_v5_2_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 2067 | −{ | |
| 2068 | − unsigned i; | |
| 2069 | − | |
| 2070 | − if (adev->vm_manager.vm_pte_funcs == NULL) { | |
| 2071 | − adev->vm_manager.vm_pte_funcs = &sdma_v5_2_vm_pte_funcs; | |
| 2072 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 2073 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 2074 | − &adev->sdma.instance[i].ring.sched; | |
| 2075 | − } | |
| 2076 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 2077 | − } | |
| 2078 | −} | |
| 2079 | − | |
| 2080 | 2065 | const struct amdgpu_ip_block_version sdma_v5_2_ip_block = { |
| 2081 | 2066 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 2082 | 2067 | .major = 5, |
| @@ -120,7 +120,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_6_0[] = { · 119 unmodified lines | ||
| 120 | 120 | |
| 121 | 121 | static void sdma_v6_0_set_ring_funcs(struct amdgpu_device *adev); |
| 122 | 122 | static void sdma_v6_0_set_buffer_funcs(struct amdgpu_device *adev); |
| 123 | −static void sdma_v6_0_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 124 | 123 | static void sdma_v6_0_set_irq_funcs(struct amdgpu_device *adev); |
| 125 | 124 | static int sdma_v6_0_start(struct amdgpu_device *adev); |
| 126 | 125 | |
| @@ -1280,6 +1279,13 @@ static void sdma_v6_0_get_csa_info(struct amdgpu_device *adev, · 1153 unmodified lines | ||
| 1280 | 1279 | csa_info->alignment = SDMA6_CSA_ALIGNMENT; |
| 1281 | 1280 | } |
| 1282 | 1281 | |
| 1282 | +static const struct amdgpu_vm_pte_funcs sdma_v6_0_vm_pte_funcs = { | |
| 1283 | + .copy_pte_num_dw = 7, | |
| 1284 | + .copy_pte = sdma_v6_0_vm_copy_pte, | |
| 1285 | + .write_pte = sdma_v6_0_vm_write_pte, | |
| 1286 | + .set_pte_pde = sdma_v6_0_vm_set_pte_pde, | |
| 1287 | +}; | |
| 1288 | + | |
| 1283 | 1289 | static int sdma_v6_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1284 | 1290 | { |
| 1285 | 1291 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1308,7 +1314,7 @@ static int sdma_v6_0_early_init(struct amdgpu_ip_block *ip_block) · 22 unmodified lines | ||
| 1308 | 1314 | |
| 1309 | 1315 | sdma_v6_0_set_ring_funcs(adev); |
| 1310 | 1316 | sdma_v6_0_set_buffer_funcs(adev); |
| 1311 | − sdma_v6_0_set_vm_pte_funcs(adev); | |
| 1317 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v6_0_vm_pte_funcs); | |
| 1312 | 1318 | sdma_v6_0_set_irq_funcs(adev); |
| 1313 | 1319 | sdma_v6_0_set_mqd_funcs(adev); |
| 1314 | 1320 | sdma_v6_0_set_ras_funcs(adev); |
| @@ -1878,11 +1884,11 @@ static void sdma_v6_0_emit_fill_buffer(struct amdgpu_ib *ib, · 563 unmodified lines | ||
| 1878 | 1884 | } |
| 1879 | 1885 | |
| 1880 | 1886 | static const struct amdgpu_buffer_funcs sdma_v6_0_buffer_funcs = { |
| 1881 | − .copy_max_bytes = 0x400000, | |
| 1887 | + .copy_max_bytes = 1 << 30, | |
| 1882 | 1888 | .copy_num_dw = 7, |
| 1883 | 1889 | .emit_copy_buffer = sdma_v6_0_emit_copy_buffer, |
| 1884 | 1890 | |
| 1885 | − .fill_max_bytes = 0x400000, | |
| 1891 | + .fill_max_bytes = 1 << 30, | |
| 1886 | 1892 | .fill_num_dw = 5, |
| 1887 | 1893 | .emit_fill_buffer = sdma_v6_0_emit_fill_buffer, |
| 1888 | 1894 | }; |
| @@ -1893,25 +1899,6 @@ static void sdma_v6_0_set_buffer_funcs(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 1893 | 1899 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 1894 | 1900 | } |
| 1895 | 1901 | |
| 1896 | −static const struct amdgpu_vm_pte_funcs sdma_v6_0_vm_pte_funcs = { | |
| 1897 | − .copy_pte_num_dw = 7, | |
| 1898 | − .copy_pte = sdma_v6_0_vm_copy_pte, | |
| 1899 | − .write_pte = sdma_v6_0_vm_write_pte, | |
| 1900 | − .set_pte_pde = sdma_v6_0_vm_set_pte_pde, | |
| 1901 | −}; | |
| 1902 | − | |
| 1903 | −static void sdma_v6_0_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 1904 | −{ | |
| 1905 | − unsigned i; | |
| 1906 | − | |
| 1907 | − adev->vm_manager.vm_pte_funcs = &sdma_v6_0_vm_pte_funcs; | |
| 1908 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 1909 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 1910 | − &adev->sdma.instance[i].ring.sched; | |
| 1911 | − } | |
| 1912 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 1913 | −} | |
| 1914 | − | |
| 1915 | 1902 | const struct amdgpu_ip_block_version sdma_v6_0_ip_block = { |
| 1916 | 1903 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1917 | 1904 | .major = 6, |
| @@ -119,7 +119,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_7_0[] = { · 118 unmodified lines | ||
| 119 | 119 | |
| 120 | 120 | static void sdma_v7_0_set_ring_funcs(struct amdgpu_device *adev); |
| 121 | 121 | static void sdma_v7_0_set_buffer_funcs(struct amdgpu_device *adev); |
| 122 | −static void sdma_v7_0_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 123 | 122 | static void sdma_v7_0_set_irq_funcs(struct amdgpu_device *adev); |
| 124 | 123 | static int sdma_v7_0_start(struct amdgpu_device *adev); |
| 125 | 124 | |
| @@ -1264,6 +1263,13 @@ static void sdma_v7_0_get_csa_info(struct amdgpu_device *adev, · 1138 unmodified lines | ||
| 1264 | 1263 | csa_info->alignment = SDMA7_CSA_ALIGNMENT; |
| 1265 | 1264 | } |
| 1266 | 1265 | |
| 1266 | +static const struct amdgpu_vm_pte_funcs sdma_v7_0_vm_pte_funcs = { | |
| 1267 | + .copy_pte_num_dw = 8, | |
| 1268 | + .copy_pte = sdma_v7_0_vm_copy_pte, | |
| 1269 | + .write_pte = sdma_v7_0_vm_write_pte, | |
| 1270 | + .set_pte_pde = sdma_v7_0_vm_set_pte_pde, | |
| 1271 | +}; | |
| 1272 | + | |
| 1267 | 1273 | static int sdma_v7_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1268 | 1274 | { |
| 1269 | 1275 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1294,7 +1300,7 @@ static int sdma_v7_0_early_init(struct amdgpu_ip_block *ip_block) · 24 unmodified lines | ||
| 1294 | 1300 | |
| 1295 | 1301 | sdma_v7_0_set_ring_funcs(adev); |
| 1296 | 1302 | sdma_v7_0_set_buffer_funcs(adev); |
| 1297 | − sdma_v7_0_set_vm_pte_funcs(adev); | |
| 1303 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v7_0_vm_pte_funcs); | |
| 1298 | 1304 | sdma_v7_0_set_irq_funcs(adev); |
| 1299 | 1305 | sdma_v7_0_set_mqd_funcs(adev); |
| 1300 | 1306 | adev->sdma.get_csa_info = &sdma_v7_0_get_csa_info; |
| @@ -1829,10 +1835,10 @@ static void sdma_v7_0_emit_fill_buffer(struct amdgpu_ib *ib, · 528 unmodified lines | ||
| 1829 | 1835 | } |
| 1830 | 1836 | |
| 1831 | 1837 | static const struct amdgpu_buffer_funcs sdma_v7_0_buffer_funcs = { |
| 1832 | − .copy_max_bytes = 0x400000, | |
| 1838 | + .copy_max_bytes = 1 << 30, | |
| 1833 | 1839 | .copy_num_dw = 8, |
| 1834 | 1840 | .emit_copy_buffer = sdma_v7_0_emit_copy_buffer, |
| 1835 | − .fill_max_bytes = 0x400000, | |
| 1841 | + .fill_max_bytes = 1 << 30, | |
| 1836 | 1842 | .fill_num_dw = 5, |
| 1837 | 1843 | .emit_fill_buffer = sdma_v7_0_emit_fill_buffer, |
| 1838 | 1844 | }; |
| @@ -1843,25 +1849,6 @@ static void sdma_v7_0_set_buffer_funcs(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 1843 | 1849 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 1844 | 1850 | } |
| 1845 | 1851 | |
| 1846 | −static const struct amdgpu_vm_pte_funcs sdma_v7_0_vm_pte_funcs = { | |
| 1847 | − .copy_pte_num_dw = 8, | |
| 1848 | − .copy_pte = sdma_v7_0_vm_copy_pte, | |
| 1849 | − .write_pte = sdma_v7_0_vm_write_pte, | |
| 1850 | − .set_pte_pde = sdma_v7_0_vm_set_pte_pde, | |
| 1851 | −}; | |
| 1852 | − | |
| 1853 | −static void sdma_v7_0_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 1854 | −{ | |
| 1855 | − unsigned i; | |
| 1856 | − | |
| 1857 | − adev->vm_manager.vm_pte_funcs = &sdma_v7_0_vm_pte_funcs; | |
| 1858 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 1859 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 1860 | − &adev->sdma.instance[i].ring.sched; | |
| 1861 | − } | |
| 1862 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 1863 | −} | |
| 1864 | − | |
| 1865 | 1852 | const struct amdgpu_ip_block_version sdma_v7_0_ip_block = { |
| 1866 | 1853 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1867 | 1854 | .major = 7, |
| @@ -110,7 +110,6 @@ static const struct amdgpu_hwip_reg_entry sdma_reg_list_7_1[] = { · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | static void sdma_v7_1_set_ring_funcs(struct amdgpu_device *adev); |
| 112 | 112 | static void sdma_v7_1_set_buffer_funcs(struct amdgpu_device *adev); |
| 113 | −static void sdma_v7_1_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 114 | 113 | static void sdma_v7_1_set_irq_funcs(struct amdgpu_device *adev); |
| 115 | 114 | static int sdma_v7_1_inst_start(struct amdgpu_device *adev, |
| 116 | 115 | uint32_t inst_mask); |
| @@ -1248,6 +1247,13 @@ static void sdma_v7_1_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring, · 1131 unmodified lines | ||
| 1248 | 1247 | amdgpu_ring_emit_reg_wait(ring, reg1, mask, mask); |
| 1249 | 1248 | } |
| 1250 | 1249 | |
| 1250 | +static const struct amdgpu_vm_pte_funcs sdma_v7_1_vm_pte_funcs = { | |
| 1251 | + .copy_pte_num_dw = 8, | |
| 1252 | + .copy_pte = sdma_v7_1_vm_copy_pte, | |
| 1253 | + .write_pte = sdma_v7_1_vm_write_pte, | |
| 1254 | + .set_pte_pde = sdma_v7_1_vm_set_pte_pde, | |
| 1255 | +}; | |
| 1256 | + | |
| 1251 | 1257 | static int sdma_v7_1_early_init(struct amdgpu_ip_block *ip_block) |
| 1252 | 1258 | { |
| 1253 | 1259 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -1261,7 +1267,7 @@ static int sdma_v7_1_early_init(struct amdgpu_ip_block *ip_block) · 7 unmodified lines | ||
| 1261 | 1267 | |
| 1262 | 1268 | sdma_v7_1_set_ring_funcs(adev); |
| 1263 | 1269 | sdma_v7_1_set_buffer_funcs(adev); |
| 1264 | − sdma_v7_1_set_vm_pte_funcs(adev); | |
| 1270 | + amdgpu_sdma_set_vm_pte_scheds(adev, &sdma_v7_1_vm_pte_funcs); | |
| 1265 | 1271 | sdma_v7_1_set_irq_funcs(adev); |
| 1266 | 1272 | sdma_v7_1_set_mqd_funcs(adev); |
| 1267 | 1273 | |
| @@ -1739,10 +1745,10 @@ static void sdma_v7_1_emit_fill_buffer(struct amdgpu_ib *ib, · 471 unmodified lines | ||
| 1739 | 1745 | } |
| 1740 | 1746 | |
| 1741 | 1747 | static const struct amdgpu_buffer_funcs sdma_v7_1_buffer_funcs = { |
| 1742 | − .copy_max_bytes = 0x400000, | |
| 1748 | + .copy_max_bytes = 1 << 30, | |
| 1743 | 1749 | .copy_num_dw = 8, |
| 1744 | 1750 | .emit_copy_buffer = sdma_v7_1_emit_copy_buffer, |
| 1745 | − .fill_max_bytes = 0x400000, | |
| 1751 | + .fill_max_bytes = 1 << 30, | |
| 1746 | 1752 | .fill_num_dw = 5, |
| 1747 | 1753 | .emit_fill_buffer = sdma_v7_1_emit_fill_buffer, |
| 1748 | 1754 | }; |
| @@ -1753,25 +1759,6 @@ static void sdma_v7_1_set_buffer_funcs(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 1753 | 1759 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 1754 | 1760 | } |
| 1755 | 1761 | |
| 1756 | −static const struct amdgpu_vm_pte_funcs sdma_v7_1_vm_pte_funcs = { | |
| 1757 | − .copy_pte_num_dw = 8, | |
| 1758 | − .copy_pte = sdma_v7_1_vm_copy_pte, | |
| 1759 | − .write_pte = sdma_v7_1_vm_write_pte, | |
| 1760 | − .set_pte_pde = sdma_v7_1_vm_set_pte_pde, | |
| 1761 | −}; | |
| 1762 | − | |
| 1763 | −static void sdma_v7_1_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 1764 | −{ | |
| 1765 | − unsigned i; | |
| 1766 | − | |
| 1767 | − adev->vm_manager.vm_pte_funcs = &sdma_v7_1_vm_pte_funcs; | |
| 1768 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 1769 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 1770 | − &adev->sdma.instance[i].ring.sched; | |
| 1771 | − } | |
| 1772 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 1773 | −} | |
| 1774 | − | |
| 1775 | 1762 | const struct amdgpu_ip_block_version sdma_v7_1_ip_block = { |
| 1776 | 1763 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1777 | 1764 | .major = 7, |
| @@ -1027,11 +1027,11 @@ static u32 si_pcie_rreg(struct amdgpu_device *adev, u32 reg) · 1026 unmodified lines | ||
| 1027 | 1027 | unsigned long flags; |
| 1028 | 1028 | u32 r; |
| 1029 | 1029 | |
| 1030 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1030 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 1031 | 1031 | WREG32(AMDGPU_PCIE_INDEX, reg); |
| 1032 | 1032 | (void)RREG32(AMDGPU_PCIE_INDEX); |
| 1033 | 1033 | r = RREG32(AMDGPU_PCIE_DATA); |
| 1034 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1034 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 1035 | 1035 | return r; |
| 1036 | 1036 | } |
| 1037 | 1037 | |
| @@ -1039,12 +1039,12 @@ static void si_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 1039 | 1039 | { |
| 1040 | 1040 | unsigned long flags; |
| 1041 | 1041 | |
| 1042 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1042 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 1043 | 1043 | WREG32(AMDGPU_PCIE_INDEX, reg); |
| 1044 | 1044 | (void)RREG32(AMDGPU_PCIE_INDEX); |
| 1045 | 1045 | WREG32(AMDGPU_PCIE_DATA, v); |
| 1046 | 1046 | (void)RREG32(AMDGPU_PCIE_DATA); |
| 1047 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1047 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 1048 | 1048 | } |
| 1049 | 1049 | |
| 1050 | 1050 | static u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -1052,11 +1052,11 @@ static u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 1052 | 1052 | unsigned long flags; |
| 1053 | 1053 | u32 r; |
| 1054 | 1054 | |
| 1055 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1055 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 1056 | 1056 | WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); |
| 1057 | 1057 | (void)RREG32(PCIE_PORT_INDEX); |
| 1058 | 1058 | r = RREG32(PCIE_PORT_DATA); |
| 1059 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1059 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 1060 | 1060 | return r; |
| 1061 | 1061 | } |
| 1062 | 1062 | |
| @@ -1064,12 +1064,12 @@ static void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 1064 | 1064 | { |
| 1065 | 1065 | unsigned long flags; |
| 1066 | 1066 | |
| 1067 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 1067 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 1068 | 1068 | WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); |
| 1069 | 1069 | (void)RREG32(PCIE_PORT_INDEX); |
| 1070 | 1070 | WREG32(PCIE_PORT_DATA, (v)); |
| 1071 | 1071 | (void)RREG32(PCIE_PORT_DATA); |
| 1072 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 1072 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 1073 | 1073 | } |
| 1074 | 1074 | |
| 1075 | 1075 | static u32 si_smc_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -1077,10 +1077,10 @@ static u32 si_smc_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 1077 | 1077 | unsigned long flags; |
| 1078 | 1078 | u32 r; |
| 1079 | 1079 | |
| 1080 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 1080 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 1081 | 1081 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 1082 | 1082 | r = RREG32(mmSMC_IND_DATA_0); |
| 1083 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 1083 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 1084 | 1084 | return r; |
| 1085 | 1085 | } |
| 1086 | 1086 | |
| @@ -1088,10 +1088,10 @@ static void si_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 1088 | 1088 | { |
| 1089 | 1089 | unsigned long flags; |
| 1090 | 1090 | |
| 1091 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 1091 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 1092 | 1092 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 1093 | 1093 | WREG32(mmSMC_IND_DATA_0, (v)); |
| 1094 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 1094 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 1095 | 1095 | } |
| 1096 | 1096 | |
| 1097 | 1097 | static u32 si_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -1099,10 +1099,10 @@ static u32 si_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 1099 | 1099 | unsigned long flags; |
| 1100 | 1100 | u32 r; |
| 1101 | 1101 | |
| 1102 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 1102 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 1103 | 1103 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 1104 | 1104 | r = RREG32(mmUVD_CTX_DATA); |
| 1105 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 1105 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 1106 | 1106 | return r; |
| 1107 | 1107 | } |
| 1108 | 1108 | |
| @@ -1110,10 +1110,10 @@ static void si_uvd_ctx_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 1110 | 1110 | { |
| 1111 | 1111 | unsigned long flags; |
| 1112 | 1112 | |
| 1113 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 1113 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 1114 | 1114 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 1115 | 1115 | WREG32(mmUVD_CTX_DATA, (v)); |
| 1116 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 1116 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 1117 | 1117 | } |
| 1118 | 1118 | |
| 1119 | 1119 | static struct amdgpu_allowed_register_entry si_allowed_read_registers[] = { |
| @@ -2037,16 +2037,14 @@ static int si_common_early_init(struct amdgpu_ip_block *ip_block) · 917 unmodified lines | ||
| 2037 | 2037 | { |
| 2038 | 2038 | struct amdgpu_device *adev = ip_block->adev; |
| 2039 | 2039 | |
| 2040 | − adev->smc_rreg = &si_smc_rreg; | |
| 2041 | − adev->smc_wreg = &si_smc_wreg; | |
| 2042 | − adev->pcie_rreg = &si_pcie_rreg; | |
| 2043 | − adev->pcie_wreg = &si_pcie_wreg; | |
| 2044 | − adev->pciep_rreg = &si_pciep_rreg; | |
| 2045 | − adev->pciep_wreg = &si_pciep_wreg; | |
| 2046 | − adev->uvd_ctx_rreg = si_uvd_ctx_rreg; | |
| 2047 | − adev->uvd_ctx_wreg = si_uvd_ctx_wreg; | |
| 2048 | − adev->didt_rreg = NULL; | |
| 2049 | − adev->didt_wreg = NULL; | |
| 2040 | + adev->reg.smc.rreg = si_smc_rreg; | |
| 2041 | + adev->reg.smc.wreg = si_smc_wreg; | |
| 2042 | + adev->reg.pcie.rreg = &si_pcie_rreg; | |
| 2043 | + adev->reg.pcie.wreg = &si_pcie_wreg; | |
| 2044 | + adev->reg.pcie.port_rreg = &si_pciep_rreg; | |
| 2045 | + adev->reg.pcie.port_wreg = &si_pciep_wreg; | |
| 2046 | + adev->reg.uvd_ctx.rreg = &si_uvd_ctx_rreg; | |
| 2047 | + adev->reg.uvd_ctx.wreg = &si_uvd_ctx_wreg; | |
| 2050 | 2048 | |
| 2051 | 2049 | adev->asic_funcs = &si_asic_funcs; |
| 2052 | 2050 | |
| @@ -2382,10 +2380,10 @@ static inline u32 si_pif_phy0_rreg(struct amdgpu_device *adev, u32 reg) · 329 unmodified lines | ||
| 2382 | 2380 | unsigned long flags; |
| 2383 | 2381 | u32 r; |
| 2384 | 2382 | |
| 2385 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 2383 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 2386 | 2384 | WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); |
| 2387 | 2385 | r = RREG32(EVERGREEN_PIF_PHY0_DATA); |
| 2388 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 2386 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 2389 | 2387 | return r; |
| 2390 | 2388 | } |
| 2391 | 2389 | |
| @@ -2393,10 +2391,10 @@ static inline void si_pif_phy0_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 2393 | 2391 | { |
| 2394 | 2392 | unsigned long flags; |
| 2395 | 2393 | |
| 2396 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 2394 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 2397 | 2395 | WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); |
| 2398 | 2396 | WREG32(EVERGREEN_PIF_PHY0_DATA, (v)); |
| 2399 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 2397 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 2400 | 2398 | } |
| 2401 | 2399 | |
| 2402 | 2400 | static inline u32 si_pif_phy1_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -2404,10 +2402,10 @@ static inline u32 si_pif_phy1_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 2404 | 2402 | unsigned long flags; |
| 2405 | 2403 | u32 r; |
| 2406 | 2404 | |
| 2407 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 2405 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 2408 | 2406 | WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); |
| 2409 | 2407 | r = RREG32(EVERGREEN_PIF_PHY1_DATA); |
| 2410 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 2408 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 2411 | 2409 | return r; |
| 2412 | 2410 | } |
| 2413 | 2411 | |
| @@ -2415,10 +2413,10 @@ static inline void si_pif_phy1_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 2415 | 2413 | { |
| 2416 | 2414 | unsigned long flags; |
| 2417 | 2415 | |
| 2418 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 2416 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 2419 | 2417 | WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); |
| 2420 | 2418 | WREG32(EVERGREEN_PIF_PHY1_DATA, (v)); |
| 2421 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 2419 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 2422 | 2420 | } |
| 2423 | 2421 | static void si_program_aspm(struct amdgpu_device *adev) |
| 2424 | 2422 | { |
| @@ -37,7 +37,6 @@ const u32 sdma_offsets[SDMA_MAX_INSTANCE] = · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | static void si_dma_set_ring_funcs(struct amdgpu_device *adev); |
| 39 | 39 | static void si_dma_set_buffer_funcs(struct amdgpu_device *adev); |
| 40 | −static void si_dma_set_vm_pte_funcs(struct amdgpu_device *adev); | |
| 41 | 40 | static void si_dma_set_irq_funcs(struct amdgpu_device *adev); |
| 42 | 41 | |
| 43 | 42 | /** |
| @@ -473,6 +472,14 @@ static void si_dma_ring_emit_wreg(struct amdgpu_ring *ring, · 429 unmodified lines | ||
| 473 | 472 | amdgpu_ring_write(ring, val); |
| 474 | 473 | } |
| 475 | 474 | |
| 475 | +static const struct amdgpu_vm_pte_funcs si_dma_vm_pte_funcs = { | |
| 476 | + .copy_pte_num_dw = 5, | |
| 477 | + .copy_pte = si_dma_vm_copy_pte, | |
| 478 | + | |
| 479 | + .write_pte = si_dma_vm_write_pte, | |
| 480 | + .set_pte_pde = si_dma_vm_set_pte_pde, | |
| 481 | +}; | |
| 482 | + | |
| 476 | 483 | static int si_dma_early_init(struct amdgpu_ip_block *ip_block) |
| 477 | 484 | { |
| 478 | 485 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -481,7 +488,7 @@ static int si_dma_early_init(struct amdgpu_ip_block *ip_block) · 2 unmodified lines | ||
| 481 | 488 | |
| 482 | 489 | si_dma_set_ring_funcs(adev); |
| 483 | 490 | si_dma_set_buffer_funcs(adev); |
| 484 | − si_dma_set_vm_pte_funcs(adev); | |
| 491 | + amdgpu_sdma_set_vm_pte_scheds(adev, &si_dma_vm_pte_funcs); | |
| 485 | 492 | si_dma_set_irq_funcs(adev); |
| 486 | 493 | |
| 487 | 494 | return 0; |
| @@ -830,26 +837,6 @@ static void si_dma_set_buffer_funcs(struct amdgpu_device *adev) · 342 unmodified lines | ||
| 830 | 837 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; |
| 831 | 838 | } |
| 832 | 839 | |
| 833 | −static const struct amdgpu_vm_pte_funcs si_dma_vm_pte_funcs = { | |
| 834 | − .copy_pte_num_dw = 5, | |
| 835 | − .copy_pte = si_dma_vm_copy_pte, | |
| 836 | − | |
| 837 | − .write_pte = si_dma_vm_write_pte, | |
| 838 | − .set_pte_pde = si_dma_vm_set_pte_pde, | |
| 839 | −}; | |
| 840 | − | |
| 841 | −static void si_dma_set_vm_pte_funcs(struct amdgpu_device *adev) | |
| 842 | −{ | |
| 843 | − unsigned i; | |
| 844 | − | |
| 845 | − adev->vm_manager.vm_pte_funcs = &si_dma_vm_pte_funcs; | |
| 846 | − for (i = 0; i < adev->sdma.num_instances; i++) { | |
| 847 | − adev->vm_manager.vm_pte_scheds[i] = | |
| 848 | − &adev->sdma.instance[i].ring.sched; | |
| 849 | − } | |
| 850 | − adev->vm_manager.vm_pte_num_scheds = adev->sdma.num_instances; | |
| 851 | −} | |
| 852 | − | |
| 853 | 840 | const struct amdgpu_ip_block_version si_dma_ip_block = |
| 854 | 841 | { |
| 855 | 842 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| @@ -245,10 +245,10 @@ static u32 soc15_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) · 244 unmodified lines | ||
| 245 | 245 | address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); |
| 246 | 246 | data = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_DATA); |
| 247 | 247 | |
| 248 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 248 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 249 | 249 | WREG32(address, ((reg) & 0x1ff)); |
| 250 | 250 | r = RREG32(data); |
| 251 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 251 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 252 | 252 | return r; |
| 253 | 253 | } |
| 254 | 254 | |
| @@ -259,10 +259,10 @@ static void soc15_uvd_ctx_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 4 unmodified lines | ||
| 259 | 259 | address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); |
| 260 | 260 | data = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_DATA); |
| 261 | 261 | |
| 262 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 262 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 263 | 263 | WREG32(address, ((reg) & 0x1ff)); |
| 264 | 264 | WREG32(data, (v)); |
| 265 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 265 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | 268 | static u32 soc15_didt_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -273,10 +273,10 @@ static u32 soc15_didt_rreg(struct amdgpu_device *adev, u32 reg) · 4 unmodified lines | ||
| 273 | 273 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 274 | 274 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); |
| 275 | 275 | |
| 276 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 276 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 277 | 277 | WREG32(address, (reg)); |
| 278 | 278 | r = RREG32(data); |
| 279 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 279 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 280 | 280 | return r; |
| 281 | 281 | } |
| 282 | 282 | |
| @@ -287,10 +287,10 @@ static void soc15_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 4 unmodified lines | ||
| 287 | 287 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 288 | 288 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); |
| 289 | 289 | |
| 290 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 290 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 291 | 291 | WREG32(address, (reg)); |
| 292 | 292 | WREG32(data, (v)); |
| 293 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 293 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 294 | 294 | } |
| 295 | 295 | |
| 296 | 296 | static u32 soc15_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -298,10 +298,10 @@ static u32 soc15_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 298 | 298 | unsigned long flags; |
| 299 | 299 | u32 r; |
| 300 | 300 | |
| 301 | − spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); | |
| 301 | + spin_lock_irqsave(&adev->reg.gc_cac.lock, flags); | |
| 302 | 302 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); |
| 303 | 303 | r = RREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA); |
| 304 | − spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); | |
| 304 | + spin_unlock_irqrestore(&adev->reg.gc_cac.lock, flags); | |
| 305 | 305 | return r; |
| 306 | 306 | } |
| 307 | 307 | |
| @@ -309,10 +309,10 @@ static void soc15_gc_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 309 | 309 | { |
| 310 | 310 | unsigned long flags; |
| 311 | 311 | |
| 312 | − spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); | |
| 312 | + spin_lock_irqsave(&adev->reg.gc_cac.lock, flags); | |
| 313 | 313 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); |
| 314 | 314 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA, (v)); |
| 315 | − spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); | |
| 315 | + spin_unlock_irqrestore(&adev->reg.gc_cac.lock, flags); | |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | 318 | static u32 soc15_se_cac_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -320,10 +320,10 @@ static u32 soc15_se_cac_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 320 | 320 | unsigned long flags; |
| 321 | 321 | u32 r; |
| 322 | 322 | |
| 323 | − spin_lock_irqsave(&adev->se_cac_idx_lock, flags); | |
| 323 | + spin_lock_irqsave(&adev->reg.se_cac.lock, flags); | |
| 324 | 324 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); |
| 325 | 325 | r = RREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA); |
| 326 | − spin_unlock_irqrestore(&adev->se_cac_idx_lock, flags); | |
| 326 | + spin_unlock_irqrestore(&adev->reg.se_cac.lock, flags); | |
| 327 | 327 | return r; |
| 328 | 328 | } |
| 329 | 329 | |
| @@ -331,10 +331,10 @@ static void soc15_se_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 331 | 331 | { |
| 332 | 332 | unsigned long flags; |
| 333 | 333 | |
| 334 | − spin_lock_irqsave(&adev->se_cac_idx_lock, flags); | |
| 334 | + spin_lock_irqsave(&adev->reg.se_cac.lock, flags); | |
| 335 | 335 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); |
| 336 | 336 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA, (v)); |
| 337 | − spin_unlock_irqrestore(&adev->se_cac_idx_lock, flags); | |
| 337 | + spin_unlock_irqrestore(&adev->reg.se_cac.lock, flags); | |
| 338 | 338 | } |
| 339 | 339 | |
| 340 | 340 | static u32 soc15_get_config_memsize(struct amdgpu_device *adev) |
| @@ -952,7 +952,6 @@ static const struct amdgpu_asic_funcs aqua_vanjaram_asic_funcs = · 611 unmodified lines | ||
| 952 | 952 | .get_pcie_replay_count = &amdgpu_nbio_get_pcie_replay_count, |
| 953 | 953 | .supports_baco = &soc15_supports_baco, |
| 954 | 954 | .query_video_codecs = &soc15_query_video_codecs, |
| 955 | − .encode_ext_smn_addressing = &aqua_vanjaram_encode_ext_smn_addressing, | |
| 956 | 955 | .get_reg_state = &aqua_vanjaram_get_reg_state, |
| 957 | 956 | }; |
| 958 | 957 | |
| @@ -961,24 +960,22 @@ static int soc15_common_early_init(struct amdgpu_ip_block *ip_block) · 2 unmodified lines | ||
| 961 | 960 | struct amdgpu_device *adev = ip_block->adev; |
| 962 | 961 | |
| 963 | 962 | adev->nbio.funcs->set_reg_remap(adev); |
| 964 | − adev->smc_rreg = NULL; | |
| 965 | − adev->smc_wreg = NULL; | |
| 966 | − adev->pcie_rreg = &amdgpu_device_indirect_rreg; | |
| 967 | − adev->pcie_wreg = &amdgpu_device_indirect_wreg; | |
| 968 | − adev->pcie_rreg_ext = &amdgpu_device_indirect_rreg_ext; | |
| 969 | − adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext; | |
| 970 | − adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | |
| 971 | − adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | |
| 972 | − adev->pcie_rreg64_ext = &amdgpu_device_indirect_rreg64_ext; | |
| 973 | − adev->pcie_wreg64_ext = &amdgpu_device_indirect_wreg64_ext; | |
| 974 | − adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg; | |
| 975 | − adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg; | |
| 976 | − adev->didt_rreg = &soc15_didt_rreg; | |
| 977 | − adev->didt_wreg = &soc15_didt_wreg; | |
| 978 | − adev->gc_cac_rreg = &soc15_gc_cac_rreg; | |
| 979 | − adev->gc_cac_wreg = &soc15_gc_cac_wreg; | |
| 980 | − adev->se_cac_rreg = &soc15_se_cac_rreg; | |
| 981 | − adev->se_cac_wreg = &soc15_se_cac_wreg; | |
| 963 | + adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; | |
| 964 | + adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; | |
| 965 | + adev->reg.pcie.rreg_ext = &amdgpu_device_indirect_rreg_ext; | |
| 966 | + adev->reg.pcie.wreg_ext = &amdgpu_device_indirect_wreg_ext; | |
| 967 | + adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; | |
| 968 | + adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; | |
| 969 | + adev->reg.pcie.rreg64_ext = &amdgpu_device_indirect_rreg64_ext; | |
| 970 | + adev->reg.pcie.wreg64_ext = &amdgpu_device_indirect_wreg64_ext; | |
| 971 | + adev->reg.uvd_ctx.rreg = &soc15_uvd_ctx_rreg; | |
| 972 | + adev->reg.uvd_ctx.wreg = &soc15_uvd_ctx_wreg; | |
| 973 | + adev->reg.didt.rreg = &soc15_didt_rreg; | |
| 974 | + adev->reg.didt.wreg = &soc15_didt_wreg; | |
| 975 | + adev->reg.gc_cac.rreg = &soc15_gc_cac_rreg; | |
| 976 | + adev->reg.gc_cac.wreg = &soc15_gc_cac_wreg; | |
| 977 | + adev->reg.se_cac.rreg = &soc15_se_cac_rreg; | |
| 978 | + adev->reg.se_cac.wreg = &soc15_se_cac_wreg; | |
| 982 | 979 | |
| 983 | 980 | adev->rev_id = amdgpu_device_get_rev_id(adev); |
| 984 | 981 | adev->external_rev_id = 0xFF; |
| @@ -1200,6 +1197,7 @@ static int soc15_common_early_init(struct amdgpu_ip_block *ip_block) · 215 unmodified lines | ||
| 1200 | 1197 | case IP_VERSION(9, 4, 4): |
| 1201 | 1198 | case IP_VERSION(9, 5, 0): |
| 1202 | 1199 | adev->asic_funcs = &aqua_vanjaram_asic_funcs; |
| 1200 | + adev->reg.smn.get_smn_base = &amdgpu_reg_smn_v1_0_get_base; | |
| 1203 | 1201 | adev->cg_flags = |
| 1204 | 1202 | AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGCG | |
| 1205 | 1203 | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_SDMA_MGCG | |
| @@ -118,7 +118,6 @@ int vega10_reg_base_init(struct amdgpu_device *adev); · 117 unmodified lines | ||
| 118 | 118 | int vega20_reg_base_init(struct amdgpu_device *adev); |
| 119 | 119 | int arct_reg_base_init(struct amdgpu_device *adev); |
| 120 | 120 | int aldebaran_reg_base_init(struct amdgpu_device *adev); |
| 121 | −u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id); | |
| 122 | 121 | int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev); |
| 123 | 122 | ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, |
| 124 | 123 | enum amdgpu_reg_state reg_state, void *buf, |
| @@ -195,19 +195,22 @@ · 194 unmodified lines | ||
| 195 | 195 | __RREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, AMDGPU_REGS_RLC, ip##_HWIP, inst) |
| 196 | 196 | |
| 197 | 197 | /* inst equals to ext for some IPs */ |
| 198 | −#define RREG32_SOC15_EXT(ip, inst, reg, ext) \ | |
| 199 | − RREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * 4 \ | |
| 200 | − + adev->asic_funcs->encode_ext_smn_addressing(ext)) \ | |
| 201 | − | |
| 202 | −#define WREG32_SOC15_EXT(ip, inst, reg, ext, value) \ | |
| 203 | − WREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * 4 \ | |
| 204 | − + adev->asic_funcs->encode_ext_smn_addressing(ext), \ | |
| 205 | − value) \ | |
| 206 | − | |
| 207 | −#define RREG64_MCA(ext, mca_base, idx) \ | |
| 208 | − RREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8)) | |
| 209 | − | |
| 210 | −#define WREG64_MCA(ext, mca_base, idx, val) \ | |
| 211 | − WREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8), val) | |
| 198 | +#define RREG32_SOC15_EXT(ip, inst, reg, ext) \ | |
| 199 | + RREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + \ | |
| 200 | + reg) * 4 + \ | |
| 201 | + amdgpu_reg_get_smn_base64(adev, ip##_HWIP, inst)) | |
| 202 | + | |
| 203 | +#define WREG32_SOC15_EXT(ip, inst, reg, ext, value) \ | |
| 204 | + WREG32_PCIE_EXT( \ | |
| 205 | + (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * \ | |
| 206 | + 4 + \ | |
| 207 | + amdgpu_reg_get_smn_base64(adev, ip##_HWIP, inst), \ | |
| 208 | + value) | |
| 209 | + | |
| 210 | +#define RREG64_MCA(smn_base, mca_base, idx) \ | |
| 211 | + RREG64_PCIE_EXT(smn_base + mca_base + (idx * 8)) | |
| 212 | + | |
| 213 | +#define WREG64_MCA(smn_base, mca_base, idx, val) \ | |
| 214 | + WREG64_PCIE_EXT(smn_base + mca_base + (idx * 8), val) | |
| 212 | 215 | |
| 213 | 216 | #endif |
| @@ -229,10 +229,10 @@ static u32 soc21_didt_rreg(struct amdgpu_device *adev, u32 reg) · 228 unmodified lines | ||
| 229 | 229 | address = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_INDEX); |
| 230 | 230 | data = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_DATA); |
| 231 | 231 | |
| 232 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 232 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 233 | 233 | WREG32(address, (reg)); |
| 234 | 234 | r = RREG32(data); |
| 235 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 235 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 236 | 236 | return r; |
| 237 | 237 | } |
| 238 | 238 | |
| @@ -243,10 +243,10 @@ static void soc21_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 4 unmodified lines | ||
| 243 | 243 | address = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_INDEX); |
| 244 | 244 | data = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_DATA); |
| 245 | 245 | |
| 246 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 246 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 247 | 247 | WREG32(address, (reg)); |
| 248 | 248 | WREG32(data, (v)); |
| 249 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 249 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 252 | static u32 soc21_get_config_memsize(struct amdgpu_device *adev) |
| @@ -589,21 +589,15 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block) · 336 unmodified lines | ||
| 589 | 589 | struct amdgpu_device *adev = ip_block->adev; |
| 590 | 590 | |
| 591 | 591 | adev->nbio.funcs->set_reg_remap(adev); |
| 592 | − adev->smc_rreg = NULL; | |
| 593 | − adev->smc_wreg = NULL; | |
| 594 | − adev->pcie_rreg = &amdgpu_device_indirect_rreg; | |
| 595 | − adev->pcie_wreg = &amdgpu_device_indirect_wreg; | |
| 596 | − adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | |
| 597 | − adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | |
| 598 | − adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | |
| 599 | − adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | |
| 600 | − | |
| 601 | − /* TODO: will add them during VCN v2 implementation */ | |
| 602 | − adev->uvd_ctx_rreg = NULL; | |
| 603 | − adev->uvd_ctx_wreg = NULL; | |
| 604 | − | |
| 605 | − adev->didt_rreg = &soc21_didt_rreg; | |
| 606 | − adev->didt_wreg = &soc21_didt_wreg; | |
| 592 | + adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; | |
| 593 | + adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; | |
| 594 | + adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; | |
| 595 | + adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; | |
| 596 | + adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; | |
| 597 | + adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; | |
| 598 | + | |
| 599 | + adev->reg.didt.rreg = &soc21_didt_rreg; | |
| 600 | + adev->reg.didt.wreg = &soc21_didt_wreg; | |
| 607 | 601 | |
| 608 | 602 | adev->asic_funcs = &soc21_asic_funcs; |
| 609 | 603 | |
| @@ -858,7 +852,9 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block) · 248 unmodified lines | ||
| 858 | 852 | AMD_CG_SUPPORT_IH_CG | |
| 859 | 853 | AMD_CG_SUPPORT_BIF_MGCG | |
| 860 | 854 | AMD_CG_SUPPORT_BIF_LS; |
| 861 | − adev->pg_flags = AMD_PG_SUPPORT_VCN | | |
| 855 | + adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG | | |
| 856 | + AMD_PG_SUPPORT_VCN | | |
| 857 | + AMD_PG_SUPPORT_JPEG_DPG | | |
| 862 | 858 | AMD_PG_SUPPORT_JPEG | |
| 863 | 859 | AMD_PG_SUPPORT_GFX_PG; |
| 864 | 860 | adev->external_rev_id = adev->rev_id + 0x1; |
| @@ -362,18 +362,12 @@ static int soc24_common_early_init(struct amdgpu_ip_block *ip_block) · 361 unmodified lines | ||
| 362 | 362 | struct amdgpu_device *adev = ip_block->adev; |
| 363 | 363 | |
| 364 | 364 | adev->nbio.funcs->set_reg_remap(adev); |
| 365 | − adev->smc_rreg = NULL; | |
| 366 | − adev->smc_wreg = NULL; | |
| 367 | − adev->pcie_rreg = &amdgpu_device_indirect_rreg; | |
| 368 | − adev->pcie_wreg = &amdgpu_device_indirect_wreg; | |
| 369 | − adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | |
| 370 | − adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | |
| 371 | − adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | |
| 372 | − adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | |
| 373 | − adev->uvd_ctx_rreg = NULL; | |
| 374 | − adev->uvd_ctx_wreg = NULL; | |
| 375 | − adev->didt_rreg = NULL; | |
| 376 | − adev->didt_wreg = NULL; | |
| 365 | + adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; | |
| 366 | + adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; | |
| 367 | + adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; | |
| 368 | + adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; | |
| 369 | + adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; | |
| 370 | + adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; | |
| 377 | 371 | |
| 378 | 372 | adev->asic_funcs = &soc24_asic_funcs; |
| 379 | 373 | |
| @@ -250,22 +250,16 @@ static int soc_v1_0_common_early_init(struct amdgpu_ip_block *ip_block) · 249 unmodified lines | ||
| 250 | 250 | { |
| 251 | 251 | struct amdgpu_device *adev = ip_block->adev; |
| 252 | 252 | |
| 253 | − adev->smc_rreg = NULL; | |
| 254 | − adev->smc_wreg = NULL; | |
| 255 | − adev->pcie_rreg = &amdgpu_device_indirect_rreg; | |
| 256 | − adev->pcie_wreg = &amdgpu_device_indirect_wreg; | |
| 257 | − adev->pcie_rreg_ext = &amdgpu_device_indirect_rreg_ext; | |
| 258 | − adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext; | |
| 259 | − adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | |
| 260 | − adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | |
| 261 | − adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | |
| 262 | − adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | |
| 263 | − adev->pcie_rreg64_ext = &amdgpu_device_indirect_rreg64_ext; | |
| 264 | − adev->pcie_wreg64_ext = &amdgpu_device_indirect_wreg64_ext; | |
| 265 | − adev->uvd_ctx_rreg = NULL; | |
| 266 | − adev->uvd_ctx_wreg = NULL; | |
| 267 | − adev->didt_rreg = NULL; | |
| 268 | − adev->didt_wreg = NULL; | |
| 253 | + adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; | |
| 254 | + adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; | |
| 255 | + adev->reg.pcie.rreg_ext = &amdgpu_device_indirect_rreg_ext; | |
| 256 | + adev->reg.pcie.wreg_ext = &amdgpu_device_indirect_wreg_ext; | |
| 257 | + adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; | |
| 258 | + adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; | |
| 259 | + adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; | |
| 260 | + adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; | |
| 261 | + adev->reg.pcie.rreg64_ext = &amdgpu_device_indirect_rreg64_ext; | |
| 262 | + adev->reg.pcie.wreg64_ext = &amdgpu_device_indirect_wreg64_ext; | |
| 269 | 263 | |
| 270 | 264 | adev->asic_funcs = &soc_v1_0_asic_funcs; |
| 271 | 265 | |
| @@ -47,11 +47,6 @@ · 46 unmodified lines | ||
| 47 | 47 | #define VCE_V1_0_DATA_SIZE (7808 * (AMDGPU_MAX_VCE_HANDLES + 1)) |
| 48 | 48 | #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02 |
| 49 | 49 | |
| 50 | −#define VCE_V1_0_GART_PAGE_START \ | |
| 51 | − (AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS) | |
| 52 | −#define VCE_V1_0_GART_ADDR_START \ | |
| 53 | − (VCE_V1_0_GART_PAGE_START * AMDGPU_GPU_PAGE_SIZE) | |
| 54 | − | |
| 55 | 50 | static void vce_v1_0_set_ring_funcs(struct amdgpu_device *adev); |
| 56 | 51 | static void vce_v1_0_set_irq_funcs(struct amdgpu_device *adev); |
| 57 | 52 | |
| @@ -535,27 +530,29 @@ static int vce_v1_0_early_init(struct amdgpu_ip_block *ip_block) · 477 unmodified lines | ||
| 535 | 530 | */ |
| 536 | 531 | static int vce_v1_0_ensure_vcpu_bo_32bit_addr(struct amdgpu_device *adev) |
| 537 | 532 | { |
| 538 | − u64 gpu_addr = amdgpu_bo_gpu_offset(adev->vce.vcpu_bo); | |
| 539 | 533 | u64 bo_size = amdgpu_bo_size(adev->vce.vcpu_bo); |
| 540 | 534 | u64 max_vcpu_bo_addr = 0xffffffff - bo_size; |
| 541 | 535 | u64 num_pages = ALIGN(bo_size, AMDGPU_GPU_PAGE_SIZE) / AMDGPU_GPU_PAGE_SIZE; |
| 542 | 536 | u64 pa = amdgpu_gmc_vram_pa(adev, adev->vce.vcpu_bo); |
| 543 | 537 | u64 flags = AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | AMDGPU_PTE_VALID; |
| 538 | + u64 vce_gart_start_offs; | |
| 539 | + int r; | |
| 544 | 540 | |
| 545 | − /* | |
| 546 | − * Check if the VCPU BO already has a 32-bit address. | |
| 547 | − * Eg. if MC is configured to put VRAM in the low address range. | |
| 548 | − */ | |
| 549 | − if (gpu_addr <= max_vcpu_bo_addr) | |
| 550 | − return 0; | |
| 541 | + r = amdgpu_gtt_mgr_alloc_entries(&adev->mman.gtt_mgr, | |
| 542 | + &adev->vce.gart_node, num_pages, | |
| 543 | + DRM_MM_INSERT_LOW); | |
| 544 | + if (r) | |
| 545 | + return r; | |
| 546 | + | |
| 547 | + vce_gart_start_offs = amdgpu_gtt_node_to_byte_offset(&adev->vce.gart_node); | |
| 551 | 548 | |
| 552 | 549 | /* Check if we can map the VCPU BO in GART to a 32-bit address. */ |
| 553 | − if (adev->gmc.gart_start + VCE_V1_0_GART_ADDR_START > max_vcpu_bo_addr) | |
| 550 | + if (adev->gmc.gart_start + vce_gart_start_offs > max_vcpu_bo_addr) | |
| 554 | 551 | return -EINVAL; |
| 555 | 552 | |
| 556 | − amdgpu_gart_map_vram_range(adev, pa, VCE_V1_0_GART_PAGE_START, | |
| 553 | + amdgpu_gart_map_vram_range(adev, pa, adev->vce.gart_node.start, | |
| 557 | 554 | num_pages, flags, adev->gart.ptr); |
| 558 | − adev->vce.gpu_addr = adev->gmc.gart_start + VCE_V1_0_GART_ADDR_START; | |
| 555 | + adev->vce.gpu_addr = adev->gmc.gart_start + vce_gart_start_offs; | |
| 559 | 556 | if (adev->vce.gpu_addr > max_vcpu_bo_addr) |
| 560 | 557 | return -EINVAL; |
| 561 | 558 | |
| @@ -610,7 +607,11 @@ static int vce_v1_0_sw_fini(struct amdgpu_ip_block *ip_block) · 48 unmodified lines | ||
| 610 | 607 | if (r) |
| 611 | 608 | return r; |
| 612 | 609 | |
| 613 | − return amdgpu_vce_sw_fini(adev); | |
| 610 | + r = amdgpu_vce_sw_fini(adev); | |
| 611 | + | |
| 612 | + amdgpu_gtt_mgr_free_entries(&adev->mman.gtt_mgr, &adev->vce.gart_node); | |
| 613 | + | |
| 614 | + return r; | |
| 614 | 615 | } |
| 615 | 616 | |
| 616 | 617 | /** |
| @@ -299,11 +299,11 @@ static u32 vi_pcie_rreg(struct amdgpu_device *adev, u32 reg) · 298 unmodified lines | ||
| 299 | 299 | unsigned long flags; |
| 300 | 300 | u32 r; |
| 301 | 301 | |
| 302 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 302 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 303 | 303 | WREG32_NO_KIQ(mmPCIE_INDEX, reg); |
| 304 | 304 | (void)RREG32_NO_KIQ(mmPCIE_INDEX); |
| 305 | 305 | r = RREG32_NO_KIQ(mmPCIE_DATA); |
| 306 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 306 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 307 | 307 | return r; |
| 308 | 308 | } |
| 309 | 309 | |
| @@ -311,12 +311,12 @@ static void vi_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 311 | 311 | { |
| 312 | 312 | unsigned long flags; |
| 313 | 313 | |
| 314 | − spin_lock_irqsave(&adev->pcie_idx_lock, flags); | |
| 314 | + spin_lock_irqsave(&adev->reg.pcie.lock, flags); | |
| 315 | 315 | WREG32_NO_KIQ(mmPCIE_INDEX, reg); |
| 316 | 316 | (void)RREG32_NO_KIQ(mmPCIE_INDEX); |
| 317 | 317 | WREG32_NO_KIQ(mmPCIE_DATA, v); |
| 318 | 318 | (void)RREG32_NO_KIQ(mmPCIE_DATA); |
| 319 | − spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | |
| 319 | + spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); | |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | static u32 vi_smc_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -324,10 +324,10 @@ static u32 vi_smc_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 324 | 324 | unsigned long flags; |
| 325 | 325 | u32 r; |
| 326 | 326 | |
| 327 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 327 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 328 | 328 | WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg)); |
| 329 | 329 | r = RREG32_NO_KIQ(mmSMC_IND_DATA_11); |
| 330 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 330 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 331 | 331 | return r; |
| 332 | 332 | } |
| 333 | 333 | |
| @@ -335,10 +335,10 @@ static void vi_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 335 | 335 | { |
| 336 | 336 | unsigned long flags; |
| 337 | 337 | |
| 338 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 338 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 339 | 339 | WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg)); |
| 340 | 340 | WREG32_NO_KIQ(mmSMC_IND_DATA_11, (v)); |
| 341 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 341 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | 344 | /* smu_8_0_d.h */ |
| @@ -350,10 +350,10 @@ static u32 cz_smc_rreg(struct amdgpu_device *adev, u32 reg) · 5 unmodified lines | ||
| 350 | 350 | unsigned long flags; |
| 351 | 351 | u32 r; |
| 352 | 352 | |
| 353 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 353 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 354 | 354 | WREG32(mmMP0PUB_IND_INDEX, (reg)); |
| 355 | 355 | r = RREG32(mmMP0PUB_IND_DATA); |
| 356 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 356 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 357 | 357 | return r; |
| 358 | 358 | } |
| 359 | 359 | |
| @@ -361,10 +361,10 @@ static void cz_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 361 | 361 | { |
| 362 | 362 | unsigned long flags; |
| 363 | 363 | |
| 364 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 364 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 365 | 365 | WREG32(mmMP0PUB_IND_INDEX, (reg)); |
| 366 | 366 | WREG32(mmMP0PUB_IND_DATA, (v)); |
| 367 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 367 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | 370 | static u32 vi_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -372,10 +372,10 @@ static u32 vi_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 372 | 372 | unsigned long flags; |
| 373 | 373 | u32 r; |
| 374 | 374 | |
| 375 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 375 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 376 | 376 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 377 | 377 | r = RREG32(mmUVD_CTX_DATA); |
| 378 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 378 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 379 | 379 | return r; |
| 380 | 380 | } |
| 381 | 381 | |
| @@ -383,10 +383,10 @@ static void vi_uvd_ctx_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 383 | 383 | { |
| 384 | 384 | unsigned long flags; |
| 385 | 385 | |
| 386 | − spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); | |
| 386 | + spin_lock_irqsave(&adev->reg.uvd_ctx.lock, flags); | |
| 387 | 387 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 388 | 388 | WREG32(mmUVD_CTX_DATA, (v)); |
| 389 | − spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); | |
| 389 | + spin_unlock_irqrestore(&adev->reg.uvd_ctx.lock, flags); | |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | 392 | static u32 vi_didt_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -394,10 +394,10 @@ static u32 vi_didt_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 394 | 394 | unsigned long flags; |
| 395 | 395 | u32 r; |
| 396 | 396 | |
| 397 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 397 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 398 | 398 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 399 | 399 | r = RREG32(mmDIDT_IND_DATA); |
| 400 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 400 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 401 | 401 | return r; |
| 402 | 402 | } |
| 403 | 403 | |
| @@ -405,10 +405,10 @@ static void vi_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 405 | 405 | { |
| 406 | 406 | unsigned long flags; |
| 407 | 407 | |
| 408 | − spin_lock_irqsave(&adev->didt_idx_lock, flags); | |
| 408 | + spin_lock_irqsave(&adev->reg.didt.lock, flags); | |
| 409 | 409 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 410 | 410 | WREG32(mmDIDT_IND_DATA, (v)); |
| 411 | − spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | |
| 411 | + spin_unlock_irqrestore(&adev->reg.didt.lock, flags); | |
| 412 | 412 | } |
| 413 | 413 | |
| 414 | 414 | static u32 vi_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) |
| @@ -416,10 +416,10 @@ static u32 vi_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) · 1 unmodified line | ||
| 416 | 416 | unsigned long flags; |
| 417 | 417 | u32 r; |
| 418 | 418 | |
| 419 | − spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); | |
| 419 | + spin_lock_irqsave(&adev->reg.gc_cac.lock, flags); | |
| 420 | 420 | WREG32(mmGC_CAC_IND_INDEX, (reg)); |
| 421 | 421 | r = RREG32(mmGC_CAC_IND_DATA); |
| 422 | − spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); | |
| 422 | + spin_unlock_irqrestore(&adev->reg.gc_cac.lock, flags); | |
| 423 | 423 | return r; |
| 424 | 424 | } |
| 425 | 425 | |
| @@ -427,10 +427,10 @@ static void vi_gc_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) · 1 unmodified line | ||
| 427 | 427 | { |
| 428 | 428 | unsigned long flags; |
| 429 | 429 | |
| 430 | − spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); | |
| 430 | + spin_lock_irqsave(&adev->reg.gc_cac.lock, flags); | |
| 431 | 431 | WREG32(mmGC_CAC_IND_INDEX, (reg)); |
| 432 | 432 | WREG32(mmGC_CAC_IND_DATA, (v)); |
| 433 | − spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); | |
| 433 | + spin_unlock_irqrestore(&adev->reg.gc_cac.lock, flags); | |
| 434 | 434 | } |
| 435 | 435 | |
| 436 | 436 | |
| @@ -649,7 +649,7 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev, · 212 unmodified lines | ||
| 649 | 649 | dw_ptr = (u32 *)bios; |
| 650 | 650 | length_dw = ALIGN(length_bytes, 4) / 4; |
| 651 | 651 | /* take the smc lock since we are using the smc index */ |
| 652 | − spin_lock_irqsave(&adev->smc_idx_lock, flags); | |
| 652 | + spin_lock_irqsave(&adev->reg.smc.lock, flags); | |
| 653 | 653 | /* set rom index to 0 */ |
| 654 | 654 | WREG32(mmSMC_IND_INDEX_11, ixROM_INDEX); |
| 655 | 655 | WREG32(mmSMC_IND_DATA_11, 0); |
| @@ -657,7 +657,7 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev, · 1 unmodified line | ||
| 657 | 657 | WREG32(mmSMC_IND_INDEX_11, ixROM_DATA); |
| 658 | 658 | for (i = 0; i < length_dw; i++) |
| 659 | 659 | dw_ptr[i] = RREG32(mmSMC_IND_DATA_11); |
| 660 | − spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | |
| 660 | + spin_unlock_irqrestore(&adev->reg.smc.lock, flags); | |
| 661 | 661 | |
| 662 | 662 | return true; |
| 663 | 663 | } |
| @@ -1454,20 +1454,20 @@ static int vi_common_early_init(struct amdgpu_ip_block *ip_block) · 790 unmodified lines | ||
| 1454 | 1454 | struct amdgpu_device *adev = ip_block->adev; |
| 1455 | 1455 | |
| 1456 | 1456 | if (adev->flags & AMD_IS_APU) { |
| 1457 | − adev->smc_rreg = &cz_smc_rreg; | |
| 1458 | − adev->smc_wreg = &cz_smc_wreg; | |
| 1457 | + adev->reg.smc.rreg = cz_smc_rreg; | |
| 1458 | + adev->reg.smc.wreg = cz_smc_wreg; | |
| 1459 | 1459 | } else { |
| 1460 | − adev->smc_rreg = &vi_smc_rreg; | |
| 1461 | − adev->smc_wreg = &vi_smc_wreg; | |
| 1460 | + adev->reg.smc.rreg = vi_smc_rreg; | |
| 1461 | + adev->reg.smc.wreg = vi_smc_wreg; | |
| 1462 | 1462 | } |
| 1463 | − adev->pcie_rreg = &vi_pcie_rreg; | |
| 1464 | − adev->pcie_wreg = &vi_pcie_wreg; | |
| 1465 | − adev->uvd_ctx_rreg = &vi_uvd_ctx_rreg; | |
| 1466 | − adev->uvd_ctx_wreg = &vi_uvd_ctx_wreg; | |
| 1467 | − adev->didt_rreg = &vi_didt_rreg; | |
| 1468 | − adev->didt_wreg = &vi_didt_wreg; | |
| 1469 | − adev->gc_cac_rreg = &vi_gc_cac_rreg; | |
| 1470 | − adev->gc_cac_wreg = &vi_gc_cac_wreg; | |
| 1463 | + adev->reg.pcie.rreg = &vi_pcie_rreg; | |
| 1464 | + adev->reg.pcie.wreg = &vi_pcie_wreg; | |
| 1465 | + adev->reg.uvd_ctx.rreg = &vi_uvd_ctx_rreg; | |
| 1466 | + adev->reg.uvd_ctx.wreg = &vi_uvd_ctx_wreg; | |
| 1467 | + adev->reg.didt.rreg = &vi_didt_rreg; | |
| 1468 | + adev->reg.didt.wreg = &vi_didt_wreg; | |
| 1469 | + adev->reg.gc_cac.rreg = &vi_gc_cac_rreg; | |
| 1470 | + adev->reg.gc_cac.wreg = &vi_gc_cac_wreg; | |
| 1471 | 1471 | |
| 1472 | 1472 | adev->asic_funcs = &vi_asic_funcs; |
| 1473 | 1473 | |
| @@ -134,9 +134,6 @@ var SQ_WAVE_MODE_DST_SRC0_SRC1_VGPR_MSB_SHIFT = 12 · 133 unmodified lines | ||
| 134 | 134 | var SQ_WAVE_MODE_DST_SRC0_SRC1_VGPR_MSB_SIZE = 6 |
| 135 | 135 | #endif |
| 136 | 136 | |
| 137 | −var TTMP11_SCHED_MODE_SHIFT = 26 | |
| 138 | −var TTMP11_SCHED_MODE_SIZE = 2 | |
| 139 | −var TTMP11_SCHED_MODE_MASK = 0xC000000 | |
| 140 | 137 | var TTMP11_DEBUG_TRAP_ENABLED_SHIFT = 23 |
| 141 | 138 | var TTMP11_DEBUG_TRAP_ENABLED_MASK = 0x800000 |
| 142 | 139 | var TTMP11_FIRST_REPLAY_SHIFT = 22 |
| @@ -342,20 +342,14 @@ static void kfd_init_apertures_vi(struct kfd_process_device *pdd, uint8_t id) · 341 unmodified lines | ||
| 342 | 342 | |
| 343 | 343 | static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id) |
| 344 | 344 | { |
| 345 | − if (KFD_GC_VERSION(pdd->dev) >= IP_VERSION(12, 1, 0)) | |
| 346 | − pdd->lds_base = pdd->dev->adev->gmc.shared_aperture_start; | |
| 347 | − else | |
| 348 | − pdd->lds_base = MAKE_LDS_APP_BASE_V9(); | |
| 345 | + pdd->lds_base = MAKE_LDS_APP_BASE_V9(); | |
| 349 | 346 | pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base); |
| 350 | 347 | |
| 351 | 348 | pdd->gpuvm_base = AMDGPU_VA_RESERVED_BOTTOM; |
| 352 | 349 | pdd->gpuvm_limit = |
| 353 | 350 | pdd->dev->kfd->shared_resources.gpuvm_size - 1; |
| 354 | 351 | |
| 355 | − if (KFD_GC_VERSION(pdd->dev) >= IP_VERSION(12, 1, 0)) | |
| 356 | − pdd->scratch_base = pdd->dev->adev->gmc.private_aperture_start; | |
| 357 | − else | |
| 358 | − pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9(); | |
| 352 | + pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9(); | |
| 359 | 353 | pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base); |
| 360 | 354 | |
| 361 | 355 | /* |
| @@ -365,6 +359,25 @@ static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id) · 3 unmodified lines | ||
| 365 | 359 | pdd->qpd.cwsr_base = AMDGPU_VA_RESERVED_TRAP_START(pdd->dev->adev); |
| 366 | 360 | } |
| 367 | 361 | |
| 362 | +static void kfd_init_apertures_v12(struct kfd_process_device *pdd, uint8_t id) | |
| 363 | +{ | |
| 364 | + pdd->lds_base = pdd->dev->adev->gmc.shared_aperture_start; | |
| 365 | + pdd->lds_limit = pdd->dev->adev->gmc.shared_aperture_end; | |
| 366 | + | |
| 367 | + pdd->gpuvm_base = AMDGPU_VA_RESERVED_BOTTOM; | |
| 368 | + pdd->gpuvm_limit = | |
| 369 | + pdd->dev->kfd->shared_resources.gpuvm_size - 1; | |
| 370 | + | |
| 371 | + pdd->scratch_base = pdd->dev->adev->gmc.private_aperture_start; | |
| 372 | + pdd->scratch_limit = pdd->dev->adev->gmc.private_aperture_end; | |
| 373 | + | |
| 374 | + /* | |
| 375 | + * Place TBA/TMA on opposite side of VM hole to prevent | |
| 376 | + * stray faults from triggering SVM on these pages. | |
| 377 | + */ | |
| 378 | + pdd->qpd.cwsr_base = AMDGPU_VA_RESERVED_TRAP_START(pdd->dev->adev); | |
| 379 | +} | |
| 380 | + | |
| 368 | 381 | int kfd_init_apertures(struct kfd_process *process) |
| 369 | 382 | { |
| 370 | 383 | uint8_t id = 0; |
| @@ -412,9 +425,11 @@ int kfd_init_apertures(struct kfd_process *process) · 41 unmodified lines | ||
| 412 | 425 | kfd_init_apertures_vi(pdd, id); |
| 413 | 426 | break; |
| 414 | 427 | default: |
| 415 | − if (KFD_GC_VERSION(dev) >= IP_VERSION(9, 0, 1)) | |
| 428 | + if (KFD_GC_VERSION(dev) >= IP_VERSION(12, 1, 0)) { | |
| 429 | + kfd_init_apertures_v12(pdd, id); | |
| 430 | + } else if (KFD_GC_VERSION(dev) >= IP_VERSION(9, 0, 1)) { | |
| 416 | 431 | kfd_init_apertures_v9(pdd, id); |
| 417 | − else { | |
| 432 | + } else { | |
| 418 | 433 | WARN(1, "Unexpected ASIC family %u", |
| 419 | 434 | dev->adev->asic_type); |
| 420 | 435 | return -EINVAL; |
| @@ -59,8 +59,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, · 58 unmodified lines | ||
| 59 | 59 | void *cpu_addr; |
| 60 | 60 | int r; |
| 61 | 61 | |
| 62 | − /* use gart window 0 */ | |
| 63 | − *gart_addr = adev->gmc.gart_start; | |
| 62 | + *gart_addr = amdgpu_compute_gart_address(&adev->gmc, entity, 0); | |
| 64 | 63 | |
| 65 | 64 | num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); |
| 66 | 65 | num_bytes = npages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE; |
| @@ -78,6 +77,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, · 11 unmodified lines | ||
| 78 | 77 | src_addr += job->ibs[0].gpu_addr; |
| 79 | 78 | |
| 80 | 79 | dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); |
| 80 | + dst_addr += (entity->gart_window_offs[0] >> AMDGPU_GPU_PAGE_SHIFT) * 8; | |
| 81 | 81 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, |
| 82 | 82 | dst_addr, num_bytes, 0); |
| 83 | 83 | |
| @@ -116,7 +116,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, · 32 unmodified lines | ||
| 116 | 116 | * multiple GTT_MAX_PAGES transfer, all sdma operations are serialized, wait for |
| 117 | 117 | * the last sdma finish fence which is returned to check copy memory is done. |
| 118 | 118 | * |
| 119 | − * Context: Process context, takes and releases gtt_window_lock | |
| 119 | + * Context: Process context | |
| 120 | 120 | * |
| 121 | 121 | * Return: |
| 122 | 122 | * 0 - OK, otherwise error code |
| @@ -136,9 +136,9 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys, · 13 unmodified lines | ||
| 136 | 136 | u64 size; |
| 137 | 137 | int r; |
| 138 | 138 | |
| 139 | − entity = &adev->mman.default_entity; | |
| 139 | + entity = &adev->mman.move_entity; | |
| 140 | 140 | |
| 141 | − mutex_lock(&adev->mman.gtt_window_lock); | |
| 141 | + mutex_lock(&entity->lock); | |
| 142 | 142 | |
| 143 | 143 | while (npages) { |
| 144 | 144 | size = min(GTT_MAX_PAGES, npages); |
| @@ -175,7 +175,7 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys, · 30 unmodified lines | ||
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | out_unlock: |
| 178 | − mutex_unlock(&adev->mman.gtt_window_lock); | |
| 178 | + mutex_unlock(&entity->lock); | |
| 179 | 179 | |
| 180 | 180 | return r; |
| 181 | 181 | } |
| @@ -70,7 +70,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 69 unmodified lines | ||
| 70 | 70 | static void set_priority(struct cik_mqd *m, struct queue_properties *q) |
| 71 | 71 | { |
| 72 | 72 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 73 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 74 | 73 | } |
| 75 | 74 | |
| 76 | 75 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -70,7 +70,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 69 unmodified lines | ||
| 70 | 70 | static void set_priority(struct v10_compute_mqd *m, struct queue_properties *q) |
| 71 | 71 | { |
| 72 | 72 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 73 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 74 | 73 | } |
| 75 | 74 | |
| 76 | 75 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -96,7 +96,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 95 unmodified lines | ||
| 96 | 96 | static void set_priority(struct v11_compute_mqd *m, struct queue_properties *q) |
| 97 | 97 | { |
| 98 | 98 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 99 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 100 | 99 | } |
| 101 | 100 | |
| 102 | 101 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -77,7 +77,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 76 unmodified lines | ||
| 77 | 77 | static void set_priority(struct v12_compute_mqd *m, struct queue_properties *q) |
| 78 | 78 | { |
| 79 | 79 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 80 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 81 | 80 | } |
| 82 | 81 | |
| 83 | 82 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -131,7 +131,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 130 unmodified lines | ||
| 131 | 131 | static void set_priority(struct v12_1_compute_mqd *m, struct queue_properties *q) |
| 132 | 132 | { |
| 133 | 133 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 134 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 135 | 134 | } |
| 136 | 135 | |
| 137 | 136 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -106,7 +106,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 105 unmodified lines | ||
| 106 | 106 | static void set_priority(struct v9_mqd *m, struct queue_properties *q) |
| 107 | 107 | { |
| 108 | 108 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 109 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 110 | 109 | } |
| 111 | 110 | |
| 112 | 111 | static bool mqd_on_vram(struct amdgpu_device *adev) |
| @@ -73,7 +73,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 72 unmodified lines | ||
| 73 | 73 | static void set_priority(struct vi_mqd *m, struct queue_properties *q) |
| 74 | 74 | { |
| 75 | 75 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 76 | − /* m->cp_hqd_queue_priority = q->priority; */ | |
| 77 | 76 | } |
| 78 | 77 | |
| 79 | 78 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: MIT |
| 2 | 2 | /* |
| 3 | − * Copyright 2015 Advanced Micro Devices, Inc. | |
| 3 | + * Copyright 2015-2026 Advanced Micro Devices, Inc. | |
| 4 | 4 | * |
| 5 | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | 6 | * copy of this software and associated documentation files (the "Software"), |
| @@ -153,6 +153,9 @@ MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB); · 146 unmodified lines | ||
| 153 | 153 | #define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin" |
| 154 | 154 | MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB); |
| 155 | 155 | |
| 156 | +#define FIRMWARE_DCN_42_DMUB "amdgpu/dcn_4_2_dmcub.bin" | |
| 157 | +MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB); | |
| 158 | + | |
| 156 | 159 | /** |
| 157 | 160 | * DOC: overview |
| 158 | 161 | * |
| @@ -1369,6 +1372,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) · 1210 unmodified lines | ||
| 1369 | 1372 | case IP_VERSION(3, 5, 0): |
| 1370 | 1373 | case IP_VERSION(3, 5, 1): |
| 1371 | 1374 | case IP_VERSION(3, 6, 0): |
| 1375 | + case IP_VERSION(4, 2, 0): | |
| 1372 | 1376 | hw_params.ips_sequential_ono = adev->external_rev_id > 0x10; |
| 1373 | 1377 | hw_params.lower_hbr3_phy_ssc = true; |
| 1374 | 1378 | break; |
| @@ -1816,6 +1820,9 @@ static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev) · 441 unmodified lines | ||
| 1816 | 1820 | case IP_VERSION(4, 0, 1): |
| 1817 | 1821 | bb_size = sizeof(struct dml2_soc_bb); |
| 1818 | 1822 | break; |
| 1823 | + case IP_VERSION(4, 2, 0): | |
| 1824 | + bb_size = sizeof(struct dml2_soc_bb); | |
| 1825 | + break; | |
| 1819 | 1826 | default: |
| 1820 | 1827 | return NULL; |
| 1821 | 1828 | } |
| @@ -1860,6 +1867,9 @@ static enum dmub_ips_disable_type dm_get_default_ips_mode( · 38 unmodified lines | ||
| 1860 | 1867 | case IP_VERSION(3, 5, 1): |
| 1861 | 1868 | ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; |
| 1862 | 1869 | break; |
| 1870 | + case IP_VERSION(4, 2, 0): | |
| 1871 | + ret = DMUB_IPS_DISABLE_ALL; | |
| 1872 | + break; | |
| 1863 | 1873 | default: |
| 1864 | 1874 | /* ASICs older than DCN35 do not have IPSs */ |
| 1865 | 1875 | if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0)) |
| @@ -2003,6 +2013,13 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 137 unmodified lines | ||
| 2003 | 2013 | if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) |
| 2004 | 2014 | init_data.num_virtual_links = 1; |
| 2005 | 2015 | |
| 2016 | + /* DCN42 and above dpia switch to unified link training path */ | |
| 2017 | + if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(4, 2, 0)) { | |
| 2018 | + init_data.flags.consolidated_dpia_dp_lt = true; | |
| 2019 | + init_data.flags.enable_dpia_pre_training = true; | |
| 2020 | + init_data.flags.unify_link_enc_assignment = true; | |
| 2021 | + init_data.flags.usb4_bw_alloc_support = true; | |
| 2022 | + } | |
| 2006 | 2023 | retrieve_dmi_info(&adev->dm); |
| 2007 | 2024 | if (adev->dm.edp0_on_dp1_quirk) |
| 2008 | 2025 | init_data.flags.support_edp0_on_dp1 = true; |
| @@ -2370,6 +2387,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) · 361 unmodified lines | ||
| 2370 | 2387 | case IP_VERSION(3, 5, 1): |
| 2371 | 2388 | case IP_VERSION(3, 6, 0): |
| 2372 | 2389 | case IP_VERSION(4, 0, 1): |
| 2390 | + case IP_VERSION(4, 2, 0): | |
| 2373 | 2391 | return 0; |
| 2374 | 2392 | default: |
| 2375 | 2393 | break; |
| @@ -2503,7 +2521,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) · 127 unmodified lines | ||
| 2503 | 2521 | case IP_VERSION(4, 0, 1): |
| 2504 | 2522 | dmub_asic = DMUB_ASIC_DCN401; |
| 2505 | 2523 | break; |
| 2506 | − | |
| 2524 | + case IP_VERSION(4, 2, 0): | |
| 2525 | + dmub_asic = DMUB_ASIC_DCN42; | |
| 2526 | + break; | |
| 2507 | 2527 | default: |
| 2508 | 2528 | /* ASIC doesn't support DMUB. */ |
| 2509 | 2529 | return 0; |
| @@ -4390,105 +4410,6 @@ static int register_hpd_handlers(struct amdgpu_device *adev) · 1880 unmodified lines | ||
| 4390 | 4410 | return 0; |
| 4391 | 4411 | } |
| 4392 | 4412 | |
| 4393 | −#if defined(CONFIG_DRM_AMD_DC_SI) | |
| 4394 | −/* Register IRQ sources and initialize IRQ callbacks */ | |
| 4395 | −static int dce60_register_irq_handlers(struct amdgpu_device *adev) | |
| 4396 | −{ | |
| 4397 | − struct dc *dc = adev->dm.dc; | |
| 4398 | − struct common_irq_params *c_irq_params; | |
| 4399 | − struct dc_interrupt_params int_params = {0}; | |
| 4400 | − int r; | |
| 4401 | − int i; | |
| 4402 | − unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY; | |
| 4403 | − | |
| 4404 | − int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; | |
| 4405 | − int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; | |
| 4406 | − | |
| 4407 | − /* | |
| 4408 | − * Actions of amdgpu_irq_add_id(): | |
| 4409 | − * 1. Register a set() function with base driver. | |
| 4410 | − * Base driver will call set() function to enable/disable an | |
| 4411 | − * interrupt in DC hardware. | |
| 4412 | − * 2. Register amdgpu_dm_irq_handler(). | |
| 4413 | − * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts | |
| 4414 | − * coming from DC hardware. | |
| 4415 | − * amdgpu_dm_irq_handler() will re-direct the interrupt to DC | |
| 4416 | − * for acknowledging and handling. | |
| 4417 | − */ | |
| 4418 | − | |
| 4419 | − /* Use VBLANK interrupt */ | |
| 4420 | − for (i = 0; i < adev->mode_info.num_crtc; i++) { | |
| 4421 | − r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq); | |
| 4422 | − if (r) { | |
| 4423 | − drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n"); | |
| 4424 | − return r; | |
| 4425 | − } | |
| 4426 | − | |
| 4427 | − int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; | |
| 4428 | − int_params.irq_source = | |
| 4429 | − dc_interrupt_to_irq_source(dc, i + 1, 0); | |
| 4430 | − | |
| 4431 | − if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || | |
| 4432 | − int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 || | |
| 4433 | − int_params.irq_source > DC_IRQ_SOURCE_VBLANK6) { | |
| 4434 | − drm_err(adev_to_drm(adev), "Failed to register vblank irq!\n"); | |
| 4435 | − return -EINVAL; | |
| 4436 | − } | |
| 4437 | − | |
| 4438 | − c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; | |
| 4439 | − | |
| 4440 | − c_irq_params->adev = adev; | |
| 4441 | − c_irq_params->irq_src = int_params.irq_source; | |
| 4442 | − | |
| 4443 | − if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, | |
| 4444 | − dm_crtc_high_irq, c_irq_params)) | |
| 4445 | − return -ENOMEM; | |
| 4446 | − } | |
| 4447 | − | |
| 4448 | − /* Use GRPH_PFLIP interrupt */ | |
| 4449 | − for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; | |
| 4450 | − i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { | |
| 4451 | − r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq); | |
| 4452 | − if (r) { | |
| 4453 | − drm_err(adev_to_drm(adev), "Failed to add page flip irq id!\n"); | |
| 4454 | − return r; | |
| 4455 | − } | |
| 4456 | − | |
| 4457 | − int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; | |
| 4458 | − int_params.irq_source = | |
| 4459 | − dc_interrupt_to_irq_source(dc, i, 0); | |
| 4460 | − | |
| 4461 | − if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || | |
| 4462 | − int_params.irq_source < DC_IRQ_SOURCE_PFLIP_FIRST || | |
| 4463 | − int_params.irq_source > DC_IRQ_SOURCE_PFLIP_LAST) { | |
| 4464 | − drm_err(adev_to_drm(adev), "Failed to register pflip irq!\n"); | |
| 4465 | − return -EINVAL; | |
| 4466 | − } | |
| 4467 | − | |
| 4468 | − c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; | |
| 4469 | − | |
| 4470 | − c_irq_params->adev = adev; | |
| 4471 | − c_irq_params->irq_src = int_params.irq_source; | |
| 4472 | − | |
| 4473 | − if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, | |
| 4474 | − dm_pflip_high_irq, c_irq_params)) | |
| 4475 | − return -ENOMEM; | |
| 4476 | − } | |
| 4477 | − | |
| 4478 | − /* HPD */ | |
| 4479 | − r = amdgpu_irq_add_id(adev, client_id, | |
| 4480 | − VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq); | |
| 4481 | − if (r) { | |
| 4482 | − drm_err(adev_to_drm(adev), "Failed to add hpd irq id!\n"); | |
| 4483 | − return r; | |
| 4484 | − } | |
| 4485 | − | |
| 4486 | − r = register_hpd_handlers(adev); | |
| 4487 | − | |
| 4488 | − return r; | |
| 4489 | −} | |
| 4490 | −#endif | |
| 4491 | − | |
| 4492 | 4413 | /* Register IRQ sources and initialize IRQ callbacks */ |
| 4493 | 4414 | static int dce110_register_irq_handlers(struct amdgpu_device *adev) |
| 4494 | 4415 | { |
| @@ -4497,7 +4418,12 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) · 2 unmodified lines | ||
| 4497 | 4418 | struct dc_interrupt_params int_params = {0}; |
| 4498 | 4419 | int r; |
| 4499 | 4420 | int i; |
| 4421 | + unsigned int src_id; | |
| 4500 | 4422 | unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY; |
| 4423 | + /* Use different interrupts for VBLANK on DCE 6 vs. newer. */ | |
| 4424 | + const unsigned int vblank_d1 = | |
| 4425 | + adev->dm.dc->ctx->dce_version >= DCE_VERSION_8_0 | |
| 4426 | + ? VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 : 1; | |
| 4501 | 4427 | |
| 4502 | 4428 | if (adev->family >= AMDGPU_FAMILY_AI) |
| 4503 | 4429 | client_id = SOC15_IH_CLIENTID_DCE; |
| @@ -4518,8 +4444,9 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) · 14 unmodified lines | ||
| 4518 | 4444 | */ |
| 4519 | 4445 | |
| 4520 | 4446 | /* Use VBLANK interrupt */ |
| 4521 | − for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) { | |
| 4522 | − r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); | |
| 4447 | + for (i = 0; i < adev->mode_info.num_crtc; i++) { | |
| 4448 | + src_id = vblank_d1 + i; | |
| 4449 | + r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->crtc_irq); | |
| 4523 | 4450 | if (r) { |
| 4524 | 4451 | drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n"); |
| 4525 | 4452 | return r; |
| @@ -4527,7 +4454,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) · 1 unmodified line | ||
| 4527 | 4454 | |
| 4528 | 4455 | int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; |
| 4529 | 4456 | int_params.irq_source = |
| 4530 | − dc_interrupt_to_irq_source(dc, i, 0); | |
| 4457 | + dc_interrupt_to_irq_source(dc, src_id, 0); | |
| 4531 | 4458 | |
| 4532 | 4459 | if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || |
| 4533 | 4460 | int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 || |
| @@ -4546,33 +4473,36 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) · 12 unmodified lines | ||
| 4546 | 4473 | return -ENOMEM; |
| 4547 | 4474 | } |
| 4548 | 4475 | |
| 4549 | − /* Use VUPDATE interrupt */ | |
| 4550 | − for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { | |
| 4551 | − r = amdgpu_irq_add_id(adev, client_id, i, &adev->vupdate_irq); | |
| 4552 | − if (r) { | |
| 4553 | − drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n"); | |
| 4554 | − return r; | |
| 4555 | − } | |
| 4556 | − | |
| 4557 | − int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; | |
| 4558 | − int_params.irq_source = | |
| 4559 | − dc_interrupt_to_irq_source(dc, i, 0); | |
| 4476 | + if (dc_supports_vrr(adev->dm.dc->ctx->dce_version)) { | |
| 4477 | + /* Use VUPDATE interrupt */ | |
| 4478 | + for (i = 0; i < adev->mode_info.num_crtc; i++) { | |
| 4479 | + src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + i * 2; | |
| 4480 | + r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->vupdate_irq); | |
| 4481 | + if (r) { | |
| 4482 | + drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n"); | |
| 4483 | + return r; | |
| 4484 | + } | |
| 4560 | 4485 | |
| 4561 | − if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || | |
| 4562 | − int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 || | |
| 4563 | − int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) { | |
| 4564 | − drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n"); | |
| 4565 | − return -EINVAL; | |
| 4566 | − } | |
| 4486 | + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; | |
| 4487 | + int_params.irq_source = | |
| 4488 | + dc_interrupt_to_irq_source(dc, src_id, 0); | |
| 4567 | 4489 | |
| 4568 | − c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; | |
| 4490 | + if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || | |
| 4491 | + int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 || | |
| 4492 | + int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) { | |
| 4493 | + drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n"); | |
| 4494 | + return -EINVAL; | |
| 4495 | + } | |
| 4569 | 4496 | |
| 4570 | − c_irq_params->adev = adev; | |
| 4571 | − c_irq_params->irq_src = int_params.irq_source; | |
| 4497 | + c_irq_params = &adev->dm.vupdate_params[ | |
| 4498 | + int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; | |
| 4499 | + c_irq_params->adev = adev; | |
| 4500 | + c_irq_params->irq_src = int_params.irq_source; | |
| 4572 | 4501 | |
| 4573 | − if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, | |
| 4574 | − dm_vupdate_high_irq, c_irq_params)) | |
| 4575 | − return -ENOMEM; | |
| 4502 | + if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, | |
| 4503 | + dm_vupdate_high_irq, c_irq_params)) | |
| 4504 | + return -ENOMEM; | |
| 4505 | + } | |
| 4576 | 4506 | } |
| 4577 | 4507 | |
| 4578 | 4508 | /* Use GRPH_PFLIP interrupt */ |
| @@ -5544,6 +5474,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 965 unmodified lines | ||
| 5544 | 5474 | case IP_VERSION(3, 5, 1): |
| 5545 | 5475 | case IP_VERSION(3, 6, 0): |
| 5546 | 5476 | case IP_VERSION(4, 0, 1): |
| 5477 | + case IP_VERSION(4, 2, 0): | |
| 5547 | 5478 | if (register_outbox_irq_handlers(dm->adev)) { |
| 5548 | 5479 | drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); |
| 5549 | 5480 | goto fail; |
| @@ -5568,6 +5499,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 18 unmodified lines | ||
| 5568 | 5499 | case IP_VERSION(3, 5, 1): |
| 5569 | 5500 | case IP_VERSION(3, 6, 0): |
| 5570 | 5501 | case IP_VERSION(4, 0, 1): |
| 5502 | + case IP_VERSION(4, 2, 0): | |
| 5571 | 5503 | psr_feature_enabled = true; |
| 5572 | 5504 | break; |
| 5573 | 5505 | default: |
| @@ -5700,11 +5632,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 126 unmodified lines | ||
| 5700 | 5632 | case CHIP_PITCAIRN: |
| 5701 | 5633 | case CHIP_VERDE: |
| 5702 | 5634 | case CHIP_OLAND: |
| 5703 | − if (dce60_register_irq_handlers(dm->adev)) { | |
| 5704 | − drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); | |
| 5705 | − goto fail; | |
| 5706 | − } | |
| 5707 | − break; | |
| 5708 | 5635 | #endif |
| 5709 | 5636 | case CHIP_BONAIRE: |
| 5710 | 5637 | case CHIP_HAWAII: |
| @@ -5750,6 +5677,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 39 unmodified lines | ||
| 5750 | 5677 | case IP_VERSION(3, 5, 1): |
| 5751 | 5678 | case IP_VERSION(3, 6, 0): |
| 5752 | 5679 | case IP_VERSION(4, 0, 1): |
| 5680 | + case IP_VERSION(4, 2, 0): | |
| 5753 | 5681 | if (dcn10_register_irq_handlers(dm->adev)) { |
| 5754 | 5682 | drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); |
| 5755 | 5683 | goto fail; |
| @@ -5898,6 +5826,9 @@ static int dm_init_microcode(struct amdgpu_device *adev) · 142 unmodified lines | ||
| 5898 | 5826 | case IP_VERSION(4, 0, 1): |
| 5899 | 5827 | fw_name_dmub = FIRMWARE_DCN_401_DMUB; |
| 5900 | 5828 | break; |
| 5829 | + case IP_VERSION(4, 2, 0): | |
| 5830 | + fw_name_dmub = FIRMWARE_DCN_42_DMUB; | |
| 5831 | + break; | |
| 5901 | 5832 | default: |
| 5902 | 5833 | /* ASIC doesn't support DMUB. */ |
| 5903 | 5834 | return 0; |
| @@ -6025,6 +5956,7 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block) · 121 unmodified lines | ||
| 6025 | 5956 | case IP_VERSION(3, 5, 1): |
| 6026 | 5957 | case IP_VERSION(3, 6, 0): |
| 6027 | 5958 | case IP_VERSION(4, 0, 1): |
| 5959 | + case IP_VERSION(4, 2, 0): | |
| 6028 | 5960 | adev->mode_info.num_crtc = 4; |
| 6029 | 5961 | adev->mode_info.num_hpd = 4; |
| 6030 | 5962 | adev->mode_info.num_dig = 4; |
| @@ -6041,8 +5973,8 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block) · 10 unmodified lines | ||
| 6041 | 5973 | adev->mode_info.funcs = &dm_display_funcs; |
| 6042 | 5974 | |
| 6043 | 5975 | /* |
| 6044 | − * Note: Do NOT change adev->audio_endpt_rreg and | |
| 6045 | − * adev->audio_endpt_wreg because they are initialised in | |
| 5976 | + * Note: Do NOT change adev->reg.audio_endpt.rreg and | |
| 5977 | + * adev->reg.audio_endpt.wreg because they are initialised in | |
| 6046 | 5978 | * amdgpu_device_init() |
| 6047 | 5979 | */ |
| 6048 | 5980 | #if defined(CONFIG_DEBUG_KERNEL_DC) |
| @@ -8583,6 +8515,12 @@ static int to_drm_connector_type(enum signal_type st, uint32_t connector_id) · 2534 unmodified lines | ||
| 8583 | 8515 | return DRM_MODE_CONNECTOR_VGA; |
| 8584 | 8516 | case SIGNAL_TYPE_DISPLAY_PORT: |
| 8585 | 8517 | case SIGNAL_TYPE_DISPLAY_PORT_MST: |
| 8518 | + /* External DP bridges have a different connector type. */ | |
| 8519 | + if (connector_id == CONNECTOR_ID_VGA) | |
| 8520 | + return DRM_MODE_CONNECTOR_VGA; | |
| 8521 | + else if (connector_id == CONNECTOR_ID_LVDS) | |
| 8522 | + return DRM_MODE_CONNECTOR_LVDS; | |
| 8523 | + | |
| 8586 | 8524 | return DRM_MODE_CONNECTOR_DisplayPort; |
| 8587 | 8525 | case SIGNAL_TYPE_DVI_DUAL_LINK: |
| 8588 | 8526 | case SIGNAL_TYPE_DVI_SINGLE_LINK: |
| @@ -9257,8 +9195,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, · 668 unmodified lines | ||
| 9257 | 9195 | connector_type == DRM_MODE_CONNECTOR_HDMIB) |
| 9258 | 9196 | amdgpu_dm_initialize_hdmi_connector(aconnector); |
| 9259 | 9197 | |
| 9260 | − if (connector_type == DRM_MODE_CONNECTOR_DisplayPort | |
| 9261 | − || connector_type == DRM_MODE_CONNECTOR_eDP) | |
| 9198 | + if (dc_is_dp_signal(link->connector_signal)) | |
| 9262 | 9199 | amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index); |
| 9263 | 9200 | |
| 9264 | 9201 | out_free: |
| @@ -12320,10 +12257,11 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev, · 3055 unmodified lines | ||
| 12320 | 12257 | int i; |
| 12321 | 12258 | |
| 12322 | 12259 | /* Overlay cursor not supported on HW before DCN |
| 12323 | − * DCN401 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions | |
| 12324 | − * as previous DCN generations, so enable native mode on DCN401 | |
| 12260 | + * DCN401/420 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions | |
| 12261 | + * as previous DCN generations, so enable native mode on DCN401/420 | |
| 12325 | 12262 | */ |
| 12326 | − if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) { | |
| 12263 | + if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1) || | |
| 12264 | + amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0)) { | |
| 12327 | 12265 | *cursor_mode = DM_CURSOR_NATIVE_MODE; |
| 12328 | 12266 | return 0; |
| 12329 | 12267 | } |
| @@ -12743,7 +12681,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 413 unmodified lines | ||
| 12743 | 12681 | |
| 12744 | 12682 | /* Check if rotation or scaling is enabled on DCN401 */ |
| 12745 | 12683 | if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) && |
| 12746 | − amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) { | |
| 12684 | + (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) || | |
| 12685 | + amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1))) { | |
| 12747 | 12686 | new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor); |
| 12748 | 12687 | |
| 12749 | 12688 | is_rotated = new_cursor_state && |
| @@ -1706,6 +1706,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state, · 1705 unmodified lines | ||
| 1706 | 1706 | struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func; |
| 1707 | 1707 | struct drm_atomic_state *state = plane_state->state; |
| 1708 | 1708 | const struct amdgpu_device *adev = drm_to_adev(colorop->dev); |
| 1709 | + bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend; | |
| 1709 | 1710 | const struct drm_device *dev = colorop->dev; |
| 1710 | 1711 | const struct drm_color_lut32 *lut3d; |
| 1711 | 1712 | uint32_t lut3d_size; |
| @@ -1722,7 +1723,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state, · 10 unmodified lines | ||
| 1722 | 1723 | } |
| 1723 | 1724 | |
| 1724 | 1725 | if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) { |
| 1725 | − if (!adev->dm.dc->caps.color.dpp.hw_3d_lut) { | |
| 1726 | + if (!has_3dlut) { | |
| 1726 | 1727 | drm_dbg(dev, "3D LUT is not supported by hardware\n"); |
| 1727 | 1728 | return -EINVAL; |
| 1728 | 1729 | } |
| @@ -1875,6 +1876,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state, · 146 unmodified lines | ||
| 1875 | 1876 | struct drm_colorop *colorop = plane_state->color_pipeline; |
| 1876 | 1877 | struct drm_device *dev = plane_state->plane->dev; |
| 1877 | 1878 | struct amdgpu_device *adev = drm_to_adev(dev); |
| 1879 | + bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend; | |
| 1878 | 1880 | int ret; |
| 1879 | 1881 | |
| 1880 | 1882 | /* 1D Curve - DEGAM TF */ |
| @@ -1907,7 +1909,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state, · 26 unmodified lines | ||
| 1907 | 1909 | if (ret) |
| 1908 | 1910 | return ret; |
| 1909 | 1911 | |
| 1910 | − if (adev->dm.dc->caps.color.dpp.hw_3d_lut) { | |
| 1912 | + if (has_3dlut) { | |
| 1911 | 1913 | /* 1D Curve & LUT - SHAPER TF & LUT */ |
| 1912 | 1914 | colorop = colorop->next; |
| 1913 | 1915 | if (!colorop) { |
| @@ -64,6 +64,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr · 63 unmodified lines | ||
| 64 | 64 | struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS]; |
| 65 | 65 | struct drm_device *dev = plane->dev; |
| 66 | 66 | struct amdgpu_device *adev = drm_to_adev(dev); |
| 67 | + bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend; | |
| 67 | 68 | int ret; |
| 68 | 69 | int i = 0; |
| 69 | 70 | |
| @@ -119,7 +120,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr · 49 unmodified lines | ||
| 119 | 120 | |
| 120 | 121 | i++; |
| 121 | 122 | |
| 122 | − if (adev->dm.dc->caps.color.dpp.hw_3d_lut) { | |
| 123 | + if (has_3dlut) { | |
| 123 | 124 | /* 1D curve - SHAPER TF */ |
| 124 | 125 | ops[i] = kzalloc_obj(*ops[0]); |
| 125 | 126 | if (!ops[i]) { |
| @@ -765,15 +765,15 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, · 764 unmodified lines | ||
| 765 | 765 | dm->adev->mode_info.crtcs[crtc_index] = acrtc; |
| 766 | 766 | |
| 767 | 767 | /* Don't enable DRM CRTC degamma property for |
| 768 | − * 1. Degamma is replaced by color pipeline. | |
| 769 | − * 2. DCE since it doesn't support programmable degamma anywhere. | |
| 770 | − * 3. DCN401 since pre-blending degamma LUT doesn't apply to cursor. | |
| 768 | + * 1. DCE since it doesn't support programmable degamma anywhere. | |
| 769 | + * 2. DCN401 since pre-blending degamma LUT doesn't apply to cursor. | |
| 770 | + * Note: DEGAMMA properties are created even if the primary plane has the | |
| 771 | + * COLOR_PIPELINE property. User space can use either the DEGAMMA properties | |
| 772 | + * or the COLOR_PIPELINE property. An atomic commit which attempts to enable | |
| 773 | + * both is rejected. | |
| 771 | 774 | */ |
| 772 | − if (plane->color_pipeline_property) | |
| 773 | − has_degamma = false; | |
| 774 | − else | |
| 775 | − has_degamma = dm->adev->dm.dc->caps.color.dpp.dcn_arch && | |
| 776 | − dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01; | |
| 775 | + has_degamma = dm->adev->dm.dc->caps.color.dpp.dcn_arch && | |
| 776 | + dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01; | |
| 777 | 777 | |
| 778 | 778 | drm_crtc_enable_color_mgmt(&acrtc->base, has_degamma ? MAX_COLOR_LUT_ENTRIES : 0, |
| 779 | 779 | true, MAX_COLOR_LUT_ENTRIES); |
| @@ -1016,6 +1016,9 @@ enum dc_edid_status dm_helpers_read_local_edid( · 1015 unmodified lines | ||
| 1016 | 1016 | else |
| 1017 | 1017 | ddc = &aconnector->i2c->base; |
| 1018 | 1018 | |
| 1019 | + if (link->dc->hwss.prepare_ddc) | |
| 1020 | + link->dc->hwss.prepare_ddc(link); | |
| 1021 | + | |
| 1019 | 1022 | /* some dongles read edid incorrectly the first time, |
| 1020 | 1023 | * do check sum and retry to make sure read correct edid. |
| 1021 | 1024 | */ |
| @@ -1162,9 +1165,9 @@ void dm_helpers_override_panel_settings( · 140 unmodified lines | ||
| 1162 | 1165 | link->panel_config.dsc.disable_dsc_edp = true; |
| 1163 | 1166 | |
| 1164 | 1167 | if (dc_get_edp_link_panel_inst(ctx->dc, link, &panel_inst) && panel_inst == 1) { |
| 1165 | − link->panel_config.psr.disable_psr = true; | |
| 1166 | − link->panel_config.psr.disallow_psrsu = true;; | |
| 1167 | − link->panel_config.psr.disallow_replay = true; | |
| 1168 | + link->panel_config.psr.disable_psr = true; | |
| 1169 | + link->panel_config.psr.disallow_psrsu = true; | |
| 1170 | + link->panel_config.psr.disallow_replay = true; | |
| 1168 | 1171 | } |
| 1169 | 1172 | } |
| 1170 | 1173 | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: MIT |
| 2 | 2 | /* |
| 3 | − * Copyright 2022 Advanced Micro Devices, Inc. | |
| 3 | + * Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 4 | 4 | * |
| 5 | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | 6 | * copy of this software and associated documentation files (the "Software"), |
| @@ -759,6 +759,7 @@ static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsig · 752 unmodified lines | ||
| 759 | 759 | case AMDGPU_FAMILY_GC_11_0_0: |
| 760 | 760 | case AMDGPU_FAMILY_GC_11_0_1: |
| 761 | 761 | case AMDGPU_FAMILY_GC_11_5_0: |
| 762 | + case AMDGPU_FAMILY_GC_11_5_4: | |
| 762 | 763 | amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity); |
| 763 | 764 | break; |
| 764 | 765 | case AMDGPU_FAMILY_GC_12_0_0: |
| @@ -1256,6 +1257,14 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane, · 491 unmodified lines | ||
| 1256 | 1257 | if (ret) |
| 1257 | 1258 | return ret; |
| 1258 | 1259 | |
| 1260 | + /* Reject commits that attempt to use both COLOR_PIPELINE and CRTC DEGAMMA_LUT */ | |
| 1261 | + if (new_plane_state->color_pipeline && new_crtc_state->degamma_lut) { | |
| 1262 | + drm_dbg_atomic(plane->dev, | |
| 1263 | + "[PLANE:%d:%s] COLOR_PIPELINE and CRTC DEGAMMA_LUT cannot be enabled simultaneously\n", | |
| 1264 | + plane->base.id, plane->name); | |
| 1265 | + return -EINVAL; | |
| 1266 | + } | |
| 1267 | + | |
| 1259 | 1268 | ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info); |
| 1260 | 1269 | if (ret) |
| 1261 | 1270 | return ret; |
| @@ -780,28 +780,33 @@ static enum bp_result bios_parser_encoder_control( · 779 unmodified lines | ||
| 780 | 780 | return bp->cmd_tbl.dig_encoder_control(bp, cntl); |
| 781 | 781 | } |
| 782 | 782 | |
| 783 | +static enum bp_result bios_parser_external_encoder_control( | |
| 784 | + struct dc_bios *dcb, | |
| 785 | + struct bp_external_encoder_control *cntl) | |
| 786 | +{ | |
| 787 | + struct bios_parser *bp = BP_FROM_DCB(dcb); | |
| 788 | + | |
| 789 | + if (!bp->cmd_tbl.external_encoder_control) | |
| 790 | + return BP_RESULT_UNSUPPORTED; | |
| 791 | + | |
| 792 | + return bp->cmd_tbl.external_encoder_control(bp, cntl); | |
| 793 | +} | |
| 794 | + | |
| 783 | 795 | static enum bp_result bios_parser_dac_load_detection( |
| 784 | 796 | struct dc_bios *dcb, |
| 785 | 797 | enum engine_id engine_id, |
| 786 | − enum dal_device_type device_type, | |
| 787 | − uint32_t enum_id) | |
| 798 | + struct graphics_object_id ext_enc_id) | |
| 788 | 799 | { |
| 789 | 800 | struct bios_parser *bp = BP_FROM_DCB(dcb); |
| 790 | 801 | struct dc_context *ctx = dcb->ctx; |
| 791 | 802 | struct bp_load_detection_parameters bp_params = {0}; |
| 792 | − enum bp_result bp_result; | |
| 803 | + struct bp_external_encoder_control ext_cntl = {0}; | |
| 804 | + enum bp_result bp_result = BP_RESULT_UNSUPPORTED; | |
| 793 | 805 | uint32_t bios_0_scratch; |
| 794 | 806 | uint32_t device_id_mask = 0; |
| 795 | 807 | |
| 796 | − bp_params.engine_id = engine_id; | |
| 797 | − bp_params.device_id = get_support_mask_for_device_id(device_type, enum_id); | |
| 798 | − | |
| 799 | − if (engine_id != ENGINE_ID_DACA && | |
| 800 | − engine_id != ENGINE_ID_DACB) | |
| 801 | − return BP_RESULT_UNSUPPORTED; | |
| 802 | − | |
| 803 | − if (!bp->cmd_tbl.dac_load_detection) | |
| 804 | − return BP_RESULT_UNSUPPORTED; | |
| 808 | + bp_params.device_id = get_support_mask_for_device_id( | |
| 809 | + DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1); | |
| 805 | 810 | |
| 806 | 811 | if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) |
| 807 | 812 | device_id_mask = ATOM_S0_CRT1_MASK; |
| @@ -815,7 +820,20 @@ static enum bp_result bios_parser_dac_load_detection( · 7 unmodified lines | ||
| 815 | 820 | bios_0_scratch &= ~device_id_mask; |
| 816 | 821 | dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); |
| 817 | 822 | |
| 818 | − bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); | |
| 823 | + if (engine_id == ENGINE_ID_DACA || engine_id == ENGINE_ID_DACB) { | |
| 824 | + if (!bp->cmd_tbl.dac_load_detection) | |
| 825 | + return BP_RESULT_UNSUPPORTED; | |
| 826 | + | |
| 827 | + bp_params.engine_id = engine_id; | |
| 828 | + bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); | |
| 829 | + } else if (ext_enc_id.id) { | |
| 830 | + if (!bp->cmd_tbl.external_encoder_control) | |
| 831 | + return BP_RESULT_UNSUPPORTED; | |
| 832 | + | |
| 833 | + ext_cntl.action = EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT; | |
| 834 | + ext_cntl.encoder_id = ext_enc_id; | |
| 835 | + bp_result = bp->cmd_tbl.external_encoder_control(bp, &ext_cntl); | |
| 836 | + } | |
| 819 | 837 | |
| 820 | 838 | if (bp_result != BP_RESULT_OK) |
| 821 | 839 | return bp_result; |
| @@ -2912,6 +2930,8 @@ static const struct dc_vbios_funcs vbios_funcs = { · 2090 unmodified lines | ||
| 2912 | 2930 | |
| 2913 | 2931 | .encoder_control = bios_parser_encoder_control, |
| 2914 | 2932 | |
| 2933 | + .external_encoder_control = bios_parser_external_encoder_control, | |
| 2934 | + | |
| 2915 | 2935 | .dac_load_detection = bios_parser_dac_load_detection, |
| 2916 | 2936 | |
| 2917 | 2937 | .transmitter_control = bios_parser_transmitter_control, |
| @@ -226,6 +226,28 @@ static enum bp_result encoder_control_dig2_v1( · 225 unmodified lines | ||
| 226 | 226 | return result; |
| 227 | 227 | } |
| 228 | 228 | |
| 229 | +static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth) | |
| 230 | +{ | |
| 231 | + switch (color_depth) { | |
| 232 | + case COLOR_DEPTH_UNDEFINED: | |
| 233 | + return PANEL_BPC_UNDEFINE; | |
| 234 | + case COLOR_DEPTH_666: | |
| 235 | + return PANEL_6BIT_PER_COLOR; | |
| 236 | + default: | |
| 237 | + case COLOR_DEPTH_888: | |
| 238 | + return PANEL_8BIT_PER_COLOR; | |
| 239 | + case COLOR_DEPTH_101010: | |
| 240 | + return PANEL_10BIT_PER_COLOR; | |
| 241 | + case COLOR_DEPTH_121212: | |
| 242 | + return PANEL_12BIT_PER_COLOR; | |
| 243 | + case COLOR_DEPTH_141414: | |
| 244 | + dm_error("14-bit color not supported by ATOMBIOS\n"); | |
| 245 | + return PANEL_BPC_UNDEFINE; | |
| 246 | + case COLOR_DEPTH_161616: | |
| 247 | + return PANEL_16BIT_PER_COLOR; | |
| 248 | + } | |
| 249 | +} | |
| 250 | + | |
| 229 | 251 | static enum bp_result encoder_control_digx_v3( |
| 230 | 252 | struct bios_parser *bp, |
| 231 | 253 | struct bp_encoder_control *cntl) |
| @@ -248,23 +270,7 @@ static enum bp_result encoder_control_digx_v3( · 16 unmodified lines | ||
| 248 | 270 | cntl->signal, |
| 249 | 271 | cntl->enable_dp_audio); |
| 250 | 272 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 251 | − | |
| 252 | − switch (cntl->color_depth) { | |
| 253 | − case COLOR_DEPTH_888: | |
| 254 | − params.ucBitPerColor = PANEL_8BIT_PER_COLOR; | |
| 255 | − break; | |
| 256 | − case COLOR_DEPTH_101010: | |
| 257 | − params.ucBitPerColor = PANEL_10BIT_PER_COLOR; | |
| 258 | − break; | |
| 259 | − case COLOR_DEPTH_121212: | |
| 260 | − params.ucBitPerColor = PANEL_12BIT_PER_COLOR; | |
| 261 | − break; | |
| 262 | − case COLOR_DEPTH_161616: | |
| 263 | − params.ucBitPerColor = PANEL_16BIT_PER_COLOR; | |
| 264 | − break; | |
| 265 | − default: | |
| 266 | − break; | |
| 267 | − } | |
| 273 | + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 268 | 274 | |
| 269 | 275 | if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) |
| 270 | 276 | result = BP_RESULT_OK; |
| @@ -294,23 +300,7 @@ static enum bp_result encoder_control_digx_v4( · 23 unmodified lines | ||
| 294 | 300 | cntl->signal, |
| 295 | 301 | cntl->enable_dp_audio)); |
| 296 | 302 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 297 | − | |
| 298 | − switch (cntl->color_depth) { | |
| 299 | − case COLOR_DEPTH_888: | |
| 300 | − params.ucBitPerColor = PANEL_8BIT_PER_COLOR; | |
| 301 | − break; | |
| 302 | − case COLOR_DEPTH_101010: | |
| 303 | − params.ucBitPerColor = PANEL_10BIT_PER_COLOR; | |
| 304 | − break; | |
| 305 | − case COLOR_DEPTH_121212: | |
| 306 | − params.ucBitPerColor = PANEL_12BIT_PER_COLOR; | |
| 307 | − break; | |
| 308 | − case COLOR_DEPTH_161616: | |
| 309 | − params.ucBitPerColor = PANEL_16BIT_PER_COLOR; | |
| 310 | − break; | |
| 311 | − default: | |
| 312 | − break; | |
| 313 | − } | |
| 303 | + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 314 | 304 | |
| 315 | 305 | if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) |
| 316 | 306 | result = BP_RESULT_OK; |
| @@ -334,23 +324,7 @@ static enum bp_result encoder_control_digx_v5( · 17 unmodified lines | ||
| 334 | 324 | cntl->signal, |
| 335 | 325 | cntl->enable_dp_audio)); |
| 336 | 326 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 337 | − | |
| 338 | − switch (cntl->color_depth) { | |
| 339 | − case COLOR_DEPTH_888: | |
| 340 | − params.ucBitPerColor = PANEL_8BIT_PER_COLOR; | |
| 341 | − break; | |
| 342 | − case COLOR_DEPTH_101010: | |
| 343 | − params.ucBitPerColor = PANEL_10BIT_PER_COLOR; | |
| 344 | − break; | |
| 345 | − case COLOR_DEPTH_121212: | |
| 346 | − params.ucBitPerColor = PANEL_12BIT_PER_COLOR; | |
| 347 | − break; | |
| 348 | − case COLOR_DEPTH_161616: | |
| 349 | − params.ucBitPerColor = PANEL_16BIT_PER_COLOR; | |
| 350 | − break; | |
| 351 | − default: | |
| 352 | − break; | |
| 353 | − } | |
| 327 | + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 354 | 328 | |
| 355 | 329 | if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) |
| 356 | 330 | switch (cntl->color_depth) { |
| @@ -1797,30 +1771,7 @@ static enum bp_result select_crtc_source_v3( · 1440 unmodified lines | ||
| 1797 | 1771 | ¶ms.ucEncodeMode)) |
| 1798 | 1772 | return BP_RESULT_BADINPUT; |
| 1799 | 1773 | |
| 1800 | − switch (bp_params->color_depth) { | |
| 1801 | − case COLOR_DEPTH_UNDEFINED: | |
| 1802 | − params.ucDstBpc = PANEL_BPC_UNDEFINE; | |
| 1803 | − break; | |
| 1804 | − case COLOR_DEPTH_666: | |
| 1805 | − params.ucDstBpc = PANEL_6BIT_PER_COLOR; | |
| 1806 | − break; | |
| 1807 | − default: | |
| 1808 | − case COLOR_DEPTH_888: | |
| 1809 | − params.ucDstBpc = PANEL_8BIT_PER_COLOR; | |
| 1810 | − break; | |
| 1811 | − case COLOR_DEPTH_101010: | |
| 1812 | − params.ucDstBpc = PANEL_10BIT_PER_COLOR; | |
| 1813 | − break; | |
| 1814 | − case COLOR_DEPTH_121212: | |
| 1815 | − params.ucDstBpc = PANEL_12BIT_PER_COLOR; | |
| 1816 | − break; | |
| 1817 | − case COLOR_DEPTH_141414: | |
| 1818 | − dm_error("14-bit color not supported by SelectCRTC_Source v3\n"); | |
| 1819 | − break; | |
| 1820 | − case COLOR_DEPTH_161616: | |
| 1821 | − params.ucDstBpc = PANEL_16BIT_PER_COLOR; | |
| 1822 | − break; | |
| 1823 | − } | |
| 1774 | + params.ucDstBpc = dc_color_depth_to_atom(bp_params->color_depth); | |
| 1824 | 1775 | |
| 1825 | 1776 | if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) |
| 1826 | 1777 | result = BP_RESULT_OK; |
| @@ -2569,6 +2520,7 @@ static enum bp_result external_encoder_control_v3( · 742 unmodified lines | ||
| 2569 | 2520 | cpu_to_le16((uint16_t)cntl->connector_obj_id.id); |
| 2570 | 2521 | break; |
| 2571 | 2522 | case EXTERNAL_ENCODER_CONTROL_SETUP: |
| 2523 | + case EXTERNAL_ENCODER_CONTROL_ENABLE: | |
| 2572 | 2524 | /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in |
| 2573 | 2525 | * 10KHz |
| 2574 | 2526 | * output display device pixel clock frequency in unit of 10KHz. |
| @@ -2585,26 +2537,24 @@ static enum bp_result external_encoder_control_v3( · 10 unmodified lines | ||
| 2585 | 2537 | if (is_input_signal_dp) { |
| 2586 | 2538 | /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, |
| 2587 | 2539 | * only valid in encoder setup with DP mode. */ |
| 2588 | − if (LINK_RATE_HIGH == cntl->link_rate) | |
| 2589 | − cntl_params->ucConfig |= 1; | |
| 2540 | + if (cntl->link_rate == LINK_RATE_LOW) | |
| 2541 | + cntl_params->ucConfig |= | |
| 2542 | + EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ; | |
| 2543 | + else if (cntl->link_rate == LINK_RATE_HIGH) | |
| 2544 | + cntl_params->ucConfig |= | |
| 2545 | + EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; | |
| 2546 | + else | |
| 2547 | + dm_error("Link rate not supported by external encoder"); | |
| 2548 | + | |
| 2590 | 2549 | /* output color depth Indicate encoder data bpc format |
| 2591 | 2550 | * in DP mode, only valid in encoder setup in DP mode. |
| 2592 | 2551 | */ |
| 2593 | − cntl_params->ucBitPerColor = | |
| 2594 | − (uint8_t)(cntl->color_depth); | |
| 2552 | + cntl_params->ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 2595 | 2553 | } |
| 2596 | 2554 | /* Indicate how many lanes used by external encoder, only valid |
| 2597 | 2555 | * in encoder setup and enableoutput. */ |
| 2598 | 2556 | cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 2599 | 2557 | break; |
| 2600 | − case EXTERNAL_ENCODER_CONTROL_ENABLE: | |
| 2601 | − cntl_params->usPixelClock = | |
| 2602 | − cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); | |
| 2603 | − cntl_params->ucEncoderMode = | |
| 2604 | − (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( | |
| 2605 | − cntl->signal, false); | |
| 2606 | − cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number; | |
| 2607 | − break; | |
| 2608 | 2558 | default: |
| 2609 | 2559 | break; |
| 2610 | 2560 | } |
| @@ -84,6 +84,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( · 83 unmodified lines | ||
| 84 | 84 | case DCN_VERSION_3_51: |
| 85 | 85 | case DCN_VERSION_3_6: |
| 86 | 86 | case DCN_VERSION_4_01: |
| 87 | + case DCN_VERSION_4_2: | |
| 87 | 88 | *h = dal_cmd_tbl_helper_dce112_get_table2(); |
| 88 | 89 | return true; |
| 89 | 90 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | # |
| 2 | −# Copyright 2017 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2017-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -29,18 +29,6 @@ AMD_DAL_CLK_MGR = $(addprefix $(AMDDALPATH)/dc/clk_mgr/,$(CLK_MGR)) · 23 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR) |
| 31 | 31 | |
| 32 | − | |
| 33 | −ifdef CONFIG_DRM_AMD_DC_SI | |
| 34 | −############################################################################### | |
| 35 | −# DCE 60 | |
| 36 | −############################################################################### | |
| 37 | −CLK_MGR_DCE60 = dce60_clk_mgr.o | |
| 38 | − | |
| 39 | −AMD_DAL_CLK_MGR_DCE60 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dce60/,$(CLK_MGR_DCE60)) | |
| 40 | − | |
| 41 | −AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCE60) | |
| 42 | −endif | |
| 43 | − | |
| 44 | 32 | ############################################################################### |
| 45 | 33 | # DCE 100 and DCE8x |
| 46 | 34 | ############################################################################### |
| @@ -188,4 +176,13 @@ CLK_MGR_DCN401 = dcn401_clk_mgr.o dcn401_clk_mgr_smu_msg.o · 141 unmodified lines | ||
| 188 | 176 | AMD_DAL_CLK_MGR_DCN401 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn401/,$(CLK_MGR_DCN401)) |
| 189 | 177 | |
| 190 | 178 | AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN401) |
| 179 | + | |
| 180 | +############################################################################### | |
| 181 | +# DCN42 | |
| 182 | +############################################################################### | |
| 183 | +CLK_MGR_DCN42 = dcn42_smu.o dcn42_clk_mgr.o | |
| 184 | + | |
| 185 | +AMD_DAL_CLK_MGR_DCN42 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn42/,$(CLK_MGR_DCN42)) | |
| 186 | + | |
| 187 | +AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN42) | |
| 191 | 188 | endif |
| @@ -34,7 +34,6 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "dce110/dce110_clk_mgr.h" |
| 35 | 35 | #include "dce112/dce112_clk_mgr.h" |
| 36 | 36 | #include "dce120/dce120_clk_mgr.h" |
| 37 | −#include "dce60/dce60_clk_mgr.h" | |
| 38 | 37 | #include "dcn10/rv1_clk_mgr.h" |
| 39 | 38 | #include "dcn10/rv2_clk_mgr.h" |
| 40 | 39 | #include "dcn20/dcn20_clk_mgr.h" |
| @@ -149,18 +148,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p · 108 unmodified lines | ||
| 149 | 148 | struct hw_asic_id asic_id = ctx->asic_id; |
| 150 | 149 | |
| 151 | 150 | switch (asic_id.chip_family) { |
| 152 | −#if defined(CONFIG_DRM_AMD_DC_SI) | |
| 153 | − case FAMILY_SI: { | |
| 154 | − struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr); | |
| 155 | − | |
| 156 | − if (clk_mgr == NULL) { | |
| 157 | − BREAK_TO_DEBUGGER(); | |
| 158 | − return NULL; | |
| 159 | − } | |
| 160 | − dce60_clk_mgr_construct(ctx, clk_mgr); | |
| 161 | − return &clk_mgr->base; | |
| 162 | − } | |
| 163 | −#endif | |
| 151 | + case FAMILY_SI: | |
| 164 | 152 | case FAMILY_CI: |
| 165 | 153 | case FAMILY_KV: { |
| 166 | 154 | struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr); |
| @@ -62,6 +62,18 @@ static const struct clk_mgr_mask disp_clk_mask = { · 61 unmodified lines | ||
| 62 | 62 | CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) |
| 63 | 63 | }; |
| 64 | 64 | |
| 65 | +/* Max clock values for each state indexed by "enum clocks_state": */ | |
| 66 | +static const struct state_dependent_clocks dce60_max_clks_by_state[] = { | |
| 67 | +/* ClocksStateInvalid - should not be used */ | |
| 68 | +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 69 | +/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */ | |
| 70 | +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 71 | +/* ClocksStateLow */ | |
| 72 | +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, | |
| 73 | +/* ClocksStateNominal */ | |
| 74 | +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, | |
| 75 | +/* ClocksStatePerformance */ | |
| 76 | +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; | |
| 65 | 77 | |
| 66 | 78 | /* Max clock values for each state indexed by "enum clocks_state": */ |
| 67 | 79 | static const struct state_dependent_clocks dce80_max_clks_by_state[] = { |
| @@ -126,6 +138,20 @@ int dce_adjust_dp_ref_freq_for_ss(struct clk_mgr_internal *clk_mgr_dce, int dp_r · 58 unmodified lines | ||
| 126 | 138 | return dp_ref_clk_khz; |
| 127 | 139 | } |
| 128 | 140 | |
| 141 | +static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) | |
| 142 | +{ | |
| 143 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 144 | + struct dc_context *ctx = clk_mgr_base->ctx; | |
| 145 | + int dp_ref_clk_khz = 0; | |
| 146 | + | |
| 147 | + if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) | |
| 148 | + dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; | |
| 149 | + else | |
| 150 | + dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz; | |
| 151 | + | |
| 152 | + return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); | |
| 153 | +} | |
| 154 | + | |
| 129 | 155 | int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) |
| 130 | 156 | { |
| 131 | 157 | struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
| @@ -134,6 +160,9 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) · 2 unmodified lines | ||
| 134 | 160 | int dp_ref_clk_khz; |
| 135 | 161 | int target_div; |
| 136 | 162 | |
| 163 | + if (clk_mgr_base->ctx->dce_version <= DCE_VERSION_6_4) | |
| 164 | + return dce60_get_dp_ref_freq_khz(clk_mgr_base); | |
| 165 | + | |
| 137 | 166 | /* ASSERT DP Reference Clock source is from DFS*/ |
| 138 | 167 | REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); |
| 139 | 168 | ASSERT(dprefclk_src_sel == 0); |
| @@ -441,27 +470,37 @@ void dce_clk_mgr_construct( · 301 unmodified lines | ||
| 441 | 470 | struct clk_mgr *base = &clk_mgr->base; |
| 442 | 471 | struct dm_pp_static_clock_info static_clk_info = {0}; |
| 443 | 472 | |
| 444 | − memcpy(clk_mgr->max_clks_by_state, | |
| 445 | − dce80_max_clks_by_state, | |
| 446 | − sizeof(dce80_max_clks_by_state)); | |
| 473 | + if (ctx->dce_version <= DCE_VERSION_6_4) | |
| 474 | + memcpy(clk_mgr->max_clks_by_state, | |
| 475 | + dce60_max_clks_by_state, | |
| 476 | + sizeof(dce60_max_clks_by_state)); | |
| 477 | + else | |
| 478 | + memcpy(clk_mgr->max_clks_by_state, | |
| 479 | + dce80_max_clks_by_state, | |
| 480 | + sizeof(dce80_max_clks_by_state)); | |
| 481 | + | |
| 447 | 482 | |
| 448 | 483 | base->ctx = ctx; |
| 449 | 484 | base->funcs = &dce_funcs; |
| 450 | 485 | |
| 451 | − clk_mgr->regs = &disp_clk_regs; | |
| 452 | − clk_mgr->clk_mgr_shift = &disp_clk_shift; | |
| 453 | − clk_mgr->clk_mgr_mask = &disp_clk_mask; | |
| 454 | − clk_mgr->dfs_bypass_disp_clk = 0; | |
| 486 | + if (ctx->dce_version >= DCE_VERSION_8_0) { | |
| 487 | + clk_mgr->regs = &disp_clk_regs; | |
| 488 | + clk_mgr->clk_mgr_shift = &disp_clk_shift; | |
| 489 | + clk_mgr->clk_mgr_mask = &disp_clk_mask; | |
| 490 | + } | |
| 455 | 491 | |
| 492 | + clk_mgr->dfs_bypass_disp_clk = 0; | |
| 456 | 493 | clk_mgr->dprefclk_ss_percentage = 0; |
| 457 | 494 | clk_mgr->dprefclk_ss_divider = 1000; |
| 458 | 495 | clk_mgr->ss_on_dprefclk = false; |
| 459 | 496 | |
| 460 | − if (dm_pp_get_static_clocks(ctx, &static_clk_info)) | |
| 461 | − clk_mgr->max_clks_state = static_clk_info.max_clocks_state; | |
| 462 | − else | |
| 463 | − clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; | |
| 464 | − clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; | |
| 497 | + if (ctx->dce_version >= DCE_VERSION_8_0) { | |
| 498 | + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) | |
| 499 | + clk_mgr->max_clks_state = static_clk_info.max_clocks_state; | |
| 500 | + else | |
| 501 | + clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; | |
| 502 | + clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; | |
| 503 | + } | |
| 465 | 504 | |
| 466 | 505 | base->clks.max_supported_dispclk_khz = |
| 467 | 506 | clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; |
| @@ -469,4 +508,3 @@ void dce_clk_mgr_construct( · 1 unmodified line | ||
| 469 | 508 | dce_clock_read_integrated_info(clk_mgr); |
| 470 | 509 | dce_clock_read_ss_info(clk_mgr); |
| 471 | 510 | } |
| 472 | − | |
| @@ -1,166 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> | |
| 3 | − * | |
| 4 | − * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | − * copy of this software and associated documentation files (the "Software"), | |
| 6 | − * to deal in the Software without restriction, including without limitation | |
| 7 | − * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | − * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | − * Software is furnished to do so, subject to the following conditions: | |
| 10 | − * | |
| 11 | − * The above copyright notice and this permission notice shall be included in | |
| 12 | − * all copies or substantial portions of the Software. | |
| 13 | − * | |
| 14 | − * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | − * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | − * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | − * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | − * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | − * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | − * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | − * | |
| 22 | − * Authors: AMD | |
| 23 | − * | |
| 24 | − */ | |
| 25 | − | |
| 26 | − | |
| 27 | −#include "dccg.h" | |
| 28 | −#include "clk_mgr_internal.h" | |
| 29 | −#include "dce100/dce_clk_mgr.h" | |
| 30 | −#include "dce110/dce110_clk_mgr.h" | |
| 31 | −#include "dce60_clk_mgr.h" | |
| 32 | −#include "reg_helper.h" | |
| 33 | −#include "dmcu.h" | |
| 34 | −#include "core_types.h" | |
| 35 | −#include "dal_asic_id.h" | |
| 36 | − | |
| 37 | −/* | |
| 38 | − * Currently the register shifts and masks in this file are used for dce60 | |
| 39 | − * which has no DPREFCLK_CNTL register | |
| 40 | − * TODO: remove this when DENTIST_DISPCLK_CNTL | |
| 41 | − * is moved to dccg, where it belongs | |
| 42 | − */ | |
| 43 | −#include "dce/dce_6_0_d.h" | |
| 44 | −#include "dce/dce_6_0_sh_mask.h" | |
| 45 | − | |
| 46 | −#define REG(reg) \ | |
| 47 | − (clk_mgr->regs->reg) | |
| 48 | − | |
| 49 | −#undef FN | |
| 50 | −#define FN(reg_name, field_name) \ | |
| 51 | − clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name | |
| 52 | − | |
| 53 | −/* set register offset */ | |
| 54 | −#define SR(reg_name)\ | |
| 55 | − .reg_name = mm ## reg_name | |
| 56 | − | |
| 57 | −static const struct clk_mgr_registers disp_clk_regs = { | |
| 58 | − CLK_COMMON_REG_LIST_DCE60_BASE() | |
| 59 | −}; | |
| 60 | − | |
| 61 | −static const struct clk_mgr_shift disp_clk_shift = { | |
| 62 | − CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(__SHIFT) | |
| 63 | −}; | |
| 64 | − | |
| 65 | −static const struct clk_mgr_mask disp_clk_mask = { | |
| 66 | − CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(_MASK) | |
| 67 | −}; | |
| 68 | − | |
| 69 | − | |
| 70 | −/* Max clock values for each state indexed by "enum clocks_state": */ | |
| 71 | −static const struct state_dependent_clocks dce60_max_clks_by_state[] = { | |
| 72 | −/* ClocksStateInvalid - should not be used */ | |
| 73 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 74 | −/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */ | |
| 75 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 76 | −/* ClocksStateLow */ | |
| 77 | −{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, | |
| 78 | −/* ClocksStateNominal */ | |
| 79 | −{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, | |
| 80 | −/* ClocksStatePerformance */ | |
| 81 | −{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; | |
| 82 | − | |
| 83 | −static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) | |
| 84 | −{ | |
| 85 | − struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 86 | − struct dc_context *ctx = clk_mgr_base->ctx; | |
| 87 | − int dp_ref_clk_khz = 0; | |
| 88 | − | |
| 89 | − if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) | |
| 90 | − dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; | |
| 91 | − else | |
| 92 | − dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz; | |
| 93 | − | |
| 94 | − return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); | |
| 95 | −} | |
| 96 | − | |
| 97 | −static void dce60_pplib_apply_display_requirements( | |
| 98 | − struct dc *dc, | |
| 99 | − struct dc_state *context) | |
| 100 | −{ | |
| 101 | − struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; | |
| 102 | − | |
| 103 | − dce110_fill_display_configs(context, pp_display_cfg); | |
| 104 | − | |
| 105 | − if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) | |
| 106 | − dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); | |
| 107 | −} | |
| 108 | − | |
| 109 | −static void dce60_update_clocks(struct clk_mgr *clk_mgr_base, | |
| 110 | − struct dc_state *context, | |
| 111 | − bool safe_to_lower) | |
| 112 | −{ | |
| 113 | − struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 114 | − struct dm_pp_power_level_change_request level_change_req; | |
| 115 | − const int max_disp_clk = | |
| 116 | − clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; | |
| 117 | − int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz); | |
| 118 | − | |
| 119 | − level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); | |
| 120 | − /* get max clock state from PPLIB */ | |
| 121 | − if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) | |
| 122 | − || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { | |
| 123 | − if (dm_pp_apply_power_level_change_request(clk_mgr_base->ctx, &level_change_req)) | |
| 124 | − clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; | |
| 125 | − } | |
| 126 | − | |
| 127 | − if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr_base->clks.dispclk_khz)) { | |
| 128 | − patched_disp_clk = dce_set_clock(clk_mgr_base, patched_disp_clk); | |
| 129 | − clk_mgr_base->clks.dispclk_khz = patched_disp_clk; | |
| 130 | − } | |
| 131 | − dce60_pplib_apply_display_requirements(clk_mgr_base->ctx->dc, context); | |
| 132 | −} | |
| 133 | − | |
| 134 | − | |
| 135 | − | |
| 136 | − | |
| 137 | − | |
| 138 | − | |
| 139 | − | |
| 140 | − | |
| 141 | −static struct clk_mgr_funcs dce60_funcs = { | |
| 142 | − .get_dp_ref_clk_frequency = dce60_get_dp_ref_freq_khz, | |
| 143 | − .update_clocks = dce60_update_clocks | |
| 144 | −}; | |
| 145 | − | |
| 146 | −void dce60_clk_mgr_construct( | |
| 147 | − struct dc_context *ctx, | |
| 148 | − struct clk_mgr_internal *clk_mgr) | |
| 149 | −{ | |
| 150 | − struct clk_mgr *base = &clk_mgr->base; | |
| 151 | − | |
| 152 | − dce_clk_mgr_construct(ctx, clk_mgr); | |
| 153 | − | |
| 154 | − memcpy(clk_mgr->max_clks_by_state, | |
| 155 | − dce60_max_clks_by_state, | |
| 156 | − sizeof(dce60_max_clks_by_state)); | |
| 157 | − | |
| 158 | − clk_mgr->regs = &disp_clk_regs; | |
| 159 | − clk_mgr->clk_mgr_shift = &disp_clk_shift; | |
| 160 | − clk_mgr->clk_mgr_mask = &disp_clk_mask; | |
| 161 | − clk_mgr->base.funcs = &dce60_funcs; | |
| 162 | − | |
| 163 | − base->clks.max_supported_dispclk_khz = | |
| 164 | − clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; | |
| 165 | −} | |
| 166 | − | |
| @@ -204,7 +204,7 @@ int dcn35_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispcl · 203 unmodified lines | ||
| 204 | 204 | khz_to_mhz_ceil(requested_dispclk_khz)); |
| 205 | 205 | |
| 206 | 206 | smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", requested_dispclk_khz, actual_dispclk_set_mhz); |
| 207 | − return actual_dispclk_set_mhz * 1000; | |
| 207 | + return (int)((long long)actual_dispclk_set_mhz * 1000); | |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | 210 | int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) |
| @@ -221,7 +221,7 @@ int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) · 10 unmodified lines | ||
| 221 | 221 | |
| 222 | 222 | /* TODO: add code for programing DP DTO, currently this is down by command table */ |
| 223 | 223 | |
| 224 | − return actual_dprefclk_set_mhz * 1000; | |
| 224 | + return (int)((long long)actual_dprefclk_set_mhz * 1000); | |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | 227 | int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz) |
| @@ -238,7 +238,7 @@ int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requeste · 10 unmodified lines | ||
| 238 | 238 | |
| 239 | 239 | smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", requested_dcfclk_khz, actual_dcfclk_set_mhz); |
| 240 | 240 | |
| 241 | − return actual_dcfclk_set_mhz * 1000; | |
| 241 | + return (int)((long long)actual_dcfclk_set_mhz * 1000); | |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | 244 | int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz) |
| @@ -255,7 +255,7 @@ int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int re · 10 unmodified lines | ||
| 255 | 255 | |
| 256 | 256 | smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n", requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz); |
| 257 | 257 | |
| 258 | − return actual_min_ds_dcfclk_mhz * 1000; | |
| 258 | + return (int)((long long)actual_min_ds_dcfclk_mhz * 1000); | |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | 261 | int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) |
| @@ -272,7 +272,7 @@ int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz · 10 unmodified lines | ||
| 272 | 272 | |
| 273 | 273 | smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", requested_dpp_khz, actual_dppclk_set_mhz); |
| 274 | 274 | |
| 275 | − return actual_dppclk_set_mhz * 1000; | |
| 275 | + return (int)((long long)actual_dppclk_set_mhz * 1000); | |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | 278 | void dcn35_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info) |
| @@ -424,7 +424,7 @@ int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr) · 145 unmodified lines | ||
| 424 | 424 | 0); |
| 425 | 425 | |
| 426 | 426 | smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk); |
| 427 | − return dprefclk * 1000; | |
| 427 | + return (int)((long long)dprefclk * 1000); | |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | 430 | int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) |
| @@ -439,7 +439,7 @@ int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) · 8 unmodified lines | ||
| 439 | 439 | 0); |
| 440 | 440 | |
| 441 | 441 | smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk); |
| 442 | − return dtbclk * 1000; | |
| 442 | + return (int)((long long)dtbclk * 1000); | |
| 443 | 443 | } |
| 444 | 444 | /* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */ |
| 445 | 445 | void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable) |
| @@ -0,0 +1,1152 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dcn42_clk_mgr.h" | |
| 6 | + | |
| 7 | +#include "dccg.h" | |
| 8 | +#include "clk_mgr_internal.h" | |
| 9 | + | |
| 10 | +// For dce12_get_dp_ref_freq_khz | |
| 11 | +#include "dce100/dce_clk_mgr.h" | |
| 12 | + | |
| 13 | +// For dcn20_update_clocks_update_dpp_dto | |
| 14 | +#include "dcn20/dcn20_clk_mgr.h" | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | +#include "reg_helper.h" | |
| 20 | +#include "core_types.h" | |
| 21 | +#include "dcn42_smu.h" | |
| 22 | +#include "dm_helpers.h" | |
| 23 | + | |
| 24 | +/* TODO: remove this include once we ported over remaining clk mgr functions*/ | |
| 25 | +#include "dcn30/dcn30_clk_mgr.h" | |
| 26 | +#include "dcn31/dcn31_clk_mgr.h" | |
| 27 | + | |
| 28 | +#include "dcn35/dcn35_clk_mgr.h" | |
| 29 | + | |
| 30 | +#include "dc_dmub_srv.h" | |
| 31 | +#include "link_service.h" | |
| 32 | +#include "logger_types.h" | |
| 33 | + | |
| 34 | + | |
| 35 | +#undef DC_LOGGER | |
| 36 | +#define DC_LOGGER \ | |
| 37 | + clk_mgr->base.base.ctx->logger | |
| 38 | + | |
| 39 | + | |
| 40 | +#define DCN_BASE__INST0_SEG1 0x000000C0 | |
| 41 | + | |
| 42 | +#define regCLK8_CLK2_BYPASS_CNTL 0x4c2a | |
| 43 | +#define regCLK8_CLK2_BYPASS_CNTL_BASE_IDX 0 | |
| 44 | +#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT 0x0 | |
| 45 | +#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT 0x10 | |
| 46 | +#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK 0x00000007L | |
| 47 | +#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV_MASK 0x000F0000L | |
| 48 | + | |
| 49 | +#define regDENTIST_DISPCLK_CNTL 0x0064 | |
| 50 | +#define regDENTIST_DISPCLK_CNTL_BASE_IDX 1 | |
| 51 | + | |
| 52 | +// DENTIST_DISPCLK_CNTL | |
| 53 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER__SHIFT 0x0 | |
| 54 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER__SHIFT 0x8 | |
| 55 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE__SHIFT 0x13 | |
| 56 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_CHG_DONE__SHIFT 0x14 | |
| 57 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_WDIVIDER__SHIFT 0x18 | |
| 58 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER_MASK 0x0000007FL | |
| 59 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER_MASK 0x00007F00L | |
| 60 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE_MASK 0x00080000L | |
| 61 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_CHG_DONE_MASK 0x00100000L | |
| 62 | +#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_WDIVIDER_MASK 0x7F000000L | |
| 63 | +#define mmDENTIST_DISPCLK_CNTL 0x0124 | |
| 64 | +#define mmCLK8_CLK_TICK_CNT_CONFIG_REG 0x1B851 | |
| 65 | +#define mmCLK8_CLK0_CURRENT_CNT 0x1B853 | |
| 66 | +#define mmCLK8_CLK1_CURRENT_CNT 0x1B854 | |
| 67 | +#define mmCLK8_CLK2_CURRENT_CNT 0x1B855 | |
| 68 | +#define mmCLK8_CLK3_CURRENT_CNT 0x1B856 | |
| 69 | +#define mmCLK8_CLK4_CURRENT_CNT 0x1B857 | |
| 70 | + | |
| 71 | + | |
| 72 | +#define mmCLK8_CLK0_BYPASS_CNTL 0x1B81A | |
| 73 | +#define mmCLK8_CLK1_BYPASS_CNTL 0x1B822 | |
| 74 | +#define mmCLK8_CLK2_BYPASS_CNTL 0x1B82A | |
| 75 | +#define mmCLK8_CLK3_BYPASS_CNTL 0x1B832 | |
| 76 | +#define mmCLK8_CLK4_BYPASS_CNTL 0x1B83A | |
| 77 | + | |
| 78 | + | |
| 79 | +#define mmCLK8_CLK0_DS_CNTL 0x1B814 | |
| 80 | +#define mmCLK8_CLK1_DS_CNTL 0x1B81C | |
| 81 | +#define mmCLK8_CLK2_DS_CNTL 0x1B824 | |
| 82 | +#define mmCLK8_CLK3_DS_CNTL 0x1B82C | |
| 83 | +#define mmCLK8_CLK4_DS_CNTL 0x1B834 | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | +#undef FN | |
| 89 | +#define FN(reg_name, field_name) \ | |
| 90 | + clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name | |
| 91 | + | |
| 92 | +#define REG(reg) \ | |
| 93 | + (clk_mgr->regs->reg) | |
| 94 | + | |
| 95 | +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg | |
| 96 | + | |
| 97 | +#define BASE(seg) BASE_INNER(seg) | |
| 98 | + | |
| 99 | +#define SR(reg_name)\ | |
| 100 | + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ | |
| 101 | + reg ## reg_name | |
| 102 | + | |
| 103 | +#define CLK_SR_DCN42(reg_name)\ | |
| 104 | + .reg_name = mm ## reg_name | |
| 105 | + | |
| 106 | +static const struct clk_mgr_registers clk_mgr_regs_dcn42 = { | |
| 107 | + CLK_REG_LIST_DCN42() | |
| 108 | +}; | |
| 109 | + | |
| 110 | +static const struct clk_mgr_shift clk_mgr_shift_dcn42 = { | |
| 111 | + CLK_COMMON_MASK_SH_LIST_DCN42(__SHIFT) | |
| 112 | +}; | |
| 113 | + | |
| 114 | +static const struct clk_mgr_mask clk_mgr_mask_dcn42 = { | |
| 115 | + CLK_COMMON_MASK_SH_LIST_DCN42(_MASK) | |
| 116 | +}; | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | +#define TO_CLK_MGR_DCN42(clk_mgr_int)\ | |
| 121 | + container_of(clk_mgr_int, struct clk_mgr_dcn42, base) | |
| 122 | + | |
| 123 | +int dcn42_get_active_display_cnt_wa( | |
| 124 | + struct dc *dc, | |
| 125 | + struct dc_state *context, | |
| 126 | + int *all_active_disps) | |
| 127 | +{ | |
| 128 | + int i, display_count = 0; | |
| 129 | + bool tmds_present = false; | |
| 130 | + | |
| 131 | + for (i = 0; i < context->stream_count; i++) { | |
| 132 | + const struct dc_stream_state *stream = context->streams[i]; | |
| 133 | + | |
| 134 | + if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A || | |
| 135 | + stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK || | |
| 136 | + stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) | |
| 137 | + tmds_present = true; | |
| 138 | + } | |
| 139 | + | |
| 140 | + for (i = 0; i < dc->link_count; i++) { | |
| 141 | + const struct dc_link *link = dc->links[i]; | |
| 142 | + | |
| 143 | + /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */ | |
| 144 | + if (link->link_enc && link->link_enc->funcs->is_dig_enabled && | |
| 145 | + link->link_enc->funcs->is_dig_enabled(link->link_enc)) | |
| 146 | + display_count++; | |
| 147 | + } | |
| 148 | + if (all_active_disps != NULL) | |
| 149 | + *all_active_disps = display_count; | |
| 150 | + /* WA for hang on HDMI after display off back on*/ | |
| 151 | + if (display_count == 0 && tmds_present) | |
| 152 | + display_count = 1; | |
| 153 | + | |
| 154 | + return display_count; | |
| 155 | +} | |
| 156 | + | |
| 157 | +void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, | |
| 158 | + struct dc_state *context, | |
| 159 | + int ref_dtbclk_khz) | |
| 160 | +{ | |
| 161 | + /* DCN42 does not implement set_dtbclk_dto function, so this is a no-op */ | |
| 162 | +} | |
| 163 | + | |
| 164 | +void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, | |
| 165 | + struct dc_state *context, bool safe_to_lower) | |
| 166 | +{ | |
| 167 | + int i; | |
| 168 | + bool dppclk_active[MAX_PIPES] = {0}; | |
| 169 | + | |
| 170 | + | |
| 171 | + clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz; | |
| 172 | + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { | |
| 173 | + int dpp_inst = 0, dppclk_khz, prev_dppclk_khz; | |
| 174 | + | |
| 175 | + dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz; | |
| 176 | + | |
| 177 | + if (context->res_ctx.pipe_ctx[i].plane_res.dpp) | |
| 178 | + dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst; | |
| 179 | + else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) { | |
| 180 | + /* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting. | |
| 181 | + * In this case just continue in loop | |
| 182 | + */ | |
| 183 | + continue; | |
| 184 | + } else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) { | |
| 185 | + /* The software state is not valid if dpp resource is NULL and | |
| 186 | + * dppclk_khz > 0. | |
| 187 | + */ | |
| 188 | + ASSERT(false); | |
| 189 | + continue; | |
| 190 | + } | |
| 191 | + | |
| 192 | + prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i]; | |
| 193 | + | |
| 194 | + if (safe_to_lower || prev_dppclk_khz < dppclk_khz) | |
| 195 | + clk_mgr->dccg->funcs->update_dpp_dto( | |
| 196 | + clk_mgr->dccg, dpp_inst, dppclk_khz); | |
| 197 | + dppclk_active[dpp_inst] = true; | |
| 198 | + } | |
| 199 | + if (safe_to_lower) | |
| 200 | + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { | |
| 201 | + struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp; | |
| 202 | + | |
| 203 | + if (old_dpp && !dppclk_active[old_dpp->inst]) | |
| 204 | + clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0); | |
| 205 | + } | |
| 206 | +} | |
| 207 | + | |
| 208 | +void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, | |
| 209 | + struct dc_state *context, | |
| 210 | + bool safe_to_lower) | |
| 211 | +{ | |
| 212 | + union dmub_rb_cmd cmd; | |
| 213 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 214 | + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; | |
| 215 | + struct dc *dc = clk_mgr_base->ctx->dc; | |
| 216 | + int display_count = 0; | |
| 217 | + bool update_dppclk = false; | |
| 218 | + bool update_dispclk = false; | |
| 219 | + bool dpp_clock_lowered = false; | |
| 220 | + int all_active_disps = 0; | |
| 221 | + | |
| 222 | + if (dc->work_arounds.skip_clock_update) | |
| 223 | + return; | |
| 224 | + | |
| 225 | + display_count = dcn42_get_active_display_cnt_wa(dc, context, &all_active_disps); | |
| 226 | + | |
| 227 | + /*dml21 issue*/ | |
| 228 | + ASSERT(new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz > 590000); //remove this section if assert is hit | |
| 229 | + if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000) | |
| 230 | + new_clocks->ref_dtbclk_khz = 600000; | |
| 231 | + | |
| 232 | + /* | |
| 233 | + * if it is safe to lower, but we are already in the lower state, we don't have to do anything | |
| 234 | + * also if safe to lower is false, we just go in the higher state | |
| 235 | + */ | |
| 236 | + if (safe_to_lower) { | |
| 237 | + if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW && | |
| 238 | + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { | |
| 239 | + dcn42_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support); | |
| 240 | + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; | |
| 241 | + } | |
| 242 | + | |
| 243 | + if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) { | |
| 244 | + if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk) | |
| 245 | + dcn42_smu_set_dtbclk(clk_mgr, false); | |
| 246 | + clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; | |
| 247 | + } | |
| 248 | + /* check that we're not already in lower */ | |
| 249 | + if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { | |
| 250 | + /* if we can go lower, go lower */ | |
| 251 | + if (display_count == 0) | |
| 252 | + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; | |
| 253 | + } | |
| 254 | + } else { | |
| 255 | + if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && | |
| 256 | + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { | |
| 257 | + dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW); | |
| 258 | + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; | |
| 259 | + } | |
| 260 | + if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) { | |
| 261 | + int actual_dtbclk = 0; | |
| 262 | + | |
| 263 | + dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); | |
| 264 | + dcn42_smu_set_dtbclk(clk_mgr, true); | |
| 265 | + if (clk_mgr_base->boot_snapshot.timer_threhold) | |
| 266 | + actual_dtbclk = REG_READ(CLK8_CLK4_CURRENT_CNT) / (clk_mgr_base->boot_snapshot.timer_threhold / 48000); | |
| 267 | + | |
| 268 | + | |
| 269 | + if (actual_dtbclk > 590000) { | |
| 270 | + clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; | |
| 271 | + clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; | |
| 272 | + } | |
| 273 | + } | |
| 274 | + | |
| 275 | + /* check that we're not already in D0 */ | |
| 276 | + if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) { | |
| 277 | + union display_idle_optimization_u idle_info = { 0 }; | |
| 278 | + | |
| 279 | + dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data); | |
| 280 | + /* update power state */ | |
| 281 | + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE; | |
| 282 | + } | |
| 283 | + } | |
| 284 | + if (dc->debug.force_min_dcfclk_mhz > 0) | |
| 285 | + new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ? | |
| 286 | + new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000); | |
| 287 | + | |
| 288 | + if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { | |
| 289 | + clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; | |
| 290 | + clk_mgr_base->clks.fclk_khz = new_clocks->fclk_khz; | |
| 291 | + clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz; | |
| 292 | + dcn42_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz); | |
| 293 | + } | |
| 294 | + | |
| 295 | + if (should_set_clock(safe_to_lower, | |
| 296 | + new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { | |
| 297 | + clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; | |
| 298 | + dcn42_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz); | |
| 299 | + } | |
| 300 | + | |
| 301 | + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. | |
| 302 | + | |
| 303 | + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { | |
| 304 | + if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) | |
| 305 | + dpp_clock_lowered = true; | |
| 306 | + clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; | |
| 307 | + update_dppclk = true; | |
| 308 | + } | |
| 309 | + | |
| 310 | + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && | |
| 311 | + (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { | |
| 312 | + int requested_dispclk_khz = new_clocks->dispclk_khz; | |
| 313 | + | |
| 314 | + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); | |
| 315 | + | |
| 316 | + /* Clamp the requested clock to PMFW based on their limit. */ | |
| 317 | + if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) | |
| 318 | + requested_dispclk_khz = dc->debug.min_disp_clk_khz; | |
| 319 | + | |
| 320 | + dcn42_smu_set_dispclk(clk_mgr, requested_dispclk_khz); | |
| 321 | + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; | |
| 322 | + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); | |
| 323 | + | |
| 324 | + update_dispclk = true; | |
| 325 | + } | |
| 326 | + | |
| 327 | + /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */ | |
| 328 | + if (!dc->debug.disable_dtb_ref_clk_switch && | |
| 329 | + should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, | |
| 330 | + clk_mgr_base->clks.ref_dtbclk_khz / 1000)) { | |
| 331 | + dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); | |
| 332 | + clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; | |
| 333 | + } | |
| 334 | + | |
| 335 | + if (dpp_clock_lowered) { | |
| 336 | + // increase per DPP DTO before lowering global dppclk | |
| 337 | + dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); | |
| 338 | + dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); | |
| 339 | + } else { | |
| 340 | + // increase global DPPCLK before lowering per DPP DTO | |
| 341 | + if (update_dppclk || update_dispclk) | |
| 342 | + dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); | |
| 343 | + dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); | |
| 344 | + } | |
| 345 | + // notify DMCUB of latest clocks | |
| 346 | + memset(&cmd, 0, sizeof(cmd)); | |
| 347 | + cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR; | |
| 348 | + cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS; | |
| 349 | + cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz; | |
| 350 | + cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz = | |
| 351 | + clk_mgr_base->clks.dcfclk_deep_sleep_khz; | |
| 352 | + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; | |
| 353 | + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; | |
| 354 | + | |
| 355 | + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); | |
| 356 | +} | |
| 357 | + | |
| 358 | + | |
| 359 | +void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base) | |
| 360 | +{ | |
| 361 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 362 | + | |
| 363 | + dcn42_smu_enable_pme_wa(clk_mgr); | |
| 364 | +} | |
| 365 | + | |
| 366 | + | |
| 367 | +bool dcn42_are_clock_states_equal(struct dc_clocks *a, | |
| 368 | + struct dc_clocks *b) | |
| 369 | +{ | |
| 370 | + if (a->dispclk_khz != b->dispclk_khz) | |
| 371 | + return false; | |
| 372 | + else if (a->dppclk_khz != b->dppclk_khz) | |
| 373 | + return false; | |
| 374 | + else if (a->dcfclk_khz != b->dcfclk_khz) | |
| 375 | + return false; | |
| 376 | + else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz) | |
| 377 | + return false; | |
| 378 | + else if (a->zstate_support != b->zstate_support) | |
| 379 | + return false; | |
| 380 | + else if (a->dtbclk_en != b->dtbclk_en) | |
| 381 | + return false; | |
| 382 | + | |
| 383 | + return true; | |
| 384 | +} | |
| 385 | + | |
| 386 | +static void dcn42_dump_clk_registers_internal(struct dcn42_clk_internal *internal, struct clk_mgr *clk_mgr_base) | |
| 387 | +{ | |
| 388 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 389 | + uint32_t ratio = 1; | |
| 390 | + | |
| 391 | + internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD = REG_READ(CLK8_CLK_TICK_CNT_CONFIG_REG) & 0xFFFFFF; | |
| 392 | + | |
| 393 | + ratio = internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD / 48000; | |
| 394 | + ASSERT(ratio != 0); | |
| 395 | + | |
| 396 | + if (ratio) { | |
| 397 | + // read dcf deep sleep divider | |
| 398 | + internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL); | |
| 399 | + internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL); | |
| 400 | + // read dispclk | |
| 401 | + internal->CLK8_CLK0_CURRENT_CNT = REG_READ(CLK8_CLK0_CURRENT_CNT) / ratio; | |
| 402 | + internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL); | |
| 403 | + // read dppclk | |
| 404 | + internal->CLK8_CLK1_CURRENT_CNT = REG_READ(CLK8_CLK1_CURRENT_CNT) / ratio; | |
| 405 | + internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL); | |
| 406 | + // read dprefclk | |
| 407 | + internal->CLK8_CLK2_CURRENT_CNT = REG_READ(CLK8_CLK2_CURRENT_CNT) / ratio; | |
| 408 | + internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL); | |
| 409 | + // read dcfclk | |
| 410 | + internal->CLK8_CLK3_CURRENT_CNT = REG_READ(CLK8_CLK3_CURRENT_CNT) / ratio; | |
| 411 | + internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL); | |
| 412 | + // read dtbclk | |
| 413 | + internal->CLK8_CLK4_CURRENT_CNT = REG_READ(CLK8_CLK4_CURRENT_CNT) / ratio; | |
| 414 | + internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL); | |
| 415 | + } | |
| 416 | + | |
| 417 | +} | |
| 418 | + | |
| 419 | +static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, | |
| 420 | + struct clk_mgr_dcn42 *clk_mgr) | |
| 421 | +{ | |
| 422 | + struct dcn42_clk_internal internal = {0}; | |
| 423 | + char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"}; | |
| 424 | + | |
| 425 | + dcn42_dump_clk_registers_internal(&internal, &clk_mgr->base.base); | |
| 426 | + regs_and_bypass->timer_threhold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD; | |
| 427 | + regs_and_bypass->dcfclk = internal.CLK8_CLK3_CURRENT_CNT / 10; | |
| 428 | + regs_and_bypass->dcf_deep_sleep_divider = internal.CLK8_CLK3_DS_CNTL / 10; | |
| 429 | + regs_and_bypass->dcf_deep_sleep_allow = internal.CLK8_CLK3_DS_CNTL & 0x10; /*bit 4: CLK0_ALLOW_DS*/ | |
| 430 | + regs_and_bypass->dprefclk = internal.CLK8_CLK2_CURRENT_CNT / 10; | |
| 431 | + regs_and_bypass->dispclk = internal.CLK8_CLK0_CURRENT_CNT / 10; | |
| 432 | + regs_and_bypass->dppclk = internal.CLK8_CLK1_CURRENT_CNT / 10; | |
| 433 | + regs_and_bypass->dtbclk = internal.CLK8_CLK4_CURRENT_CNT / 10; | |
| 434 | + | |
| 435 | + regs_and_bypass->dppclk_bypass = internal.CLK8_CLK1_BYPASS_CNTL & 0x0007; | |
| 436 | + if (regs_and_bypass->dppclk_bypass > 4) | |
| 437 | + regs_and_bypass->dppclk_bypass = 0; | |
| 438 | + regs_and_bypass->dcfclk_bypass = internal.CLK8_CLK3_BYPASS_CNTL & 0x0007; | |
| 439 | + if (regs_and_bypass->dcfclk_bypass > 4) | |
| 440 | + regs_and_bypass->dcfclk_bypass = 0; | |
| 441 | + regs_and_bypass->dispclk_bypass = internal.CLK8_CLK0_BYPASS_CNTL & 0x0007; | |
| 442 | + if (regs_and_bypass->dispclk_bypass > 4) | |
| 443 | + regs_and_bypass->dispclk_bypass = 0; | |
| 444 | + regs_and_bypass->dprefclk_bypass = internal.CLK8_CLK2_BYPASS_CNTL & 0x0007; | |
| 445 | + if (regs_and_bypass->dprefclk_bypass > 4) | |
| 446 | + regs_and_bypass->dprefclk_bypass = 0; | |
| 447 | + | |
| 448 | + if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { | |
| 449 | + DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n"); | |
| 450 | + | |
| 451 | + DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n", | |
| 452 | + regs_and_bypass->dcfclk, | |
| 453 | + regs_and_bypass->dcf_deep_sleep_divider, | |
| 454 | + regs_and_bypass->dcf_deep_sleep_allow, | |
| 455 | + bypass_clks[(int) regs_and_bypass->dcfclk_bypass]); | |
| 456 | + | |
| 457 | + DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n", | |
| 458 | + regs_and_bypass->dprefclk, | |
| 459 | + bypass_clks[(int) regs_and_bypass->dprefclk_bypass]); | |
| 460 | + | |
| 461 | + DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n", | |
| 462 | + regs_and_bypass->dispclk, | |
| 463 | + bypass_clks[(int) regs_and_bypass->dispclk_bypass]); | |
| 464 | + | |
| 465 | + //split | |
| 466 | + DC_LOG_SMU("SPLIT\n"); | |
| 467 | + | |
| 468 | + // REGISTER VALUES | |
| 469 | + DC_LOG_SMU("reg_name,value,clk_type\n"); | |
| 470 | + | |
| 471 | + DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n", | |
| 472 | + internal.CLK8_CLK3_CURRENT_CNT); | |
| 473 | + | |
| 474 | + DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider\n", | |
| 475 | + internal.CLK8_CLK3_DS_CNTL); | |
| 476 | + | |
| 477 | + DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow\n", | |
| 478 | + (internal.CLK8_CLK3_DS_CNTL & 0x10)); | |
| 479 | + | |
| 480 | + DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk\n", | |
| 481 | + internal.CLK8_CLK2_CURRENT_CNT); | |
| 482 | + | |
| 483 | + DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk\n", | |
| 484 | + internal.CLK8_CLK0_CURRENT_CNT); | |
| 485 | + | |
| 486 | + DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk\n", | |
| 487 | + internal.CLK8_CLK1_CURRENT_CNT); | |
| 488 | + | |
| 489 | + DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n", | |
| 490 | + internal.CLK8_CLK3_BYPASS_CNTL); | |
| 491 | + | |
| 492 | + DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass\n", | |
| 493 | + internal.CLK8_CLK2_BYPASS_CNTL); | |
| 494 | + | |
| 495 | + DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass\n", | |
| 496 | + internal.CLK8_CLK0_BYPASS_CNTL); | |
| 497 | + | |
| 498 | + DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass\n", | |
| 499 | + internal.CLK8_CLK1_BYPASS_CNTL); | |
| 500 | + } | |
| 501 | +} | |
| 502 | + | |
| 503 | +bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base) | |
| 504 | +{ | |
| 505 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 506 | + struct dc_context *ctx = clk_mgr->base.ctx; | |
| 507 | + | |
| 508 | + | |
| 509 | + if (ctx->dc->config.ignore_dpref_ss) { | |
| 510 | + /*revert bios's ss info for test only*/ | |
| 511 | + return (clk_mgr->dprefclk_ss_percentage == 0); | |
| 512 | + } | |
| 513 | + /*need to update after BU*/ | |
| 514 | + return false; | |
| 515 | +} | |
| 516 | + | |
| 517 | +static void init_clk_states(struct clk_mgr *clk_mgr) | |
| 518 | +{ | |
| 519 | + uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz; | |
| 520 | + | |
| 521 | + memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); | |
| 522 | + | |
| 523 | + clk_mgr->clks.dtbclk_en = true; // request DTBCLK disable on first commit | |
| 524 | + clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk | |
| 525 | + clk_mgr->clks.p_state_change_support = true; | |
| 526 | + clk_mgr->clks.prev_p_state_change_support = true; | |
| 527 | + clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; | |
| 528 | + clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN; | |
| 529 | +} | |
| 530 | + | |
| 531 | +static void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, | |
| 532 | + struct dcn42_smu_dpm_clks *smu_dpm_clks) | |
| 533 | +{ | |
| 534 | + DpmClocks_t_dcn42 *table = smu_dpm_clks->dpm_clks; | |
| 535 | + | |
| 536 | + if (!clk_mgr->smu_ver) | |
| 537 | + return; | |
| 538 | + | |
| 539 | + if (!table || smu_dpm_clks->mc_address.quad_part == 0) | |
| 540 | + return; | |
| 541 | + | |
| 542 | + memset(table, 0, sizeof(*table)); | |
| 543 | + | |
| 544 | + dcn42_smu_set_dram_addr_high(clk_mgr, | |
| 545 | + smu_dpm_clks->mc_address.high_part); | |
| 546 | + dcn42_smu_set_dram_addr_low(clk_mgr, | |
| 547 | + smu_dpm_clks->mc_address.low_part); | |
| 548 | + dcn42_smu_transfer_dpm_table_smu_2_dram(clk_mgr); | |
| 549 | +} | |
| 550 | + | |
| 551 | +void dcn42_init_single_clock(unsigned int *entry_0, | |
| 552 | + uint32_t *smu_entry_0, | |
| 553 | + uint8_t num_levels) | |
| 554 | +{ | |
| 555 | + int i; | |
| 556 | + char *entry_i = (char *)entry_0; | |
| 557 | + | |
| 558 | + ASSERT(num_levels <= MAX_NUM_DPM_LVL); | |
| 559 | + if (num_levels > MAX_NUM_DPM_LVL) | |
| 560 | + num_levels = MAX_NUM_DPM_LVL; | |
| 561 | + | |
| 562 | + | |
| 563 | + for (i = 0; i < num_levels; i++) { | |
| 564 | + *((unsigned int *)entry_i) = smu_entry_0[i]; | |
| 565 | + entry_i += sizeof(struct clk_limit_table_entry); | |
| 566 | + } | |
| 567 | +} | |
| 568 | + | |
| 569 | +unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio) | |
| 570 | +{ | |
| 571 | + switch (wck_ratio) { | |
| 572 | + case WCK_RATIO_1_2: | |
| 573 | + return 2; | |
| 574 | + | |
| 575 | + case WCK_RATIO_1_4: | |
| 576 | + return 4; | |
| 577 | + | |
| 578 | + default: | |
| 579 | + break; | |
| 580 | + } | |
| 581 | + | |
| 582 | + return 1; | |
| 583 | +} | |
| 584 | + | |
| 585 | +void dcn42_init_clocks(struct clk_mgr *clk_mgr_base) | |
| 586 | +{ | |
| 587 | + struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 588 | + struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int); | |
| 589 | + struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 }; | |
| 590 | + | |
| 591 | + init_clk_states(clk_mgr_base); | |
| 592 | + | |
| 593 | + // to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk | |
| 594 | + if (dcn42_is_spll_ssc_enabled(clk_mgr_base)) | |
| 595 | + clk_mgr_base->dp_dto_source_clock_in_khz = | |
| 596 | + dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr_base->dprefclk_khz); | |
| 597 | + else | |
| 598 | + clk_mgr_base->dp_dto_source_clock_in_khz = clk_mgr_base->dprefclk_khz; | |
| 599 | + | |
| 600 | + dcn42_dump_clk_registers(&clk_mgr_base->boot_snapshot, clk_mgr); | |
| 601 | + | |
| 602 | + clk_mgr_base->clks.ref_dtbclk_khz = clk_mgr_base->boot_snapshot.dtbclk * 10; | |
| 603 | + if (clk_mgr_base->boot_snapshot.dtbclk > 59000) { | |
| 604 | + /*dtbclk enabled based on*/ | |
| 605 | + clk_mgr_base->clks.dtbclk_en = true; | |
| 606 | + } | |
| 607 | + | |
| 608 | + smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem( | |
| 609 | + clk_mgr_base->ctx, | |
| 610 | + DC_MEM_ALLOC_TYPE_GART, | |
| 611 | + sizeof(DpmClocks_t_dcn42), | |
| 612 | + &smu_dpm_clks.mc_address.quad_part); | |
| 613 | + | |
| 614 | + ASSERT(smu_dpm_clks.dpm_clks); | |
| 615 | + if (clk_mgr_base->ctx->dc->debug.pstate_enabled && clk_mgr_int->smu_present && smu_dpm_clks.mc_address.quad_part != 0) { | |
| 616 | + int i; | |
| 617 | + DpmClocks_t_dcn42 *dpm_clks = smu_dpm_clks.dpm_clks; | |
| 618 | + | |
| 619 | + dcn42_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks); | |
| 620 | + DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" | |
| 621 | + "NumDispClkLevelsEnabled: %d\n" | |
| 622 | + "NumSocClkLevelsEnabled: %d\n" | |
| 623 | + "VcnClkLevelsEnabled: %d\n" | |
| 624 | + "FClkLevelsEnabled: %d\n" | |
| 625 | + "NumMemPstatesEnabled: %d\n" | |
| 626 | + "MinGfxClk: %d\n" | |
| 627 | + "MaxGfxClk: %d\n", | |
| 628 | + dpm_clks->NumDcfClkLevelsEnabled, | |
| 629 | + dpm_clks->NumDispClkLevelsEnabled, | |
| 630 | + dpm_clks->NumSocClkLevelsEnabled, | |
| 631 | + dpm_clks->VcnClkLevelsEnabled, | |
| 632 | + dpm_clks->NumFclkLevelsEnabled, | |
| 633 | + dpm_clks->NumMemPstatesEnabled, | |
| 634 | + dpm_clks->MinGfxClk, | |
| 635 | + dpm_clks->MaxGfxClk); | |
| 636 | + | |
| 637 | + for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) { | |
| 638 | + DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n", | |
| 639 | + i, | |
| 640 | + dpm_clks->DcfClocks[i]); | |
| 641 | + } | |
| 642 | + for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) { | |
| 643 | + DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n", | |
| 644 | + i, dpm_clks->DispClocks[i]); | |
| 645 | + } | |
| 646 | + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { | |
| 647 | + DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n", | |
| 648 | + i, dpm_clks->SocClocks[i]); | |
| 649 | + } | |
| 650 | + for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { | |
| 651 | + DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n", | |
| 652 | + i, dpm_clks->FclkClocks_Freq[i]); | |
| 653 | + DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n", | |
| 654 | + i, dpm_clks->FclkClocks_Voltage[i]); | |
| 655 | + } | |
| 656 | + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) | |
| 657 | + DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n", | |
| 658 | + i, dpm_clks->SocVoltage[i]); | |
| 659 | + | |
| 660 | + for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++) { | |
| 661 | + DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d\n" | |
| 662 | + "dpm_clks->MemPstateTable[%d].MemClk= %d\n" | |
| 663 | + "dpm_clks->MemPstateTable[%d].Voltage = %d\n", | |
| 664 | + i, dpm_clks->MemPstateTable[i].UClk, | |
| 665 | + i, dpm_clks->MemPstateTable[i].MemClk, | |
| 666 | + i, dpm_clks->MemPstateTable[i].Voltage); | |
| 667 | + } | |
| 668 | + | |
| 669 | + if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) { | |
| 670 | + /* DCFCLK */ | |
| 671 | + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, | |
| 672 | + dpm_clks->DcfClocks, | |
| 673 | + dpm_clks->NumDcfClkLevelsEnabled); | |
| 674 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled; | |
| 675 | + | |
| 676 | + /* SOCCLK */ | |
| 677 | + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz, | |
| 678 | + dpm_clks->SocClocks, | |
| 679 | + dpm_clks->NumSocClkLevelsEnabled); | |
| 680 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled; | |
| 681 | + | |
| 682 | + /* DISPCLK */ | |
| 683 | + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, | |
| 684 | + dpm_clks->DispClocks, | |
| 685 | + dpm_clks->NumDispClkLevelsEnabled); | |
| 686 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled; | |
| 687 | + | |
| 688 | + /* DPPCLK */ | |
| 689 | + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz, | |
| 690 | + dpm_clks->DppClocks, | |
| 691 | + dpm_clks->NumDispClkLevelsEnabled); | |
| 692 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled; | |
| 693 | + | |
| 694 | + /* FCLK */ | |
| 695 | + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz, | |
| 696 | + dpm_clks->FclkClocks_Freq, | |
| 697 | + NUM_FCLK_DPM_LEVELS); | |
| 698 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled; | |
| 699 | + clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled; | |
| 700 | + | |
| 701 | + /* Memory Pstate table is in reverse order*/ | |
| 702 | + ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS); | |
| 703 | + if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS) | |
| 704 | + dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS; | |
| 705 | + for (i = 0; i < dpm_clks->NumMemPstatesEnabled; i++) { | |
| 706 | + clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].UClk; | |
| 707 | + clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio) ; | |
| 708 | + } | |
| 709 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumMemPstatesEnabled; | |
| 710 | + | |
| 711 | + /* DTBCLK*/ | |
| 712 | + clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = clk_mgr_base->clks.ref_dtbclk_khz / 1000; | |
| 713 | + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1; | |
| 714 | + | |
| 715 | + /* Refresh bounding box */ | |
| 716 | + clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box( | |
| 717 | + clk_mgr_base->ctx->dc, clk_mgr_base->bw_params); | |
| 718 | + } | |
| 719 | + } | |
| 720 | + if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0) | |
| 721 | + dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART, | |
| 722 | + smu_dpm_clks.dpm_clks); | |
| 723 | +} | |
| 724 | + | |
| 725 | +static struct clk_bw_params dcn42_bw_params = { | |
| 726 | + .vram_type = Ddr4MemType, | |
| 727 | + .num_channels = 1, | |
| 728 | + .clk_table = { | |
| 729 | + .num_entries = 4, | |
| 730 | + }, | |
| 731 | + | |
| 732 | +}; | |
| 733 | + | |
| 734 | +static struct wm_table ddr5_wm_table = { | |
| 735 | + .entries = { | |
| 736 | + { | |
| 737 | + .wm_inst = WM_A, | |
| 738 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 739 | + .pstate_latency_us = 11.72, | |
| 740 | + .sr_exit_time_us = 28.0, | |
| 741 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 742 | + .valid = true, | |
| 743 | + }, | |
| 744 | + { | |
| 745 | + .wm_inst = WM_B, | |
| 746 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 747 | + .pstate_latency_us = 11.72, | |
| 748 | + .sr_exit_time_us = 28.0, | |
| 749 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 750 | + .valid = true, | |
| 751 | + }, | |
| 752 | + { | |
| 753 | + .wm_inst = WM_C, | |
| 754 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 755 | + .pstate_latency_us = 11.72, | |
| 756 | + .sr_exit_time_us = 28.0, | |
| 757 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 758 | + .valid = true, | |
| 759 | + }, | |
| 760 | + { | |
| 761 | + .wm_inst = WM_D, | |
| 762 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 763 | + .pstate_latency_us = 11.72, | |
| 764 | + .sr_exit_time_us = 28.0, | |
| 765 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 766 | + .valid = true, | |
| 767 | + }, | |
| 768 | + } | |
| 769 | +}; | |
| 770 | + | |
| 771 | +static struct wm_table lpddr5_wm_table = { | |
| 772 | + .entries = { | |
| 773 | + { | |
| 774 | + .wm_inst = WM_A, | |
| 775 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 776 | + .pstate_latency_us = 11.65333, | |
| 777 | + .sr_exit_time_us = 28.0, | |
| 778 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 779 | + .valid = true, | |
| 780 | + }, | |
| 781 | + { | |
| 782 | + .wm_inst = WM_B, | |
| 783 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 784 | + .pstate_latency_us = 11.65333, | |
| 785 | + .sr_exit_time_us = 28.0, | |
| 786 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 787 | + .valid = true, | |
| 788 | + }, | |
| 789 | + { | |
| 790 | + .wm_inst = WM_C, | |
| 791 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 792 | + .pstate_latency_us = 11.65333, | |
| 793 | + .sr_exit_time_us = 28.0, | |
| 794 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 795 | + .valid = true, | |
| 796 | + }, | |
| 797 | + { | |
| 798 | + .wm_inst = WM_D, | |
| 799 | + .wm_type = WM_TYPE_PSTATE_CHG, | |
| 800 | + .pstate_latency_us = 11.65333, | |
| 801 | + .sr_exit_time_us = 28.0, | |
| 802 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 803 | + .valid = true, | |
| 804 | + }, | |
| 805 | + } | |
| 806 | +}; | |
| 807 | + | |
| 808 | +struct dcn42_ss_info_table dcn42_ss_info_table = { | |
| 809 | + .ss_divider = 1000, | |
| 810 | + .ss_percentage = {0, 0, 375, 375, 375} | |
| 811 | +}; | |
| 812 | + | |
| 813 | +static void dcn42_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr) | |
| 814 | +{ | |
| 815 | + uint32_t clock_source; | |
| 816 | + | |
| 817 | + clock_source = (REG_READ(CLK8_CLK2_BYPASS_CNTL) & CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK); | |
| 818 | + // If it's DFS mode, clock_source is 0. | |
| 819 | + if (dcn42_is_spll_ssc_enabled(&clk_mgr->base) && (clock_source < ARRAY_SIZE(dcn42_ss_info_table.ss_percentage))) { | |
| 820 | + clk_mgr->dprefclk_ss_percentage = dcn42_ss_info_table.ss_percentage[clock_source]; | |
| 821 | + | |
| 822 | + if (clk_mgr->dprefclk_ss_percentage != 0) { | |
| 823 | + clk_mgr->ss_on_dprefclk = true; | |
| 824 | + clk_mgr->dprefclk_ss_divider = dcn42_ss_info_table.ss_divider; | |
| 825 | + } | |
| 826 | + } | |
| 827 | +} | |
| 828 | + | |
| 829 | +/* Exposed for dcn42b reuse */ | |
| 830 | +void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table) | |
| 831 | +{ | |
| 832 | + int i, num_valid_sets; | |
| 833 | + | |
| 834 | + num_valid_sets = 0; | |
| 835 | + | |
| 836 | + for (i = 0; i < WM_SET_COUNT; i++) { | |
| 837 | + /* skip empty entries, the smu array has no holes*/ | |
| 838 | + if (!bw_params->wm_table.entries[i].valid) | |
| 839 | + continue; | |
| 840 | + | |
| 841 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst; | |
| 842 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type; | |
| 843 | + /* We will not select WM based on fclk, so leave it as unconstrained */ | |
| 844 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; | |
| 845 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; | |
| 846 | + | |
| 847 | + if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) { | |
| 848 | + if (i == 0) | |
| 849 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0; | |
| 850 | + else { | |
| 851 | + /* add 1 to make it non-overlapping with next lvl */ | |
| 852 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = | |
| 853 | + bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1; | |
| 854 | + } | |
| 855 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk = | |
| 856 | + bw_params->clk_table.entries[i].dcfclk_mhz; | |
| 857 | + | |
| 858 | + } else { | |
| 859 | + /* unconstrained for memory retraining */ | |
| 860 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; | |
| 861 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; | |
| 862 | + | |
| 863 | + /* Modify previous watermark range to cover up to max */ | |
| 864 | + if (num_valid_sets > 0) | |
| 865 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; | |
| 866 | + } | |
| 867 | + num_valid_sets++; | |
| 868 | + } | |
| 869 | + | |
| 870 | + ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */ | |
| 871 | + | |
| 872 | + /* modify the min and max to make sure we cover the whole range*/ | |
| 873 | + table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0; | |
| 874 | + table->WatermarkRow[WM_DCFCLK][0].MinClock = 0; | |
| 875 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF; | |
| 876 | + table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; | |
| 877 | + | |
| 878 | + /* This is for writeback only, does not matter currently as no writeback support*/ | |
| 879 | + table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A; | |
| 880 | + table->WatermarkRow[WM_SOCCLK][0].MinClock = 0; | |
| 881 | + table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF; | |
| 882 | + table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0; | |
| 883 | + table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF; | |
| 884 | +} | |
| 885 | + | |
| 886 | +void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base) | |
| 887 | +{ | |
| 888 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 889 | + struct clk_mgr_dcn42 *clk_mgr_dcn42 = TO_CLK_MGR_DCN42(clk_mgr); | |
| 890 | + struct dcn42_watermarks *table = clk_mgr_dcn42->smu_wm_set.wm_set; | |
| 891 | + | |
| 892 | + if (!clk_mgr->smu_ver) | |
| 893 | + return; | |
| 894 | + | |
| 895 | + if (!table || clk_mgr_dcn42->smu_wm_set.mc_address.quad_part == 0) | |
| 896 | + return; | |
| 897 | + | |
| 898 | + memset(table, 0, sizeof(*table)); | |
| 899 | + | |
| 900 | + dcn42_build_watermark_ranges(clk_mgr_base->bw_params, table); | |
| 901 | + | |
| 902 | + dcn42_smu_set_dram_addr_high(clk_mgr, | |
| 903 | + clk_mgr_dcn42->smu_wm_set.mc_address.high_part); | |
| 904 | + dcn42_smu_set_dram_addr_low(clk_mgr, | |
| 905 | + clk_mgr_dcn42->smu_wm_set.mc_address.low_part); | |
| 906 | + dcn42_smu_transfer_wm_table_dram_2_smu(clk_mgr); | |
| 907 | +} | |
| 908 | + | |
| 909 | +void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base) | |
| 910 | +{ | |
| 911 | + int display_count; | |
| 912 | + struct dc *dc = clk_mgr_base->ctx->dc; | |
| 913 | + struct dc_state *context = dc->current_state; | |
| 914 | + | |
| 915 | + if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { | |
| 916 | + display_count = dcn42_get_active_display_cnt_wa(dc, context, NULL); | |
| 917 | + /* if we can go lower, go lower */ | |
| 918 | + if (display_count == 0) | |
| 919 | + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; | |
| 920 | + } | |
| 921 | + | |
| 922 | + if (clk_mgr_base->clks.pwr_state == DCN_PWR_STATE_LOW_POWER) { | |
| 923 | + union display_idle_optimization_u idle_info = { 0 }; | |
| 924 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 925 | + | |
| 926 | + idle_info.idle_info.df_request_disabled = 1; | |
| 927 | + idle_info.idle_info.phy_ref_clk_off = 1; | |
| 928 | + idle_info.idle_info.s0i2_rdy = 1; | |
| 929 | + dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data); | |
| 930 | + } | |
| 931 | +} | |
| 932 | + | |
| 933 | +void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base) | |
| 934 | +{ | |
| 935 | + | |
| 936 | +} | |
| 937 | + | |
| 938 | +static void dcn42_init_clocks_fpga(struct clk_mgr *clk_mgr) | |
| 939 | +{ | |
| 940 | + init_clk_states(clk_mgr); | |
| 941 | + | |
| 942 | +} | |
| 943 | + | |
| 944 | +static void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, | |
| 945 | + struct dc_state *context, | |
| 946 | + bool safe_to_lower) | |
| 947 | +{ | |
| 948 | + struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr); | |
| 949 | + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; | |
| 950 | + int fclk_adj = new_clocks->fclk_khz; | |
| 951 | + | |
| 952 | + /* TODO: remove this after correctly set by DML */ | |
| 953 | + new_clocks->dcfclk_khz = 400000; | |
| 954 | + new_clocks->socclk_khz = 400000; | |
| 955 | + | |
| 956 | + /* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */ | |
| 957 | + //int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000; | |
| 958 | + new_clocks->fclk_khz = 4320000; | |
| 959 | + | |
| 960 | + if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr->clks.phyclk_khz)) | |
| 961 | + clk_mgr->clks.phyclk_khz = new_clocks->phyclk_khz; | |
| 962 | + | |
| 963 | + if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr->clks.dcfclk_khz)) | |
| 964 | + clk_mgr->clks.dcfclk_khz = new_clocks->dcfclk_khz; | |
| 965 | + | |
| 966 | + if (should_set_clock(safe_to_lower, | |
| 967 | + new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz)) | |
| 968 | + clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; | |
| 969 | + | |
| 970 | + if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr->clks.socclk_khz)) | |
| 971 | + clk_mgr->clks.socclk_khz = new_clocks->socclk_khz; | |
| 972 | + | |
| 973 | + if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr->clks.dramclk_khz)) | |
| 974 | + clk_mgr->clks.dramclk_khz = new_clocks->dramclk_khz; | |
| 975 | + | |
| 976 | + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->clks.dppclk_khz)) | |
| 977 | + clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz; | |
| 978 | + | |
| 979 | + if (should_set_clock(safe_to_lower, fclk_adj, clk_mgr->clks.fclk_khz)) | |
| 980 | + clk_mgr->clks.fclk_khz = fclk_adj; | |
| 981 | + | |
| 982 | + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr->clks.dispclk_khz)) | |
| 983 | + clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz; | |
| 984 | + | |
| 985 | + /* Both fclk and ref_dppclk run on the same scemi clock. | |
| 986 | + * So take the higher value since the DPP DTO is typically programmed | |
| 987 | + * such that max dppclk is 1:1 with ref_dppclk. | |
| 988 | + */ | |
| 989 | + if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz) | |
| 990 | + clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz; | |
| 991 | + if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz) | |
| 992 | + clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz; | |
| 993 | + | |
| 994 | + // Both fclk and ref_dppclk run on the same scemi clock. | |
| 995 | + clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz; | |
| 996 | + | |
| 997 | + /* TODO: set dtbclk in correct place */ | |
| 998 | + clk_mgr->clks.dtbclk_en = true; | |
| 999 | + | |
| 1000 | + dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks); | |
| 1001 | + dcn42_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower); | |
| 1002 | + | |
| 1003 | + dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz); | |
| 1004 | +} | |
| 1005 | + | |
| 1006 | +unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type) | |
| 1007 | +{ | |
| 1008 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 1009 | + | |
| 1010 | + unsigned int num_clk_levels; | |
| 1011 | + | |
| 1012 | + switch (clk_type) { | |
| 1013 | + case CLK_TYPE_DISPCLK: | |
| 1014 | + num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; | |
| 1015 | + return num_clk_levels ? | |
| 1016 | + clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 : | |
| 1017 | + clk_mgr->base.boot_snapshot.dispclk; | |
| 1018 | + case CLK_TYPE_DPPCLK: | |
| 1019 | + num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels; | |
| 1020 | + return num_clk_levels ? | |
| 1021 | + clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dppclk_mhz * 1000 : | |
| 1022 | + clk_mgr->base.boot_snapshot.dppclk; | |
| 1023 | + case CLK_TYPE_DSCCLK: | |
| 1024 | + num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; | |
| 1025 | + return num_clk_levels ? | |
| 1026 | + clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 / 3 : | |
| 1027 | + clk_mgr->base.boot_snapshot.dispclk / 3; | |
| 1028 | + default: | |
| 1029 | + break; | |
| 1030 | + } | |
| 1031 | + | |
| 1032 | + return 0; | |
| 1033 | +} | |
| 1034 | + | |
| 1035 | +static int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base) | |
| 1036 | +{ | |
| 1037 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 1038 | + uint32_t dispclk_wdivider; | |
| 1039 | + int disp_divider; | |
| 1040 | + | |
| 1041 | + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider); | |
| 1042 | + disp_divider = dentist_get_divider_from_did(dispclk_wdivider); | |
| 1043 | + | |
| 1044 | + /* Return DISPCLK freq in Khz */ | |
| 1045 | + if (disp_divider) | |
| 1046 | + return (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider; | |
| 1047 | + | |
| 1048 | + return 0; | |
| 1049 | +} | |
| 1050 | +bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base) | |
| 1051 | +{ | |
| 1052 | + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | |
| 1053 | + return clk_mgr->smu_present; | |
| 1054 | +} | |
| 1055 | + | |
| 1056 | +static struct clk_mgr_funcs dcn42_funcs = { | |
| 1057 | + .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, | |
| 1058 | + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, | |
| 1059 | + .update_clocks = dcn42_update_clocks, | |
| 1060 | + .init_clocks = dcn42_init_clocks, | |
| 1061 | + .enable_pme_wa = dcn42_enable_pme_wa, | |
| 1062 | + .are_clock_states_equal = dcn42_are_clock_states_equal, | |
| 1063 | + .notify_wm_ranges = dcn42_notify_wm_ranges, | |
| 1064 | + .set_low_power_state = dcn42_set_low_power_state, | |
| 1065 | + .exit_low_power_state = dcn42_exit_low_power_state, | |
| 1066 | + .get_max_clock_khz = dcn42_get_max_clock_khz, | |
| 1067 | + .get_dispclk_from_dentist = dcn42_get_dispclk_from_dentist, | |
| 1068 | + .is_smu_present = dcn42_is_smu_present, | |
| 1069 | +}; | |
| 1070 | + | |
| 1071 | +struct clk_mgr_funcs dcn42_fpga_funcs = { | |
| 1072 | + .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, | |
| 1073 | + .update_clocks = dcn42_update_clocks_fpga, | |
| 1074 | + .init_clocks = dcn42_init_clocks_fpga, | |
| 1075 | + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, | |
| 1076 | +}; | |
| 1077 | + | |
| 1078 | +void dcn42_clk_mgr_construct( | |
| 1079 | + struct dc_context *ctx, | |
| 1080 | + struct clk_mgr_dcn42 *clk_mgr, | |
| 1081 | + struct pp_smu_funcs *pp_smu, | |
| 1082 | + struct dccg *dccg) | |
| 1083 | +{ | |
| 1084 | + clk_mgr->base.base.ctx = ctx; | |
| 1085 | + clk_mgr->base.base.funcs = &dcn42_funcs; | |
| 1086 | + clk_mgr->base.regs = &clk_mgr_regs_dcn42; | |
| 1087 | + clk_mgr->base.clk_mgr_shift = &clk_mgr_shift_dcn42; | |
| 1088 | + clk_mgr->base.clk_mgr_mask = &clk_mgr_mask_dcn42; | |
| 1089 | + | |
| 1090 | + clk_mgr->base.pp_smu = pp_smu; | |
| 1091 | + | |
| 1092 | + clk_mgr->base.dccg = dccg; | |
| 1093 | + clk_mgr->base.dfs_bypass_disp_clk = 0; | |
| 1094 | + | |
| 1095 | + clk_mgr->base.dprefclk_ss_percentage = 0; | |
| 1096 | + clk_mgr->base.dprefclk_ss_divider = 1000; | |
| 1097 | + clk_mgr->base.ss_on_dprefclk = false; | |
| 1098 | + clk_mgr->base.dfs_ref_freq_khz = 48000; /*sync with pmfw*/ | |
| 1099 | + | |
| 1100 | + clk_mgr->smu_wm_set.wm_set = (struct dcn42_watermarks *)dm_helpers_allocate_gpu_mem( | |
| 1101 | + clk_mgr->base.base.ctx, | |
| 1102 | + DC_MEM_ALLOC_TYPE_GART, | |
| 1103 | + sizeof(struct dcn42_watermarks), | |
| 1104 | + &clk_mgr->smu_wm_set.mc_address.quad_part); | |
| 1105 | + | |
| 1106 | + ASSERT(clk_mgr->smu_wm_set.wm_set); | |
| 1107 | + | |
| 1108 | + /* Changed from DCN3.2_clock_frequency doc to match | |
| 1109 | + * dcn32_dump_clk_registers from 4 * dentist_vco_freq_khz / | |
| 1110 | + * dprefclk DID divider | |
| 1111 | + */ | |
| 1112 | + clk_mgr->base.base.dprefclk_khz = 600000; | |
| 1113 | + | |
| 1114 | + clk_mgr->base.smu_present = false; | |
| 1115 | + | |
| 1116 | + if (ctx->dc_bios->integrated_info) { | |
| 1117 | + clk_mgr->base.base.dentist_vco_freq_khz = ctx->dc_bios->integrated_info->dentist_vco_freq; | |
| 1118 | + | |
| 1119 | + if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) | |
| 1120 | + dcn42_bw_params.wm_table = lpddr5_wm_table; | |
| 1121 | + else | |
| 1122 | + dcn42_bw_params.wm_table = ddr5_wm_table; | |
| 1123 | + dcn42_bw_params.vram_type = ctx->dc_bios->integrated_info->memory_type; | |
| 1124 | + dcn42_bw_params.dram_channel_width_bytes = ctx->dc_bios->integrated_info->memory_type == 0x22 ? 8 : 4; | |
| 1125 | + dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 4; | |
| 1126 | + } | |
| 1127 | + /* in case we don't get a value from the BIOS, use default */ | |
| 1128 | + if (clk_mgr->base.base.dentist_vco_freq_khz == 0) | |
| 1129 | + clk_mgr->base.base.dentist_vco_freq_khz = 3000000; /* 3000MHz */ | |
| 1130 | + | |
| 1131 | + /* Saved clocks configured at boot for debug purposes */ | |
| 1132 | + dcn42_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr); | |
| 1133 | + | |
| 1134 | + if (clk_mgr->base.smu_present) | |
| 1135 | + clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base); | |
| 1136 | + clk_mgr->base.base.clks.ref_dtbclk_khz = 600000; | |
| 1137 | + dce_clock_read_ss_info(&clk_mgr->base); | |
| 1138 | + /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/ | |
| 1139 | + | |
| 1140 | + dcn42_read_ss_info_from_lut(&clk_mgr->base); | |
| 1141 | + | |
| 1142 | + clk_mgr->base.base.bw_params = &dcn42_bw_params; | |
| 1143 | +} | |
| 1144 | + | |
| 1145 | +void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int) | |
| 1146 | +{ | |
| 1147 | + struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int); | |
| 1148 | + | |
| 1149 | + if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0) | |
| 1150 | + dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_GART, | |
| 1151 | + clk_mgr->smu_wm_set.wm_set); | |
| 1152 | +} | |
| @@ -0,0 +1,79 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +#ifndef __DCN42_CLK_MGR_H__ | |
| 26 | +#define __DCN42_CLK_MGR_H__ | |
| 27 | +#include "clk_mgr_internal.h" | |
| 28 | + | |
| 29 | +#define NUM_CLOCK_SOURCES 5 | |
| 30 | + | |
| 31 | +struct dcn42_watermarks; | |
| 32 | + | |
| 33 | +struct dcn42_smu_watermark_set { | |
| 34 | + struct dcn42_watermarks *wm_set; | |
| 35 | + union large_integer mc_address; | |
| 36 | +}; | |
| 37 | + | |
| 38 | +struct dcn42_ss_info_table { | |
| 39 | + uint32_t ss_divider; | |
| 40 | + uint32_t ss_percentage[NUM_CLOCK_SOURCES]; | |
| 41 | +}; | |
| 42 | + | |
| 43 | +struct clk_mgr_dcn42 { | |
| 44 | + struct clk_mgr_internal base; | |
| 45 | + struct dcn42_smu_watermark_set smu_wm_set; | |
| 46 | +}; | |
| 47 | + | |
| 48 | +bool dcn42_are_clock_states_equal(struct dc_clocks *a, | |
| 49 | + struct dc_clocks *b); | |
| 50 | +void dcn42_init_clocks(struct clk_mgr *clk_mgr); | |
| 51 | +void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, | |
| 52 | + struct dc_state *context, | |
| 53 | + bool safe_to_lower); | |
| 54 | + | |
| 55 | +void dcn42_clk_mgr_construct(struct dc_context *ctx, | |
| 56 | + struct clk_mgr_dcn42 *clk_mgr, | |
| 57 | + struct pp_smu_funcs *pp_smu, | |
| 58 | + struct dccg *dccg); | |
| 59 | + | |
| 60 | +void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int); | |
| 61 | + | |
| 62 | +/* Exposed for dcn42b reuse */ | |
| 63 | +void dcn42_init_single_clock(unsigned int *entry_0, | |
| 64 | + uint32_t *smu_entry_0, | |
| 65 | + uint8_t num_levels); | |
| 66 | +unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio); | |
| 67 | +extern struct dcn42_ss_info_table dcn42_ss_info_table; | |
| 68 | +void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table); | |
| 69 | +void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base); | |
| 70 | +void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base); | |
| 71 | +void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base); | |
| 72 | +void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base); | |
| 73 | +unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type); | |
| 74 | +bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base); | |
| 75 | +int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int *all_active_disps); | |
| 76 | +void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower); | |
| 77 | +void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz); | |
| 78 | +bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base); | |
| 79 | +#endif //__DCN42_CLK_MGR_H__ | |
| @@ -0,0 +1,431 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | +#include "core_types.h" | |
| 8 | +#include "clk_mgr_internal.h" | |
| 9 | +#include "reg_helper.h" | |
| 10 | +#include "dm_helpers.h" | |
| 11 | +#include "dcn42_smu.h" | |
| 12 | + | |
| 13 | +#include "mp/mp_15_0_0_offset.h" | |
| 14 | +#include "mp/mp_15_0_0_sh_mask.h" | |
| 15 | + | |
| 16 | +#ifdef BASE_INNER | |
| 17 | +#undef BASE_INNER | |
| 18 | +#endif | |
| 19 | + | |
| 20 | +#define MP1_BASE__INST0_SEG0 0x00016000 | |
| 21 | +#define MP1_BASE__INST0_SEG1 0x00016200 | |
| 22 | +#define MP1_BASE__INST0_SEG2 0x00E00000 | |
| 23 | +#define MP1_BASE__INST0_SEG3 0x00E80000 | |
| 24 | +#define MP1_BASE__INST0_SEG4 0x00EC0000 | |
| 25 | +#define MP1_BASE__INST0_SEG5 0x00F00000 | |
| 26 | +#define MP1_BASE__INST0_SEG6 0x02400400 | |
| 27 | +#define MP1_BASE__INST0_SEG7 0x0243F400 | |
| 28 | +#define MP1_BASE__INST0_SEG8 0x3C004000 | |
| 29 | +#define MP1_BASE__INST0_SEG9 0x3C3F4000 | |
| 30 | + | |
| 31 | +#define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg | |
| 32 | + | |
| 33 | +#define BASE(seg) BASE_INNER(seg) | |
| 34 | + | |
| 35 | +#define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name) | |
| 36 | + | |
| 37 | +#define FN(reg_name, field) \ | |
| 38 | + FD(reg_name##__##field) | |
| 39 | + | |
| 40 | +#include "logger_types.h" | |
| 41 | +#undef DC_LOGGER | |
| 42 | +#define DC_LOGGER \ | |
| 43 | + CTX->logger | |
| 44 | +#define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); } | |
| 45 | + | |
| 46 | +// VBIOS and DAL to PMFW Interface | |
| 47 | + | |
| 48 | +// DAL to PMFW interface registers | |
| 49 | +#define DAL_MSG_REG MP1_SMN_C2PMSG_71 | |
| 50 | +#define DAL_RESP_REG MP1_SMN_C2PMSG_72 | |
| 51 | +#define DAL_ARG_REG MP1_SMN_C2PMSG_73 | |
| 52 | + | |
| 53 | +/** @defgroup ResponseCodes PMFW Response Codes | |
| 54 | +* @{ | |
| 55 | +*/ | |
| 56 | +// SMU Response Codes: | |
| 57 | +#define DALSMC_Result_OK 0x01 ///< Message Response OK | |
| 58 | +#define DALSMC_Result_Failed 0xFF ///< Message Response Failed | |
| 59 | +#define DALSMC_Result_UnknownCmd 0xFE ///< Message Response Unknown Command | |
| 60 | +#define DALSMC_Result_CmdRejectedPrereq 0xFD ///< Message Response Command Failed Prerequisite | |
| 61 | +#define DALSMC_Result_CmdRejectedBusy 0xFC ///< Message Response Command Rejected due to PMFW is busy. Sender should retry sending this message | |
| 62 | +/** @}*/ | |
| 63 | + | |
| 64 | +// Message Definitions: | |
| 65 | +/** @defgroup definitions Message definitions | |
| 66 | +* @{ | |
| 67 | +*/ | |
| 68 | +#define DALSMC_MSG_TestMessage 0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team | |
| 69 | +#define DALSMC_MSG_GetPmfwVersion 0x02 ///< Get version | |
| 70 | +#define DALSMC_MSG_SetDispclkFreq 0x03 ///< Set display clock frequency in MHZ | |
| 71 | +#define DALSMC_MSG_SetDppclkFreq 0x04 ///< Set DPP clock frequency in MHZ | |
| 72 | +#define DALSMC_MSG_SetHardMinDcfclkByFreq 0x05 ///< Set DCF clock frequency hard min in MHZ | |
| 73 | +#define DALSMC_MSG_SetMinDeepSleepDcfclk 0x06 ///< Set DCF clock minimum frequency in deep sleep in MHZ | |
| 74 | +#define DALSMC_MSG_UpdatePmeRestore 0x07 ///< To ask PMFW to write into Azalia for PME wake up event | |
| 75 | +#define DALSMC_MSG_SetDramAddrHigh 0x08 ///< Set DRAM address high 32 bits for WM table transfer | |
| 76 | +#define DALSMC_MSG_SetDramAddrLow 0x09 ///< Set DRAM address low 32 bits for WM table transfer | |
| 77 | + | |
| 78 | +#define DALSMC_MSG_TransferTableSmu2Dram 0x0A ///< Transfer table from PMFW SRAM to system DRAM | |
| 79 | +#define DALSMC_MSG_TransferTableDram2Smu 0x0B ///< Transfer table from system DRAM to PMFW | |
| 80 | +#define DALSMC_MSG_SetDisplayIdleOptimizations 0x0C ///< Set Idle state optimization for display off | |
| 81 | +#define DALSMC_MSG_GetDprefclkFreq 0x0D ///< Get DPREF clock frequency. Return in MHZ | |
| 82 | +#define DALSMC_MSG_GetDtbclkFreq 0x0E ///< Get DTB clock frequency. Return in MHZ | |
| 83 | +#define DALSMC_MSG_AllowZstatesEntry 0x0F ///< Inform PMFW of display allowing Zstate entry | |
| 84 | +#define DALSMC_MSG_SetDtbClk 0x10 ///< Inform PMFW to turn of/off DTB cl0ck. arg = 1: turn DTB on with 600MHZ; arg = 0: turn DTB clk off | |
| 85 | +#define DALSMC_MSG_DispIPS2Exit 0x11 ///< Display IPS2 exit | |
| 86 | + | |
| 87 | +#define DALSMC_MSG_QueryIPS2Support 0x12 ///< Return 1: support; else not supported | |
| 88 | +#define DALSMC_Message_Count 0x13 ///< Total number of VBIS and DAL messages | |
| 89 | +/** @}*/ | |
| 90 | + | |
| 91 | + | |
| 92 | +union dcn42_dpia_host_router_bw { | |
| 93 | + struct { | |
| 94 | + uint32_t hr_id : 16; | |
| 95 | + uint32_t bw_mbps : 16; | |
| 96 | + } bits; | |
| 97 | + uint32_t all; | |
| 98 | +}; | |
| 99 | + | |
| 100 | +/* | |
| 101 | + * Function to be used instead of REG_WAIT macro because the wait ends when | |
| 102 | + * the register is NOT EQUAL to zero, and because `the translation in msg_if.h | |
| 103 | + * won't work with REG_WAIT. | |
| 104 | + */ | |
| 105 | +static uint32_t dcn42_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, | |
| 106 | + unsigned int delay_us, unsigned int max_retries) | |
| 107 | +{ | |
| 108 | + uint32_t res_val; | |
| 109 | + | |
| 110 | + do { | |
| 111 | + res_val = REG_READ(DAL_RESP_REG); | |
| 112 | + if (res_val != DALSMC_Result_CmdRejectedBusy) | |
| 113 | + break; | |
| 114 | + | |
| 115 | + if (delay_us >= 1000) | |
| 116 | + msleep(delay_us/1000); | |
| 117 | + else if (delay_us > 0) | |
| 118 | + udelay(delay_us); | |
| 119 | + | |
| 120 | + if (clk_mgr->base.ctx->dc->debug.disable_timeout) | |
| 121 | + max_retries++; | |
| 122 | + } while (max_retries--); | |
| 123 | + | |
| 124 | + return res_val; | |
| 125 | +} | |
| 126 | + | |
| 127 | +static int dcn42_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, | |
| 128 | + unsigned int msg_id, | |
| 129 | + unsigned int param) | |
| 130 | +{ | |
| 131 | + uint32_t result; | |
| 132 | + | |
| 133 | + result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000); | |
| 134 | + | |
| 135 | + if (result != DALSMC_Result_OK) { | |
| 136 | + DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id); | |
| 137 | + | |
| 138 | + if (result == DALSMC_Result_CmdRejectedBusy) | |
| 139 | + return -1; | |
| 140 | + } | |
| 141 | + | |
| 142 | + /* First clear response register */ | |
| 143 | + REG_WRITE(DAL_RESP_REG, DALSMC_Result_CmdRejectedBusy); | |
| 144 | + | |
| 145 | + /* Set the parameter register for the SMU message, unit is Mhz */ | |
| 146 | + REG_WRITE(DAL_ARG_REG, param); | |
| 147 | + | |
| 148 | + /* Trigger the message transaction by writing the message ID */ | |
| 149 | + REG_WRITE(DAL_MSG_REG, msg_id); | |
| 150 | + | |
| 151 | + result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000); | |
| 152 | + | |
| 153 | + if (result == DALSMC_Result_Failed) { | |
| 154 | + if (msg_id == DALSMC_MSG_TransferTableDram2Smu && | |
| 155 | + param == TABLE_WATERMARKS) | |
| 156 | + DC_LOG_WARNING("Watermarks table not configured properly by SMU"); | |
| 157 | + REG_WRITE(DAL_RESP_REG, DALSMC_Result_OK); | |
| 158 | + DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id); | |
| 159 | + return -1; | |
| 160 | + } | |
| 161 | + | |
| 162 | + if (IS_SMU_TIMEOUT(result)) { | |
| 163 | + ASSERT(0); | |
| 164 | + result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000); | |
| 165 | + //dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000); | |
| 166 | + DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id); | |
| 167 | + } | |
| 168 | + | |
| 169 | + return REG_READ(DAL_ARG_REG); | |
| 170 | +} | |
| 171 | + | |
| 172 | +int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr) | |
| 173 | +{ | |
| 174 | + return dcn42_smu_send_msg_with_param( | |
| 175 | + clk_mgr, | |
| 176 | + DALSMC_MSG_GetPmfwVersion, | |
| 177 | + 0); | |
| 178 | +} | |
| 179 | + | |
| 180 | + | |
| 181 | +int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz) | |
| 182 | +{ | |
| 183 | + int actual_dispclk_set_mhz; | |
| 184 | + | |
| 185 | + if (!clk_mgr->smu_present) | |
| 186 | + return requested_dispclk_khz; | |
| 187 | + | |
| 188 | + /* Unit of SMU msg parameter is Mhz */ | |
| 189 | + actual_dispclk_set_mhz = dcn42_smu_send_msg_with_param( | |
| 190 | + clk_mgr, | |
| 191 | + DALSMC_MSG_SetDispclkFreq, | |
| 192 | + khz_to_mhz_ceil(requested_dispclk_khz)); | |
| 193 | + | |
| 194 | + smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", | |
| 195 | + requested_dispclk_khz, actual_dispclk_set_mhz); | |
| 196 | + return (int)((long long)actual_dispclk_set_mhz * 1000); | |
| 197 | +} | |
| 198 | + | |
| 199 | + | |
| 200 | +int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz) | |
| 201 | +{ | |
| 202 | + int actual_dcfclk_set_mhz; | |
| 203 | + | |
| 204 | + if (!clk_mgr->smu_present) | |
| 205 | + return requested_dcfclk_khz; | |
| 206 | + | |
| 207 | + actual_dcfclk_set_mhz = dcn42_smu_send_msg_with_param( | |
| 208 | + clk_mgr, | |
| 209 | + DALSMC_MSG_SetHardMinDcfclkByFreq, | |
| 210 | + khz_to_mhz_ceil(requested_dcfclk_khz)); | |
| 211 | + | |
| 212 | + smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", | |
| 213 | + requested_dcfclk_khz, actual_dcfclk_set_mhz); | |
| 214 | + | |
| 215 | + return (int)((long long)actual_dcfclk_set_mhz * 1000); | |
| 216 | +} | |
| 217 | + | |
| 218 | +int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz) | |
| 219 | +{ | |
| 220 | + int actual_min_ds_dcfclk_mhz; | |
| 221 | + | |
| 222 | + if (!clk_mgr->smu_present) | |
| 223 | + return requested_min_ds_dcfclk_khz; | |
| 224 | + | |
| 225 | + actual_min_ds_dcfclk_mhz = dcn42_smu_send_msg_with_param( | |
| 226 | + clk_mgr, | |
| 227 | + DALSMC_MSG_SetMinDeepSleepDcfclk, | |
| 228 | + khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); | |
| 229 | + | |
| 230 | + smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n", | |
| 231 | + requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz); | |
| 232 | + | |
| 233 | + return (int)((long long)actual_min_ds_dcfclk_mhz * 1000); | |
| 234 | +} | |
| 235 | + | |
| 236 | +int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) | |
| 237 | +{ | |
| 238 | + int actual_dppclk_set_mhz; | |
| 239 | + | |
| 240 | + if (!clk_mgr->smu_present) | |
| 241 | + return requested_dpp_khz; | |
| 242 | + | |
| 243 | + actual_dppclk_set_mhz = dcn42_smu_send_msg_with_param( | |
| 244 | + clk_mgr, | |
| 245 | + DALSMC_MSG_SetDppclkFreq, | |
| 246 | + khz_to_mhz_ceil(requested_dpp_khz)); | |
| 247 | + | |
| 248 | + smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", | |
| 249 | + requested_dpp_khz, actual_dppclk_set_mhz); | |
| 250 | + | |
| 251 | + return (int)((long long)actual_dppclk_set_mhz * 1000); | |
| 252 | +} | |
| 253 | + | |
| 254 | +void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info) | |
| 255 | +{ | |
| 256 | + if (!clk_mgr->base.ctx->dc->debug.pstate_enabled) | |
| 257 | + return; | |
| 258 | + | |
| 259 | + if (!clk_mgr->smu_present) | |
| 260 | + return; | |
| 261 | + | |
| 262 | + dcn42_smu_send_msg_with_param( | |
| 263 | + clk_mgr, | |
| 264 | + DALSMC_MSG_SetDisplayIdleOptimizations, | |
| 265 | + idle_info); | |
| 266 | + smu_print("%s: SMC_MSG_SetDisplayIdleOptimizations idle_info = %x\n", __func__, idle_info); | |
| 267 | +} | |
| 268 | + | |
| 269 | +void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable) | |
| 270 | +{ | |
| 271 | + union display_idle_optimization_u idle_info = { 0 }; | |
| 272 | + | |
| 273 | + if (!clk_mgr->smu_present) | |
| 274 | + return; | |
| 275 | + | |
| 276 | + if (enable) { | |
| 277 | + idle_info.idle_info.df_request_disabled = 1; | |
| 278 | + idle_info.idle_info.phy_ref_clk_off = 1; | |
| 279 | + } | |
| 280 | + | |
| 281 | + dcn42_smu_send_msg_with_param( | |
| 282 | + clk_mgr, | |
| 283 | + DALSMC_MSG_SetDisplayIdleOptimizations, | |
| 284 | + idle_info.data); | |
| 285 | + smu_print("%s smu_enable_phy_refclk_pwrdwn = %d\n", __func__, enable ? 1 : 0); | |
| 286 | +} | |
| 287 | + | |
| 288 | +void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr) | |
| 289 | +{ | |
| 290 | + if (!clk_mgr->smu_present) | |
| 291 | + return; | |
| 292 | + | |
| 293 | + dcn42_smu_send_msg_with_param( | |
| 294 | + clk_mgr, | |
| 295 | + DALSMC_MSG_UpdatePmeRestore, | |
| 296 | + 0); | |
| 297 | + smu_print("%s: SMC_MSG_UpdatePmeRestore\n", __func__); | |
| 298 | +} | |
| 299 | + | |
| 300 | +void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high) | |
| 301 | +{ | |
| 302 | + if (!clk_mgr->smu_present) | |
| 303 | + return; | |
| 304 | + | |
| 305 | + dcn42_smu_send_msg_with_param(clk_mgr, | |
| 306 | + DALSMC_MSG_SetDramAddrHigh, addr_high); | |
| 307 | +} | |
| 308 | + | |
| 309 | +void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low) | |
| 310 | +{ | |
| 311 | + if (!clk_mgr->smu_present) | |
| 312 | + return; | |
| 313 | + | |
| 314 | + dcn42_smu_send_msg_with_param(clk_mgr, | |
| 315 | + DALSMC_MSG_SetDramAddrLow, addr_low); | |
| 316 | +} | |
| 317 | + | |
| 318 | +void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr) | |
| 319 | +{ | |
| 320 | + if (!clk_mgr->smu_present) | |
| 321 | + return; | |
| 322 | + | |
| 323 | + dcn42_smu_send_msg_with_param(clk_mgr, | |
| 324 | + DALSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS); | |
| 325 | +} | |
| 326 | + | |
| 327 | +void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr) | |
| 328 | +{ | |
| 329 | + if (!clk_mgr->smu_present) | |
| 330 | + return; | |
| 331 | + | |
| 332 | + dcn42_smu_send_msg_with_param(clk_mgr, | |
| 333 | + DALSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS); | |
| 334 | +} | |
| 335 | + | |
| 336 | +void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support) | |
| 337 | +{ | |
| 338 | + unsigned int msg_id, param, retv; | |
| 339 | + | |
| 340 | + if (!clk_mgr->smu_present) | |
| 341 | + return; | |
| 342 | + | |
| 343 | + switch (support) { | |
| 344 | + | |
| 345 | + case DCN_ZSTATE_SUPPORT_ALLOW: | |
| 346 | + msg_id = DALSMC_MSG_AllowZstatesEntry; | |
| 347 | + param = (1 << 10) | (1 << 9) | (1 << 8); | |
| 348 | + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW, param = 0x%x\n", __func__, param); | |
| 349 | + break; | |
| 350 | + | |
| 351 | + case DCN_ZSTATE_SUPPORT_DISALLOW: | |
| 352 | + msg_id = DALSMC_MSG_AllowZstatesEntry; | |
| 353 | + param = 0; | |
| 354 | + smu_print("%s: SMC_MSG_AllowZstatesEntry msg_id = DISALLOW, param = 0x%x\n", __func__, param); | |
| 355 | + break; | |
| 356 | + | |
| 357 | + | |
| 358 | + case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY: | |
| 359 | + msg_id = DALSMC_MSG_AllowZstatesEntry; | |
| 360 | + param = (1 << 10); | |
| 361 | + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z10_ONLY, param = 0x%x\n", __func__, param); | |
| 362 | + break; | |
| 363 | + | |
| 364 | + case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY: | |
| 365 | + msg_id = DALSMC_MSG_AllowZstatesEntry; | |
| 366 | + param = (1 << 10) | (1 << 8); | |
| 367 | + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_Z10_ONLY, param = 0x%x\n", __func__, param); | |
| 368 | + break; | |
| 369 | + | |
| 370 | + case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY: | |
| 371 | + msg_id = DALSMC_MSG_AllowZstatesEntry; | |
| 372 | + param = (1 << 8); | |
| 373 | + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_ONLY, param = 0x%x\n", __func__, param); | |
| 374 | + break; | |
| 375 | + | |
| 376 | + default: //DCN_ZSTATE_SUPPORT_UNKNOWN | |
| 377 | + msg_id = DALSMC_MSG_AllowZstatesEntry; | |
| 378 | + param = 0; | |
| 379 | + break; | |
| 380 | + } | |
| 381 | + | |
| 382 | + | |
| 383 | + retv = dcn42_smu_send_msg_with_param( | |
| 384 | + clk_mgr, | |
| 385 | + msg_id, | |
| 386 | + param); | |
| 387 | + smu_print("%s: msg_id = %d, param = 0x%x, return = 0x%x\n", __func__, msg_id, param, retv); | |
| 388 | +} | |
| 389 | + | |
| 390 | +int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr) | |
| 391 | +{ | |
| 392 | + int dprefclk; | |
| 393 | + | |
| 394 | + if (!clk_mgr->smu_present) | |
| 395 | + return 0; | |
| 396 | + | |
| 397 | + dprefclk = dcn42_smu_send_msg_with_param(clk_mgr, | |
| 398 | + DALSMC_MSG_GetDprefclkFreq, | |
| 399 | + 0); | |
| 400 | + | |
| 401 | + smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk); | |
| 402 | + return (int)((long long)dprefclk * 1000); | |
| 403 | +} | |
| 404 | + | |
| 405 | +int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) | |
| 406 | +{ | |
| 407 | + int dtbclk; | |
| 408 | + | |
| 409 | + if (!clk_mgr->smu_present) | |
| 410 | + return 0; | |
| 411 | + | |
| 412 | + dtbclk = dcn42_smu_send_msg_with_param(clk_mgr, | |
| 413 | + DALSMC_MSG_GetDtbclkFreq, | |
| 414 | + 0); | |
| 415 | + | |
| 416 | + smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk); | |
| 417 | + return (int)((long long)dtbclk * 1000); | |
| 418 | +} | |
| 419 | +/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */ | |
| 420 | +void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable) | |
| 421 | +{ | |
| 422 | + if (!clk_mgr->smu_present) | |
| 423 | + return; | |
| 424 | + | |
| 425 | + dcn42_smu_send_msg_with_param( | |
| 426 | + clk_mgr, | |
| 427 | + DALSMC_MSG_SetDtbClk, | |
| 428 | + enable); | |
| 429 | + smu_print("%s: smu_set_dtbclk = %d\n", __func__, enable ? 1 : 0); | |
| 430 | +} | |
| 431 | + | |
| @@ -0,0 +1,190 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +#ifndef DAL_DC_42_SMU_H_ | |
| 26 | +#define DAL_DC_42_SMU_H_ | |
| 27 | + | |
| 28 | +#include "os_types.h" | |
| 29 | + | |
| 30 | +#ifndef PMFW_DRIVER_IF_H | |
| 31 | +#define PMFW_DRIVER_IF_H | |
| 32 | +#define PMFW_DRIVER_IF_VERSION 7 | |
| 33 | + | |
| 34 | +typedef enum { | |
| 35 | + DSPCLK_DCFCLK = 0, | |
| 36 | + DSPCLK_DISPCLK, | |
| 37 | + DSPCLK_PIXCLK, | |
| 38 | + DSPCLK_PHYCLK, | |
| 39 | + DSPCLK_COUNT, | |
| 40 | +} DSPCLK_e; | |
| 41 | + | |
| 42 | +typedef struct { | |
| 43 | + uint16_t Freq; // in MHz | |
| 44 | + uint16_t Vid; // min voltage in SVI3 VID | |
| 45 | +} DisplayClockTable_t; | |
| 46 | + | |
| 47 | +typedef struct { | |
| 48 | + uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz) | |
| 49 | + uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz) | |
| 50 | + uint16_t MinMclk; | |
| 51 | + uint16_t MaxMclk; | |
| 52 | + | |
| 53 | + uint8_t WmSetting; | |
| 54 | + uint8_t WmType; // Used for normal pstate change or memory retraining | |
| 55 | + uint8_t Padding[2]; | |
| 56 | +} WatermarkRowGeneric_t; | |
| 57 | + | |
| 58 | +#define NUM_WM_RANGES 4 | |
| 59 | +#define WM_PSTATE_CHG 0 | |
| 60 | +#define WM_RETRAINING 1 | |
| 61 | + | |
| 62 | +typedef enum { | |
| 63 | + WM_SOCCLK = 0, | |
| 64 | + WM_DCFCLK, | |
| 65 | + WM_COUNT, | |
| 66 | +} WM_CLOCK_e; | |
| 67 | + | |
| 68 | +typedef struct { | |
| 69 | + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; | |
| 70 | + | |
| 71 | + uint32_t MmHubPadding[7]; // SMU internal use | |
| 72 | +} Watermarks_t; | |
| 73 | + | |
| 74 | +#define NUM_DCFCLK_DPM_LEVELS 8 | |
| 75 | +#define NUM_DISPCLK_DPM_LEVELS 8 | |
| 76 | +#define NUM_DPPCLK_DPM_LEVELS 8 | |
| 77 | +#define NUM_SOCCLK_DPM_LEVELS 8 | |
| 78 | +#define NUM_VCN_DPM_LEVELS 8 | |
| 79 | +#define NUM_SOC_VOLTAGE_LEVELS 8 | |
| 80 | +#define NUM_VPE_DPM_LEVELS 8 | |
| 81 | +#define NUM_FCLK_DPM_LEVELS 8 | |
| 82 | +#define NUM_MEM_PSTATE_LEVELS 4 | |
| 83 | + | |
| 84 | +typedef enum { | |
| 85 | + WCK_RATIO_1_1 = 0, // DDR5, Wck:ck is always 1:1; | |
| 86 | + WCK_RATIO_1_2, | |
| 87 | + WCK_RATIO_1_4, | |
| 88 | + WCK_RATIO_MAX | |
| 89 | +} WCK_RATIO_e; | |
| 90 | + | |
| 91 | +typedef struct { | |
| 92 | + uint32_t UClk; | |
| 93 | + uint32_t MemClk; | |
| 94 | + uint32_t Voltage; | |
| 95 | + uint8_t WckRatio; | |
| 96 | + uint8_t Spare[3]; | |
| 97 | +} MemPstateTable_t; | |
| 98 | + | |
| 99 | + | |
| 100 | + // Watermarks | |
| 101 | + | |
| 102 | + | |
| 103 | +// Freq in MHz | |
| 104 | +// Voltage in milli volts with 2 fractional bits | |
| 105 | +typedef struct { | |
| 106 | + uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; | |
| 107 | + uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; | |
| 108 | + uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; | |
| 109 | + uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; | |
| 110 | + uint32_t VClocks[NUM_VCN_DPM_LEVELS]; | |
| 111 | + uint32_t DClocks[NUM_VCN_DPM_LEVELS]; | |
| 112 | + uint32_t VPEClocks[NUM_VPE_DPM_LEVELS]; | |
| 113 | + uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS]; | |
| 114 | + uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS]; | |
| 115 | + uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; | |
| 116 | + MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS]; | |
| 117 | + | |
| 118 | + uint8_t NumDcfClkLevelsEnabled; | |
| 119 | + uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk | |
| 120 | + uint8_t NumSocClkLevelsEnabled; | |
| 121 | + uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk | |
| 122 | + | |
| 123 | + uint8_t VpeClkLevelsEnabled; | |
| 124 | + uint8_t NumMemPstatesEnabled; | |
| 125 | + uint8_t NumFclkLevelsEnabled; | |
| 126 | + uint8_t spare; | |
| 127 | + | |
| 128 | + uint32_t MinGfxClk; | |
| 129 | + uint32_t MaxGfxClk; | |
| 130 | +} DpmClocks_t_dcn42; | |
| 131 | + | |
| 132 | +// Throttler Status Bitmask | |
| 133 | + | |
| 134 | + | |
| 135 | +#define TABLE_BIOS_IF 0 // Called by BIOS | |
| 136 | +#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS | |
| 137 | +#define TABLE_CUSTOM_DPM 2 // Called by Driver | |
| 138 | +#define TABLE_SPARE1 3 | |
| 139 | +#define TABLE_DPMCLOCKS 4 // Called by Driver | |
| 140 | +#define TABLE_MOMENTARY_PM 5 // Called by Tools | |
| 141 | +#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log | |
| 142 | +#define TABLE_SMU_METRICS 7 // Called by Driver | |
| 143 | +#define TABLE_COUNT 8 | |
| 144 | + | |
| 145 | +#endif | |
| 146 | + | |
| 147 | +struct dcn42_watermarks { | |
| 148 | + // Watermarks | |
| 149 | + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; | |
| 150 | + uint32_t MmHubPadding[7]; // SMU internal use | |
| 151 | +}; | |
| 152 | + | |
| 153 | +struct dcn42_smu_dpm_clks { | |
| 154 | + DpmClocks_t_dcn42 *dpm_clks; | |
| 155 | + union large_integer mc_address; | |
| 156 | +}; | |
| 157 | + | |
| 158 | +struct display_idle_optimization { | |
| 159 | + unsigned int df_request_disabled : 1; | |
| 160 | + unsigned int phy_ref_clk_off : 1; | |
| 161 | + unsigned int s0i2_rdy : 1; | |
| 162 | + unsigned int reserved : 29; | |
| 163 | +}; | |
| 164 | + | |
| 165 | +union display_idle_optimization_u { | |
| 166 | + struct display_idle_optimization idle_info; | |
| 167 | + uint32_t data; | |
| 168 | +}; | |
| 169 | + | |
| 170 | +int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr); | |
| 171 | +int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz); | |
| 172 | +int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz); | |
| 173 | +int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz); | |
| 174 | +int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz); | |
| 175 | +void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info); | |
| 176 | +void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); | |
| 177 | +void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr); | |
| 178 | +void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high); | |
| 179 | +void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low); | |
| 180 | +void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr); | |
| 181 | +void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); | |
| 182 | + | |
| 183 | +void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support); | |
| 184 | +void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable); | |
| 185 | +void dcn42_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); | |
| 186 | + | |
| 187 | +int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr); | |
| 188 | +int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr); | |
| 189 | + | |
| 190 | +#endif /* DAL_DC_42_SMU_H_ */ | |
| @@ -442,75 +442,6 @@ static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struc · 441 unmodified lines | ||
| 442 | 442 | return false; |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | −/** | |
| 446 | − * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR | |
| 447 | − * @dc: dc reference | |
| 448 | − * @stream: Initial dc stream state | |
| 449 | − * @adjust: Updated parameters for vertical_total_min and vertical_total_max | |
| 450 | − * | |
| 451 | − * Looks up the pipe context of dc_stream_state and updates the | |
| 452 | − * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh | |
| 453 | − * Rate, which is a power-saving feature that targets reducing panel | |
| 454 | − * refresh rate while the screen is static | |
| 455 | − * | |
| 456 | − * Return: %true if the pipe context is found and adjusted; | |
| 457 | − * %false if the pipe context is not found. | |
| 458 | − */ | |
| 459 | −bool dc_stream_adjust_vmin_vmax(struct dc *dc, | |
| 460 | − struct dc_stream_state *stream, | |
| 461 | − struct dc_crtc_timing_adjust *adjust) | |
| 462 | −{ | |
| 463 | − int i; | |
| 464 | − | |
| 465 | − /* | |
| 466 | − * Don't adjust DRR while there's bandwidth optimizations pending to | |
| 467 | − * avoid conflicting with firmware updates. | |
| 468 | − */ | |
| 469 | − if (dc->ctx->dce_version > DCE_VERSION_MAX) { | |
| 470 | − if (dc->optimized_required && | |
| 471 | − (stream->adjust.v_total_max != adjust->v_total_max || | |
| 472 | − stream->adjust.v_total_min != adjust->v_total_min)) { | |
| 473 | − stream->adjust.timing_adjust_pending = true; | |
| 474 | − return false; | |
| 475 | − } | |
| 476 | − } | |
| 477 | − | |
| 478 | − dc_exit_ips_for_hw_access(dc); | |
| 479 | − | |
| 480 | − stream->adjust.v_total_max = adjust->v_total_max; | |
| 481 | − stream->adjust.v_total_mid = adjust->v_total_mid; | |
| 482 | − stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; | |
| 483 | − stream->adjust.v_total_min = adjust->v_total_min; | |
| 484 | − stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; | |
| 485 | − | |
| 486 | − if (dc->caps.max_v_total != 0 && | |
| 487 | − (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { | |
| 488 | − stream->adjust.timing_adjust_pending = false; | |
| 489 | − if (adjust->allow_otg_v_count_halt) | |
| 490 | − return set_long_vtotal(dc, stream, adjust); | |
| 491 | − else | |
| 492 | − return false; | |
| 493 | − } | |
| 494 | − | |
| 495 | − for (i = 0; i < MAX_PIPES; i++) { | |
| 496 | − struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; | |
| 497 | − | |
| 498 | − if (pipe->stream == stream && pipe->stream_res.tg) { | |
| 499 | − dc->hwss.set_drr(&pipe, | |
| 500 | − 1, | |
| 501 | − *adjust); | |
| 502 | − stream->adjust.timing_adjust_pending = false; | |
| 503 | − | |
| 504 | − if (dc->hwss.notify_cursor_offload_drr_update) | |
| 505 | − dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream); | |
| 506 | − | |
| 507 | − return true; | |
| 508 | − } | |
| 509 | − } | |
| 510 | − | |
| 511 | − return false; | |
| 512 | −} | |
| 513 | − | |
| 514 | 445 | /** |
| 515 | 446 | * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of |
| 516 | 447 | * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate) |
| @@ -1274,6 +1205,8 @@ static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *conte · 757 unmodified lines | ||
| 1274 | 1205 | get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); |
| 1275 | 1206 | else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC) |
| 1276 | 1207 | get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); |
| 1208 | + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) | |
| 1209 | + get_refresh_rate_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); | |
| 1277 | 1210 | } |
| 1278 | 1211 | } |
| 1279 | 1212 | } |
| @@ -1323,6 +1256,83 @@ void dc_get_visual_confirm_for_stream( · 43 unmodified lines | ||
| 1323 | 1256 | } |
| 1324 | 1257 | } |
| 1325 | 1258 | |
| 1259 | +/** | |
| 1260 | + * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR | |
| 1261 | + * @dc: dc reference | |
| 1262 | + * @stream: Initial dc stream state | |
| 1263 | + * @adjust: Updated parameters for vertical_total_min and vertical_total_max | |
| 1264 | + * | |
| 1265 | + * Looks up the pipe context of dc_stream_state and updates the | |
| 1266 | + * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh | |
| 1267 | + * Rate, which is a power-saving feature that targets reducing panel | |
| 1268 | + * refresh rate while the screen is static | |
| 1269 | + * | |
| 1270 | + * Return: %true if the pipe context is found and adjusted; | |
| 1271 | + * %false if the pipe context is not found. | |
| 1272 | + */ | |
| 1273 | +bool dc_stream_adjust_vmin_vmax(struct dc *dc, | |
| 1274 | + struct dc_stream_state *stream, | |
| 1275 | + struct dc_crtc_timing_adjust *adjust) | |
| 1276 | +{ | |
| 1277 | + int i; | |
| 1278 | + | |
| 1279 | + /* | |
| 1280 | + * Don't adjust DRR while there's bandwidth optimizations pending to | |
| 1281 | + * avoid conflicting with firmware updates. | |
| 1282 | + */ | |
| 1283 | + if (dc->ctx->dce_version > DCE_VERSION_MAX) { | |
| 1284 | + if (dc->optimized_required && | |
| 1285 | + (stream->adjust.v_total_max != adjust->v_total_max || | |
| 1286 | + stream->adjust.v_total_min != adjust->v_total_min)) { | |
| 1287 | + stream->adjust.timing_adjust_pending = true; | |
| 1288 | + return false; | |
| 1289 | + } | |
| 1290 | + } | |
| 1291 | + | |
| 1292 | + dc_exit_ips_for_hw_access(dc); | |
| 1293 | + | |
| 1294 | + stream->adjust.v_total_max = adjust->v_total_max; | |
| 1295 | + stream->adjust.v_total_mid = adjust->v_total_mid; | |
| 1296 | + stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; | |
| 1297 | + stream->adjust.v_total_min = adjust->v_total_min; | |
| 1298 | + stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; | |
| 1299 | + | |
| 1300 | + if (dc->caps.max_v_total != 0 && | |
| 1301 | + (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { | |
| 1302 | + stream->adjust.timing_adjust_pending = false; | |
| 1303 | + if (adjust->allow_otg_v_count_halt) | |
| 1304 | + return set_long_vtotal(dc, stream, adjust); | |
| 1305 | + else | |
| 1306 | + return false; | |
| 1307 | + } | |
| 1308 | + | |
| 1309 | + for (i = 0; i < MAX_PIPES; i++) { | |
| 1310 | + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; | |
| 1311 | + | |
| 1312 | + if (pipe->stream == stream && pipe->stream_res.tg) { | |
| 1313 | + dc->hwss.set_drr(&pipe, | |
| 1314 | + 1, | |
| 1315 | + *adjust); | |
| 1316 | + stream->adjust.timing_adjust_pending = false; | |
| 1317 | + | |
| 1318 | + if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) { | |
| 1319 | + if (pipe->stream && pipe->plane_state) { | |
| 1320 | + dc_update_visual_confirm_color(dc, dc->current_state, pipe); | |
| 1321 | + dc->hwss.update_visual_confirm_color(dc, pipe, pipe->plane_res.hubp->mpcc_id); | |
| 1322 | + | |
| 1323 | + } | |
| 1324 | + } | |
| 1325 | + | |
| 1326 | + if (dc->hwss.notify_cursor_offload_drr_update) | |
| 1327 | + dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream); | |
| 1328 | + | |
| 1329 | + return true; | |
| 1330 | + } | |
| 1331 | + } | |
| 1332 | + | |
| 1333 | + return false; | |
| 1334 | +} | |
| 1335 | + | |
| 1326 | 1336 | static void disable_dangling_plane(struct dc *dc, struct dc_state *context) |
| 1327 | 1337 | { |
| 1328 | 1338 | int i, j; |
| @@ -3064,7 +3074,7 @@ struct surface_update_descriptor dc_check_update_surfaces_for_stream( · 1735 unmodified lines | ||
| 3064 | 3074 | { |
| 3065 | 3075 | if (stream_update) |
| 3066 | 3076 | stream_update->stream->update_flags.raw = 0; |
| 3067 | − for (size_t i = 0; i < surface_count; i++) | |
| 3077 | + for (int i = 0; i < surface_count; i++) | |
| 3068 | 3078 | updates[i].surface->update_flags.raw = 0; |
| 3069 | 3079 | |
| 3070 | 3080 | return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update); |
| @@ -5540,6 +5550,9 @@ void dc_power_down_on_boot(struct dc *dc) · 2469 unmodified lines | ||
| 5540 | 5550 | { |
| 5541 | 5551 | if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW && |
| 5542 | 5552 | dc->hwss.power_down_on_boot) { |
| 5553 | + if (dc->current_state->stream_count > 0) | |
| 5554 | + return; | |
| 5555 | + | |
| 5543 | 5556 | if (dc->caps.ips_support) |
| 5544 | 5557 | dc_exit_ips_for_hw_access(dc); |
| 5545 | 5558 | dc->hwss.power_down_on_boot(dc); |
| @@ -5551,12 +5564,12 @@ void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state) · 5 unmodified lines | ||
| 5551 | 5564 | if (!dc->current_state) |
| 5552 | 5565 | return; |
| 5553 | 5566 | |
| 5567 | + dc_exit_ips_for_hw_access(dc); | |
| 5568 | + | |
| 5554 | 5569 | switch (power_state) { |
| 5555 | 5570 | case DC_ACPI_CM_POWER_STATE_D0: |
| 5556 | 5571 | dc_state_construct(dc, dc->current_state); |
| 5557 | 5572 | |
| 5558 | − dc_exit_ips_for_hw_access(dc); | |
| 5559 | − | |
| 5560 | 5573 | dc_z10_restore(dc); |
| 5561 | 5574 | |
| 5562 | 5575 | dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2015 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2015-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -846,6 +846,16 @@ void hwss_build_fast_sequence(struct dc *dc, · 840 unmodified lines | ||
| 846 | 846 | block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE; |
| 847 | 847 | (*num_steps)++; |
| 848 | 848 | } |
| 849 | + if (current_mpc_pipe->plane_state->update_flags.bits.cm_hist_change) { | |
| 850 | + block_sequence[*num_steps].params.control_cm_hist_params.dpp | |
| 851 | + = current_mpc_pipe->plane_res.dpp; | |
| 852 | + block_sequence[*num_steps].params.control_cm_hist_params.cm_hist_control | |
| 853 | + = current_mpc_pipe->plane_state->cm_hist_control; | |
| 854 | + block_sequence[*num_steps].params.control_cm_hist_params.color_space | |
| 855 | + = current_mpc_pipe->plane_state->color_space; | |
| 856 | + block_sequence[*num_steps].func = DPP_PROGRAM_CM_HIST; | |
| 857 | + (*num_steps)++; | |
| 858 | + } | |
| 849 | 859 | } |
| 850 | 860 | if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) { |
| 851 | 861 | block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc; |
| @@ -1029,6 +1039,9 @@ void hwss_execute_sequence(struct dc *dc, · 177 unmodified lines | ||
| 1029 | 1039 | case HUBP_PROGRAM_MCACHE_ID: |
| 1030 | 1040 | hwss_program_mcache_id_and_split_coordinate(params); |
| 1031 | 1041 | break; |
| 1042 | + case DPP_PROGRAM_CM_HIST: | |
| 1043 | + hwss_program_cm_hist(params); | |
| 1044 | + break; | |
| 1032 | 1045 | case PROGRAM_CURSOR_UPDATE_NOW: |
| 1033 | 1046 | dc->hwss.program_cursor_offload_now( |
| 1034 | 1047 | params->program_cursor_update_now_params.dc, |
| @@ -2054,6 +2067,16 @@ void hwss_program_mcache_id_and_split_coordinate(union block_sequence_params *pa · 1019 unmodified lines | ||
| 2054 | 2067 | |
| 2055 | 2068 | } |
| 2056 | 2069 | |
| 2070 | +void hwss_program_cm_hist(union block_sequence_params *params) | |
| 2071 | +{ | |
| 2072 | + struct dpp *dpp = params->control_cm_hist_params.dpp; | |
| 2073 | + | |
| 2074 | + if (dpp && dpp->funcs->dpp_cm_hist_control) | |
| 2075 | + dpp->funcs->dpp_cm_hist_control(dpp, | |
| 2076 | + params->control_cm_hist_params.cm_hist_control, | |
| 2077 | + params->control_cm_hist_params.color_space); | |
| 2078 | +} | |
| 2079 | + | |
| 2057 | 2080 | void get_surface_tile_visual_confirm_color( |
| 2058 | 2081 | struct pipe_ctx *pipe_ctx, |
| 2059 | 2082 | struct tg_color *color) |
| @@ -3370,6 +3393,20 @@ void hwss_add_opp_program_bit_depth_reduction(struct block_sequence_state *seq_s · 1310 unmodified lines | ||
| 3370 | 3393 | } |
| 3371 | 3394 | } |
| 3372 | 3395 | |
| 3396 | +void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state, | |
| 3397 | + struct dpp *dpp, | |
| 3398 | + struct cm_hist_control cm_hist_control, | |
| 3399 | + enum dc_color_space color_space) | |
| 3400 | +{ | |
| 3401 | + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { | |
| 3402 | + seq_state->steps[*seq_state->num_steps].func = DPP_PROGRAM_CM_HIST; | |
| 3403 | + seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.dpp = dpp; | |
| 3404 | + seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.cm_hist_control = cm_hist_control; | |
| 3405 | + seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.color_space = color_space; | |
| 3406 | + (*seq_state->num_steps)++; | |
| 3407 | + } | |
| 3408 | +} | |
| 3409 | + | |
| 3373 | 3410 | void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state, |
| 3374 | 3411 | struct dc *dc, |
| 3375 | 3412 | bool enable) |
| @@ -4071,3 +4108,24 @@ void hwss_add_tg_get_frame_count(struct block_sequence_state *seq_state, · 695 unmodified lines | ||
| 4071 | 4108 | (*seq_state->num_steps)++; |
| 4072 | 4109 | } |
| 4073 | 4110 | } |
| 4111 | + | |
| 4112 | + | |
| 4113 | +void get_refresh_rate_confirm_color(struct pipe_ctx *pipe_ctx, struct tg_color *color) | |
| 4114 | +{ | |
| 4115 | + uint32_t color_value = MAX_TG_COLOR_VALUE; | |
| 4116 | + unsigned int refresh_rate = 0; | |
| 4117 | + uint32_t scaling_factor = 0; | |
| 4118 | + if (pipe_ctx && pipe_ctx->stream && color) { | |
| 4119 | + refresh_rate = (pipe_ctx->stream->timing.pix_clk_100hz * 100) / (pipe_ctx->stream->adjust.v_total_max * pipe_ctx->stream->timing.h_total); | |
| 4120 | + | |
| 4121 | + uint32_t min_refresh_rate = pipe_ctx->stream->timing.min_refresh_in_uhz / 1000000; | |
| 4122 | + uint32_t max_refresh_rate = pipe_ctx->stream->timing.max_refresh_in_uhz / 1000000; | |
| 4123 | + | |
| 4124 | + if (max_refresh_rate - min_refresh_rate) | |
| 4125 | + scaling_factor = MAX_TG_COLOR_VALUE * (refresh_rate - min_refresh_rate) / (max_refresh_rate - min_refresh_rate); | |
| 4126 | + | |
| 4127 | + pipe_ctx->visual_confirm_color.color_r_cr = color_value; | |
| 4128 | + pipe_ctx->visual_confirm_color.color_g_y = scaling_factor; | |
| 4129 | + pipe_ctx->visual_confirm_color.color_b_cb = color_value; | |
| 4130 | + } | |
| 4131 | +} | |
| @@ -78,6 +78,7 @@ · 77 unmodified lines | ||
| 78 | 78 | #include "dcn351/dcn351_resource.h" |
| 79 | 79 | #include "dcn36/dcn36_resource.h" |
| 80 | 80 | #include "dcn401/dcn401_resource.h" |
| 81 | +#include "dcn42/dcn42_resource.h" | |
| 81 | 82 | #if defined(CONFIG_DRM_AMD_DC_FP) |
| 82 | 83 | #include "dc_spl_translate.h" |
| 83 | 84 | #endif |
| @@ -252,6 +253,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) · 168 unmodified lines | ||
| 252 | 253 | ASICREV_IS_GC_12_0_0_A0(asic_id.hw_internal_rev)) |
| 253 | 254 | dc_version = DCN_VERSION_4_01; |
| 254 | 255 | break; |
| 256 | + case AMDGPU_FAMILY_GC_11_5_4: | |
| 257 | + dc_version = DCN_VERSION_4_2; | |
| 258 | + break; | |
| 255 | 259 | default: |
| 256 | 260 | dc_version = DCE_VERSION_UNKNOWN; |
| 257 | 261 | break; |
| @@ -368,6 +372,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, · 110 unmodified lines | ||
| 368 | 372 | case DCN_VERSION_4_01: |
| 369 | 373 | res_pool = dcn401_create_resource_pool(init_data, dc); |
| 370 | 374 | break; |
| 375 | + case DCN_VERSION_4_2: | |
| 376 | + res_pool = dcn42_create_resource_pool(init_data, dc); | |
| 377 | + break; | |
| 371 | 378 | #endif /* CONFIG_DRM_AMD_DC_FP */ |
| 372 | 379 | default: |
| 373 | 380 | break; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2012-2023 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2012-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -63,7 +63,7 @@ struct dcn_dsc_reg_state; · 57 unmodified lines | ||
| 63 | 63 | struct dcn_optc_reg_state; |
| 64 | 64 | struct dcn_dccg_reg_state; |
| 65 | 65 | |
| 66 | −#define DC_VER "3.2.369" | |
| 66 | +#define DC_VER "3.2.372" | |
| 67 | 67 | |
| 68 | 68 | /** |
| 69 | 69 | * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC |
| @@ -581,6 +581,7 @@ enum visual_confirm { · 511 unmodified lines | ||
| 581 | 581 | VISUAL_CONFIRM_HW_CURSOR = 20, |
| 582 | 582 | VISUAL_CONFIRM_VABC = 21, |
| 583 | 583 | VISUAL_CONFIRM_DCC = 22, |
| 584 | + VISUAL_CONFIRM_BOOSTED_REFRESH_RATE = 23, | |
| 584 | 585 | VISUAL_CONFIRM_EXPLICIT = 0x80000000, |
| 585 | 586 | }; |
| 586 | 587 | |
| @@ -733,6 +734,8 @@ struct dc_clocks { · 146 unmodified lines | ||
| 733 | 734 | struct { |
| 734 | 735 | uint8_t base_efficiency; //LP1 |
| 735 | 736 | uint8_t low_power_efficiency; //LP2 |
| 737 | + uint8_t z8_stutter_efficiency; | |
| 738 | + int z8_stutter_period; | |
| 736 | 739 | } stutter_efficiency; |
| 737 | 740 | }; |
| 738 | 741 | |
| @@ -1211,6 +1214,7 @@ struct dc_debug_options { · 472 unmodified lines | ||
| 1211 | 1214 | unsigned int num_fast_flips_to_steady_state_override; |
| 1212 | 1215 | bool enable_dmu_recovery; |
| 1213 | 1216 | unsigned int force_vmin_threshold; |
| 1217 | + bool enable_otg_frame_sync_pwa; | |
| 1214 | 1218 | }; |
| 1215 | 1219 | |
| 1216 | 1220 | |
| @@ -1419,6 +1423,7 @@ struct dc_plane_status { · 202 unmodified lines | ||
| 1419 | 1423 | struct dc_plane_address current_address; |
| 1420 | 1424 | bool is_flip_pending; |
| 1421 | 1425 | bool is_right_eye; |
| 1426 | + struct cm_hist cm_hist; | |
| 1422 | 1427 | }; |
| 1423 | 1428 | |
| 1424 | 1429 | union surface_update_flags { |
| @@ -1455,6 +1460,7 @@ union surface_update_flags { · 30 unmodified lines | ||
| 1455 | 1460 | uint32_t mcm_transfer_function_enable_change:1; /* disable or enable MCM transfer func */ |
| 1456 | 1461 | uint32_t full_update:1; |
| 1457 | 1462 | uint32_t sdr_white_level_nits:1; |
| 1463 | + uint32_t cm_hist_change:1; | |
| 1458 | 1464 | } bits; |
| 1459 | 1465 | |
| 1460 | 1466 | uint32_t raw; |
| @@ -1539,6 +1545,7 @@ struct dc_plane_state { · 78 unmodified lines | ||
| 1539 | 1545 | int sharpness_level; |
| 1540 | 1546 | enum linear_light_scaling linear_light_scaling; |
| 1541 | 1547 | unsigned int sdr_white_level_nits; |
| 1548 | + struct cm_hist_control cm_hist_control; | |
| 1542 | 1549 | struct spl_sharpness_range sharpness_range; |
| 1543 | 1550 | enum sharpness_range_source sharpness_source; |
| 1544 | 1551 | }; |
| @@ -1682,6 +1689,10 @@ struct dc_scratch_space { · 137 unmodified lines | ||
| 1682 | 1689 | struct panel_cntl *panel_cntl; |
| 1683 | 1690 | struct link_encoder *link_enc; |
| 1684 | 1691 | struct graphics_object_id link_id; |
| 1692 | + | |
| 1693 | + /* External encoder eg. NUTMEG or TRAVIS used on CIK APUs. */ | |
| 1694 | + struct graphics_object_id ext_enc_id; | |
| 1695 | + | |
| 1685 | 1696 | /* Endpoint type distinguishes display endpoints which do not have entries |
| 1686 | 1697 | * in the BIOS connector table from those that do. Helps when tracking link |
| 1687 | 1698 | * encoder to display endpoint assignments. |
| @@ -1843,6 +1854,7 @@ struct dc_fast_update { · 155 unmodified lines | ||
| 1843 | 1854 | struct dc_transfer_func *out_transfer_func; |
| 1844 | 1855 | struct dc_csc_transform *output_csc_transform; |
| 1845 | 1856 | const struct dc_csc_transform *cursor_csc_color_matrix; |
| 1857 | + struct cm_hist_control *cm_hist_control; | |
| 1846 | 1858 | }; |
| 1847 | 1859 | |
| 1848 | 1860 | struct dc_surface_update { |
| @@ -1875,6 +1887,7 @@ struct dc_surface_update { · 26 unmodified lines | ||
| 1875 | 1887 | const struct dc_csc_transform *cursor_csc_color_matrix; |
| 1876 | 1888 | unsigned int sdr_white_level_nits; |
| 1877 | 1889 | struct dc_bias_and_scale bias_and_scale; |
| 1890 | + struct cm_hist_control *cm_hist_control; | |
| 1878 | 1891 | }; |
| 1879 | 1892 | |
| 1880 | 1893 | struct dc_underflow_debug_data { |
| @@ -97,11 +97,13 @@ struct dc_vbios_funcs { · 96 unmodified lines | ||
| 97 | 97 | enum bp_result (*encoder_control)( |
| 98 | 98 | struct dc_bios *bios, |
| 99 | 99 | struct bp_encoder_control *cntl); |
| 100 | + enum bp_result (*external_encoder_control)( | |
| 101 | + struct dc_bios *bios, | |
| 102 | + struct bp_external_encoder_control *cntl); | |
| 100 | 103 | enum bp_result (*dac_load_detection)( |
| 101 | 104 | struct dc_bios *bios, |
| 102 | 105 | enum engine_id engine_id, |
| 103 | − enum dal_device_type device_type, | |
| 104 | − uint32_t enum_id); | |
| 106 | + struct graphics_object_id ext_enc_id); | |
| 105 | 107 | enum bp_result (*transmitter_control)( |
| 106 | 108 | struct dc_bios *bios, |
| 107 | 109 | struct bp_transmitter_control *cntl); |
| @@ -947,8 +947,8 @@ union dp_tun_cap_support { · 946 unmodified lines | ||
| 947 | 947 | /* DPCD[0xE000E] DP_IN_ADAPTER_INFO register. */ |
| 948 | 948 | union dpia_info { |
| 949 | 949 | struct { |
| 950 | − uint8_t dpia_num :5; | |
| 951 | − uint8_t rsvd :3; | |
| 950 | + uint8_t dpia_num :6; | |
| 951 | + uint8_t rsvd :2; | |
| 952 | 952 | } bits; |
| 953 | 953 | uint8_t raw; |
| 954 | 954 | }; |
| @@ -751,6 +751,8 @@ char *dce_version_to_string(const int version) · 750 unmodified lines | ||
| 751 | 751 | return "DCN 3.6"; |
| 752 | 752 | case DCN_VERSION_4_01: |
| 753 | 753 | return "DCN 4.0.1"; |
| 754 | + case DCN_VERSION_4_2: | |
| 755 | + return "DCN 4.2"; | |
| 754 | 756 | default: |
| 755 | 757 | return "Unknown"; |
| 756 | 758 | } |
| @@ -271,6 +271,15 @@ enum tile_split_values_new { · 270 unmodified lines | ||
| 271 | 271 | DC_SURF_TILE_SPLIT_1KB = 0x4, |
| 272 | 272 | }; |
| 273 | 273 | |
| 274 | +enum otg_pwa_sync_mode { | |
| 275 | + DC_OTG_PWA_FRAME_SYNC_MODE_VSYNC = 0x0, | |
| 276 | + DC_OTG_PWA_FRAME_SYNC_MODE_VSTARTUP = 0x1, | |
| 277 | +}; | |
| 278 | +struct otc_pwa_frame_sync { | |
| 279 | + enum otg_pwa_sync_mode pwa_sync_mode; | |
| 280 | + uint32_t pwa_frame_sync_line_offset; | |
| 281 | +}; | |
| 282 | + | |
| 274 | 283 | /* TODO: These values come from hardware spec. We need to readdress this |
| 275 | 284 | * if they ever change. |
| 276 | 285 | */ |
| @@ -1137,6 +1146,7 @@ struct mcif_buf_params { · 860 unmodified lines | ||
| 1137 | 1146 | unsigned int warmup_pitch; |
| 1138 | 1147 | unsigned int swlock; |
| 1139 | 1148 | unsigned int p_vmid; |
| 1149 | + uint8_t tmz_id; | |
| 1140 | 1150 | }; |
| 1141 | 1151 | |
| 1142 | 1152 | |
| @@ -1162,5 +1172,68 @@ struct phy_state { · 19 unmodified lines | ||
| 1162 | 1172 | enum symclk_state symclk_state; |
| 1163 | 1173 | }; |
| 1164 | 1174 | |
| 1175 | +enum cm_hist_tap_point { | |
| 1176 | + CM_HIST_TAP_POINT_1, | |
| 1177 | + CM_HIST_TAP_POINT_2, | |
| 1178 | + CM_HIST_TAP_POINT_3, | |
| 1179 | + CM_HIST_TAP_POINT_4, | |
| 1180 | +}; | |
| 1181 | + | |
| 1182 | +enum cm_hist_src { | |
| 1183 | + CM_HIST_SRC1, | |
| 1184 | + CM_HIST_SRC2, | |
| 1185 | + CM_HIST_SRC3, | |
| 1186 | +}; | |
| 1187 | + | |
| 1188 | +enum cm_hist_format { | |
| 1189 | + CM_HIST_FORMAT_FIXED_POINT, | |
| 1190 | + CM_HIST_FORMAT_FP16_POS, | |
| 1191 | + CM_HIST_FORMAT_FP16_POS_AND_NEG, | |
| 1192 | +}; | |
| 1193 | + | |
| 1194 | +enum cm_hist_read_channel_mask { | |
| 1195 | + CM_HIST_READ_DISABLED, | |
| 1196 | + CM_HIST_READ_CH1, | |
| 1197 | + CM_HIST_READ_CH2, | |
| 1198 | + CM_HIST_READ_CH1_CH2, | |
| 1199 | + CM_HIST_READ_CH3, | |
| 1200 | + CM_HIST_READ_CH1_CH3, | |
| 1201 | + CM_HIST_READ_CH2_CH3, | |
| 1202 | + CM_HIST_READ_ALL, | |
| 1203 | +}; | |
| 1204 | + | |
| 1205 | +enum cm_hist_src1_mode { | |
| 1206 | + CM_HIST_SRC1_MODE_R_OR_CR, | |
| 1207 | + CM_HIST_SRC1_MODE_MAX_RGB, | |
| 1208 | +}; | |
| 1209 | + | |
| 1210 | +enum cm_hist_src2_mode { | |
| 1211 | + CM_HIST_SRC2_MODE_G_OR_Y, | |
| 1212 | + CM_HIST_SRC2_MODE_RGB_TO_Y, | |
| 1213 | +}; | |
| 1214 | + | |
| 1215 | +enum cm_hist_src3_mode { | |
| 1216 | + CM_HIST_SRC3_MODE_B_OR_CB, | |
| 1217 | + CM_HIST_SRC3_MODE_MIN_RGB, | |
| 1218 | +}; | |
| 1219 | + | |
| 1220 | +struct cm_hist_control { | |
| 1221 | + enum cm_hist_tap_point tap_point; | |
| 1222 | + uint32_t channels_enabled; | |
| 1223 | + enum cm_hist_src1_mode src_1_select; | |
| 1224 | + enum cm_hist_src2_mode src_2_select; | |
| 1225 | + enum cm_hist_src3_mode src_3_select; | |
| 1226 | + enum cm_hist_src ch1_src; | |
| 1227 | + enum cm_hist_src ch2_src; | |
| 1228 | + enum cm_hist_src ch3_src; | |
| 1229 | + enum cm_hist_format format; | |
| 1230 | + enum cm_hist_read_channel_mask read_channel_mask; | |
| 1231 | +}; | |
| 1232 | + | |
| 1233 | +struct cm_hist { | |
| 1234 | + uint32_t ch1[256]; | |
| 1235 | + uint32_t ch2[256]; | |
| 1236 | + uint32_t ch3[256]; | |
| 1237 | +}; | |
| 1165 | 1238 | #endif /* DC_HW_TYPES_H */ |
| 1166 | 1239 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2012-15 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2012-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -1346,6 +1346,7 @@ enum dc_cm2_gpu_mem_layout { · 1340 unmodified lines | ||
| 1346 | 1346 | |
| 1347 | 1347 | enum dc_cm2_gpu_mem_pixel_component_order { |
| 1348 | 1348 | DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA, |
| 1349 | + DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA | |
| 1349 | 1350 | }; |
| 1350 | 1351 | |
| 1351 | 1352 | enum dc_cm2_gpu_mem_format { |
| @@ -1367,6 +1368,9 @@ struct dc_cm2_gpu_mem_format_parameters { · 15 unmodified lines | ||
| 1367 | 1368 | |
| 1368 | 1369 | enum dc_cm2_gpu_mem_size { |
| 1369 | 1370 | DC_CM2_GPU_MEM_SIZE_171717, |
| 1371 | + DC_CM2_GPU_MEM_SIZE_333333, | |
| 1372 | + DC_CM2_GPU_MEM_SIZE_454545, | |
| 1373 | + DC_CM2_GPU_MEM_SIZE_656565, | |
| 1370 | 1374 | DC_CM2_GPU_MEM_SIZE_TRANSFORMED, |
| 1371 | 1375 | }; |
| 1372 | 1376 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | |
| 2 | −# Copyright 2022 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -100,4 +100,13 @@ DCCG_DCN401 = dcn401_dccg.o · 94 unmodified lines | ||
| 100 | 100 | AMD_DAL_DCCG_DCN401 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn401/,$(DCCG_DCN401)) |
| 101 | 101 | |
| 102 | 102 | AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN401) |
| 103 | + | |
| 104 | +############################################################################### | |
| 105 | +# DCN42 | |
| 106 | +############################################################################### | |
| 107 | +DCCG_DCN42 = dcn42_dccg.o | |
| 108 | + | |
| 109 | +AMD_DAL_DCCG_DCN42 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn42/,$(DCCG_DCN42)) | |
| 110 | + | |
| 111 | +AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN42) | |
| 103 | 112 | endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2018 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2018-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -362,6 +362,16 @@ · 356 unmodified lines | ||
| 362 | 362 | type SYMCLK32_LE3_EN;\ |
| 363 | 363 | type DP_DTO_ENABLE[MAX_PIPES]; |
| 364 | 364 | |
| 365 | +#define DCCG42_REG_FIELD_LIST(type) \ | |
| 366 | + type OTG0_ADD_PIXEL;\ | |
| 367 | + type OTG1_ADD_PIXEL;\ | |
| 368 | + type OTG2_ADD_PIXEL;\ | |
| 369 | + type OTG0_DROP_PIXEL;\ | |
| 370 | + type OTG1_DROP_PIXEL;\ | |
| 371 | + type OTG2_DROP_PIXEL;\ | |
| 372 | + type OTG3_ADD_PIXEL;\ | |
| 373 | + type OTG3_DROP_PIXEL; | |
| 374 | + | |
| 365 | 375 | struct dccg_shift { |
| 366 | 376 | DCCG_REG_FIELD_LIST(uint8_t) |
| 367 | 377 | DCCG3_REG_FIELD_LIST(uint8_t) |
| @@ -370,6 +380,7 @@ struct dccg_shift { · 2 unmodified lines | ||
| 370 | 380 | DCCG32_REG_FIELD_LIST(uint8_t) |
| 371 | 381 | DCCG35_REG_FIELD_LIST(uint8_t) |
| 372 | 382 | DCCG401_REG_FIELD_LIST(uint8_t) |
| 383 | + DCCG42_REG_FIELD_LIST(uint8_t) | |
| 373 | 384 | }; |
| 374 | 385 | |
| 375 | 386 | struct dccg_mask { |
| @@ -380,6 +391,7 @@ struct dccg_mask { · 4 unmodified lines | ||
| 380 | 391 | DCCG32_REG_FIELD_LIST(uint32_t) |
| 381 | 392 | DCCG35_REG_FIELD_LIST(uint32_t) |
| 382 | 393 | DCCG401_REG_FIELD_LIST(uint32_t) |
| 394 | + DCCG42_REG_FIELD_LIST(uint32_t) | |
| 383 | 395 | }; |
| 384 | 396 | |
| 385 | 397 | #define DCCG_REG_VARIABLE_LIST \ |
| @@ -493,6 +505,7 @@ struct dccg_mask { · 107 unmodified lines | ||
| 493 | 505 | |
| 494 | 506 | struct dccg_registers { |
| 495 | 507 | DCCG_REG_VARIABLE_LIST; |
| 508 | + uint32_t OTG_ADD_DROP_PIXEL_CNTL; | |
| 496 | 509 | }; |
| 497 | 510 | |
| 498 | 511 | struct dcn_dccg { |
| @@ -0,0 +1,278 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "reg_helper.h" | |
| 6 | +#include "core_types.h" | |
| 7 | +#include "dcn35/dcn35_dccg.h" | |
| 8 | +#include "dcn42_dccg.h" | |
| 9 | + | |
| 10 | +#define TO_DCN_DCCG(dccg)\ | |
| 11 | + container_of(dccg, struct dcn_dccg, base) | |
| 12 | + | |
| 13 | +#define REG(reg) \ | |
| 14 | + (dccg_dcn->regs->reg) | |
| 15 | + | |
| 16 | +#undef FN | |
| 17 | +#define FN(reg_name, field_name) \ | |
| 18 | + dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name | |
| 19 | + | |
| 20 | +#define CTX \ | |
| 21 | + dccg_dcn->base.ctx | |
| 22 | +#define DC_LOGGER \ | |
| 23 | + dccg->ctx->logger | |
| 24 | + | |
| 25 | +void dccg42_otg_add_pixel(struct dccg *dccg, | |
| 26 | + uint32_t otg_inst) | |
| 27 | +{ | |
| 28 | + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | |
| 29 | + | |
| 30 | + switch (otg_inst) { | |
| 31 | + case 0: | |
| 32 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 33 | + OTG0_ADD_PIXEL, 1); | |
| 34 | + break; | |
| 35 | + case 1: | |
| 36 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 37 | + OTG1_ADD_PIXEL, 1); | |
| 38 | + break; | |
| 39 | + case 2: | |
| 40 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 41 | + OTG2_ADD_PIXEL, 1); | |
| 42 | + break; | |
| 43 | + case 3: | |
| 44 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 45 | + OTG3_ADD_PIXEL, 1); | |
| 46 | + break; | |
| 47 | + default: | |
| 48 | + ASSERT(0); | |
| 49 | + } | |
| 50 | +} | |
| 51 | + | |
| 52 | +void dccg42_otg_drop_pixel(struct dccg *dccg, | |
| 53 | + uint32_t otg_inst) | |
| 54 | +{ | |
| 55 | + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | |
| 56 | + | |
| 57 | + switch (otg_inst) { | |
| 58 | + case 0: | |
| 59 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 60 | + OTG0_DROP_PIXEL, 1); | |
| 61 | + break; | |
| 62 | + case 1: | |
| 63 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 64 | + OTG1_DROP_PIXEL, 1); | |
| 65 | + break; | |
| 66 | + case 2: | |
| 67 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 68 | + OTG2_DROP_PIXEL, 1); | |
| 69 | + break; | |
| 70 | + case 3: | |
| 71 | + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, | |
| 72 | + OTG3_DROP_PIXEL, 1); | |
| 73 | + break; | |
| 74 | + default: | |
| 75 | + ASSERT(0); | |
| 76 | + } | |
| 77 | +} | |
| 78 | + | |
| 79 | +void dccg42_enable_global_fgcg(struct dccg *dccg, bool value) | |
| 80 | +{ | |
| 81 | + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | |
| 82 | + | |
| 83 | + if (dccg->ctx->dc->debug.disable_clock_gate) | |
| 84 | + value = false; | |
| 85 | + REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value); | |
| 86 | +} | |
| 87 | + | |
| 88 | +void dccg42_set_physymclk( | |
| 89 | + struct dccg *dccg, | |
| 90 | + int phy_inst, | |
| 91 | + enum physymclk_clock_source clk_src, | |
| 92 | + bool force_enable) | |
| 93 | +{ | |
| 94 | + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | |
| 95 | + | |
| 96 | + switch (phy_inst) { | |
| 97 | + case 0: | |
| 98 | + if (force_enable) { | |
| 99 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 100 | + PHYASYMCLK_ROOT_GATE_DISABLE, 1); | |
| 101 | + REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, | |
| 102 | + PHYASYMCLK_EN, 1, | |
| 103 | + PHYASYMCLK_SRC_SEL, clk_src); | |
| 104 | + } else { | |
| 105 | + REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, | |
| 106 | + PHYASYMCLK_EN, 0, | |
| 107 | + PHYASYMCLK_SRC_SEL, 0); | |
| 108 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 109 | + PHYASYMCLK_ROOT_GATE_DISABLE, | |
| 110 | + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); | |
| 111 | + } | |
| 112 | + break; | |
| 113 | + case 1: | |
| 114 | + if (force_enable) { | |
| 115 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 116 | + PHYBSYMCLK_ROOT_GATE_DISABLE, 1); | |
| 117 | + REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, | |
| 118 | + PHYBSYMCLK_EN, 1, | |
| 119 | + PHYBSYMCLK_SRC_SEL, clk_src); | |
| 120 | + } else { | |
| 121 | + REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, | |
| 122 | + PHYBSYMCLK_EN, 0, | |
| 123 | + PHYBSYMCLK_SRC_SEL, 0); | |
| 124 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 125 | + PHYBSYMCLK_ROOT_GATE_DISABLE, | |
| 126 | + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); | |
| 127 | + } | |
| 128 | + break; | |
| 129 | + case 2: | |
| 130 | + if (force_enable) { | |
| 131 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 132 | + PHYCSYMCLK_ROOT_GATE_DISABLE, 1); | |
| 133 | + REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, | |
| 134 | + PHYCSYMCLK_EN, 1, | |
| 135 | + PHYCSYMCLK_SRC_SEL, clk_src); | |
| 136 | + } else { | |
| 137 | + REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, | |
| 138 | + PHYCSYMCLK_EN, 0, | |
| 139 | + PHYCSYMCLK_SRC_SEL, 0); | |
| 140 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 141 | + PHYCSYMCLK_ROOT_GATE_DISABLE, | |
| 142 | + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); | |
| 143 | + } | |
| 144 | + break; | |
| 145 | + case 3: | |
| 146 | + if (force_enable) { | |
| 147 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 148 | + PHYDSYMCLK_ROOT_GATE_DISABLE, 1); | |
| 149 | + REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, | |
| 150 | + PHYDSYMCLK_EN, 1, | |
| 151 | + PHYDSYMCLK_SRC_SEL, clk_src); | |
| 152 | + } else { | |
| 153 | + REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, | |
| 154 | + PHYDSYMCLK_EN, 0, | |
| 155 | + PHYDSYMCLK_SRC_SEL, 0); | |
| 156 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 157 | + PHYDSYMCLK_ROOT_GATE_DISABLE, | |
| 158 | + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); | |
| 159 | + } | |
| 160 | + break; | |
| 161 | + case 4: | |
| 162 | + if (force_enable) { | |
| 163 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 164 | + PHYESYMCLK_ROOT_GATE_DISABLE, 1); | |
| 165 | + REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, | |
| 166 | + PHYESYMCLK_EN, 1, | |
| 167 | + PHYESYMCLK_SRC_SEL, clk_src); | |
| 168 | + } else { | |
| 169 | + REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, | |
| 170 | + PHYESYMCLK_EN, 0, | |
| 171 | + PHYESYMCLK_SRC_SEL, 0); | |
| 172 | + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, | |
| 173 | + PHYESYMCLK_ROOT_GATE_DISABLE, | |
| 174 | + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); | |
| 175 | + } | |
| 176 | + break; | |
| 177 | + default: | |
| 178 | + BREAK_TO_DEBUGGER(); | |
| 179 | + return; | |
| 180 | + } | |
| 181 | +} | |
| 182 | + | |
| 183 | +static void dccg42_init(struct dccg *dccg) | |
| 184 | +{ | |
| 185 | + int otg_inst; | |
| 186 | + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | |
| 187 | + | |
| 188 | + /* Set HPO stream encoder to use refclk to avoid case where PHY is | |
| 189 | + * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which | |
| 190 | + * will cause DCN to hang. | |
| 191 | + */ | |
| 192 | + for (otg_inst = 0; otg_inst < 4; otg_inst++) | |
| 193 | + dccg35_disable_symclk32_se(dccg, otg_inst); | |
| 194 | + | |
| 195 | + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) { | |
| 196 | + dccg401_disable_symclk32_le(dccg, 0); | |
| 197 | + dccg401_disable_symclk32_le(dccg, 1); | |
| 198 | + dccg401_disable_symclk32_le(dccg, 2); | |
| 199 | + dccg401_disable_symclk32_le(dccg, 3); | |
| 200 | + } | |
| 201 | + | |
| 202 | + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { | |
| 203 | + dccg401_disable_dpstreamclk(dccg, 0); | |
| 204 | + dccg401_disable_dpstreamclk(dccg, 1); | |
| 205 | + dccg401_disable_dpstreamclk(dccg, 2); | |
| 206 | + dccg401_disable_dpstreamclk(dccg, 3); | |
| 207 | + } | |
| 208 | + if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) { | |
| 209 | + REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, | |
| 210 | + PHYASYMCLK_ROOT_GATE_DISABLE, 1, | |
| 211 | + PHYBSYMCLK_ROOT_GATE_DISABLE, 1, | |
| 212 | + PHYCSYMCLK_ROOT_GATE_DISABLE, 1, | |
| 213 | + PHYDSYMCLK_ROOT_GATE_DISABLE, 1, | |
| 214 | + PHYESYMCLK_ROOT_GATE_DISABLE, 1); | |
| 215 | + } | |
| 216 | +} | |
| 217 | + | |
| 218 | + | |
| 219 | +static const struct dccg_funcs dccg42_funcs = { | |
| 220 | + .update_dpp_dto = dccg35_update_dpp_dto, | |
| 221 | + .dpp_root_clock_control = dccg35_dpp_root_clock_control, | |
| 222 | + .get_dccg_ref_freq = dccg401_get_dccg_ref_freq, | |
| 223 | + .dccg_init = dccg42_init, | |
| 224 | + .set_dpstreamclk = dccg401_set_dpstreamclk, | |
| 225 | + /* Redundant with above^ */ | |
| 226 | + /* .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, */ | |
| 227 | + .enable_symclk32_se = dccg31_enable_symclk32_se, | |
| 228 | + .disable_symclk32_se = dccg35_disable_symclk32_se, | |
| 229 | + .enable_symclk32_le = dccg401_enable_symclk32_le, | |
| 230 | + .disable_symclk32_le = dccg401_disable_symclk32_le, | |
| 231 | + .set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating, | |
| 232 | + .set_physymclk = dccg42_set_physymclk, | |
| 233 | + .set_dtbclk_dto = NULL, | |
| 234 | + .set_dto_dscclk = dccg401_set_dto_dscclk, | |
| 235 | + .set_ref_dscclk = dccg401_set_ref_dscclk, | |
| 236 | + .set_valid_pixel_rate = NULL, | |
| 237 | + .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, | |
| 238 | + .set_audio_dtbclk_dto = NULL, | |
| 239 | + .otg_add_pixel = dccg42_otg_add_pixel, | |
| 240 | + .otg_drop_pixel = dccg42_otg_drop_pixel, | |
| 241 | + .disable_dsc = dccg35_disable_dscclk, | |
| 242 | + .enable_dsc = dccg35_enable_dscclk, | |
| 243 | + .set_pixel_rate_div = dccg401_set_pixel_rate_div, | |
| 244 | + .get_pixel_rate_div = dccg401_get_pixel_rate_div, | |
| 245 | + .trigger_dio_fifo_resync = dccg35_trigger_dio_fifo_resync, | |
| 246 | + .set_dp_dto = dccg401_set_dp_dto, | |
| 247 | + .enable_symclk_se = dccg35_enable_symclk_se, | |
| 248 | + .disable_symclk_se = dccg35_disable_symclk_se, | |
| 249 | + .set_dtbclk_p_src = dccg401_set_dtbclk_p_src, | |
| 250 | + .dccg_root_gate_disable_control = dccg35_root_gate_disable_control, | |
| 251 | + .dccg_read_reg_state = dccg31_read_reg_state, | |
| 252 | + .dccg_enable_global_fgcg = dccg42_enable_global_fgcg, | |
| 253 | +}; | |
| 254 | + | |
| 255 | +struct dccg *dccg42_create( | |
| 256 | + struct dc_context *ctx, | |
| 257 | + const struct dccg_registers *regs, | |
| 258 | + const struct dccg_shift *dccg_shift, | |
| 259 | + const struct dccg_mask *dccg_mask) | |
| 260 | +{ | |
| 261 | + struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); | |
| 262 | + struct dccg *base; | |
| 263 | + | |
| 264 | + if (dccg_dcn == NULL) { | |
| 265 | + BREAK_TO_DEBUGGER(); | |
| 266 | + return NULL; | |
| 267 | + } | |
| 268 | + | |
| 269 | + base = &dccg_dcn->base; | |
| 270 | + base->ctx = ctx; | |
| 271 | + base->funcs = &dccg42_funcs; | |
| 272 | + | |
| 273 | + dccg_dcn->regs = regs; | |
| 274 | + dccg_dcn->dccg_shift = dccg_shift; | |
| 275 | + dccg_dcn->dccg_mask = dccg_mask; | |
| 276 | + | |
| 277 | + return &dccg_dcn->base; | |
| 278 | +} | |
| @@ -0,0 +1,263 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2024-2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + * Authors: AMD | |
| 24 | + * | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef __DCN42_DCCG_H__ | |
| 28 | +#define __DCN42_DCCG_H__ | |
| 29 | + | |
| 30 | +#include "dcn401/dcn401_dccg.h" | |
| 31 | + | |
| 32 | +#define DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh) \ | |
| 33 | + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\ | |
| 34 | + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\ | |
| 35 | + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 2, mask_sh),\ | |
| 36 | + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\ | |
| 37 | + DCCG_SF(DPPCLK_CTRL, DPPCLK0_EN, mask_sh),\ | |
| 38 | + DCCG_SF(DPPCLK_CTRL, DPPCLK1_EN, mask_sh),\ | |
| 39 | + DCCG_SF(DPPCLK_CTRL, DPPCLK2_EN, mask_sh),\ | |
| 40 | + DCCG_SF(DPPCLK_CTRL, DPPCLK3_EN, mask_sh),\ | |
| 41 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_DELAY, mask_sh),\ | |
| 42 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_SIZE, mask_sh),\ | |
| 43 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, mask_sh),\ | |
| 44 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_MAX_ERRDET_CYCLES, mask_sh),\ | |
| 45 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_RESET, mask_sh),\ | |
| 46 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_STATE, mask_sh),\ | |
| 47 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_OVR_EN, mask_sh),\ | |
| 48 | + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_CHG_FWD_CORR_DISABLE, mask_sh),\ | |
| 49 | + DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\ | |
| 50 | + DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\ | |
| 51 | + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ | |
| 52 | + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ | |
| 53 | + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, mask_sh),\ | |
| 54 | + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_SRC_SEL, mask_sh),\ | |
| 55 | + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, mask_sh),\ | |
| 56 | + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\ | |
| 57 | + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\ | |
| 58 | + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\ | |
| 59 | + DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\ | |
| 60 | + DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\ | |
| 61 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\ | |
| 62 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\ | |
| 63 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\ | |
| 64 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\ | |
| 65 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_SRC_SEL, mask_sh),\ | |
| 66 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_SRC_SEL, mask_sh),\ | |
| 67 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\ | |
| 68 | + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\ | |
| 69 | + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\ | |
| 70 | + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\ | |
| 71 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\ | |
| 72 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\ | |
| 73 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\ | |
| 74 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\ | |
| 75 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_EN, mask_sh),\ | |
| 76 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_EN, mask_sh),\ | |
| 77 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_EN, mask_sh),\ | |
| 78 | + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\ | |
| 79 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, mask_sh),\ | |
| 80 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, mask_sh),\ | |
| 81 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_SRC_SEL, mask_sh),\ | |
| 82 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_SRC_SEL, mask_sh),\ | |
| 83 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_EN, mask_sh),\ | |
| 84 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_EN, mask_sh),\ | |
| 85 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_EN, mask_sh),\ | |
| 86 | + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_EN, mask_sh),\ | |
| 87 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\ | |
| 88 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\ | |
| 89 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\ | |
| 90 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\ | |
| 91 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_ADD_PIXEL, mask_sh),\ | |
| 92 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_ADD_PIXEL, mask_sh),\ | |
| 93 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_ADD_PIXEL, mask_sh),\ | |
| 94 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_ADD_PIXEL, mask_sh),\ | |
| 95 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_DROP_PIXEL, mask_sh),\ | |
| 96 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_DROP_PIXEL, mask_sh),\ | |
| 97 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_DROP_PIXEL, mask_sh),\ | |
| 98 | + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_DROP_PIXEL, mask_sh),\ | |
| 99 | + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG0_TMDS_PIXEL_RATE_DIV, mask_sh),\ | |
| 100 | + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO0_INT, mask_sh),\ | |
| 101 | + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG1_TMDS_PIXEL_RATE_DIV, mask_sh),\ | |
| 102 | + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO1_INT, mask_sh),\ | |
| 103 | + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG2_TMDS_PIXEL_RATE_DIV, mask_sh),\ | |
| 104 | + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO2_INT, mask_sh),\ | |
| 105 | + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_TMDS_PIXEL_RATE_DIV, mask_sh),\ | |
| 106 | + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO3_INT, mask_sh),\ | |
| 107 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_SRC_SEL, mask_sh),\ | |
| 108 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_EN, mask_sh),\ | |
| 109 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_SRC_SEL, mask_sh),\ | |
| 110 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_EN, mask_sh),\ | |
| 111 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_SRC_SEL, mask_sh),\ | |
| 112 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_EN, mask_sh),\ | |
| 113 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\ | |
| 114 | + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\ | |
| 115 | + DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ | |
| 116 | + DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ | |
| 117 | + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh),\ | |
| 118 | + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\ | |
| 119 | + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ | |
| 120 | + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh),\ | |
| 121 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 122 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 123 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 124 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 125 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 0, mask_sh),\ | |
| 126 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 1, mask_sh),\ | |
| 127 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 2, mask_sh),\ | |
| 128 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 3, mask_sh),\ | |
| 129 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\ | |
| 130 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\ | |
| 131 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\ | |
| 132 | + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\ | |
| 133 | + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_EN, mask_sh),\ | |
| 134 | + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\ | |
| 135 | + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\ | |
| 136 | + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\ | |
| 137 | + DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\ | |
| 138 | + DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\ | |
| 139 | + DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\ | |
| 140 | + DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\ | |
| 141 | + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\ | |
| 142 | + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\ | |
| 143 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL, DISPCLK_DCCG_GATE_DISABLE, mask_sh),\ | |
| 144 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh),\ | |
| 145 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\ | |
| 146 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh),\ | |
| 147 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh),\ | |
| 148 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh),\ | |
| 149 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh),\ | |
| 150 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh),\ | |
| 151 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh),\ | |
| 152 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh),\ | |
| 153 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh),\ | |
| 154 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 155 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 156 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 157 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 158 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ | |
| 159 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\ | |
| 160 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\ | |
| 161 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\ | |
| 162 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\ | |
| 163 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\ | |
| 164 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE2_GATE_DISABLE, mask_sh),\ | |
| 165 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE3_GATE_DISABLE, mask_sh),\ | |
| 166 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE0_GATE_DISABLE, mask_sh),\ | |
| 167 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE1_GATE_DISABLE, mask_sh),\ | |
| 168 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE2_GATE_DISABLE, mask_sh),\ | |
| 169 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE3_GATE_DISABLE, mask_sh),\ | |
| 170 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE0_GATE_DISABLE, mask_sh),\ | |
| 171 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE1_GATE_DISABLE, mask_sh),\ | |
| 172 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE2_GATE_DISABLE, mask_sh),\ | |
| 173 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE3_GATE_DISABLE, mask_sh),\ | |
| 174 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, HDMICHARCLK0_ROOT_GATE_DISABLE, mask_sh),\ | |
| 175 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYA_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 176 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYB_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 177 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYC_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 178 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYD_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 179 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\ | |
| 180 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\ | |
| 181 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\ | |
| 182 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\ | |
| 183 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, mask_sh),\ | |
| 184 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, mask_sh),\ | |
| 185 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, mask_sh),\ | |
| 186 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, mask_sh),\ | |
| 187 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, mask_sh),\ | |
| 188 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, mask_sh),\ | |
| 189 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, mask_sh),\ | |
| 190 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, mask_sh),\ | |
| 191 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\ | |
| 192 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, mask_sh),\ | |
| 193 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, mask_sh),\ | |
| 194 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, mask_sh),\ | |
| 195 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\ | |
| 196 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\ | |
| 197 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\ | |
| 198 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\ | |
| 199 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, mask_sh),\ | |
| 200 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, mask_sh),\ | |
| 201 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, mask_sh),\ | |
| 202 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, mask_sh),\ | |
| 203 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, mask_sh),\ | |
| 204 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, mask_sh),\ | |
| 205 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, mask_sh),\ | |
| 206 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\ | |
| 207 | + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\ | |
| 208 | + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\ | |
| 209 | + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\ | |
| 210 | + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\ | |
| 211 | + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\ | |
| 212 | + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\ | |
| 213 | + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\ | |
| 214 | + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\ | |
| 215 | + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\ | |
| 216 | + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\ | |
| 217 | + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\ | |
| 218 | + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh) | |
| 219 | + | |
| 220 | +#define DCCG_MASK_SH_LIST_DCN42(mask_sh) \ | |
| 221 | + DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh),\ | |
| 222 | + DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, mask_sh),\ | |
| 223 | + DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_SRC_SEL, mask_sh),\ | |
| 224 | + DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\ | |
| 225 | + DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh),\ | |
| 226 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 227 | + DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\ | |
| 228 | + DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\ | |
| 229 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 230 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYE_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ | |
| 231 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, mask_sh),\ | |
| 232 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, mask_sh),\ | |
| 233 | + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, mask_sh),\ | |
| 234 | + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_SRC_SEL, mask_sh),\ | |
| 235 | + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_SRC_SEL, mask_sh),\ | |
| 236 | + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_SRC_SEL, mask_sh),\ | |
| 237 | + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_SRC_SEL, mask_sh),\ | |
| 238 | + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\ | |
| 239 | + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\ | |
| 240 | + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\ | |
| 241 | + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh) | |
| 242 | + | |
| 243 | + | |
| 244 | +void dccg42_otg_add_pixel(struct dccg *dccg, | |
| 245 | + uint32_t otg_inst); | |
| 246 | + | |
| 247 | +void dccg42_otg_drop_pixel(struct dccg *dccg, | |
| 248 | + uint32_t otg_inst); | |
| 249 | +void dccg42_enable_global_fgcg(struct dccg *dccg, bool value); | |
| 250 | + | |
| 251 | +void dccg42_set_physymclk( | |
| 252 | + struct dccg *dccg, | |
| 253 | + int phy_inst, | |
| 254 | + enum physymclk_clock_source clk_src, | |
| 255 | + bool force_enable); | |
| 256 | + | |
| 257 | +struct dccg *dccg42_create( | |
| 258 | + struct dc_context *ctx, | |
| 259 | + const struct dccg_registers *regs, | |
| 260 | + const struct dccg_shift *dccg_shift, | |
| 261 | + const struct dccg_mask *dccg_mask); | |
| 262 | + | |
| 263 | +#endif //__DCN42_DCCG_H__ | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2012-16 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2012-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -300,6 +300,64 @@ · 294 unmodified lines | ||
| 300 | 300 | ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \ |
| 301 | 301 | ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh) |
| 302 | 302 | |
| 303 | +#define ABM_MASK_SH_LIST_DCN42(mask_sh) \ | |
| 304 | + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ | |
| 305 | + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ | |
| 306 | + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ | |
| 307 | + ABM1_HG_VMAX_SEL, mask_sh), \ | |
| 308 | + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ | |
| 309 | + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ | |
| 310 | + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ | |
| 311 | + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ | |
| 312 | + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ | |
| 313 | + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ | |
| 314 | + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ | |
| 315 | + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ | |
| 316 | + ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ | |
| 317 | + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ | |
| 318 | + ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ | |
| 319 | + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ | |
| 320 | + ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ | |
| 321 | + BL1_PWM_USER_LEVEL, mask_sh), \ | |
| 322 | + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ | |
| 323 | + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ | |
| 324 | + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ | |
| 325 | + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ | |
| 326 | + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ | |
| 327 | + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ | |
| 328 | + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ | |
| 329 | + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ | |
| 330 | + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ | |
| 331 | + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ | |
| 332 | + ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \ | |
| 333 | + ABM1_ACE_SLOPE_DATA, mask_sh), \ | |
| 334 | + ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \ | |
| 335 | + ABM1_ACE_OFFSET_DATA, mask_sh), \ | |
| 336 | + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ | |
| 337 | + ABM1_ACE_OFFSET_SLOPE_INDEX, mask_sh), \ | |
| 338 | + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ | |
| 339 | + ABM1_ACE_IGNORE_MASTER_LOCK_EN, mask_sh), \ | |
| 340 | + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ | |
| 341 | + ABM1_ACE_READBACK_DB_REG_VALUE_EN, mask_sh), \ | |
| 342 | + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ | |
| 343 | + ABM1_ACE_DBUF_REG_UPDATE_PENDING, mask_sh), \ | |
| 344 | + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ | |
| 345 | + ABM1_ACE_LOCK, mask_sh), \ | |
| 346 | + ABM_SF(ABM0_DC_ABM1_HG_RESULT_DATA, \ | |
| 347 | + ABM1_HG_RESULT_DATA, mask_sh), \ | |
| 348 | + ABM_SF(ABM0_DC_ABM1_HG_RESULT_INDEX, \ | |
| 349 | + ABM1_HG_RESULT_INDEX, mask_sh), \ | |
| 350 | + ABM_SF(ABM0_DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, \ | |
| 351 | + ABM1_HG_BIN_33_40_SHIFT_INDEX, mask_sh), \ | |
| 352 | + ABM_SF(ABM0_DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, \ | |
| 353 | + ABM1_HG_BIN_33_64_SHIFT_FLAG, mask_sh), \ | |
| 354 | + ABM_SF(ABM0_DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, \ | |
| 355 | + ABM1_HG_BIN_41_48_SHIFT_INDEX, mask_sh), \ | |
| 356 | + ABM_SF(ABM0_DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, \ | |
| 357 | + ABM1_HG_BIN_49_56_SHIFT_INDEX, mask_sh), \ | |
| 358 | + ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \ | |
| 359 | + ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh) | |
| 360 | + | |
| 303 | 361 | #define ABM_REG_FIELD_LIST(type) \ |
| 304 | 362 | type ABM1_HG_NUM_OF_BINS_SEL; \ |
| 305 | 363 | type ABM1_HG_VMAX_SEL; \ |
| @@ -1150,98 +1150,6 @@ void dce_aud_wall_dto_setup( · 1149 unmodified lines | ||
| 1150 | 1150 | } |
| 1151 | 1151 | } |
| 1152 | 1152 | |
| 1153 | −#if defined(CONFIG_DRM_AMD_DC_SI) | |
| 1154 | −static void dce60_aud_wall_dto_setup( | |
| 1155 | − struct audio *audio, | |
| 1156 | − enum signal_type signal, | |
| 1157 | − const struct audio_crtc_info *crtc_info, | |
| 1158 | − const struct audio_pll_info *pll_info) | |
| 1159 | −{ | |
| 1160 | − struct dce_audio *aud = DCE_AUD(audio); | |
| 1161 | − | |
| 1162 | − struct azalia_clock_info clock_info = { 0 }; | |
| 1163 | − | |
| 1164 | − if (dc_is_hdmi_signal(signal)) { | |
| 1165 | − uint32_t src_sel; | |
| 1166 | − | |
| 1167 | − /*DTO0 Programming goal: | |
| 1168 | − -generate 24MHz, 128*Fs from 24MHz | |
| 1169 | − -use DTO0 when an active HDMI port is connected | |
| 1170 | − (optionally a DP is connected) */ | |
| 1171 | − | |
| 1172 | − /* calculate DTO settings */ | |
| 1173 | − get_azalia_clock_info_hdmi( | |
| 1174 | − crtc_info->requested_pixel_clock_100Hz, | |
| 1175 | − crtc_info->calculated_pixel_clock_100Hz, | |
| 1176 | − &clock_info); | |
| 1177 | − | |
| 1178 | − DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d"\ | |
| 1179 | − "calculated_pixel_clock_100Hz =%d\n"\ | |
| 1180 | − "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ | |
| 1181 | − crtc_info->requested_pixel_clock_100Hz,\ | |
| 1182 | − crtc_info->calculated_pixel_clock_100Hz,\ | |
| 1183 | − clock_info.audio_dto_module,\ | |
| 1184 | − clock_info.audio_dto_phase); | |
| 1185 | − | |
| 1186 | − /* On TN/SI, Program DTO source select and DTO select before | |
| 1187 | − programming DTO modulo and DTO phase. These bits must be | |
| 1188 | − programmed first, otherwise there will be no HDMI audio at boot | |
| 1189 | − up. This is a HW sequence change (different from old ASICs). | |
| 1190 | − Caution when changing this programming sequence. | |
| 1191 | − | |
| 1192 | − HDMI enabled, using DTO0 | |
| 1193 | − program master CRTC for DTO0 */ | |
| 1194 | − src_sel = pll_info->dto_source - DTO_SOURCE_ID0; | |
| 1195 | − REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE, | |
| 1196 | − DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel, | |
| 1197 | − DCCG_AUDIO_DTO_SEL, 0); | |
| 1198 | − | |
| 1199 | − /* module */ | |
| 1200 | − REG_UPDATE(DCCG_AUDIO_DTO0_MODULE, | |
| 1201 | − DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module); | |
| 1202 | − | |
| 1203 | − /* phase */ | |
| 1204 | − REG_UPDATE(DCCG_AUDIO_DTO0_PHASE, | |
| 1205 | − DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase); | |
| 1206 | − } else { | |
| 1207 | − /*DTO1 Programming goal: | |
| 1208 | − -generate 24MHz, 128*Fs from 24MHz (DCE6 does not support 512*Fs) | |
| 1209 | − -default is to used DTO1, and switch to DTO0 when an audio | |
| 1210 | − master HDMI port is connected | |
| 1211 | − -use as default for DP | |
| 1212 | − | |
| 1213 | − calculate DTO settings */ | |
| 1214 | − get_azalia_clock_info_dp( | |
| 1215 | − crtc_info->requested_pixel_clock_100Hz, | |
| 1216 | − pll_info, | |
| 1217 | − &clock_info); | |
| 1218 | − | |
| 1219 | − /* Program DTO select before programming DTO modulo and DTO | |
| 1220 | − phase. default to use DTO1 */ | |
| 1221 | − | |
| 1222 | − REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, | |
| 1223 | − DCCG_AUDIO_DTO_SEL, 1); | |
| 1224 | − | |
| 1225 | − /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1) | |
| 1226 | − * Cannot select 512fs for DP | |
| 1227 | − * | |
| 1228 | − * DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask | |
| 1229 | − */ | |
| 1230 | − | |
| 1231 | − /* module */ | |
| 1232 | − REG_UPDATE(DCCG_AUDIO_DTO1_MODULE, | |
| 1233 | − DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module); | |
| 1234 | − | |
| 1235 | − /* phase */ | |
| 1236 | − REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, | |
| 1237 | − DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); | |
| 1238 | − | |
| 1239 | − /* DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask in DCCG_AUDIO_DTO_SOURCE reg */ | |
| 1240 | − | |
| 1241 | − } | |
| 1242 | −} | |
| 1243 | −#endif | |
| 1244 | − | |
| 1245 | 1153 | static bool dce_aud_endpoint_valid(struct audio *audio) |
| 1246 | 1154 | { |
| 1247 | 1155 | uint32_t value; |
| @@ -1303,18 +1211,6 @@ static const struct audio_funcs funcs = { · 55 unmodified lines | ||
| 1303 | 1211 | .destroy = dce_aud_destroy, |
| 1304 | 1212 | }; |
| 1305 | 1213 | |
| 1306 | −#if defined(CONFIG_DRM_AMD_DC_SI) | |
| 1307 | −static const struct audio_funcs dce60_funcs = { | |
| 1308 | − .endpoint_valid = dce_aud_endpoint_valid, | |
| 1309 | − .hw_init = dce_aud_hw_init, | |
| 1310 | − .wall_dto_setup = dce60_aud_wall_dto_setup, | |
| 1311 | − .az_enable = dce_aud_az_enable, | |
| 1312 | − .az_disable = dce_aud_az_disable, | |
| 1313 | − .az_configure = dce_aud_az_configure, | |
| 1314 | − .destroy = dce_aud_destroy, | |
| 1315 | −}; | |
| 1316 | −#endif | |
| 1317 | − | |
| 1318 | 1214 | void dce_aud_destroy(struct audio **audio) |
| 1319 | 1215 | { |
| 1320 | 1216 | struct dce_audio *aud = DCE_AUD(*audio); |
| @@ -1347,30 +1243,3 @@ struct audio *dce_audio_create( · 26 unmodified lines | ||
| 1347 | 1243 | audio->masks = masks; |
| 1348 | 1244 | return &audio->base; |
| 1349 | 1245 | } |
| 1350 | − | |
| 1351 | −#if defined(CONFIG_DRM_AMD_DC_SI) | |
| 1352 | −struct audio *dce60_audio_create( | |
| 1353 | − struct dc_context *ctx, | |
| 1354 | − unsigned int inst, | |
| 1355 | − const struct dce_audio_registers *reg, | |
| 1356 | − const struct dce_audio_shift *shifts, | |
| 1357 | − const struct dce_audio_mask *masks | |
| 1358 | − ) | |
| 1359 | −{ | |
| 1360 | − struct dce_audio *audio = kzalloc_obj(*audio); | |
| 1361 | − | |
| 1362 | − if (audio == NULL) { | |
| 1363 | − ASSERT_CRITICAL(audio); | |
| 1364 | − return NULL; | |
| 1365 | − } | |
| 1366 | − | |
| 1367 | − audio->base.ctx = ctx; | |
| 1368 | − audio->base.inst = inst; | |
| 1369 | − audio->base.funcs = &dce60_funcs; | |
| 1370 | − | |
| 1371 | − audio->regs = reg; | |
| 1372 | − audio->shifts = shifts; | |
| 1373 | − audio->masks = masks; | |
| 1374 | − return &audio->base; | |
| 1375 | −} | |
| 1376 | −#endif | |
| @@ -151,15 +151,6 @@ struct audio *dce_audio_create( · 150 unmodified lines | ||
| 151 | 151 | const struct dce_audio_shift *shifts, |
| 152 | 152 | const struct dce_audio_mask *masks); |
| 153 | 153 | |
| 154 | −#if defined(CONFIG_DRM_AMD_DC_SI) | |
| 155 | −struct audio *dce60_audio_create( | |
| 156 | − struct dc_context *ctx, | |
| 157 | − unsigned int inst, | |
| 158 | − const struct dce_audio_registers *reg, | |
| 159 | − const struct dce_audio_shift *shifts, | |
| 160 | − const struct dce_audio_mask *masks); | |
| 161 | −#endif | |
| 162 | − | |
| 163 | 154 | void dce_aud_destroy(struct audio **audio); |
| 164 | 155 | |
| 165 | 156 | void dce_aud_hw_init(struct audio *audio); |
| @@ -1,966 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Copyright 2012-16 Advanced Micro Devices, Inc. | |
| 3 | − * | |
| 4 | − * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | − * copy of this software and associated documentation files (the "Software"), | |
| 6 | − * to deal in the Software without restriction, including without limitation | |
| 7 | − * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | − * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | − * Software is furnished to do so, subject to the following conditions: | |
| 10 | − * | |
| 11 | − * The above copyright notice and this permission notice shall be included in | |
| 12 | − * all copies or substantial portions of the Software. | |
| 13 | − * | |
| 14 | − * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | − * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | − * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | − * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | − * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | − * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | − * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | − * | |
| 22 | − * Authors: AMD | |
| 23 | − * | |
| 24 | − */ | |
| 25 | − | |
| 26 | −#include <linux/slab.h> | |
| 27 | − | |
| 28 | −#include "dce_clk_mgr.h" | |
| 29 | − | |
| 30 | −#include "reg_helper.h" | |
| 31 | −#include "dmcu.h" | |
| 32 | −#include "core_types.h" | |
| 33 | −#include "dal_asic_id.h" | |
| 34 | − | |
| 35 | −#define TO_DCE_CLK_MGR(clocks)\ | |
| 36 | − container_of(clocks, struct dce_clk_mgr, base) | |
| 37 | − | |
| 38 | −#define REG(reg) \ | |
| 39 | − (clk_mgr_dce->regs->reg) | |
| 40 | − | |
| 41 | −#undef FN | |
| 42 | −#define FN(reg_name, field_name) \ | |
| 43 | − clk_mgr_dce->clk_mgr_shift->field_name, clk_mgr_dce->clk_mgr_mask->field_name | |
| 44 | − | |
| 45 | −#define CTX \ | |
| 46 | − clk_mgr_dce->base.ctx | |
| 47 | −#define DC_LOGGER \ | |
| 48 | − clk_mgr->ctx->logger | |
| 49 | − | |
| 50 | −/* Max clock values for each state indexed by "enum clocks_state": */ | |
| 51 | −static const struct state_dependent_clocks dce80_max_clks_by_state[] = { | |
| 52 | −/* ClocksStateInvalid - should not be used */ | |
| 53 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 54 | −/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ | |
| 55 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 56 | −/* ClocksStateLow */ | |
| 57 | −{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, | |
| 58 | −/* ClocksStateNominal */ | |
| 59 | −{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, | |
| 60 | −/* ClocksStatePerformance */ | |
| 61 | −{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; | |
| 62 | − | |
| 63 | −static const struct state_dependent_clocks dce110_max_clks_by_state[] = { | |
| 64 | −/*ClocksStateInvalid - should not be used*/ | |
| 65 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 66 | −/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ | |
| 67 | −{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, | |
| 68 | −/*ClocksStateLow*/ | |
| 69 | −{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, | |
| 70 | −/*ClocksStateNominal*/ | |
| 71 | −{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, | |
| 72 | −/*ClocksStatePerformance*/ | |
| 73 | −{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; | |
| 74 | − | |
| 75 | −static const struct state_dependent_clocks dce112_max_clks_by_state[] = { | |
| 76 | −/*ClocksStateInvalid - should not be used*/ | |
| 77 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 78 | −/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ | |
| 79 | −{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, | |
| 80 | −/*ClocksStateLow*/ | |
| 81 | −{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, | |
| 82 | −/*ClocksStateNominal*/ | |
| 83 | −{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, | |
| 84 | −/*ClocksStatePerformance*/ | |
| 85 | −{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; | |
| 86 | − | |
| 87 | −static const struct state_dependent_clocks dce120_max_clks_by_state[] = { | |
| 88 | −/*ClocksStateInvalid - should not be used*/ | |
| 89 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 90 | −/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ | |
| 91 | −{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, | |
| 92 | −/*ClocksStateLow*/ | |
| 93 | −{ .display_clk_khz = 460000, .pixel_clk_khz = 400000 }, | |
| 94 | −/*ClocksStateNominal*/ | |
| 95 | −{ .display_clk_khz = 670000, .pixel_clk_khz = 600000 }, | |
| 96 | −/*ClocksStatePerformance*/ | |
| 97 | −{ .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; | |
| 98 | − | |
| 99 | −int dentist_get_divider_from_did(int did) | |
| 100 | −{ | |
| 101 | − if (did < DENTIST_BASE_DID_1) | |
| 102 | − did = DENTIST_BASE_DID_1; | |
| 103 | − if (did > DENTIST_MAX_DID) | |
| 104 | − did = DENTIST_MAX_DID; | |
| 105 | − | |
| 106 | − if (did < DENTIST_BASE_DID_2) { | |
| 107 | − return DENTIST_DIVIDER_RANGE_1_START + DENTIST_DIVIDER_RANGE_1_STEP | |
| 108 | − * (did - DENTIST_BASE_DID_1); | |
| 109 | − } else if (did < DENTIST_BASE_DID_3) { | |
| 110 | − return DENTIST_DIVIDER_RANGE_2_START + DENTIST_DIVIDER_RANGE_2_STEP | |
| 111 | − * (did - DENTIST_BASE_DID_2); | |
| 112 | − } else if (did < DENTIST_BASE_DID_4) { | |
| 113 | − return DENTIST_DIVIDER_RANGE_3_START + DENTIST_DIVIDER_RANGE_3_STEP | |
| 114 | − * (did - DENTIST_BASE_DID_3); | |
| 115 | − } else { | |
| 116 | − return DENTIST_DIVIDER_RANGE_4_START + DENTIST_DIVIDER_RANGE_4_STEP | |
| 117 | − * (did - DENTIST_BASE_DID_4); | |
| 118 | − } | |
| 119 | −} | |
| 120 | − | |
| 121 | −/* SW will adjust DP REF Clock average value for all purposes | |
| 122 | − * (DP DTO / DP Audio DTO and DP GTC) | |
| 123 | − if clock is spread for all cases: | |
| 124 | − -if SS enabled on DP Ref clock and HW de-spreading enabled with SW | |
| 125 | − calculations for DS_INCR/DS_MODULO (this is planned to be default case) | |
| 126 | − -if SS enabled on DP Ref clock and HW de-spreading enabled with HW | |
| 127 | − calculations (not planned to be used, but average clock should still | |
| 128 | − be valid) | |
| 129 | − -if SS enabled on DP Ref clock and HW de-spreading disabled | |
| 130 | − (should not be case with CIK) then SW should program all rates | |
| 131 | − generated according to average value (case as with previous ASICs) | |
| 132 | − */ | |
| 133 | −static int clk_mgr_adjust_dp_ref_freq_for_ss(struct dce_clk_mgr *clk_mgr_dce, int dp_ref_clk_khz) | |
| 134 | −{ | |
| 135 | − if (clk_mgr_dce->ss_on_dprefclk && clk_mgr_dce->dprefclk_ss_divider != 0) { | |
| 136 | − struct fixed31_32 ss_percentage = dc_fixpt_div_int( | |
| 137 | − dc_fixpt_from_fraction(clk_mgr_dce->dprefclk_ss_percentage, | |
| 138 | − clk_mgr_dce->dprefclk_ss_divider), 200); | |
| 139 | − struct fixed31_32 adj_dp_ref_clk_khz; | |
| 140 | − | |
| 141 | − ss_percentage = dc_fixpt_sub(dc_fixpt_one, ss_percentage); | |
| 142 | − adj_dp_ref_clk_khz = dc_fixpt_mul_int(ss_percentage, dp_ref_clk_khz); | |
| 143 | − dp_ref_clk_khz = dc_fixpt_floor(adj_dp_ref_clk_khz); | |
| 144 | − } | |
| 145 | − return dp_ref_clk_khz; | |
| 146 | −} | |
| 147 | − | |
| 148 | −static int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr) | |
| 149 | −{ | |
| 150 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 151 | − int dprefclk_wdivider; | |
| 152 | − int dprefclk_src_sel; | |
| 153 | − int dp_ref_clk_khz = 600000; | |
| 154 | − int target_div; | |
| 155 | − | |
| 156 | − /* ASSERT DP Reference Clock source is from DFS*/ | |
| 157 | − REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); | |
| 158 | − ASSERT(dprefclk_src_sel == 0); | |
| 159 | − | |
| 160 | − /* Read the mmDENTIST_DISPCLK_CNTL to get the currently | |
| 161 | − * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ | |
| 162 | − REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); | |
| 163 | − | |
| 164 | − /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ | |
| 165 | − target_div = dentist_get_divider_from_did(dprefclk_wdivider); | |
| 166 | − | |
| 167 | − /* Calculate the current DFS clock, in kHz.*/ | |
| 168 | − dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR | |
| 169 | − * clk_mgr_dce->dentist_vco_freq_khz) / target_div; | |
| 170 | − | |
| 171 | − return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce, dp_ref_clk_khz); | |
| 172 | −} | |
| 173 | − | |
| 174 | −int dce12_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr) | |
| 175 | −{ | |
| 176 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 177 | − | |
| 178 | − return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce, clk_mgr_dce->dprefclk_khz); | |
| 179 | −} | |
| 180 | − | |
| 181 | −/* unit: in_khz before mode set, get pixel clock from context. ASIC register | |
| 182 | − * may not be programmed yet | |
| 183 | − */ | |
| 184 | −static uint32_t get_max_pixel_clock_for_all_paths(struct dc_state *context) | |
| 185 | −{ | |
| 186 | − uint32_t max_pix_clk = 0; | |
| 187 | − int i; | |
| 188 | − | |
| 189 | − for (i = 0; i < MAX_PIPES; i++) { | |
| 190 | − struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
| 191 | − | |
| 192 | − if (pipe_ctx->stream == NULL) | |
| 193 | − continue; | |
| 194 | − | |
| 195 | − /* do not check under lay */ | |
| 196 | − if (pipe_ctx->top_pipe) | |
| 197 | − continue; | |
| 198 | − | |
| 199 | − if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 > max_pix_clk) | |
| 200 | − max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; | |
| 201 | − | |
| 202 | − /* raise clock state for HBR3/2 if required. Confirmed with HW DCE/DPCS | |
| 203 | − * logic for HBR3 still needs Nominal (0.8V) on VDDC rail | |
| 204 | − */ | |
| 205 | − if (dc_is_dp_signal(pipe_ctx->stream->signal) && | |
| 206 | − pipe_ctx->stream_res.pix_clk_params.requested_sym_clk > max_pix_clk) | |
| 207 | − max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_sym_clk; | |
| 208 | − } | |
| 209 | − | |
| 210 | − return max_pix_clk; | |
| 211 | −} | |
| 212 | − | |
| 213 | −static enum dm_pp_clocks_state dce_get_required_clocks_state( | |
| 214 | − struct clk_mgr *clk_mgr, | |
| 215 | − struct dc_state *context) | |
| 216 | −{ | |
| 217 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 218 | − int i; | |
| 219 | − enum dm_pp_clocks_state low_req_clk; | |
| 220 | − int max_pix_clk = get_max_pixel_clock_for_all_paths(context); | |
| 221 | − | |
| 222 | − /* Iterate from highest supported to lowest valid state, and update | |
| 223 | − * lowest RequiredState with the lowest state that satisfies | |
| 224 | − * all required clocks | |
| 225 | − */ | |
| 226 | − for (i = clk_mgr_dce->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--) | |
| 227 | − if (context->bw_ctx.bw.dce.dispclk_khz > | |
| 228 | − clk_mgr_dce->max_clks_by_state[i].display_clk_khz | |
| 229 | − || max_pix_clk > | |
| 230 | − clk_mgr_dce->max_clks_by_state[i].pixel_clk_khz) | |
| 231 | − break; | |
| 232 | − | |
| 233 | − low_req_clk = i + 1; | |
| 234 | − if (low_req_clk > clk_mgr_dce->max_clks_state) { | |
| 235 | − /* set max clock state for high phyclock, invalid on exceeding display clock */ | |
| 236 | − if (clk_mgr_dce->max_clks_by_state[clk_mgr_dce->max_clks_state].display_clk_khz | |
| 237 | − < context->bw_ctx.bw.dce.dispclk_khz) | |
| 238 | − low_req_clk = DM_PP_CLOCKS_STATE_INVALID; | |
| 239 | − else | |
| 240 | − low_req_clk = clk_mgr_dce->max_clks_state; | |
| 241 | − } | |
| 242 | − | |
| 243 | − return low_req_clk; | |
| 244 | −} | |
| 245 | − | |
| 246 | −static int dce_set_clock( | |
| 247 | − struct clk_mgr *clk_mgr, | |
| 248 | − int requested_clk_khz) | |
| 249 | −{ | |
| 250 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 251 | − struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; | |
| 252 | − struct dc_bios *bp = clk_mgr->ctx->dc_bios; | |
| 253 | − int actual_clock = requested_clk_khz; | |
| 254 | − struct dmcu *dmcu = clk_mgr_dce->base.ctx->dc->res_pool->dmcu; | |
| 255 | − | |
| 256 | − /* Make sure requested clock isn't lower than minimum threshold*/ | |
| 257 | − if (requested_clk_khz > 0) | |
| 258 | − requested_clk_khz = max(requested_clk_khz, | |
| 259 | − clk_mgr_dce->dentist_vco_freq_khz / 64); | |
| 260 | − | |
| 261 | − /* Prepare to program display clock*/ | |
| 262 | − pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10; | |
| 263 | − pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; | |
| 264 | − | |
| 265 | − if (clk_mgr_dce->dfs_bypass_active) | |
| 266 | − pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true; | |
| 267 | − | |
| 268 | − bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); | |
| 269 | − | |
| 270 | − if (clk_mgr_dce->dfs_bypass_active) { | |
| 271 | − /* Cache the fixed display clock*/ | |
| 272 | − clk_mgr_dce->dfs_bypass_disp_clk = | |
| 273 | − pxl_clk_params.dfs_bypass_display_clock; | |
| 274 | − actual_clock = pxl_clk_params.dfs_bypass_display_clock; | |
| 275 | − } | |
| 276 | − | |
| 277 | − /* from power down, we need mark the clock state as ClocksStateNominal | |
| 278 | − * from HWReset, so when resume we will call pplib voltage regulator.*/ | |
| 279 | − if (requested_clk_khz == 0) | |
| 280 | − clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; | |
| 281 | − | |
| 282 | − if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) | |
| 283 | − dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); | |
| 284 | − | |
| 285 | − return actual_clock; | |
| 286 | −} | |
| 287 | − | |
| 288 | −int dce112_set_clock(struct clk_mgr *clk_mgr, int requested_clk_khz) | |
| 289 | −{ | |
| 290 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 291 | − struct bp_set_dce_clock_parameters dce_clk_params; | |
| 292 | − struct dc_bios *bp = clk_mgr->ctx->dc_bios; | |
| 293 | − struct dc *core_dc = clk_mgr->ctx->dc; | |
| 294 | − struct dmcu *dmcu = core_dc->res_pool->dmcu; | |
| 295 | − int actual_clock = requested_clk_khz; | |
| 296 | − /* Prepare to program display clock*/ | |
| 297 | − memset(&dce_clk_params, 0, sizeof(dce_clk_params)); | |
| 298 | − | |
| 299 | − /* Make sure requested clock isn't lower than minimum threshold*/ | |
| 300 | − if (requested_clk_khz > 0) | |
| 301 | − requested_clk_khz = max(requested_clk_khz, | |
| 302 | − clk_mgr_dce->dentist_vco_freq_khz / 62); | |
| 303 | − | |
| 304 | − dce_clk_params.target_clock_frequency = requested_clk_khz; | |
| 305 | − dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; | |
| 306 | − dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; | |
| 307 | − | |
| 308 | − bp->funcs->set_dce_clock(bp, &dce_clk_params); | |
| 309 | − actual_clock = dce_clk_params.target_clock_frequency; | |
| 310 | − | |
| 311 | − /* from power down, we need mark the clock state as ClocksStateNominal | |
| 312 | − * from HWReset, so when resume we will call pplib voltage regulator.*/ | |
| 313 | − if (requested_clk_khz == 0) | |
| 314 | − clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; | |
| 315 | − | |
| 316 | − /*Program DP ref Clock*/ | |
| 317 | − /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ | |
| 318 | − dce_clk_params.target_clock_frequency = 0; | |
| 319 | − dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; | |
| 320 | − | |
| 321 | − if (!((clk_mgr->ctx->asic_id.chip_family == FAMILY_AI) && | |
| 322 | − ASICREV_IS_VEGA20_P(clk_mgr->ctx->asic_id.hw_internal_rev))) | |
| 323 | − dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = | |
| 324 | − (dce_clk_params.pll_id == | |
| 325 | − CLOCK_SOURCE_COMBO_DISPLAY_PLL0); | |
| 326 | − else | |
| 327 | − dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = false; | |
| 328 | − | |
| 329 | − bp->funcs->set_dce_clock(bp, &dce_clk_params); | |
| 330 | − | |
| 331 | − if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { | |
| 332 | − if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { | |
| 333 | − if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock) | |
| 334 | − dmcu->funcs->set_psr_wait_loop(dmcu, | |
| 335 | − actual_clock / 1000 / 7); | |
| 336 | − } | |
| 337 | − } | |
| 338 | − | |
| 339 | − clk_mgr_dce->dfs_bypass_disp_clk = actual_clock; | |
| 340 | − return actual_clock; | |
| 341 | −} | |
| 342 | − | |
| 343 | −static void dce_clock_read_integrated_info(struct dce_clk_mgr *clk_mgr_dce) | |
| 344 | −{ | |
| 345 | − struct dc_debug_options *debug = &clk_mgr_dce->base.ctx->dc->debug; | |
| 346 | − struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; | |
| 347 | − struct integrated_info info = { { { 0 } } }; | |
| 348 | − struct dc_firmware_info fw_info = { { 0 } }; | |
| 349 | − int i; | |
| 350 | − | |
| 351 | − if (bp->integrated_info) | |
| 352 | − info = *bp->integrated_info; | |
| 353 | − | |
| 354 | − clk_mgr_dce->dentist_vco_freq_khz = info.dentist_vco_freq; | |
| 355 | − if (clk_mgr_dce->dentist_vco_freq_khz == 0) { | |
| 356 | − bp->funcs->get_firmware_info(bp, &fw_info); | |
| 357 | − clk_mgr_dce->dentist_vco_freq_khz = | |
| 358 | − fw_info.smu_gpu_pll_output_freq; | |
| 359 | − if (clk_mgr_dce->dentist_vco_freq_khz == 0) | |
| 360 | − clk_mgr_dce->dentist_vco_freq_khz = 3600000; | |
| 361 | − } | |
| 362 | − | |
| 363 | − /*update the maximum display clock for each power state*/ | |
| 364 | − for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { | |
| 365 | − enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; | |
| 366 | − | |
| 367 | − switch (i) { | |
| 368 | − case 0: | |
| 369 | − clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; | |
| 370 | − break; | |
| 371 | − | |
| 372 | − case 1: | |
| 373 | − clk_state = DM_PP_CLOCKS_STATE_LOW; | |
| 374 | − break; | |
| 375 | − | |
| 376 | − case 2: | |
| 377 | − clk_state = DM_PP_CLOCKS_STATE_NOMINAL; | |
| 378 | − break; | |
| 379 | − | |
| 380 | − case 3: | |
| 381 | − clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; | |
| 382 | − break; | |
| 383 | − | |
| 384 | − default: | |
| 385 | − clk_state = DM_PP_CLOCKS_STATE_INVALID; | |
| 386 | − break; | |
| 387 | − } | |
| 388 | − | |
| 389 | − /*Do not allow bad VBIOS/SBIOS to override with invalid values, | |
| 390 | − * check for > 100MHz*/ | |
| 391 | − if (info.disp_clk_voltage[i].max_supported_clk >= 100000) | |
| 392 | − clk_mgr_dce->max_clks_by_state[clk_state].display_clk_khz = | |
| 393 | − info.disp_clk_voltage[i].max_supported_clk; | |
| 394 | − } | |
| 395 | − | |
| 396 | − if (!debug->disable_dfs_bypass && bp->integrated_info) | |
| 397 | − if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) | |
| 398 | − clk_mgr_dce->dfs_bypass_enabled = true; | |
| 399 | −} | |
| 400 | − | |
| 401 | −void dce_clock_read_ss_info(struct dce_clk_mgr *clk_mgr_dce) | |
| 402 | −{ | |
| 403 | − struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; | |
| 404 | − int ss_info_num = bp->funcs->get_ss_entry_number( | |
| 405 | − bp, AS_SIGNAL_TYPE_GPU_PLL); | |
| 406 | − | |
| 407 | − if (ss_info_num) { | |
| 408 | − struct spread_spectrum_info info = { { 0 } }; | |
| 409 | − enum bp_result result = bp->funcs->get_spread_spectrum_info( | |
| 410 | − bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info); | |
| 411 | − | |
| 412 | − /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS | |
| 413 | − * even if SS not enabled and in that case | |
| 414 | − * SSInfo.spreadSpectrumPercentage !=0 would be sign | |
| 415 | − * that SS is enabled | |
| 416 | − */ | |
| 417 | − if (result == BP_RESULT_OK && | |
| 418 | − info.spread_spectrum_percentage != 0) { | |
| 419 | − clk_mgr_dce->ss_on_dprefclk = true; | |
| 420 | − clk_mgr_dce->dprefclk_ss_divider = info.spread_percentage_divider; | |
| 421 | − | |
| 422 | − if (info.type.CENTER_MODE == 0) { | |
| 423 | − /* TODO: Currently for DP Reference clock we | |
| 424 | − * need only SS percentage for | |
| 425 | − * downspread */ | |
| 426 | − clk_mgr_dce->dprefclk_ss_percentage = | |
| 427 | − info.spread_spectrum_percentage; | |
| 428 | − } | |
| 429 | − | |
| 430 | − return; | |
| 431 | − } | |
| 432 | − | |
| 433 | − result = bp->funcs->get_spread_spectrum_info( | |
| 434 | − bp, AS_SIGNAL_TYPE_DISPLAY_PORT, 0, &info); | |
| 435 | − | |
| 436 | − /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS | |
| 437 | − * even if SS not enabled and in that case | |
| 438 | − * SSInfo.spreadSpectrumPercentage !=0 would be sign | |
| 439 | − * that SS is enabled | |
| 440 | − */ | |
| 441 | − if (result == BP_RESULT_OK && | |
| 442 | − info.spread_spectrum_percentage != 0) { | |
| 443 | − clk_mgr_dce->ss_on_dprefclk = true; | |
| 444 | − clk_mgr_dce->dprefclk_ss_divider = info.spread_percentage_divider; | |
| 445 | − | |
| 446 | − if (info.type.CENTER_MODE == 0) { | |
| 447 | − /* Currently for DP Reference clock we | |
| 448 | − * need only SS percentage for | |
| 449 | − * downspread */ | |
| 450 | − clk_mgr_dce->dprefclk_ss_percentage = | |
| 451 | − info.spread_spectrum_percentage; | |
| 452 | − } | |
| 453 | − if (clk_mgr_dce->base.ctx->dc->debug.ignore_dpref_ss) | |
| 454 | − clk_mgr_dce->dprefclk_ss_percentage = 0; | |
| 455 | − } | |
| 456 | − } | |
| 457 | −} | |
| 458 | − | |
| 459 | −/** | |
| 460 | − * dce121_clock_patch_xgmi_ss_info() - Save XGMI spread spectrum info | |
| 461 | − * @clk_mgr: clock manager base structure | |
| 462 | − * | |
| 463 | − * Reads from VBIOS the XGMI spread spectrum info and saves it within | |
| 464 | − * the dce clock manager. This operation will overwrite the existing dprefclk | |
| 465 | − * SS values if the vBIOS query succeeds. Otherwise, it does nothing. It also | |
| 466 | − * sets the ->xgmi_enabled flag. | |
| 467 | − */ | |
| 468 | −void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr) | |
| 469 | −{ | |
| 470 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 471 | − enum bp_result result; | |
| 472 | − struct spread_spectrum_info info = { { 0 } }; | |
| 473 | − struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; | |
| 474 | − | |
| 475 | − clk_mgr_dce->xgmi_enabled = false; | |
| 476 | − | |
| 477 | − result = bp->funcs->get_spread_spectrum_info(bp, AS_SIGNAL_TYPE_XGMI, | |
| 478 | − 0, &info); | |
| 479 | − if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) { | |
| 480 | − clk_mgr_dce->xgmi_enabled = true; | |
| 481 | − clk_mgr_dce->ss_on_dprefclk = true; | |
| 482 | − clk_mgr_dce->dprefclk_ss_divider = | |
| 483 | − info.spread_percentage_divider; | |
| 484 | − | |
| 485 | − if (info.type.CENTER_MODE == 0) { | |
| 486 | − /* Currently for DP Reference clock we | |
| 487 | − * need only SS percentage for | |
| 488 | − * downspread */ | |
| 489 | − clk_mgr_dce->dprefclk_ss_percentage = | |
| 490 | − info.spread_spectrum_percentage; | |
| 491 | − } | |
| 492 | − } | |
| 493 | −} | |
| 494 | − | |
| 495 | −void dce110_fill_display_configs( | |
| 496 | − const struct dc_state *context, | |
| 497 | − struct dm_pp_display_configuration *pp_display_cfg) | |
| 498 | −{ | |
| 499 | − int j; | |
| 500 | − int num_cfgs = 0; | |
| 501 | − | |
| 502 | − for (j = 0; j < context->stream_count; j++) { | |
| 503 | − int k; | |
| 504 | − | |
| 505 | − const struct dc_stream_state *stream = context->streams[j]; | |
| 506 | − struct dm_pp_single_disp_config *cfg = | |
| 507 | − &pp_display_cfg->disp_configs[num_cfgs]; | |
| 508 | − const struct pipe_ctx *pipe_ctx = NULL; | |
| 509 | − | |
| 510 | − for (k = 0; k < MAX_PIPES; k++) | |
| 511 | − if (stream == context->res_ctx.pipe_ctx[k].stream) { | |
| 512 | − pipe_ctx = &context->res_ctx.pipe_ctx[k]; | |
| 513 | − break; | |
| 514 | − } | |
| 515 | − | |
| 516 | − ASSERT(pipe_ctx != NULL); | |
| 517 | − | |
| 518 | − /* only notify active stream */ | |
| 519 | − if (stream->dpms_off) | |
| 520 | − continue; | |
| 521 | − | |
| 522 | − num_cfgs++; | |
| 523 | − cfg->signal = pipe_ctx->stream->signal; | |
| 524 | − cfg->pipe_idx = pipe_ctx->stream_res.tg->inst; | |
| 525 | − cfg->src_height = stream->src.height; | |
| 526 | − cfg->src_width = stream->src.width; | |
| 527 | − cfg->ddi_channel_mapping = | |
| 528 | − stream->link->ddi_channel_mapping.raw; | |
| 529 | − cfg->transmitter = | |
| 530 | − stream->link->link_enc->transmitter; | |
| 531 | − cfg->link_settings.lane_count = | |
| 532 | − stream->link->cur_link_settings.lane_count; | |
| 533 | − cfg->link_settings.link_rate = | |
| 534 | − stream->link->cur_link_settings.link_rate; | |
| 535 | − cfg->link_settings.link_spread = | |
| 536 | − stream->link->cur_link_settings.link_spread; | |
| 537 | − cfg->sym_clock = stream->phy_pix_clk; | |
| 538 | − /* Round v_refresh*/ | |
| 539 | − cfg->v_refresh = stream->timing.pix_clk_100hz * 100; | |
| 540 | − cfg->v_refresh /= stream->timing.h_total; | |
| 541 | − cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) | |
| 542 | − / stream->timing.v_total; | |
| 543 | − } | |
| 544 | − | |
| 545 | − pp_display_cfg->display_count = num_cfgs; | |
| 546 | −} | |
| 547 | − | |
| 548 | −static uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) | |
| 549 | −{ | |
| 550 | − uint8_t j; | |
| 551 | − uint32_t min_vertical_blank_time = -1; | |
| 552 | − | |
| 553 | − for (j = 0; j < context->stream_count; j++) { | |
| 554 | − struct dc_stream_state *stream = context->streams[j]; | |
| 555 | − uint32_t vertical_blank_in_pixels = 0; | |
| 556 | − uint32_t vertical_blank_time = 0; | |
| 557 | − | |
| 558 | − vertical_blank_in_pixels = stream->timing.h_total * | |
| 559 | − (stream->timing.v_total | |
| 560 | − - stream->timing.v_addressable); | |
| 561 | − | |
| 562 | − vertical_blank_time = vertical_blank_in_pixels | |
| 563 | − * 10000 / stream->timing.pix_clk_100hz; | |
| 564 | − | |
| 565 | − if (min_vertical_blank_time > vertical_blank_time) | |
| 566 | − min_vertical_blank_time = vertical_blank_time; | |
| 567 | − } | |
| 568 | − | |
| 569 | − return min_vertical_blank_time; | |
| 570 | −} | |
| 571 | − | |
| 572 | −static int determine_sclk_from_bounding_box( | |
| 573 | − const struct dc *dc, | |
| 574 | − int required_sclk) | |
| 575 | −{ | |
| 576 | − int i; | |
| 577 | − | |
| 578 | − /* | |
| 579 | − * Some asics do not give us sclk levels, so we just report the actual | |
| 580 | − * required sclk | |
| 581 | − */ | |
| 582 | − if (dc->sclk_lvls.num_levels == 0) | |
| 583 | − return required_sclk; | |
| 584 | − | |
| 585 | − for (i = 0; i < dc->sclk_lvls.num_levels; i++) { | |
| 586 | − if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) | |
| 587 | − return dc->sclk_lvls.clocks_in_khz[i]; | |
| 588 | − } | |
| 589 | − /* | |
| 590 | − * even maximum level could not satisfy requirement, this | |
| 591 | − * is unexpected at this stage, should have been caught at | |
| 592 | − * validation time | |
| 593 | − */ | |
| 594 | − ASSERT(0); | |
| 595 | − return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; | |
| 596 | −} | |
| 597 | − | |
| 598 | −static void dce_pplib_apply_display_requirements( | |
| 599 | − struct dc *dc, | |
| 600 | − struct dc_state *context) | |
| 601 | −{ | |
| 602 | − struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; | |
| 603 | − | |
| 604 | − pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); | |
| 605 | − | |
| 606 | − dce110_fill_display_configs(context, pp_display_cfg); | |
| 607 | − | |
| 608 | − if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) | |
| 609 | − dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); | |
| 610 | −} | |
| 611 | − | |
| 612 | −static void dce11_pplib_apply_display_requirements( | |
| 613 | − struct dc *dc, | |
| 614 | − struct dc_state *context) | |
| 615 | −{ | |
| 616 | − struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; | |
| 617 | − | |
| 618 | − pp_display_cfg->all_displays_in_sync = | |
| 619 | − context->bw_ctx.bw.dce.all_displays_in_sync; | |
| 620 | − pp_display_cfg->nb_pstate_switch_disable = | |
| 621 | − context->bw_ctx.bw.dce.nbp_state_change_enable == false; | |
| 622 | − pp_display_cfg->cpu_cc6_disable = | |
| 623 | − context->bw_ctx.bw.dce.cpuc_state_change_enable == false; | |
| 624 | − pp_display_cfg->cpu_pstate_disable = | |
| 625 | − context->bw_ctx.bw.dce.cpup_state_change_enable == false; | |
| 626 | − pp_display_cfg->cpu_pstate_separation_time = | |
| 627 | − context->bw_ctx.bw.dce.blackout_recovery_time_us; | |
| 628 | − | |
| 629 | − pp_display_cfg->min_memory_clock_khz = context->bw_ctx.bw.dce.yclk_khz | |
| 630 | − / MEMORY_TYPE_MULTIPLIER_CZ; | |
| 631 | − | |
| 632 | − pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( | |
| 633 | − dc, | |
| 634 | − context->bw_ctx.bw.dce.sclk_khz); | |
| 635 | − | |
| 636 | − /* | |
| 637 | − * As workaround for >4x4K lightup set dcfclock to min_engine_clock value. | |
| 638 | − * This is not required for less than 5 displays, | |
| 639 | − * thus don't request decfclk in dc to avoid impact | |
| 640 | − * on power saving. | |
| 641 | − * | |
| 642 | − */ | |
| 643 | − pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4) ? | |
| 644 | − pp_display_cfg->min_engine_clock_khz : 0; | |
| 645 | − | |
| 646 | − pp_display_cfg->min_engine_clock_deep_sleep_khz | |
| 647 | − = context->bw_ctx.bw.dce.sclk_deep_sleep_khz; | |
| 648 | − | |
| 649 | − pp_display_cfg->avail_mclk_switch_time_us = | |
| 650 | − dce110_get_min_vblank_time_us(context); | |
| 651 | − /* TODO: dce11.2*/ | |
| 652 | − pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; | |
| 653 | − | |
| 654 | − pp_display_cfg->disp_clk_khz = dc->res_pool->clk_mgr->clks.dispclk_khz; | |
| 655 | − | |
| 656 | − dce110_fill_display_configs(context, pp_display_cfg); | |
| 657 | − | |
| 658 | − /* TODO: is this still applicable?*/ | |
| 659 | − if (pp_display_cfg->display_count == 1) { | |
| 660 | − const struct dc_crtc_timing *timing = | |
| 661 | − &context->streams[0]->timing; | |
| 662 | − | |
| 663 | − pp_display_cfg->crtc_index = | |
| 664 | − pp_display_cfg->disp_configs[0].pipe_idx; | |
| 665 | − pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; | |
| 666 | − } | |
| 667 | − | |
| 668 | − if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) | |
| 669 | − dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); | |
| 670 | −} | |
| 671 | − | |
| 672 | −static void dce_update_clocks(struct clk_mgr *clk_mgr, | |
| 673 | − struct dc_state *context, | |
| 674 | − bool safe_to_lower) | |
| 675 | −{ | |
| 676 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 677 | − struct dm_pp_power_level_change_request level_change_req; | |
| 678 | − int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; | |
| 679 | − | |
| 680 | − /*TODO: W/A for dal3 linux, investigate why this works */ | |
| 681 | − if (!clk_mgr_dce->dfs_bypass_active) | |
| 682 | − patched_disp_clk = patched_disp_clk * 115 / 100; | |
| 683 | − | |
| 684 | − level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); | |
| 685 | − /* get max clock state from PPLIB */ | |
| 686 | − if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) | |
| 687 | − || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { | |
| 688 | − if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req)) | |
| 689 | − clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; | |
| 690 | − } | |
| 691 | − | |
| 692 | − if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { | |
| 693 | − patched_disp_clk = dce_set_clock(clk_mgr, patched_disp_clk); | |
| 694 | − clk_mgr->clks.dispclk_khz = patched_disp_clk; | |
| 695 | − } | |
| 696 | − dce_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); | |
| 697 | −} | |
| 698 | − | |
| 699 | −static void dce11_update_clocks(struct clk_mgr *clk_mgr, | |
| 700 | − struct dc_state *context, | |
| 701 | − bool safe_to_lower) | |
| 702 | −{ | |
| 703 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 704 | − struct dm_pp_power_level_change_request level_change_req; | |
| 705 | − int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; | |
| 706 | − | |
| 707 | − /*TODO: W/A for dal3 linux, investigate why this works */ | |
| 708 | − if (!clk_mgr_dce->dfs_bypass_active) | |
| 709 | − patched_disp_clk = patched_disp_clk * 115 / 100; | |
| 710 | − | |
| 711 | − level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); | |
| 712 | − /* get max clock state from PPLIB */ | |
| 713 | − if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) | |
| 714 | − || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { | |
| 715 | − if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req)) | |
| 716 | − clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; | |
| 717 | − } | |
| 718 | − | |
| 719 | − if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { | |
| 720 | − context->bw_ctx.bw.dce.dispclk_khz = dce_set_clock(clk_mgr, patched_disp_clk); | |
| 721 | − clk_mgr->clks.dispclk_khz = patched_disp_clk; | |
| 722 | − } | |
| 723 | − dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); | |
| 724 | −} | |
| 725 | − | |
| 726 | −static void dce112_update_clocks(struct clk_mgr *clk_mgr, | |
| 727 | − struct dc_state *context, | |
| 728 | − bool safe_to_lower) | |
| 729 | −{ | |
| 730 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 731 | − struct dm_pp_power_level_change_request level_change_req; | |
| 732 | − int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; | |
| 733 | − | |
| 734 | − /*TODO: W/A for dal3 linux, investigate why this works */ | |
| 735 | − if (!clk_mgr_dce->dfs_bypass_active) | |
| 736 | − patched_disp_clk = patched_disp_clk * 115 / 100; | |
| 737 | − | |
| 738 | − level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); | |
| 739 | − /* get max clock state from PPLIB */ | |
| 740 | − if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) | |
| 741 | − || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { | |
| 742 | − if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req)) | |
| 743 | − clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; | |
| 744 | − } | |
| 745 | − | |
| 746 | − if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { | |
| 747 | − patched_disp_clk = dce112_set_clock(clk_mgr, patched_disp_clk); | |
| 748 | − clk_mgr->clks.dispclk_khz = patched_disp_clk; | |
| 749 | − } | |
| 750 | − dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); | |
| 751 | −} | |
| 752 | − | |
| 753 | −static void dce12_update_clocks(struct clk_mgr *clk_mgr, | |
| 754 | − struct dc_state *context, | |
| 755 | − bool safe_to_lower) | |
| 756 | −{ | |
| 757 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); | |
| 758 | − struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; | |
| 759 | − int max_pix_clk = get_max_pixel_clock_for_all_paths(context); | |
| 760 | − int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; | |
| 761 | − | |
| 762 | − /*TODO: W/A for dal3 linux, investigate why this works */ | |
| 763 | − if (!clk_mgr_dce->dfs_bypass_active) | |
| 764 | − patched_disp_clk = patched_disp_clk * 115 / 100; | |
| 765 | − | |
| 766 | − if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { | |
| 767 | − clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK; | |
| 768 | − /* | |
| 769 | − * When xGMI is enabled, the display clk needs to be adjusted | |
| 770 | − * with the WAFL link's SS percentage. | |
| 771 | − */ | |
| 772 | − if (clk_mgr_dce->xgmi_enabled) | |
| 773 | − patched_disp_clk = clk_mgr_adjust_dp_ref_freq_for_ss( | |
| 774 | − clk_mgr_dce, patched_disp_clk); | |
| 775 | − clock_voltage_req.clocks_in_khz = patched_disp_clk; | |
| 776 | − clk_mgr->clks.dispclk_khz = dce112_set_clock(clk_mgr, patched_disp_clk); | |
| 777 | − | |
| 778 | − dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req); | |
| 779 | − } | |
| 780 | − | |
| 781 | − if (should_set_clock(safe_to_lower, max_pix_clk, clk_mgr->clks.phyclk_khz)) { | |
| 782 | − clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAYPHYCLK; | |
| 783 | − clock_voltage_req.clocks_in_khz = max_pix_clk; | |
| 784 | − clk_mgr->clks.phyclk_khz = max_pix_clk; | |
| 785 | − | |
| 786 | − dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req); | |
| 787 | − } | |
| 788 | − dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); | |
| 789 | −} | |
| 790 | − | |
| 791 | −static const struct clk_mgr_funcs dce120_funcs = { | |
| 792 | − .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, | |
| 793 | − .update_clocks = dce12_update_clocks | |
| 794 | −}; | |
| 795 | − | |
| 796 | −static const struct clk_mgr_funcs dce112_funcs = { | |
| 797 | − .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz, | |
| 798 | − .update_clocks = dce112_update_clocks | |
| 799 | −}; | |
| 800 | − | |
| 801 | −static const struct clk_mgr_funcs dce110_funcs = { | |
| 802 | − .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz, | |
| 803 | − .update_clocks = dce11_update_clocks, | |
| 804 | −}; | |
| 805 | − | |
| 806 | −static const struct clk_mgr_funcs dce_funcs = { | |
| 807 | − .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz, | |
| 808 | − .update_clocks = dce_update_clocks | |
| 809 | −}; | |
| 810 | − | |
| 811 | −static void dce_clk_mgr_construct( | |
| 812 | − struct dce_clk_mgr *clk_mgr_dce, | |
| 813 | − struct dc_context *ctx, | |
| 814 | − const struct clk_mgr_registers *regs, | |
| 815 | − const struct clk_mgr_shift *clk_shift, | |
| 816 | − const struct clk_mgr_mask *clk_mask) | |
| 817 | −{ | |
| 818 | − struct clk_mgr *base = &clk_mgr_dce->base; | |
| 819 | − struct dm_pp_static_clock_info static_clk_info = {0}; | |
| 820 | − | |
| 821 | − base->ctx = ctx; | |
| 822 | − base->funcs = &dce_funcs; | |
| 823 | − | |
| 824 | − clk_mgr_dce->regs = regs; | |
| 825 | − clk_mgr_dce->clk_mgr_shift = clk_shift; | |
| 826 | − clk_mgr_dce->clk_mgr_mask = clk_mask; | |
| 827 | − | |
| 828 | − clk_mgr_dce->dfs_bypass_disp_clk = 0; | |
| 829 | − | |
| 830 | − clk_mgr_dce->dprefclk_ss_percentage = 0; | |
| 831 | − clk_mgr_dce->dprefclk_ss_divider = 1000; | |
| 832 | − clk_mgr_dce->ss_on_dprefclk = false; | |
| 833 | − | |
| 834 | − | |
| 835 | − if (dm_pp_get_static_clocks(ctx, &static_clk_info)) | |
| 836 | − clk_mgr_dce->max_clks_state = static_clk_info.max_clocks_state; | |
| 837 | − else | |
| 838 | − clk_mgr_dce->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; | |
| 839 | − clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; | |
| 840 | − | |
| 841 | − dce_clock_read_integrated_info(clk_mgr_dce); | |
| 842 | − dce_clock_read_ss_info(clk_mgr_dce); | |
| 843 | −} | |
| 844 | − | |
| 845 | −struct clk_mgr *dce_clk_mgr_create( | |
| 846 | − struct dc_context *ctx, | |
| 847 | − const struct clk_mgr_registers *regs, | |
| 848 | − const struct clk_mgr_shift *clk_shift, | |
| 849 | − const struct clk_mgr_mask *clk_mask) | |
| 850 | −{ | |
| 851 | − struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); | |
| 852 | − | |
| 853 | − if (clk_mgr_dce == NULL) { | |
| 854 | − BREAK_TO_DEBUGGER(); | |
| 855 | − return NULL; | |
| 856 | − } | |
| 857 | − | |
| 858 | − memcpy(clk_mgr_dce->max_clks_by_state, | |
| 859 | − dce80_max_clks_by_state, | |
| 860 | − sizeof(dce80_max_clks_by_state)); | |
| 861 | − | |
| 862 | − dce_clk_mgr_construct( | |
| 863 | − clk_mgr_dce, ctx, regs, clk_shift, clk_mask); | |
| 864 | − | |
| 865 | − return &clk_mgr_dce->base; | |
| 866 | −} | |
| 867 | − | |
| 868 | −struct clk_mgr *dce110_clk_mgr_create( | |
| 869 | − struct dc_context *ctx, | |
| 870 | − const struct clk_mgr_registers *regs, | |
| 871 | − const struct clk_mgr_shift *clk_shift, | |
| 872 | − const struct clk_mgr_mask *clk_mask) | |
| 873 | −{ | |
| 874 | − struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); | |
| 875 | − | |
| 876 | − if (clk_mgr_dce == NULL) { | |
| 877 | − BREAK_TO_DEBUGGER(); | |
| 878 | − return NULL; | |
| 879 | − } | |
| 880 | − | |
| 881 | − memcpy(clk_mgr_dce->max_clks_by_state, | |
| 882 | − dce110_max_clks_by_state, | |
| 883 | − sizeof(dce110_max_clks_by_state)); | |
| 884 | − | |
| 885 | − dce_clk_mgr_construct( | |
| 886 | − clk_mgr_dce, ctx, regs, clk_shift, clk_mask); | |
| 887 | − | |
| 888 | − clk_mgr_dce->base.funcs = &dce110_funcs; | |
| 889 | − | |
| 890 | − return &clk_mgr_dce->base; | |
| 891 | −} | |
| 892 | − | |
| 893 | −struct clk_mgr *dce112_clk_mgr_create( | |
| 894 | − struct dc_context *ctx, | |
| 895 | − const struct clk_mgr_registers *regs, | |
| 896 | − const struct clk_mgr_shift *clk_shift, | |
| 897 | − const struct clk_mgr_mask *clk_mask) | |
| 898 | −{ | |
| 899 | − struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); | |
| 900 | − | |
| 901 | − if (clk_mgr_dce == NULL) { | |
| 902 | − BREAK_TO_DEBUGGER(); | |
| 903 | − return NULL; | |
| 904 | − } | |
| 905 | − | |
| 906 | − memcpy(clk_mgr_dce->max_clks_by_state, | |
| 907 | − dce112_max_clks_by_state, | |
| 908 | − sizeof(dce112_max_clks_by_state)); | |
| 909 | − | |
| 910 | − dce_clk_mgr_construct( | |
| 911 | − clk_mgr_dce, ctx, regs, clk_shift, clk_mask); | |
| 912 | − | |
| 913 | − clk_mgr_dce->base.funcs = &dce112_funcs; | |
| 914 | − | |
| 915 | − return &clk_mgr_dce->base; | |
| 916 | −} | |
| 917 | − | |
| 918 | −struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx) | |
| 919 | −{ | |
| 920 | − struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); | |
| 921 | − | |
| 922 | − if (clk_mgr_dce == NULL) { | |
| 923 | − BREAK_TO_DEBUGGER(); | |
| 924 | − return NULL; | |
| 925 | − } | |
| 926 | − | |
| 927 | − memcpy(clk_mgr_dce->max_clks_by_state, | |
| 928 | − dce120_max_clks_by_state, | |
| 929 | − sizeof(dce120_max_clks_by_state)); | |
| 930 | − | |
| 931 | − dce_clk_mgr_construct( | |
| 932 | − clk_mgr_dce, ctx, NULL, NULL, NULL); | |
| 933 | − | |
| 934 | − clk_mgr_dce->dprefclk_khz = 600000; | |
| 935 | − clk_mgr_dce->base.funcs = &dce120_funcs; | |
| 936 | − | |
| 937 | − return &clk_mgr_dce->base; | |
| 938 | −} | |
| 939 | − | |
| 940 | −struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx) | |
| 941 | −{ | |
| 942 | − struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); | |
| 943 | − | |
| 944 | − if (clk_mgr_dce == NULL) { | |
| 945 | − BREAK_TO_DEBUGGER(); | |
| 946 | − return NULL; | |
| 947 | − } | |
| 948 | − | |
| 949 | − memcpy(clk_mgr_dce->max_clks_by_state, dce120_max_clks_by_state, | |
| 950 | − sizeof(dce120_max_clks_by_state)); | |
| 951 | − | |
| 952 | − dce_clk_mgr_construct(clk_mgr_dce, ctx, NULL, NULL, NULL); | |
| 953 | − | |
| 954 | − clk_mgr_dce->dprefclk_khz = 625000; | |
| 955 | − clk_mgr_dce->base.funcs = &dce120_funcs; | |
| 956 | − | |
| 957 | − return &clk_mgr_dce->base; | |
| 958 | −} | |
| 959 | − | |
| 960 | −void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr) | |
| 961 | −{ | |
| 962 | − struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(*clk_mgr); | |
| 963 | − | |
| 964 | − kfree(clk_mgr_dce); | |
| 965 | − *clk_mgr = NULL; | |
| 966 | −} | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | # |
| 2 | −# Copyright 2020 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2020-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -123,4 +123,13 @@ DIO_DCN401 = dcn401_dio_link_encoder.o dcn401_dio_stream_encoder.o · 117 unmodified lines | ||
| 123 | 123 | AMD_DAL_DIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/dio/dcn401/,$(DIO_DCN401)) |
| 124 | 124 | |
| 125 | 125 | AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN401) |
| 126 | + | |
| 127 | +############################################################################### | |
| 128 | +# DCN42 | |
| 129 | +############################################################################### | |
| 130 | +DIO_DCN42 = dcn42_dio_link_encoder.o dcn42_dio_stream_encoder.o | |
| 131 | + | |
| 132 | +AMD_DAL_DIO_DCN42 = $(addprefix $(AMDDALPATH)/dc/dio/dcn42/,$(DIO_DCN42)) | |
| 133 | + | |
| 134 | +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN42) | |
| 126 | 135 | endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2012-15 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2012-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -190,6 +190,7 @@ struct dcn10_stream_enc_registers { · 184 unmodified lines | ||
| 190 | 190 | uint32_t DIG_FE_CLK_CNTL; |
| 191 | 191 | uint32_t DIG_FE_EN_CNTL; |
| 192 | 192 | uint32_t STREAM_MAPPER_CONTROL; |
| 193 | + uint32_t DIG_FE_AUDIO_CNTL; | |
| 193 | 194 | }; |
| 194 | 195 | |
| 195 | 196 | |
| @@ -598,6 +599,11 @@ struct dcn10_stream_enc_registers { · 402 unmodified lines | ||
| 598 | 599 | type DP_VID_N_INTERVAL;\ |
| 599 | 600 | type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ |
| 600 | 601 | type DP_STEER_FIFO_ENABLE |
| 602 | + | |
| 603 | +#define SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(type) \ | |
| 604 | + type DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL;\ | |
| 605 | + type APG_CLOCK_ENABLE | |
| 606 | + | |
| 601 | 607 | struct dcn10_stream_encoder_shift { |
| 602 | 608 | SE_REG_FIELD_LIST_DCN1_0(uint8_t); |
| 603 | 609 | uint8_t HDMI_ACP_SEND; |
| @@ -606,6 +612,7 @@ struct dcn10_stream_encoder_shift { · 2 unmodified lines | ||
| 606 | 612 | SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); |
| 607 | 613 | SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); |
| 608 | 614 | SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); |
| 615 | + SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(uint32_t); | |
| 609 | 616 | }; |
| 610 | 617 | |
| 611 | 618 | struct dcn10_stream_encoder_mask { |
| @@ -616,6 +623,7 @@ struct dcn10_stream_encoder_mask { · 4 unmodified lines | ||
| 616 | 623 | SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); |
| 617 | 624 | SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); |
| 618 | 625 | SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); |
| 626 | + SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(uint32_t); | |
| 619 | 627 | }; |
| 620 | 628 | |
| 621 | 629 | struct dcn10_stream_encoder { |
| @@ -0,0 +1,205 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "reg_helper.h" | |
| 6 | + | |
| 7 | +#include "core_types.h" | |
| 8 | +#include "link_encoder.h" | |
| 9 | +#include "dcn35/dcn35_dio_link_encoder.h" | |
| 10 | +#include "dcn42_dio_link_encoder.h" | |
| 11 | + | |
| 12 | +#ifndef MIN | |
| 13 | +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) | |
| 14 | +#endif | |
| 15 | + | |
| 16 | +#define CTX \ | |
| 17 | + enc10->base.ctx | |
| 18 | +#define DC_LOGGER \ | |
| 19 | + enc10->base.ctx->logger | |
| 20 | + | |
| 21 | +#define REG(reg)\ | |
| 22 | + (enc10->link_regs->reg) | |
| 23 | + | |
| 24 | +#undef FN | |
| 25 | +#define FN(reg_name, field_name) \ | |
| 26 | + enc10->link_shift->field_name, enc10->link_mask->field_name | |
| 27 | + | |
| 28 | +#define HPD_REG(reg)\ | |
| 29 | + (enc10->hpd_regs->reg) | |
| 30 | + | |
| 31 | +#define HPD_REG_GET(reg_name, field, val) \ | |
| 32 | + generic_reg_get(CTX, HPD_REG(reg_name), \ | |
| 33 | + FN(reg_name, field), val) | |
| 34 | + | |
| 35 | +#define HPD_REG_SET_N(reg_name, n, initial_val, ...) \ | |
| 36 | + generic_reg_set_ex(CTX, \ | |
| 37 | + HPD_REG(reg_name), \ | |
| 38 | + initial_val, \ | |
| 39 | + n, __VA_ARGS__) | |
| 40 | + | |
| 41 | +#define HPD_REG_SET_2(reg, init_value, f1, v1, f2, v2) \ | |
| 42 | + HPD_REG_SET_N(reg, 2, init_value, \ | |
| 43 | + FN(reg, f1), v1,\ | |
| 44 | + FN(reg, f2), v2) | |
| 45 | + | |
| 46 | +bool dcn42_get_hpd_state(struct link_encoder *enc) | |
| 47 | +{ | |
| 48 | + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); | |
| 49 | + uint32_t state; | |
| 50 | + | |
| 51 | + HPD_REG_GET(DC_HPD_INT_STATUS, DC_HPD_SENSE, &state); | |
| 52 | + | |
| 53 | + return state; | |
| 54 | +} | |
| 55 | + | |
| 56 | +bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms) | |
| 57 | +{ | |
| 58 | + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); | |
| 59 | + | |
| 60 | + HPD_REG_SET_2(DC_HPD_TOGGLE_FILT_CNTL, 0, | |
| 61 | + DC_HPD_CONNECT_INT_DELAY, delay_on_connect_in_ms, | |
| 62 | + DC_HPD_DISCONNECT_INT_DELAY, delay_on_disconnect_in_ms); | |
| 63 | + | |
| 64 | + return true; | |
| 65 | +} | |
| 66 | + | |
| 67 | +static const struct link_encoder_funcs dcn42_link_enc_funcs = { | |
| 68 | + .read_state = link_enc2_read_state, | |
| 69 | + .validate_output_with_stream = | |
| 70 | + dcn30_link_encoder_validate_output_with_stream, | |
| 71 | + .hw_init = dcn35_link_encoder_init, | |
| 72 | + .setup = dcn35_link_encoder_setup, | |
| 73 | + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, | |
| 74 | + .enable_dp_output = dcn35_link_encoder_enable_dp_output, | |
| 75 | + .enable_dp_mst_output = dcn35_link_encoder_enable_dp_mst_output, | |
| 76 | + .disable_output = dcn35_link_encoder_disable_output, | |
| 77 | + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, | |
| 78 | + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, | |
| 79 | + .update_mst_stream_allocation_table = | |
| 80 | + dcn10_link_encoder_update_mst_stream_allocation_table, | |
| 81 | + .psr_program_dp_dphy_fast_training = | |
| 82 | + dcn10_psr_program_dp_dphy_fast_training, | |
| 83 | + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, | |
| 84 | + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, | |
| 85 | + .enable_hpd = dcn10_link_encoder_enable_hpd, | |
| 86 | + .disable_hpd = dcn10_link_encoder_disable_hpd, | |
| 87 | + .is_dig_enabled = dcn35_is_dig_enabled, | |
| 88 | + .destroy = dcn10_link_encoder_destroy, | |
| 89 | + .fec_set_enable = enc2_fec_set_enable, | |
| 90 | + .fec_set_ready = enc2_fec_set_ready, | |
| 91 | + .fec_is_active = enc2_fec_is_active, | |
| 92 | + .get_dig_frontend = dcn10_get_dig_frontend, | |
| 93 | + .get_dig_mode = dcn401_get_dig_mode, | |
| 94 | + .is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode, | |
| 95 | + .get_max_link_cap = dcn32_link_encoder_get_max_link_cap, | |
| 96 | + .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, | |
| 97 | + .enable_dpia_output = dcn35_link_encoder_enable_dpia_output, | |
| 98 | + .disable_dpia_output = dcn35_link_encoder_disable_dpia_output, | |
| 99 | + .get_hpd_state = dcn42_get_hpd_state, | |
| 100 | + .program_hpd_filter = dcn42_program_hpd_filter, | |
| 101 | +}; | |
| 102 | + | |
| 103 | +void dcn42_link_encoder_construct( | |
| 104 | + struct dcn20_link_encoder *enc20, | |
| 105 | + const struct encoder_init_data *init_data, | |
| 106 | + const struct encoder_feature_support *enc_features, | |
| 107 | + const struct dcn10_link_enc_registers *link_regs, | |
| 108 | + const struct dcn10_link_enc_aux_registers *aux_regs, | |
| 109 | + const struct dcn10_link_enc_hpd_registers *hpd_regs, | |
| 110 | + const struct dcn10_link_enc_shift *link_shift, | |
| 111 | + const struct dcn10_link_enc_mask *link_mask) | |
| 112 | +{ | |
| 113 | + struct bp_connector_speed_cap_info bp_cap_info = {0}; | |
| 114 | + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; | |
| 115 | + enum bp_result result = BP_RESULT_OK; | |
| 116 | + struct dcn10_link_encoder *enc10 = &enc20->enc10; | |
| 117 | + | |
| 118 | + enc10->base.funcs = &dcn42_link_enc_funcs; | |
| 119 | + enc10->base.ctx = init_data->ctx; | |
| 120 | + enc10->base.id = init_data->encoder; | |
| 121 | + | |
| 122 | + enc10->base.hpd_source = init_data->hpd_source; | |
| 123 | + enc10->base.connector = init_data->connector; | |
| 124 | + | |
| 125 | + | |
| 126 | + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; | |
| 127 | + | |
| 128 | + enc10->base.features = *enc_features; | |
| 129 | + if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 130 | + enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 131 | + | |
| 132 | + enc10->base.transmitter = init_data->transmitter; | |
| 133 | + | |
| 134 | + /* set the flag to indicate whether driver poll the I2C data pin | |
| 135 | + * while doing the DP sink detect | |
| 136 | + */ | |
| 137 | + | |
| 138 | +/* if (dal_adapter_service_is_feature_supported(as, | |
| 139 | + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) | |
| 140 | + enc10->base.features.flags.bits. | |
| 141 | + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ | |
| 142 | + | |
| 143 | + enc10->base.output_signals = | |
| 144 | + SIGNAL_TYPE_DVI_SINGLE_LINK | | |
| 145 | + SIGNAL_TYPE_DVI_DUAL_LINK | | |
| 146 | + SIGNAL_TYPE_LVDS | | |
| 147 | + SIGNAL_TYPE_DISPLAY_PORT | | |
| 148 | + SIGNAL_TYPE_DISPLAY_PORT_MST | | |
| 149 | + SIGNAL_TYPE_EDP | | |
| 150 | + SIGNAL_TYPE_HDMI_TYPE_A; | |
| 151 | + | |
| 152 | + enc10->link_regs = link_regs; | |
| 153 | + enc10->aux_regs = aux_regs; | |
| 154 | + enc10->hpd_regs = hpd_regs; | |
| 155 | + enc10->link_shift = link_shift; | |
| 156 | + enc10->link_mask = link_mask; | |
| 157 | + | |
| 158 | + switch (enc10->base.transmitter) { | |
| 159 | + case TRANSMITTER_UNIPHY_A: | |
| 160 | + enc10->base.preferred_engine = ENGINE_ID_DIGA; | |
| 161 | + break; | |
| 162 | + case TRANSMITTER_UNIPHY_B: | |
| 163 | + enc10->base.preferred_engine = ENGINE_ID_DIGB; | |
| 164 | + break; | |
| 165 | + case TRANSMITTER_UNIPHY_C: | |
| 166 | + enc10->base.preferred_engine = ENGINE_ID_DIGC; | |
| 167 | + break; | |
| 168 | + case TRANSMITTER_UNIPHY_D: | |
| 169 | + enc10->base.preferred_engine = ENGINE_ID_DIGD; | |
| 170 | + break; | |
| 171 | + case TRANSMITTER_UNIPHY_E: | |
| 172 | + enc10->base.preferred_engine = ENGINE_ID_DIGE; | |
| 173 | + break; | |
| 174 | + default: | |
| 175 | + ASSERT_CRITICAL(false); | |
| 176 | + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; | |
| 177 | + } | |
| 178 | + | |
| 179 | + /* default to one to mirror Windows behavior */ | |
| 180 | + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; | |
| 181 | + | |
| 182 | + if (bp_funcs->get_connector_speed_cap_info) | |
| 183 | + result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, | |
| 184 | + enc10->base.connector, &bp_cap_info); | |
| 185 | + | |
| 186 | + /* Override features with DCE-specific values */ | |
| 187 | + if (result == BP_RESULT_OK) { | |
| 188 | + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = | |
| 189 | + bp_cap_info.DP_HBR2_EN; | |
| 190 | + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = | |
| 191 | + bp_cap_info.DP_HBR3_EN; | |
| 192 | + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; | |
| 193 | + enc10->base.features.flags.bits.IS_DP2_CAPABLE = 1; | |
| 194 | + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; | |
| 195 | + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; | |
| 196 | + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; | |
| 197 | + } else { | |
| 198 | + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", | |
| 199 | + __func__, | |
| 200 | + result); | |
| 201 | + } | |
| 202 | + if (enc10->base.ctx->dc->debug.hdmi20_disable) { | |
| 203 | + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; | |
| 204 | + } | |
| 205 | +} | |
| @@ -0,0 +1,140 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +#ifndef __DC_LINK_ENCODER__DCN42_H__ | |
| 26 | +#define __DC_LINK_ENCODER__DCN42_H__ | |
| 27 | + | |
| 28 | +#include "dcn401/dcn401_dio_link_encoder.h" | |
| 29 | + | |
| 30 | +#define LINK_ENCODER_MASK_SH_LIST_DCN42(mask_sh) \ | |
| 31 | + LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_BE_ENABLE, mask_sh),\ | |
| 32 | + LE_SF(DIG0_DIG_BE_CNTL, DIG_RB_SWITCH_EN, mask_sh),\ | |
| 33 | + LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\ | |
| 34 | + LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\ | |
| 35 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_MODE, mask_sh),\ | |
| 36 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, mask_sh),\ | |
| 37 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SOFT_RESET, mask_sh),\ | |
| 38 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, HDCP_SOFT_RESET, mask_sh),\ | |
| 39 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_CLOCK_ON, mask_sh),\ | |
| 40 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_HDCP_CLOCK_ON, mask_sh),\ | |
| 41 | + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_TMDS_CLOCK_ON, mask_sh),\ | |
| 42 | + LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ | |
| 43 | + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ | |
| 44 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\ | |
| 45 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\ | |
| 46 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\ | |
| 47 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\ | |
| 48 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\ | |
| 49 | + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\ | |
| 50 | + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\ | |
| 51 | + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\ | |
| 52 | + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\ | |
| 53 | + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\ | |
| 54 | + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\ | |
| 55 | + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\ | |
| 56 | + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\ | |
| 57 | + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\ | |
| 58 | + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\ | |
| 59 | + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\ | |
| 60 | + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\ | |
| 61 | + LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\ | |
| 62 | + LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\ | |
| 63 | + LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\ | |
| 64 | + LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\ | |
| 65 | + LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\ | |
| 66 | + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\ | |
| 67 | + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\ | |
| 68 | + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\ | |
| 69 | + LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ | |
| 70 | + LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\ | |
| 71 | + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\ | |
| 72 | + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\ | |
| 73 | + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\ | |
| 74 | + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\ | |
| 75 | + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\ | |
| 76 | + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\ | |
| 77 | + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\ | |
| 78 | + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\ | |
| 79 | + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\ | |
| 80 | + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\ | |
| 81 | + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\ | |
| 82 | + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\ | |
| 83 | + LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\ | |
| 84 | + LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\ | |
| 85 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\ | |
| 86 | + LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh),\ | |
| 87 | + LE_SF(HPD0_DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\ | |
| 88 | + LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\ | |
| 89 | + LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh),\ | |
| 90 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ | |
| 91 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ | |
| 92 | + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ | |
| 93 | + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ | |
| 94 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ | |
| 95 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ | |
| 96 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ | |
| 97 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ | |
| 98 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ | |
| 99 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ | |
| 100 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ | |
| 101 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ | |
| 102 | + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ | |
| 103 | + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ | |
| 104 | + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ | |
| 105 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ | |
| 106 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ | |
| 107 | + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\ | |
| 108 | + LE_SF(DIO_CLK_CNTL, DISPCLK_R_GATE_DIS, mask_sh),\ | |
| 109 | + LE_SF(DIO_CLK_CNTL, DISPCLK_G_GATE_DIS, mask_sh),\ | |
| 110 | + LE_SF(DIO_CLK_CNTL, REFCLK_R_GATE_DIS, mask_sh),\ | |
| 111 | + LE_SF(DIO_CLK_CNTL, REFCLK_G_GATE_DIS, mask_sh),\ | |
| 112 | + LE_SF(DIO_CLK_CNTL, SOCCLK_G_GATE_DIS, mask_sh),\ | |
| 113 | + LE_SF(DIO_CLK_CNTL, SYMCLK_FE_R_GATE_DIS, mask_sh),\ | |
| 114 | + LE_SF(DIO_CLK_CNTL, SYMCLK_FE_G_GATE_DIS, mask_sh),\ | |
| 115 | + LE_SF(DIO_CLK_CNTL, SYMCLK_R_GATE_DIS, mask_sh),\ | |
| 116 | + LE_SF(DIO_CLK_CNTL, SYMCLK_G_GATE_DIS, mask_sh),\ | |
| 117 | + LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh),\ | |
| 118 | + LE_SF(DIO_CLK_CNTL, DISPCLK_G_HDCP_GATE_DIS, mask_sh),\ | |
| 119 | + LE_SF(DIO_CLK_CNTL, SYMCLKA_G_HDCP_GATE_DIS, mask_sh),\ | |
| 120 | + LE_SF(DIO_CLK_CNTL, SYMCLKB_G_HDCP_GATE_DIS, mask_sh),\ | |
| 121 | + LE_SF(DIO_CLK_CNTL, SYMCLKC_G_HDCP_GATE_DIS, mask_sh),\ | |
| 122 | + LE_SF(DIO_CLK_CNTL, SYMCLKD_G_HDCP_GATE_DIS, mask_sh),\ | |
| 123 | + LE_SF(DIO_CLK_CNTL, SYMCLKE_G_HDCP_GATE_DIS, mask_sh),\ | |
| 124 | + LE_SF(DIO_CLK_CNTL, SYMCLKF_G_HDCP_GATE_DIS, mask_sh),\ | |
| 125 | + LE_SF(DIO_CLK_CNTL, SYMCLKG_G_HDCP_GATE_DIS, mask_sh) | |
| 126 | + | |
| 127 | +void dcn42_link_encoder_construct( | |
| 128 | + struct dcn20_link_encoder *enc20, | |
| 129 | + const struct encoder_init_data *init_data, | |
| 130 | + const struct encoder_feature_support *enc_features, | |
| 131 | + const struct dcn10_link_enc_registers *link_regs, | |
| 132 | + const struct dcn10_link_enc_aux_registers *aux_regs, | |
| 133 | + const struct dcn10_link_enc_hpd_registers *hpd_regs, | |
| 134 | + const struct dcn10_link_enc_shift *link_shift, | |
| 135 | + const struct dcn10_link_enc_mask *link_mask); | |
| 136 | + | |
| 137 | +bool dcn42_get_hpd_state(struct link_encoder *enc); | |
| 138 | +bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms); | |
| 139 | + | |
| 140 | +#endif /* __DC_LINK_ENCODER__DCN42_H__ */ | |
| @@ -0,0 +1,522 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dc_bios_types.h" | |
| 6 | +#include "dcn30/dcn30_dio_stream_encoder.h" | |
| 7 | +#include "dcn32/dcn32_dio_stream_encoder.h" | |
| 8 | +#include "dcn35/dcn35_dio_stream_encoder.h" | |
| 9 | +#include "dcn401/dcn401_dio_stream_encoder.h" | |
| 10 | +#include "dcn31/dcn31_apg.h" | |
| 11 | + | |
| 12 | +#include "dcn42_dio_stream_encoder.h" | |
| 13 | +#include "reg_helper.h" | |
| 14 | +#include "hw_shared.h" | |
| 15 | +#include "link_service.h" | |
| 16 | +#include "dpcd_defs.h" | |
| 17 | + | |
| 18 | +#define DC_LOGGER \ | |
| 19 | + enc1->base.ctx->logger | |
| 20 | + | |
| 21 | +#define REG(reg)\ | |
| 22 | + (enc1->regs->reg) | |
| 23 | + | |
| 24 | +#undef FN | |
| 25 | +#define FN(reg_name, field_name) \ | |
| 26 | + enc1->se_shift->field_name, enc1->se_mask->field_name | |
| 27 | + | |
| 28 | +#define VBI_LINE_0 0 | |
| 29 | +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 | |
| 30 | + | |
| 31 | +#define CTX \ | |
| 32 | + enc1->base.ctx | |
| 33 | + | |
| 34 | +/* setup stream encoder in hdmi mode */ | |
| 35 | +static void enc42_stream_encoder_hdmi_set_stream_attribute( | |
| 36 | + struct stream_encoder *enc, | |
| 37 | + struct dc_crtc_timing *crtc_timing, | |
| 38 | + int actual_pix_clk_khz, | |
| 39 | + bool enable_audio) | |
| 40 | +{ | |
| 41 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 42 | + | |
| 43 | + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { | |
| 44 | + struct bp_encoder_control cntl = {0}; | |
| 45 | + | |
| 46 | + cntl.action = ENCODER_CONTROL_SETUP; | |
| 47 | + cntl.engine_id = enc1->base.id; | |
| 48 | + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; | |
| 49 | + cntl.enable_dp_audio = enable_audio; | |
| 50 | + cntl.pixel_clock = actual_pix_clk_khz; | |
| 51 | + cntl.lanes_number = LANE_COUNT_FOUR; | |
| 52 | + | |
| 53 | + if (enc1->base.bp->funcs->encoder_control( | |
| 54 | + enc1->base.bp, &cntl) != BP_RESULT_OK) | |
| 55 | + return; | |
| 56 | + | |
| 57 | + } else { | |
| 58 | + | |
| 59 | + //Set pattern for clock channel, default vlue 0x63 does not work | |
| 60 | + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); | |
| 61 | + | |
| 62 | + //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup | |
| 63 | + | |
| 64 | + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg | |
| 65 | + | |
| 66 | + /* DIG_START is removed from the register spec */ | |
| 67 | + } | |
| 68 | + | |
| 69 | + /* Configure pixel encoding */ | |
| 70 | + enc401_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); | |
| 71 | + | |
| 72 | + /* setup HDMI engine */ | |
| 73 | + REG_UPDATE_4(HDMI_CONTROL, | |
| 74 | + HDMI_DEEP_COLOR_ENABLE, 0, | |
| 75 | + HDMI_DATA_SCRAMBLE_EN, 0, | |
| 76 | + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, | |
| 77 | + HDMI_CLOCK_CHANNEL_RATE, 0); | |
| 78 | + | |
| 79 | + /* Configure color depth */ | |
| 80 | + switch (crtc_timing->display_color_depth) { | |
| 81 | + case COLOR_DEPTH_888: | |
| 82 | + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); | |
| 83 | + break; | |
| 84 | + case COLOR_DEPTH_101010: | |
| 85 | + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { | |
| 86 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 87 | + HDMI_DEEP_COLOR_DEPTH, 1, | |
| 88 | + HDMI_DEEP_COLOR_ENABLE, 0); | |
| 89 | + } else { | |
| 90 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 91 | + HDMI_DEEP_COLOR_DEPTH, 1, | |
| 92 | + HDMI_DEEP_COLOR_ENABLE, 1); | |
| 93 | + } | |
| 94 | + break; | |
| 95 | + case COLOR_DEPTH_121212: | |
| 96 | + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { | |
| 97 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 98 | + HDMI_DEEP_COLOR_DEPTH, 2, | |
| 99 | + HDMI_DEEP_COLOR_ENABLE, 0); | |
| 100 | + } else { | |
| 101 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 102 | + HDMI_DEEP_COLOR_DEPTH, 2, | |
| 103 | + HDMI_DEEP_COLOR_ENABLE, 1); | |
| 104 | + } | |
| 105 | + break; | |
| 106 | + case COLOR_DEPTH_161616: | |
| 107 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 108 | + HDMI_DEEP_COLOR_DEPTH, 3, | |
| 109 | + HDMI_DEEP_COLOR_ENABLE, 1); | |
| 110 | + break; | |
| 111 | + default: | |
| 112 | + break; | |
| 113 | + } | |
| 114 | + | |
| 115 | + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { | |
| 116 | + /* enable HDMI data scrambler | |
| 117 | + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M | |
| 118 | + * Clock channel frequency is 1/4 of character rate. | |
| 119 | + */ | |
| 120 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 121 | + HDMI_DATA_SCRAMBLE_EN, 1, | |
| 122 | + HDMI_CLOCK_CHANNEL_RATE, 1); | |
| 123 | + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { | |
| 124 | + | |
| 125 | + /* TODO: New feature for DCE11, still need to implement */ | |
| 126 | + | |
| 127 | + /* enable HDMI data scrambler | |
| 128 | + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE | |
| 129 | + * Clock channel frequency is the same | |
| 130 | + * as character rate | |
| 131 | + */ | |
| 132 | + REG_UPDATE_2(HDMI_CONTROL, | |
| 133 | + HDMI_DATA_SCRAMBLE_EN, 1, | |
| 134 | + HDMI_CLOCK_CHANNEL_RATE, 0); | |
| 135 | + } | |
| 136 | + | |
| 137 | + /* Enable transmission of General Control packet on every frame */ | |
| 138 | + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, | |
| 139 | + HDMI_GC_CONT, 1, | |
| 140 | + HDMI_GC_SEND, 1, | |
| 141 | + HDMI_NULL_SEND, 1); | |
| 142 | + | |
| 143 | + /* Disable Audio Content Protection packet transmission */ | |
| 144 | + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); | |
| 145 | + /* following belongs to audio */ | |
| 146 | + /* Enable Audio InfoFrame packet transmission. */ | |
| 147 | + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); | |
| 148 | + | |
| 149 | + /* Select line number on which to send Audio InfoFrame packets */ | |
| 150 | + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE, | |
| 151 | + VBI_LINE_0 + 2); | |
| 152 | + | |
| 153 | + /* set HDMI GC AVMUTE */ | |
| 154 | + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); | |
| 155 | +} | |
| 156 | + | |
| 157 | +static void enc42_stream_encoder_stop_dp_info_packets( | |
| 158 | + struct stream_encoder *enc) | |
| 159 | +{ | |
| 160 | + /* stop generic packets on DP */ | |
| 161 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 162 | + uint32_t value = 0; | |
| 163 | + | |
| 164 | + REG_SET_9(DP_SEC_CNTL, 0, | |
| 165 | + DP_SEC_GSP0_ENABLE, 0, | |
| 166 | + DP_SEC_GSP1_ENABLE, 0, | |
| 167 | + DP_SEC_GSP2_ENABLE, 0, | |
| 168 | + DP_SEC_GSP3_ENABLE, 0, | |
| 169 | + DP_SEC_GSP4_ENABLE, 0, | |
| 170 | + DP_SEC_GSP5_ENABLE, 0, | |
| 171 | + DP_SEC_GSP6_ENABLE, 0, | |
| 172 | + DP_SEC_GSP7_ENABLE, 0, | |
| 173 | + DP_SEC_STREAM_ENABLE, 0); | |
| 174 | + | |
| 175 | + /* this register shared with audio info frame. | |
| 176 | + * therefore we need to keep master enabled | |
| 177 | + * if at least one of the fields is not 0 | |
| 178 | + */ | |
| 179 | + value = REG_READ(DP_SEC_CNTL); | |
| 180 | + if (value) | |
| 181 | + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); | |
| 182 | +} | |
| 183 | + | |
| 184 | +static void enc42_stream_encoder_update_hdmi_info_packets( | |
| 185 | + struct stream_encoder *enc, | |
| 186 | + const struct encoder_info_frame *info_frame) | |
| 187 | +{ | |
| 188 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 189 | + | |
| 190 | + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); | |
| 191 | + REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, 1); | |
| 192 | + | |
| 193 | + /*Always add mandatory packets first followed by optional ones*/ | |
| 194 | + enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); | |
| 195 | + enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); | |
| 196 | + enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); | |
| 197 | + enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); | |
| 198 | + enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); | |
| 199 | + enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); | |
| 200 | + enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); | |
| 201 | +} | |
| 202 | + | |
| 203 | +static void enc42_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, | |
| 204 | + bool enable, | |
| 205 | + uint8_t *dsc_packed_pps, | |
| 206 | + bool immediate_update) | |
| 207 | +{ | |
| 208 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 209 | + | |
| 210 | + if (enable) { | |
| 211 | + struct dc_info_packet pps_sdp; | |
| 212 | + int i; | |
| 213 | + | |
| 214 | + /* Configure for PPS packet size (128 bytes) */ | |
| 215 | + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); | |
| 216 | + | |
| 217 | + /* Load PPS into infoframe (SDP) registers */ | |
| 218 | + pps_sdp.valid = true; | |
| 219 | + pps_sdp.hb0 = 0; | |
| 220 | + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; | |
| 221 | + pps_sdp.hb2 = 127; | |
| 222 | + pps_sdp.hb3 = 0; | |
| 223 | + | |
| 224 | + for (i = 0; i < 4; i++) { | |
| 225 | + memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); | |
| 226 | + enc1->base.vpg->funcs->update_generic_info_packet( | |
| 227 | + enc1->base.vpg, | |
| 228 | + 11 + i, | |
| 229 | + &pps_sdp, | |
| 230 | + immediate_update); | |
| 231 | + } | |
| 232 | + | |
| 233 | + /* SW should make sure VBID[6] update line number is bigger | |
| 234 | + * than PPS transmit line number | |
| 235 | + */ | |
| 236 | + REG_UPDATE(DP_GSP11_CNTL, | |
| 237 | + DP_SEC_GSP11_LINE_NUM, 2); | |
| 238 | + REG_UPDATE_2(DP_MSA_VBID_MISC, | |
| 239 | + DP_VBID6_LINE_REFERENCE, 0, | |
| 240 | + DP_VBID6_LINE_NUM, 3); | |
| 241 | + | |
| 242 | + /* Send PPS data at the line number specified above. | |
| 243 | + * DP spec requires PPS to be sent only when it changes, however since | |
| 244 | + * decoder has to be able to handle its change on every frame, we're | |
| 245 | + * sending it always (i.e. on every frame) to reduce the chance it'd be | |
| 246 | + * missed by decoder. If it turns out required to send PPS only when it | |
| 247 | + * changes, we can use DP_SEC_GSP11_SEND register. | |
| 248 | + */ | |
| 249 | + REG_UPDATE(DP_GSP11_CNTL, | |
| 250 | + DP_SEC_GSP11_ENABLE, 1); | |
| 251 | + REG_UPDATE(DP_SEC_CNTL, | |
| 252 | + DP_SEC_STREAM_ENABLE, 1); | |
| 253 | + } else { | |
| 254 | + /* Disable Generic Stream Packet 11 (GSP) transmission */ | |
| 255 | + REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); | |
| 256 | + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); | |
| 257 | + } | |
| 258 | +} | |
| 259 | + | |
| 260 | +static void enc42_se_dp_audio_setup( | |
| 261 | + struct stream_encoder *enc, | |
| 262 | + unsigned int az_inst, | |
| 263 | + struct audio_info *info) | |
| 264 | +{ | |
| 265 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 266 | + enc42_se_enable_audio_clock(enc, true); | |
| 267 | + | |
| 268 | + REG_UPDATE(DIG_FE_AUDIO_CNTL, | |
| 269 | + DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); | |
| 270 | + | |
| 271 | + enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); | |
| 272 | +} | |
| 273 | + | |
| 274 | +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 | |
| 275 | +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 | |
| 276 | + | |
| 277 | +static void enc42_se_setup_dp_audio( | |
| 278 | + struct stream_encoder *enc) | |
| 279 | +{ | |
| 280 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 281 | + | |
| 282 | + /* --- DP Audio packet configurations --- */ | |
| 283 | + | |
| 284 | + /* ATP Configuration */ | |
| 285 | + REG_SET(DP_SEC_AUD_N, 0, | |
| 286 | + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); | |
| 287 | + | |
| 288 | + /* Async/auto-calc timestamp mode */ | |
| 289 | + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, | |
| 290 | + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); | |
| 291 | +} | |
| 292 | + | |
| 293 | +static void enc42_se_dp_audio_enable( | |
| 294 | + struct stream_encoder *enc) | |
| 295 | +{ | |
| 296 | + ASSERT (enc->apg); | |
| 297 | + enc42_se_enable_audio_clock(enc, true); | |
| 298 | + /*APG_CONTROL2 for DP*/ | |
| 299 | + enc42_se_setup_dp_audio(enc); | |
| 300 | + /*DP_SEC_CNTL programming*/ | |
| 301 | + enc1_se_enable_dp_audio(enc); | |
| 302 | + /*APG_en*/ | |
| 303 | + enc->apg->funcs->enable_apg(enc->apg); | |
| 304 | + | |
| 305 | +} | |
| 306 | + | |
| 307 | +static void enc42_se_disable_dp_audio( | |
| 308 | + struct stream_encoder *enc) | |
| 309 | +{ | |
| 310 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 311 | + uint32_t value = 0; | |
| 312 | + | |
| 313 | + /* Disable Audio packets */ | |
| 314 | + REG_UPDATE_5(DP_SEC_CNTL, | |
| 315 | + DP_SEC_ASP_ENABLE, 0, | |
| 316 | + DP_SEC_ATP_ENABLE, 0, | |
| 317 | + DP_SEC_AIP_ENABLE, 0, | |
| 318 | + DP_SEC_ACM_ENABLE, 0, | |
| 319 | + DP_SEC_STREAM_ENABLE, 0); | |
| 320 | + | |
| 321 | + /* This register shared with encoder info frame. Therefore we need to | |
| 322 | + * keep master enabled if at least on of the fields is not 0 | |
| 323 | + */ | |
| 324 | + value = REG_READ(DP_SEC_CNTL); | |
| 325 | + if (value != 0) | |
| 326 | + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); | |
| 327 | +} | |
| 328 | + | |
| 329 | +static void enc42_se_dp_audio_disable( | |
| 330 | + struct stream_encoder *enc) | |
| 331 | +{ | |
| 332 | + | |
| 333 | + enc->apg->funcs->disable_apg(enc->apg); | |
| 334 | + enc42_se_disable_dp_audio(enc); | |
| 335 | + enc42_se_enable_audio_clock(enc, false); | |
| 336 | +} | |
| 337 | + | |
| 338 | +static void enc42_se_setup_hdmi_audio( | |
| 339 | + struct stream_encoder *enc, | |
| 340 | + const struct audio_crtc_info *crtc_info) | |
| 341 | +{ | |
| 342 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 343 | + | |
| 344 | + struct audio_clock_info audio_clock_info = {0}; | |
| 345 | + | |
| 346 | + /* HDMI_AUDIO_PACKET_CONTROL */ | |
| 347 | + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, | |
| 348 | + HDMI_AUDIO_DELAY_EN, 1); | |
| 349 | + | |
| 350 | + /* HDMI_ACR_PACKET_CONTROL */ | |
| 351 | + REG_UPDATE_2(HDMI_ACR_PACKET_CONTROL, | |
| 352 | + HDMI_ACR_AUTO_SEND, 1, | |
| 353 | + HDMI_ACR_SOURCE, 0); | |
| 354 | + | |
| 355 | + /* Program audio clock sample/regeneration parameters */ | |
| 356 | + get_audio_clock_info(crtc_info->color_depth, | |
| 357 | + crtc_info->requested_pixel_clock_100Hz, | |
| 358 | + crtc_info->calculated_pixel_clock_100Hz, | |
| 359 | + &audio_clock_info); | |
| 360 | + DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d" \ | |
| 361 | + "calculated_pixel_clock_100Hz = %d\n", __func__,\ | |
| 362 | + crtc_info->requested_pixel_clock_100Hz, \ | |
| 363 | + crtc_info->calculated_pixel_clock_100Hz); | |
| 364 | + | |
| 365 | + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ | |
| 366 | + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); | |
| 367 | + | |
| 368 | + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ | |
| 369 | + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); | |
| 370 | + | |
| 371 | + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ | |
| 372 | + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); | |
| 373 | + | |
| 374 | + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ | |
| 375 | + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); | |
| 376 | + | |
| 377 | + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ | |
| 378 | + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); | |
| 379 | + | |
| 380 | + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ | |
| 381 | + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); | |
| 382 | + | |
| 383 | + /* Video driver cannot know in advance which sample rate will | |
| 384 | + * be used by HD Audio driver | |
| 385 | + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is | |
| 386 | + * programmed below in interruppt callback | |
| 387 | + */ | |
| 388 | +} | |
| 389 | + | |
| 390 | +static void enc42_se_hdmi_audio_disable( | |
| 391 | + struct stream_encoder *enc) | |
| 392 | +{ | |
| 393 | + ASSERT (enc->apg); | |
| 394 | + enc->apg->funcs->disable_apg(enc->apg); | |
| 395 | + enc42_se_enable_audio_clock(enc, false); | |
| 396 | +} | |
| 397 | + | |
| 398 | +void enc42_se_enable_audio_clock( | |
| 399 | + struct stream_encoder *enc, | |
| 400 | + bool enable) | |
| 401 | +{ | |
| 402 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 403 | + | |
| 404 | + REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, !!enable); | |
| 405 | +} | |
| 406 | + | |
| 407 | + | |
| 408 | +static void enc42_se_hdmi_audio_setup( | |
| 409 | + struct stream_encoder *enc, | |
| 410 | + unsigned int az_inst, | |
| 411 | + struct audio_info *info, | |
| 412 | + struct audio_crtc_info *audio_crtc_info) | |
| 413 | +{ | |
| 414 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 415 | + | |
| 416 | + ASSERT (enc->apg); | |
| 417 | + enc42_se_enable_audio_clock(enc, true); | |
| 418 | + /*ACR setup*/ | |
| 419 | + enc42_se_setup_hdmi_audio(enc, audio_crtc_info); | |
| 420 | + | |
| 421 | + REG_UPDATE(DIG_FE_AUDIO_CNTL, | |
| 422 | + DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); | |
| 423 | + | |
| 424 | + /*APG_DBG_GEN_CONTROL*/ | |
| 425 | + enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); | |
| 426 | + /*APG enable*/ | |
| 427 | + enc->apg->funcs->enable_apg(enc->apg); | |
| 428 | +} | |
| 429 | + | |
| 430 | +static void enc42_audio_mute_control( | |
| 431 | + struct stream_encoder *enc, | |
| 432 | + bool mute) | |
| 433 | +{ | |
| 434 | + if (mute) | |
| 435 | + enc->apg->funcs->disable_apg(enc->apg); | |
| 436 | + else | |
| 437 | + enc->apg->funcs->enable_apg(enc->apg); | |
| 438 | +} | |
| 439 | +void enc42_reset_hdmi_stream_attribute( | |
| 440 | + struct stream_encoder *enc) | |
| 441 | +{ | |
| 442 | + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 443 | + | |
| 444 | + REG_UPDATE_3(HDMI_CONTROL, | |
| 445 | + HDMI_DEEP_COLOR_ENABLE, 0, | |
| 446 | + HDMI_DATA_SCRAMBLE_EN, 0, | |
| 447 | + HDMI_CLOCK_CHANNEL_RATE, 0); | |
| 448 | +} | |
| 449 | + | |
| 450 | +static const struct stream_encoder_funcs dcn42_str_enc_funcs = { | |
| 451 | + .dp_set_stream_attribute = | |
| 452 | + enc401_stream_encoder_dp_set_stream_attribute, | |
| 453 | + .hdmi_set_stream_attribute = | |
| 454 | + enc42_stream_encoder_hdmi_set_stream_attribute, | |
| 455 | + .dvi_set_stream_attribute = | |
| 456 | + enc401_stream_encoder_dvi_set_stream_attribute, | |
| 457 | + .set_throttled_vcp_size = | |
| 458 | + enc1_stream_encoder_set_throttled_vcp_size, | |
| 459 | + .update_hdmi_info_packets = | |
| 460 | + enc42_stream_encoder_update_hdmi_info_packets, | |
| 461 | + .stop_hdmi_info_packets = | |
| 462 | + enc3_stream_encoder_stop_hdmi_info_packets, | |
| 463 | + .update_dp_info_packets_sdp_line_num = | |
| 464 | + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, | |
| 465 | + .update_dp_info_packets = | |
| 466 | + enc3_stream_encoder_update_dp_info_packets, | |
| 467 | + .stop_dp_info_packets = | |
| 468 | + enc42_stream_encoder_stop_dp_info_packets, | |
| 469 | + .dp_blank = | |
| 470 | + enc1_stream_encoder_dp_blank, | |
| 471 | + .dp_unblank = | |
| 472 | + enc401_stream_encoder_dp_unblank, | |
| 473 | + .audio_mute_control = enc42_audio_mute_control, | |
| 474 | + | |
| 475 | + .dp_audio_setup = enc42_se_dp_audio_setup, | |
| 476 | + .dp_audio_enable = enc42_se_dp_audio_enable, | |
| 477 | + .dp_audio_disable = enc42_se_dp_audio_disable, | |
| 478 | + | |
| 479 | + .hdmi_audio_setup = enc42_se_hdmi_audio_setup, | |
| 480 | + .hdmi_audio_disable = enc42_se_hdmi_audio_disable, | |
| 481 | + .setup_stereo_sync = enc1_setup_stereo_sync, | |
| 482 | + .set_avmute = enc1_stream_encoder_set_avmute, | |
| 483 | + .dig_connect_to_otg = enc1_dig_connect_to_otg, | |
| 484 | + .dig_source_otg = enc1_dig_source_otg, | |
| 485 | + | |
| 486 | + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, | |
| 487 | + | |
| 488 | + .enc_read_state = enc401_read_state, | |
| 489 | + .dp_set_dsc_config = NULL, | |
| 490 | + .dp_set_dsc_pps_info_packet = enc42_dp_set_dsc_pps_info_packet, | |
| 491 | + .set_dynamic_metadata = enc401_set_dynamic_metadata, | |
| 492 | + .hdmi_reset_stream_attribute = enc42_reset_hdmi_stream_attribute, | |
| 493 | + .enable_stream = enc401_stream_encoder_enable, | |
| 494 | + | |
| 495 | + .set_input_mode = enc401_set_dig_input_mode, | |
| 496 | + .enable_fifo = enc35_enable_fifo, | |
| 497 | + .disable_fifo = enc35_disable_fifo, | |
| 498 | + .map_stream_to_link = enc401_stream_encoder_map_to_link, | |
| 499 | +}; | |
| 500 | + | |
| 501 | +void dcn42_dio_stream_encoder_construct( | |
| 502 | + struct dcn10_stream_encoder *enc1, | |
| 503 | + struct dc_context *ctx, | |
| 504 | + struct dc_bios *bp, | |
| 505 | + enum engine_id eng_id, | |
| 506 | + struct vpg *vpg, | |
| 507 | + struct apg *apg, | |
| 508 | + const struct dcn10_stream_enc_registers *regs, | |
| 509 | + const struct dcn10_stream_encoder_shift *se_shift, | |
| 510 | + const struct dcn10_stream_encoder_mask *se_mask) | |
| 511 | +{ | |
| 512 | + enc1->base.funcs = &dcn42_str_enc_funcs; | |
| 513 | + enc1->base.ctx = ctx; | |
| 514 | + enc1->base.id = eng_id; | |
| 515 | + enc1->base.bp = bp; | |
| 516 | + enc1->base.vpg = vpg; | |
| 517 | + enc1->base.apg = apg; | |
| 518 | + enc1->regs = regs; | |
| 519 | + enc1->se_shift = se_shift; | |
| 520 | + enc1->se_mask = se_mask; | |
| 521 | + enc1->base.stream_enc_inst = vpg->inst; | |
| 522 | +} | |
| @@ -0,0 +1,206 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 - Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + * Authors: AMD | |
| 24 | + * | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef __DC_DIO_STREAM_ENCODER_DCN42_H__ | |
| 28 | +#define __DC_DIO_STREAM_ENCODER_DCN42_H__ | |
| 29 | + | |
| 30 | +#include "dcn30/dcn30_vpg.h" | |
| 31 | +#include "stream_encoder.h" | |
| 32 | +#include "dcn20/dcn20_stream_encoder.h" | |
| 33 | + | |
| 34 | +#define SE_COMMON_MASK_SH_LIST_DCN42(mask_sh)\ | |
| 35 | + SE_SF(DP0_DP_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\ | |
| 36 | + SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_FORMAT, mask_sh),\ | |
| 37 | + SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\ | |
| 38 | + SE_SF(DP0_DP_PIXEL_FORMAT, COMPRESSED_PIXEL_FORMAT, mask_sh),\ | |
| 39 | + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ | |
| 40 | + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ | |
| 41 | + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ | |
| 42 | + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ | |
| 43 | + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ | |
| 44 | + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ | |
| 45 | + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ | |
| 46 | + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ | |
| 47 | + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ | |
| 48 | + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE, mask_sh),\ | |
| 49 | + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ | |
| 50 | + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ | |
| 51 | + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ | |
| 52 | + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ | |
| 53 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ | |
| 54 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ | |
| 55 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ | |
| 56 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ | |
| 57 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ | |
| 58 | + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ | |
| 59 | + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ | |
| 60 | + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ | |
| 61 | + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ | |
| 62 | + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ | |
| 63 | + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ | |
| 64 | + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ | |
| 65 | + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ | |
| 66 | + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ | |
| 67 | + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ | |
| 68 | + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_ENABLE, mask_sh),\ | |
| 69 | + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ | |
| 70 | + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ | |
| 71 | + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ | |
| 72 | + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ | |
| 73 | + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ | |
| 74 | + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ | |
| 75 | + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ | |
| 76 | + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ | |
| 77 | + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ | |
| 78 | + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ | |
| 79 | + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ | |
| 80 | + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ | |
| 81 | + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ | |
| 82 | + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ | |
| 83 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ | |
| 84 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ | |
| 85 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ | |
| 86 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ | |
| 87 | + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ | |
| 88 | + SE_SF(DIG1_HDMI_CONTROL, TMDS_PIXEL_ENCODING, mask_sh),\ | |
| 89 | + SE_SF(DIG1_HDMI_CONTROL, TMDS_COLOR_FORMAT, mask_sh),\ | |
| 90 | + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ | |
| 91 | + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ | |
| 92 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ | |
| 93 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ | |
| 94 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ | |
| 95 | + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ | |
| 96 | + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ | |
| 97 | + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ | |
| 98 | + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ | |
| 99 | + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ | |
| 100 | + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ | |
| 101 | + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ | |
| 102 | + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ | |
| 103 | + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ | |
| 104 | + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ | |
| 105 | + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ | |
| 106 | + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ | |
| 107 | + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ | |
| 108 | + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ | |
| 109 | + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ | |
| 110 | + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ | |
| 111 | + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ | |
| 112 | + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ | |
| 113 | + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ | |
| 114 | + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_INTERVAL, mask_sh),\ | |
| 115 | + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ | |
| 116 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ | |
| 117 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ | |
| 118 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ | |
| 119 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ | |
| 120 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ | |
| 121 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ | |
| 122 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ | |
| 123 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ | |
| 124 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ | |
| 125 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ | |
| 126 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ | |
| 127 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ | |
| 128 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ | |
| 129 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ | |
| 130 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ | |
| 131 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ | |
| 132 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ | |
| 133 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ | |
| 134 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ | |
| 135 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ | |
| 136 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ | |
| 137 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ | |
| 138 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ | |
| 139 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ | |
| 140 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ | |
| 141 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ | |
| 142 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ | |
| 143 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ | |
| 144 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ | |
| 145 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ | |
| 146 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ | |
| 147 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ | |
| 148 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ | |
| 149 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ | |
| 150 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ | |
| 151 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ | |
| 152 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ | |
| 153 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ | |
| 154 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ | |
| 155 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ | |
| 156 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ | |
| 157 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ | |
| 158 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ | |
| 159 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ | |
| 160 | + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ | |
| 161 | + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ | |
| 162 | + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ | |
| 163 | + SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ | |
| 164 | + SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ | |
| 165 | + SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ | |
| 166 | + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ | |
| 167 | + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ | |
| 168 | + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ | |
| 169 | + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ | |
| 170 | + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ | |
| 171 | + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ | |
| 172 | + SE_SF(DIG0_HDMI_CONTROL, DOLBY_VISION_EN, mask_sh),\ | |
| 173 | + SE_SF(DIG0_DIG_FE_EN_CNTL, DIG_FE_ENABLE, mask_sh),\ | |
| 174 | + SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_MODE, mask_sh),\ | |
| 175 | + SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, mask_sh),\ | |
| 176 | + SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SOFT_RESET, mask_sh),\ | |
| 177 | + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ | |
| 178 | + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ | |
| 179 | + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ | |
| 180 | + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE, mask_sh),\ | |
| 181 | + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\ | |
| 182 | + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\ | |
| 183 | + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\ | |
| 184 | + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\ | |
| 185 | + SE_SF(DIG0_STREAM_MAPPER_CONTROL, DIG_STREAM_LINK_TARGET, mask_sh),\ | |
| 186 | + SE_SF(DIG0_DIG_FE_AUDIO_CNTL, DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\ | |
| 187 | + SE_SF(DIG0_DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, mask_sh) | |
| 188 | + | |
| 189 | +void dcn42_dio_stream_encoder_construct( | |
| 190 | + struct dcn10_stream_encoder *enc1, | |
| 191 | + struct dc_context *ctx, | |
| 192 | + struct dc_bios *bp, | |
| 193 | + enum engine_id eng_id, | |
| 194 | + struct vpg *vpg, | |
| 195 | + struct apg *apg, | |
| 196 | + const struct dcn10_stream_enc_registers *regs, | |
| 197 | + const struct dcn10_stream_encoder_shift *se_shift, | |
| 198 | + const struct dcn10_stream_encoder_mask *se_mask); | |
| 199 | + | |
| 200 | +void enc42_se_enable_audio_clock( | |
| 201 | + struct stream_encoder *enc, | |
| 202 | + bool enable); | |
| 203 | + | |
| 204 | +void enc42_reset_hdmi_stream_attribute( | |
| 205 | + struct stream_encoder *enc); | |
| 206 | +#endif /* __DC_DIO_STREAM_ENCODER_DCN42_H__ */ | |
| @@ -734,8 +734,12 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s · 733 unmodified lines | ||
| 734 | 734 | memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); |
| 735 | 735 | |
| 736 | 736 | dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable; |
| 737 | − dml_dispcfg->gpuvm_max_page_table_levels = 4; | |
| 738 | − dml_dispcfg->hostvm_enable = false; | |
| 737 | + if (dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels) | |
| 738 | + dml_dispcfg->gpuvm_max_page_table_levels = dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels; | |
| 739 | + else | |
| 740 | + dml_dispcfg->gpuvm_max_page_table_levels = 4; | |
| 741 | + dml_dispcfg->hostvm_enable = dml_ctx->config.hostvm_enable; | |
| 742 | + dml_dispcfg->hostvm_max_non_cached_page_table_levels = dml_ctx->v21.dml_init.soc_bb.hostvm_max_non_cached_page_table_levels; | |
| 739 | 743 | dml_dispcfg->minimize_det_reallocation = true; |
| 740 | 744 | dml_dispcfg->overrides.enable_subvp_implicit_pmo = true; |
| 741 | 745 | |
| @@ -374,128 +374,135 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c · 373 unmodified lines | ||
| 374 | 374 | dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state); |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | −void dml21_build_fams2_programming(const struct dc *dc, | |
| 377 | +static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc, | |
| 378 | 378 | struct dc_state *context, |
| 379 | 379 | struct dml2_context *dml_ctx) |
| 380 | 380 | { |
| 381 | − int i, j, k; | |
| 381 | + int dc_stream_idx, dc_plane_idx, dc_pipe_idx; | |
| 382 | 382 | unsigned int num_fams2_streams = 0; |
| 383 | 383 | |
| 384 | − /* reset fams2 data */ | |
| 385 | − memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | |
| 386 | − memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | |
| 387 | − memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES); | |
| 388 | − memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); | |
| 384 | + for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) { | |
| 385 | + int dml_stream_idx; | |
| 386 | + struct dc_stream_state *phantom_stream; | |
| 387 | + struct dc_stream_status *phantom_status; | |
| 388 | + enum fams2_stream_type type = 0; | |
| 389 | 389 | |
| 390 | − if ((dml_ctx->v21.mode_programming.programming->fams2_required) || | |
| 391 | − (dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu)) { | |
| 392 | − for (i = 0; i < context->stream_count; i++) { | |
| 393 | − int dml_stream_idx; | |
| 394 | − struct dc_stream_state *phantom_stream; | |
| 395 | − struct dc_stream_status *phantom_status; | |
| 396 | − enum fams2_stream_type type = 0; | |
| 390 | + union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; | |
| 391 | + union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams]; | |
| 397 | 392 | |
| 398 | − union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; | |
| 399 | − union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams]; | |
| 393 | + struct dc_stream_state *stream = context->streams[dc_stream_idx]; | |
| 400 | 394 | |
| 401 | − struct dc_stream_state *stream = context->streams[i]; | |
| 395 | + if (context->stream_status[dc_stream_idx].plane_count == 0 || | |
| 396 | + dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) { | |
| 397 | + /* can ignore blanked or phantom streams */ | |
| 398 | + continue; | |
| 399 | + } | |
| 402 | 400 | |
| 403 | − if (context->stream_status[i].plane_count == 0 || | |
| 404 | − dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) { | |
| 405 | − /* can ignore blanked or phantom streams */ | |
| 406 | − continue; | |
| 407 | − } | |
| 401 | + dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); | |
| 402 | + if (dml_stream_idx < 0) { | |
| 403 | + ASSERT(dml_stream_idx >= 0); | |
| 404 | + continue; | |
| 405 | + } | |
| 408 | 406 | |
| 409 | − dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); | |
| 410 | − if (dml_stream_idx < 0) { | |
| 411 | − ASSERT(dml_stream_idx >= 0); | |
| 412 | − continue; | |
| 407 | + /* copy static state from PMO */ | |
| 408 | + memcpy(static_base_state, | |
| 409 | + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, | |
| 410 | + sizeof(union dmub_cmd_fams2_config)); | |
| 411 | + | |
| 412 | + memcpy(static_sub_state, | |
| 413 | + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, | |
| 414 | + sizeof(union dmub_cmd_fams2_config)); | |
| 415 | + | |
| 416 | + switch (dc->debug.fams_version.minor) { | |
| 417 | + case 1: | |
| 418 | + default: | |
| 419 | + type = static_base_state->stream_v1.base.type; | |
| 420 | + | |
| 421 | + /* get information from context */ | |
| 422 | + static_base_state->stream_v1.base.num_planes = context->stream_status[dc_stream_idx].plane_count; | |
| 423 | + static_base_state->stream_v1.base.otg_inst = context->stream_status[dc_stream_idx].primary_otg_inst; | |
| 424 | + | |
| 425 | + /* populate pipe masks for planes */ | |
| 426 | + for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) { | |
| 427 | + for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { | |
| 428 | + if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream && | |
| 429 | + context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == stream->stream_id && | |
| 430 | + context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == context->stream_status[dc_stream_idx].plane_states[dc_plane_idx]) { | |
| 431 | + static_base_state->stream_v1.base.pipe_mask |= (1 << dc_pipe_idx); | |
| 432 | + static_base_state->stream_v1.base.plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx); | |
| 433 | + } | |
| 434 | + } | |
| 413 | 435 | } |
| 436 | + } | |
| 414 | 437 | |
| 415 | − /* copy static state from PMO */ | |
| 416 | − memcpy(static_base_state, | |
| 417 | − &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, | |
| 418 | − sizeof(union dmub_cmd_fams2_config)); | |
| 419 | − | |
| 420 | − if (dc->debug.fams_version.major == 3) { | |
| 421 | − memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams], | |
| 422 | − &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2, | |
| 423 | − sizeof(union dmub_fams2_stream_static_sub_state_v2)); | |
| 424 | − } else { | |
| 425 | − memcpy(static_sub_state, | |
| 426 | − &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, | |
| 427 | − sizeof(union dmub_cmd_fams2_config)); | |
| 428 | − } | |
| 438 | + | |
| 439 | + /* get per method programming */ | |
| 440 | + switch (type) { | |
| 441 | + case FAMS2_STREAM_TYPE_VBLANK: | |
| 442 | + case FAMS2_STREAM_TYPE_VACTIVE: | |
| 443 | + case FAMS2_STREAM_TYPE_DRR: | |
| 444 | + break; | |
| 445 | + case FAMS2_STREAM_TYPE_SUBVP: | |
| 446 | + phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); | |
| 447 | + if (!phantom_stream) | |
| 448 | + break; | |
| 449 | + | |
| 450 | + phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); | |
| 451 | + | |
| 452 | + /* phantom status should always be present */ | |
| 453 | + ASSERT(phantom_status); | |
| 454 | + if (!phantom_status) | |
| 455 | + break; | |
| 429 | 456 | |
| 430 | 457 | switch (dc->debug.fams_version.minor) { |
| 431 | 458 | case 1: |
| 432 | 459 | default: |
| 433 | − type = static_base_state->stream_v1.base.type; | |
| 434 | − | |
| 435 | − /* get information from context */ | |
| 436 | − static_base_state->stream_v1.base.num_planes = context->stream_status[i].plane_count; | |
| 437 | − static_base_state->stream_v1.base.otg_inst = context->stream_status[i].primary_otg_inst; | |
| 438 | − | |
| 439 | − /* populate pipe masks for planes */ | |
| 440 | − for (j = 0; j < context->stream_status[i].plane_count; j++) { | |
| 441 | − for (k = 0; k < dc->res_pool->pipe_count; k++) { | |
| 442 | − if (context->res_ctx.pipe_ctx[k].stream && | |
| 443 | − context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id && | |
| 444 | − context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) { | |
| 445 | − static_base_state->stream_v1.base.pipe_mask |= (1 << k); | |
| 446 | − static_base_state->stream_v1.base.plane_pipe_masks[j] |= (1 << k); | |
| 460 | + static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst; | |
| 461 | + | |
| 462 | + /* populate pipe masks for phantom planes */ | |
| 463 | + for (dc_plane_idx = 0; dc_plane_idx < phantom_status->plane_count; dc_plane_idx++) { | |
| 464 | + for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { | |
| 465 | + if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream && | |
| 466 | + context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == phantom_stream->stream_id && | |
| 467 | + context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == phantom_status->plane_states[dc_plane_idx]) { | |
| 468 | + switch (dc->debug.fams_version.minor) { | |
| 469 | + case 1: | |
| 470 | + default: | |
| 471 | + static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << dc_pipe_idx); | |
| 472 | + static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx); | |
| 473 | + } | |
| 447 | 474 | } |
| 448 | 475 | } |
| 449 | 476 | } |
| 450 | 477 | } |
| 478 | + break; | |
| 479 | + default: | |
| 480 | + ASSERT(false); | |
| 481 | + break; | |
| 482 | + } | |
| 451 | 483 | |
| 484 | + num_fams2_streams++; | |
| 485 | + } | |
| 452 | 486 | |
| 453 | − /* get per method programming */ | |
| 454 | − switch (type) { | |
| 455 | − case FAMS2_STREAM_TYPE_VBLANK: | |
| 456 | − case FAMS2_STREAM_TYPE_VACTIVE: | |
| 457 | − case FAMS2_STREAM_TYPE_DRR: | |
| 458 | − break; | |
| 459 | − case FAMS2_STREAM_TYPE_SUBVP: | |
| 460 | − phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); | |
| 461 | − if (!phantom_stream) | |
| 462 | − break; | |
| 463 | − | |
| 464 | − phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); | |
| 465 | − | |
| 466 | − /* phantom status should always be present */ | |
| 467 | − ASSERT(phantom_status); | |
| 468 | − if (!phantom_status) | |
| 469 | − break; | |
| 470 | − | |
| 471 | − switch (dc->debug.fams_version.minor) { | |
| 472 | − case 1: | |
| 473 | − default: | |
| 474 | − static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst; | |
| 475 | − | |
| 476 | − /* populate pipe masks for phantom planes */ | |
| 477 | − for (j = 0; j < phantom_status->plane_count; j++) { | |
| 478 | − for (k = 0; k < dc->res_pool->pipe_count; k++) { | |
| 479 | − if (context->res_ctx.pipe_ctx[k].stream && | |
| 480 | − context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id && | |
| 481 | − context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) { | |
| 482 | − switch (dc->debug.fams_version.minor) { | |
| 483 | − case 1: | |
| 484 | − default: | |
| 485 | − static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << k); | |
| 486 | − static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k); | |
| 487 | − } | |
| 488 | − } | |
| 489 | − } | |
| 490 | − } | |
| 491 | − } | |
| 492 | − break; | |
| 493 | − default: | |
| 494 | − ASSERT(false); | |
| 495 | − break; | |
| 496 | − } | |
| 487 | + return num_fams2_streams; | |
| 488 | +} | |
| 489 | + | |
| 490 | +void dml21_build_fams2_programming(const struct dc *dc, | |
| 491 | + struct dc_state *context, | |
| 492 | + struct dml2_context *dml_ctx) | |
| 493 | +{ | |
| 494 | + unsigned int num_fams2_streams = 0; | |
| 495 | + | |
| 496 | + /* reset fams2 data */ | |
| 497 | + memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | |
| 498 | + memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | |
| 499 | + memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES); | |
| 500 | + memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); | |
| 497 | 501 | |
| 498 | − num_fams2_streams++; | |
| 502 | + if (dml_ctx->v21.mode_programming.programming->fams2_required || | |
| 503 | + dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu) { | |
| 504 | + if (dc->debug.fams_version.major == 2) { | |
| 505 | + num_fams2_streams = dml21_build_fams2_stream_programming_v2(dc, context, dml_ctx); | |
| 499 | 506 | } |
| 500 | 507 | } |
| 501 | 508 | |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | struct dc_state; |
| 10 | 10 | struct dc_plane_state; |
| 11 | 11 | struct pipe_ctx; |
| 12 | +struct dc_dmub_srv; | |
| 12 | 13 | |
| 13 | 14 | struct dml2_context; |
| 14 | 15 | struct dml2_display_rq_regs; |
| @@ -160,6 +160,8 @@ struct dml2_soc_bb { · 159 unmodified lines | ||
| 160 | 160 | unsigned long return_bus_width_bytes; |
| 161 | 161 | unsigned long hostvm_min_page_size_kbytes; |
| 162 | 162 | unsigned long gpuvm_min_page_size_kbytes; |
| 163 | + unsigned int hostvm_max_non_cached_page_table_levels; | |
| 164 | + unsigned int gpuvm_max_page_table_levels; | |
| 163 | 165 | double phy_downspread_percent; |
| 164 | 166 | double dcn_downspread_percent; |
| 165 | 167 | double dispclk_dppclk_vco_speed_mhz; |
| @@ -909,10 +909,10 @@ static unsigned int get_source_mpc_factor(const struct dml2_context *ctx, · 908 unmodified lines | ||
| 909 | 909 | const struct dc_plane_state *plane) |
| 910 | 910 | { |
| 911 | 911 | struct pipe_ctx *dpp_pipes[MAX_PIPES] = {0}; |
| 912 | − int dpp_pipe_count = ctx->config.callbacks.get_dpp_pipes_for_plane(plane, | |
| 913 | − &state->res_ctx, dpp_pipes); | |
| 914 | 912 | |
| 915 | − ASSERT(dpp_pipe_count > 0); | |
| 913 | + if (ctx->config.callbacks.get_dpp_pipes_for_plane(plane, &state->res_ctx, dpp_pipes) <= 0) | |
| 914 | + ASSERT(false); | |
| 915 | + | |
| 916 | 916 | return ctx->config.callbacks.get_mpc_slice_count(dpp_pipes[0]); |
| 917 | 917 | } |
| 918 | 918 | |
| @@ -239,6 +239,7 @@ struct dml2_configuration_options { · 238 unmodified lines | ||
| 239 | 239 | |
| 240 | 240 | bool use_clock_dc_limits; |
| 241 | 241 | bool gpuvm_enable; |
| 242 | + bool hostvm_enable; | |
| 242 | 243 | bool force_tdlut_enable; |
| 243 | 244 | void *bb_from_dmub; |
| 244 | 245 | }; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | |
| 2 | −# Copyright 2022 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -80,4 +80,12 @@ AMD_DAL_DPP_DCN401 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn401/,$(DPP_DCN401)) · 74 unmodified lines | ||
| 80 | 80 | |
| 81 | 81 | AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN401) |
| 82 | 82 | |
| 83 | +############################################################################### | |
| 84 | +# DCN42 | |
| 85 | +############################################################################### | |
| 86 | +DPP_DCN42 = dcn42_dpp.o | |
| 87 | + | |
| 88 | +AMD_DAL_DPP_DCN42 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn42/,$(DPP_DCN42)) | |
| 89 | + | |
| 90 | +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN42) | |
| 83 | 91 | endif |
| @@ -1,4 +1,5 @@ | ||
| 1 | −/* Copyright 2023 Advanced Micro Devices, Inc. | |
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* Copyright 2023-2026 Advanced Micro Devices, Inc. | |
| 2 | 3 | * |
| 3 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 4 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -653,6 +654,8 @@ · 648 unmodified lines | ||
| 653 | 654 | |
| 654 | 655 | struct dcn401_dpp_registers { |
| 655 | 656 | DPP_REG_VARIABLE_LIST_DCN401; |
| 657 | + uint32_t ALPHA_2BIT_LUT01; | |
| 658 | + uint32_t ALPHA_2BIT_LUT23; | |
| 656 | 659 | }; |
| 657 | 660 | |
| 658 | 661 | struct dcn401_dpp_shift { |
| @@ -0,0 +1,333 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dm_services.h" | |
| 6 | +#include "core_types.h" | |
| 7 | +#include "reg_helper.h" | |
| 8 | +#include "dcn42_dpp.h" | |
| 9 | +#include "dcn35/dcn35_dpp.h" | |
| 10 | + | |
| 11 | +#define REG(reg)\ | |
| 12 | + dpp->tf_regs->reg | |
| 13 | + | |
| 14 | +#define CTX \ | |
| 15 | + dpp->base.ctx | |
| 16 | + | |
| 17 | +#undef FN | |
| 18 | +#define FN(reg_name, field_name) \ | |
| 19 | + dpp->tf_shift->field_name, dpp->tf_mask->field_name | |
| 20 | + | |
| 21 | +static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space) | |
| 22 | +{ | |
| 23 | + // Coefs in s.6.12. | |
| 24 | + // Y = 0.2126R + 0.7152G + 0.0722B | |
| 25 | + static const uint32_t luma_transform_bt_709[] = {0x1cb36, 0x1e6e2, 0x1b27b}; | |
| 26 | + // Y = 0.2627R + 0.678G + 0.0593B | |
| 27 | + static const uint32_t luma_transform_bt_2020[] = {0x1d0d0, 0x1e5b2, 0x1ae5c}; | |
| 28 | + | |
| 29 | + switch (color_space) { | |
| 30 | + case COLOR_SPACE_2020_RGB_FULLRANGE: | |
| 31 | + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: | |
| 32 | + return luma_transform_bt_2020; | |
| 33 | + default: | |
| 34 | + return luma_transform_bt_709; | |
| 35 | + } | |
| 36 | +} | |
| 37 | + | |
| 38 | +static void dpp42_dpp_cm_hist_control( | |
| 39 | + struct dpp *dpp_base, | |
| 40 | + struct cm_hist_control cntl, | |
| 41 | + enum dc_color_space color_space) | |
| 42 | +{ | |
| 43 | + struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base); | |
| 44 | + | |
| 45 | + REG_UPDATE_10( | |
| 46 | + CM_HIST_CNTL, | |
| 47 | + CM_HIST_SEL, cntl.tap_point, | |
| 48 | + CM_HIST_CH_EN, cntl.channels_enabled, | |
| 49 | + CM_HIST_SRC1_SEL, cntl.src_1_select, | |
| 50 | + CM_HIST_SRC2_SEL, cntl.src_2_select, | |
| 51 | + CM_HIST_SRC3_SEL, cntl.src_3_select, | |
| 52 | + CM_HIST_CH1_XBAR, cntl.ch1_src, | |
| 53 | + CM_HIST_CH2_XBAR, cntl.ch2_src, | |
| 54 | + CM_HIST_CH3_XBAR, cntl.ch3_src, | |
| 55 | + CM_HIST_FORMAT, cntl.format, | |
| 56 | + CM_HIST_READ_CHANNEL_MASK, cntl.read_channel_mask); | |
| 57 | + | |
| 58 | + if (cntl.src_2_select == CM_HIST_SRC2_MODE_RGB_TO_Y) { | |
| 59 | + const uint32_t *luma_transform = get_hist_rgb_luma_coefs(color_space); | |
| 60 | + | |
| 61 | + REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, luma_transform[0]); | |
| 62 | + REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, luma_transform[1]); | |
| 63 | + REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, luma_transform[2]); | |
| 64 | + } else { | |
| 65 | + REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, 0); | |
| 66 | + REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, 0x1f000); // 1 in s.6.12 | |
| 67 | + REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, 0); | |
| 68 | + } | |
| 69 | +} | |
| 70 | + | |
| 71 | +static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out) | |
| 72 | +{ | |
| 73 | + struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base); | |
| 74 | + uint32_t channel_mask = 0; | |
| 75 | + uint32_t rdy_status = 0, rdy_status_a = 0, rdy_status_b = 0; | |
| 76 | + bool ch1, ch2, ch3; | |
| 77 | + | |
| 78 | + if (hist_out == NULL) | |
| 79 | + return false; | |
| 80 | + | |
| 81 | + | |
| 82 | + REG_GET(CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, &channel_mask); | |
| 83 | + ch1 = (channel_mask & 1) > 0; | |
| 84 | + ch2 = (channel_mask & 2) > 0; | |
| 85 | + ch3 = (channel_mask & 4) > 0; | |
| 86 | + | |
| 87 | + REG_GET(CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, &rdy_status_a); | |
| 88 | + REG_GET(CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, &rdy_status_b); | |
| 89 | + | |
| 90 | + rdy_status = rdy_status_a || rdy_status_b; | |
| 91 | + | |
| 92 | + if (rdy_status) { | |
| 93 | + REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 1); | |
| 94 | + REG_UPDATE(CM_HIST_INDEX, CM_HIST_INDEX, 0); | |
| 95 | + for (int i = 0; i < 256; i++) { | |
| 96 | + uint32_t temp; | |
| 97 | + | |
| 98 | + if (ch1) { | |
| 99 | + REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp); | |
| 100 | + hist_out->ch1[i] += temp; | |
| 101 | + } | |
| 102 | + if (ch2) { | |
| 103 | + REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp); | |
| 104 | + hist_out->ch2[i] += temp; | |
| 105 | + } | |
| 106 | + if (ch3) { | |
| 107 | + REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp); | |
| 108 | + hist_out->ch3[i] += temp; | |
| 109 | + } | |
| 110 | + } | |
| 111 | + REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 0); | |
| 112 | + return true; | |
| 113 | + } else { | |
| 114 | + return false; | |
| 115 | + } | |
| 116 | +} | |
| 117 | + | |
| 118 | +static void dpp42_dpp_setup( | |
| 119 | + struct dpp *dpp_base, | |
| 120 | + enum surface_pixel_format format, | |
| 121 | + enum expansion_mode mode, | |
| 122 | + struct dc_csc_transform input_csc_color_matrix, | |
| 123 | + enum dc_color_space input_color_space, | |
| 124 | + struct cnv_alpha_2bit_lut *alpha_2bit_lut) | |
| 125 | +{ | |
| 126 | + struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); | |
| 127 | + uint32_t pixel_format = 0; | |
| 128 | + uint32_t alpha_en = 1; | |
| 129 | + enum dc_color_space color_space = COLOR_SPACE_SRGB; | |
| 130 | + enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS; | |
| 131 | + uint32_t is_2bit = 0; | |
| 132 | + uint32_t alpha_plane_enable = 0; | |
| 133 | + uint32_t dealpha_en = 0, dealpha_ablnd_en = 0; | |
| 134 | + uint32_t realpha_en = 0, realpha_ablnd_en = 0; | |
| 135 | + struct out_csc_color_matrix tbl_entry; | |
| 136 | + int i; | |
| 137 | + | |
| 138 | + REG_SET_2(FORMAT_CONTROL, 0, | |
| 139 | + CNVC_BYPASS, 0, | |
| 140 | + FORMAT_EXPANSION_MODE, mode); | |
| 141 | + | |
| 142 | + REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0); | |
| 143 | + REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0); | |
| 144 | + REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0); | |
| 145 | + REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0); | |
| 146 | + | |
| 147 | + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0); | |
| 148 | + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1); | |
| 149 | + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2); | |
| 150 | + | |
| 151 | + switch (format) { | |
| 152 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: | |
| 153 | + pixel_format = 1; | |
| 154 | + break; | |
| 155 | + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: | |
| 156 | + pixel_format = 3; | |
| 157 | + alpha_en = 0; | |
| 158 | + break; | |
| 159 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: | |
| 160 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: | |
| 161 | + pixel_format = 8; | |
| 162 | + break; | |
| 163 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: | |
| 164 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: | |
| 165 | + pixel_format = 10; | |
| 166 | + is_2bit = 1; | |
| 167 | + break; | |
| 168 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: | |
| 169 | + pixel_format = 65; | |
| 170 | + color_space = COLOR_SPACE_YCBCR709; | |
| 171 | + select = INPUT_CSC_SELECT_ICSC; | |
| 172 | + break; | |
| 173 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: | |
| 174 | + pixel_format = 64; | |
| 175 | + color_space = COLOR_SPACE_YCBCR709; | |
| 176 | + select = INPUT_CSC_SELECT_ICSC; | |
| 177 | + break; | |
| 178 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: | |
| 179 | + pixel_format = 67; | |
| 180 | + color_space = COLOR_SPACE_YCBCR709; | |
| 181 | + select = INPUT_CSC_SELECT_ICSC; | |
| 182 | + break; | |
| 183 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: | |
| 184 | + pixel_format = 66; | |
| 185 | + color_space = COLOR_SPACE_YCBCR709; | |
| 186 | + select = INPUT_CSC_SELECT_ICSC; | |
| 187 | + break; | |
| 188 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: | |
| 189 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: | |
| 190 | + pixel_format = 26; /* ARGB16161616_UNORM */ | |
| 191 | + break; | |
| 192 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: | |
| 193 | + pixel_format = 24; | |
| 194 | + break; | |
| 195 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: | |
| 196 | + pixel_format = 25; | |
| 197 | + break; | |
| 198 | + case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: | |
| 199 | + pixel_format = 12; | |
| 200 | + color_space = COLOR_SPACE_YCBCR709; | |
| 201 | + select = INPUT_CSC_SELECT_ICSC; | |
| 202 | + break; | |
| 203 | + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: | |
| 204 | + pixel_format = 112; | |
| 205 | + alpha_en = 0; | |
| 206 | + break; | |
| 207 | + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: | |
| 208 | + pixel_format = 113; | |
| 209 | + alpha_en = 0; | |
| 210 | + break; | |
| 211 | + case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: | |
| 212 | + pixel_format = 114; | |
| 213 | + color_space = COLOR_SPACE_YCBCR709; | |
| 214 | + select = INPUT_CSC_SELECT_ICSC; | |
| 215 | + is_2bit = 1; | |
| 216 | + break; | |
| 217 | + case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102: | |
| 218 | + pixel_format = 115; | |
| 219 | + color_space = COLOR_SPACE_YCBCR709; | |
| 220 | + select = INPUT_CSC_SELECT_ICSC; | |
| 221 | + is_2bit = 1; | |
| 222 | + break; | |
| 223 | + case SURFACE_PIXEL_FORMAT_GRPH_RGBE: | |
| 224 | + pixel_format = 116; | |
| 225 | + alpha_plane_enable = 0; | |
| 226 | + break; | |
| 227 | + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: | |
| 228 | + pixel_format = 116; | |
| 229 | + alpha_plane_enable = 1; | |
| 230 | + break; | |
| 231 | + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: | |
| 232 | + pixel_format = 118; | |
| 233 | + alpha_en = 0; | |
| 234 | + break; | |
| 235 | + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: | |
| 236 | + pixel_format = 119; | |
| 237 | + alpha_en = 0; | |
| 238 | + break; | |
| 239 | + default: | |
| 240 | + break; | |
| 241 | + } | |
| 242 | + | |
| 243 | + /* Set default color space based on format if none is given. */ | |
| 244 | + color_space = input_color_space ? input_color_space : color_space; | |
| 245 | + | |
| 246 | + if (is_2bit == 1 && alpha_2bit_lut != NULL) { | |
| 247 | + REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0); | |
| 248 | + REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1); | |
| 249 | + REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2); | |
| 250 | + REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3); | |
| 251 | + } | |
| 252 | + | |
| 253 | + REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0, | |
| 254 | + CNVC_SURFACE_PIXEL_FORMAT, pixel_format, | |
| 255 | + CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable); | |
| 256 | + REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); | |
| 257 | + | |
| 258 | + REG_SET_2(PRE_DEALPHA, 0, | |
| 259 | + PRE_DEALPHA_EN, dealpha_en, | |
| 260 | + PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en); | |
| 261 | + REG_SET_2(PRE_REALPHA, 0, | |
| 262 | + PRE_REALPHA_EN, realpha_en, | |
| 263 | + PRE_REALPHA_ABLND_EN, realpha_ablnd_en); | |
| 264 | + | |
| 265 | + /* If input adjustment exists, program the ICSC with those values. */ | |
| 266 | + if (input_csc_color_matrix.enable_adjustment == true) { | |
| 267 | + for (i = 0; i < 12; i++) | |
| 268 | + tbl_entry.regval[i] = input_csc_color_matrix.matrix[i]; | |
| 269 | + | |
| 270 | + tbl_entry.color_space = input_color_space; | |
| 271 | + | |
| 272 | + if (color_space >= COLOR_SPACE_YCBCR601) | |
| 273 | + select = INPUT_CSC_SELECT_ICSC; | |
| 274 | + else | |
| 275 | + select = INPUT_CSC_SELECT_BYPASS; | |
| 276 | + | |
| 277 | + dpp3_program_post_csc(dpp_base, color_space, select, | |
| 278 | + &tbl_entry); | |
| 279 | + } else { | |
| 280 | + dpp3_program_post_csc(dpp_base, color_space, select, NULL); | |
| 281 | + } | |
| 282 | +} | |
| 283 | + | |
| 284 | +static struct dpp_funcs dcn42_dpp_funcs = { | |
| 285 | + .dpp_program_gamcor_lut = dpp3_program_gamcor_lut, | |
| 286 | + .dpp_read_state = dpp401_read_state, | |
| 287 | + .dpp_reset = dpp_reset, | |
| 288 | + .dpp_set_scaler = dpp401_dscl_set_scaler_manual_scale, | |
| 289 | + .dpp_get_optimal_number_of_taps = dpp3_get_optimal_number_of_taps, | |
| 290 | + .dpp_set_pre_degam = dpp3_set_pre_degam, | |
| 291 | + .dpp_setup = dpp42_dpp_setup, | |
| 292 | + .dpp_program_cm_dealpha = dpp3_program_cm_dealpha, | |
| 293 | + .dpp_program_cm_bias = dpp3_program_cm_bias, | |
| 294 | + .dpp_program_bias_and_scale = dpp35_program_bias_and_scale_fcnv, | |
| 295 | + .dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer, | |
| 296 | + .set_cursor_attributes = dpp401_set_cursor_attributes, | |
| 297 | + .set_cursor_position = dpp401_set_cursor_position, | |
| 298 | + .set_optional_cursor_attributes = dpp401_set_optional_cursor_attributes, | |
| 299 | + .dpp_dppclk_control = dpp35_dppclk_control, | |
| 300 | + .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier, | |
| 301 | + .set_cursor_matrix = dpp401_set_cursor_matrix, | |
| 302 | + .dpp_cm_hist_control = dpp42_dpp_cm_hist_control, | |
| 303 | + .dpp_cm_hist_read = dpp42_dpp_cm_hist_read, | |
| 304 | + .dpp_read_reg_state = dpp30_read_reg_state, | |
| 305 | +}; | |
| 306 | + | |
| 307 | + | |
| 308 | +static struct dpp_caps dcn42_dpp_cap = { | |
| 309 | + .dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT, | |
| 310 | + .max_lb_partitions = 63, | |
| 311 | + .dscl_calc_lb_num_partitions = dscl401_calc_lb_num_partitions, | |
| 312 | +}; | |
| 313 | + | |
| 314 | +bool dpp42_construct( | |
| 315 | + struct dcn42_dpp *dpp, | |
| 316 | + struct dc_context *ctx, | |
| 317 | + uint32_t inst, | |
| 318 | + const struct dcn42_dpp_registers *tf_regs, | |
| 319 | + const struct dcn42_dpp_shift *tf_shift, | |
| 320 | + const struct dcn42_dpp_mask *tf_mask) | |
| 321 | +{ | |
| 322 | + dpp->base.ctx = ctx; | |
| 323 | + | |
| 324 | + dpp->base.inst = inst; | |
| 325 | + dpp->base.funcs = &dcn42_dpp_funcs; | |
| 326 | + dpp->base.caps = &dcn42_dpp_cap; | |
| 327 | + | |
| 328 | + dpp->tf_regs = tf_regs; | |
| 329 | + dpp->tf_shift = tf_shift; | |
| 330 | + dpp->tf_mask = tf_mask; | |
| 331 | + | |
| 332 | + return true; | |
| 333 | +} | |
| @@ -0,0 +1,469 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* Copyright 2026 Advanced Micro Devices, Inc. */ | |
| 3 | + | |
| 4 | +#ifndef __DCN42_DPP_H__ | |
| 5 | +#define __DCN42_DPP_H__ | |
| 6 | + | |
| 7 | +#include "dcn401/dcn401_dpp.h" | |
| 8 | + | |
| 9 | +#define TO_DCN42_DPP(dpp)\ | |
| 10 | + container_of(dpp, struct dcn42_dpp, base) | |
| 11 | + | |
| 12 | +#define DPP_REG_LIST_SH_MASK_DCN42_COMMON(mask_sh)\ | |
| 13 | + TF_SF(CM0_CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, mask_sh),\ | |
| 14 | + TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_EN, mask_sh),\ | |
| 15 | + TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_ABLND, mask_sh),\ | |
| 16 | + TF_SF(CM0_CM_BIAS_CR_R, CM_BIAS_CR_R, mask_sh),\ | |
| 17 | + TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_Y_G, mask_sh),\ | |
| 18 | + TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_CB_B, mask_sh),\ | |
| 19 | + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\ | |
| 20 | + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, mask_sh),\ | |
| 21 | + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\ | |
| 22 | + TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_MODE, mask_sh),\ | |
| 23 | + TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_SELECT, mask_sh),\ | |
| 24 | + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE, mask_sh),\ | |
| 25 | + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, mask_sh),\ | |
| 26 | + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_PWL_DISABLE, mask_sh),\ | |
| 27 | + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, mask_sh),\ | |
| 28 | + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, mask_sh),\ | |
| 29 | + TF_SF(CM0_CM_GAMCOR_LUT_INDEX, CM_GAMCOR_LUT_INDEX, mask_sh),\ | |
| 30 | + TF_SF(CM0_CM_GAMCOR_LUT_DATA, CM_GAMCOR_LUT_DATA, mask_sh),\ | |
| 31 | + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_WRITE_COLOR_MASK, mask_sh),\ | |
| 32 | + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_COLOR_SEL, mask_sh),\ | |
| 33 | + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_DBG, mask_sh),\ | |
| 34 | + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_HOST_SEL, mask_sh),\ | |
| 35 | + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_CONFIG_MODE, mask_sh),\ | |
| 36 | + TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_B, mask_sh),\ | |
| 37 | + TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ | |
| 38 | + TF_SF(CM0_CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ | |
| 39 | + TF_SF(CM0_CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ | |
| 40 | + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL1_B, CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ | |
| 41 | + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_B, mask_sh),\ | |
| 42 | + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ | |
| 43 | + TF_SF(CM0_CM_GAMCOR_RAMA_OFFSET_B, CM_GAMCOR_RAMA_OFFSET_B, mask_sh),\ | |
| 44 | + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ | |
| 45 | + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ | |
| 46 | + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ | |
| 47 | + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ | |
| 48 | + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ | |
| 49 | + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ | |
| 50 | + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ | |
| 51 | + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ | |
| 52 | + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ | |
| 53 | + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ | |
| 54 | + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ | |
| 55 | + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ | |
| 56 | + TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ | |
| 57 | + TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\ | |
| 58 | + TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ | |
| 59 | + TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ | |
| 60 | + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ | |
| 61 | + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ | |
| 62 | + TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ | |
| 63 | + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ | |
| 64 | + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ | |
| 65 | + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ | |
| 66 | + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ | |
| 67 | + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ | |
| 68 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ | |
| 69 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ | |
| 70 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ | |
| 71 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ | |
| 72 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ | |
| 73 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ | |
| 74 | + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ | |
| 75 | + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ | |
| 76 | + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ | |
| 77 | + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ | |
| 78 | + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ | |
| 79 | + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ | |
| 80 | + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ | |
| 81 | + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ | |
| 82 | + TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ | |
| 83 | + TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ | |
| 84 | + TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ | |
| 85 | + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ | |
| 86 | + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ | |
| 87 | + TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ | |
| 88 | + TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ | |
| 89 | + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ | |
| 90 | + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ | |
| 91 | + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ | |
| 92 | + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ | |
| 93 | + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ | |
| 94 | + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ | |
| 95 | + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ | |
| 96 | + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ | |
| 97 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ | |
| 98 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ | |
| 99 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ | |
| 100 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ | |
| 101 | + TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ | |
| 102 | + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ | |
| 103 | + TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_EN, mask_sh), \ | |
| 104 | + TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_ABLND_EN, mask_sh), \ | |
| 105 | + TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_EN, mask_sh), \ | |
| 106 | + TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_ABLND_EN, mask_sh), \ | |
| 107 | + TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE, mask_sh), \ | |
| 108 | + TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE_CURRENT, mask_sh), \ | |
| 109 | + TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C11, mask_sh), \ | |
| 110 | + TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C12, mask_sh), \ | |
| 111 | + TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C33, mask_sh), \ | |
| 112 | + TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C34, mask_sh), \ | |
| 113 | + TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE, mask_sh), \ | |
| 114 | + TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE_CURRENT, mask_sh), \ | |
| 115 | + TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C11, mask_sh), \ | |
| 116 | + TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C12, mask_sh), \ | |
| 117 | + TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C33, mask_sh), \ | |
| 118 | + TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C34, mask_sh), \ | |
| 119 | + TF_SF(CM0_CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_INDEX, mask_sh), \ | |
| 120 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ | |
| 121 | + TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \ | |
| 122 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ | |
| 123 | + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ | |
| 124 | + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_ALPHA_PLANE_ENABLE, mask_sh), \ | |
| 125 | + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ | |
| 126 | + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ | |
| 127 | + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ | |
| 128 | + TF_SF(CM_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ | |
| 129 | + TF_SF(CM_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ | |
| 130 | + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_BIAS_G_Y, mask_sh), \ | |
| 131 | + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_SCALE_G_Y, mask_sh), \ | |
| 132 | + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_BIAS_RB_CRCB, mask_sh), \ | |
| 133 | + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_SCALE_RB_CRCB, mask_sh), \ | |
| 134 | + TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE, mask_sh), \ | |
| 135 | + TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE_CURRENT, mask_sh), \ | |
| 136 | + TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_COEF_FORMAT, mask_sh), \ | |
| 137 | + TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C11_A, mask_sh), \ | |
| 138 | + TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C12_A, mask_sh), \ | |
| 139 | + TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C13_A, mask_sh), \ | |
| 140 | + TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C14_A, mask_sh), \ | |
| 141 | + TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C21_A, mask_sh), \ | |
| 142 | + TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C22_A, mask_sh), \ | |
| 143 | + TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C23_A, mask_sh), \ | |
| 144 | + TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C24_A, mask_sh), \ | |
| 145 | + TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C31_A, mask_sh), \ | |
| 146 | + TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C32_A, mask_sh), \ | |
| 147 | + TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C33_A, mask_sh), \ | |
| 148 | + TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C34_A, mask_sh), \ | |
| 149 | + TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ | |
| 150 | + TF_SF(CM0_CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, mask_sh), \ | |
| 151 | + TF_SF(CM0_CM_CONTROL, CM_BYPASS, mask_sh), \ | |
| 152 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SEL, mask_sh), \ | |
| 153 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH_EN, mask_sh), \ | |
| 154 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC1_SEL, mask_sh), \ | |
| 155 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC2_SEL, mask_sh), \ | |
| 156 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC3_SEL, mask_sh), \ | |
| 157 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH1_XBAR, mask_sh), \ | |
| 158 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH2_XBAR, mask_sh), \ | |
| 159 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH3_XBAR, mask_sh), \ | |
| 160 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_FORMAT, mask_sh), \ | |
| 161 | + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, mask_sh), \ | |
| 162 | + TF_SF(CM0_CM_HIST_LOCK, CM_HIST_LOCK, mask_sh), \ | |
| 163 | + TF_SF(CM0_CM_HIST_INDEX, CM_HIST_INDEX, mask_sh), \ | |
| 164 | + TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \ | |
| 165 | + TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \ | |
| 166 | + TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, mask_sh), \ | |
| 167 | + TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, mask_sh), \ | |
| 168 | + TF_SF(CM0_CM_HIST_SCALE_SRC1, CM_HIST_SCALE_SRC1, mask_sh), \ | |
| 169 | + TF_SF(CM0_CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, mask_sh), \ | |
| 170 | + TF_SF(CM0_CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, mask_sh), \ | |
| 171 | + TF_SF(CM0_CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, mask_sh), \ | |
| 172 | + TF_SF(CM0_CM_HIST_SCALE_SRC3, CM_HIST_SCALE_SRC3, mask_sh), \ | |
| 173 | + TF_SF(CM0_CM_HIST_BIAS_SRC1, CM_HIST_BIAS_SRC1, mask_sh), \ | |
| 174 | + TF_SF(CM0_CM_HIST_BIAS_SRC2, CM_HIST_BIAS_SRC2, mask_sh), \ | |
| 175 | + TF_SF(CM0_CM_HIST_BIAS_SRC3, CM_HIST_BIAS_SRC3, mask_sh), \ | |
| 176 | + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ | |
| 177 | + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ | |
| 178 | + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ | |
| 179 | + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ | |
| 180 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CNV16, mask_sh), \ | |
| 181 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, mask_sh), \ | |
| 182 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE, mask_sh), \ | |
| 183 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE_C, mask_sh), \ | |
| 184 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_R, mask_sh), \ | |
| 185 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_G, mask_sh), \ | |
| 186 | + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_B, mask_sh), \ | |
| 187 | + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, mask_sh), \ | |
| 188 | + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, mask_sh), \ | |
| 189 | + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, mask_sh), \ | |
| 190 | + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, mask_sh), \ | |
| 191 | + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_R, FCNV_FP_BIAS_R, mask_sh), \ | |
| 192 | + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_G, FCNV_FP_BIAS_G, mask_sh), \ | |
| 193 | + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_B, FCNV_FP_BIAS_B, mask_sh), \ | |
| 194 | + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_R, FCNV_FP_SCALE_R, mask_sh), \ | |
| 195 | + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_G, FCNV_FP_SCALE_G, mask_sh), \ | |
| 196 | + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_B, FCNV_FP_SCALE_B, mask_sh), \ | |
| 197 | + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_EN, mask_sh), \ | |
| 198 | + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, LUMA_KEYER_EN, mask_sh), \ | |
| 199 | + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_MODE, mask_sh), \ | |
| 200 | + TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_LOW, mask_sh), \ | |
| 201 | + TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_HIGH, mask_sh), \ | |
| 202 | + TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_LOW, mask_sh), \ | |
| 203 | + TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_HIGH, mask_sh), \ | |
| 204 | + TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_LOW, mask_sh), \ | |
| 205 | + TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_HIGH, mask_sh), \ | |
| 206 | + TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_LOW, mask_sh), \ | |
| 207 | + TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_HIGH, mask_sh), \ | |
| 208 | + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIX_INV_MODE, mask_sh), \ | |
| 209 | + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIXEL_ALPHA_MOD_EN, mask_sh), \ | |
| 210 | + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\ | |
| 211 | + TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\ | |
| 212 | + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\ | |
| 213 | + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, mask_sh),\ | |
| 214 | + TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh),\ | |
| 215 | + TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_MATRIX_MODE, mask_sh),\ | |
| 216 | + TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_LTONL_EN, mask_sh),\ | |
| 217 | + TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_EN, mask_sh),\ | |
| 218 | + TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_RINGEST_FORCE_EN, mask_sh),\ | |
| 219 | + TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_2TAP_SHARP_FACTOR, mask_sh),\ | |
| 220 | + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF1_EN, mask_sh),\ | |
| 221 | + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_MODE, mask_sh),\ | |
| 222 | + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF3_MODE, mask_sh),\ | |
| 223 | + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT1_GAIN, mask_sh),\ | |
| 224 | + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT2_GAIN, mask_sh),\ | |
| 225 | + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_ROC_GAIN, mask_sh),\ | |
| 226 | + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG1, mask_sh),\ | |
| 227 | + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG2, mask_sh),\ | |
| 228 | + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN1, mask_sh),\ | |
| 229 | + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN2, mask_sh),\ | |
| 230 | + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXA, mask_sh),\ | |
| 231 | + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXB, mask_sh),\ | |
| 232 | + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINA, mask_sh),\ | |
| 233 | + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINB, mask_sh),\ | |
| 234 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_IN_SEG0, mask_sh),\ | |
| 235 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_BASE_SEG0, mask_sh),\ | |
| 236 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_SLOPE_SEG0, mask_sh),\ | |
| 237 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_IN_SEG1, mask_sh),\ | |
| 238 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_BASE_SEG1, mask_sh),\ | |
| 239 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_SLOPE_SEG1, mask_sh),\ | |
| 240 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_IN_SEG2, mask_sh),\ | |
| 241 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_BASE_SEG2, mask_sh),\ | |
| 242 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_SLOPE_SEG2, mask_sh),\ | |
| 243 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_IN_SEG3, mask_sh),\ | |
| 244 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_BASE_SEG3, mask_sh),\ | |
| 245 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_SLOPE_SEG3, mask_sh),\ | |
| 246 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_IN_SEG4, mask_sh),\ | |
| 247 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_BASE_SEG4, mask_sh),\ | |
| 248 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_SLOPE_SEG4, mask_sh),\ | |
| 249 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_IN_SEG5, mask_sh),\ | |
| 250 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_BASE_SEG5, mask_sh),\ | |
| 251 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_SLOPE_SEG5, mask_sh),\ | |
| 252 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_IN_SEG6, mask_sh),\ | |
| 253 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_BASE_SEG6, mask_sh),\ | |
| 254 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_SLOPE_SEG6, mask_sh),\ | |
| 255 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_IN_SEG7, mask_sh),\ | |
| 256 | + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_BASE_SEG7, mask_sh),\ | |
| 257 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_IN_SEG0, mask_sh),\ | |
| 258 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_BASE_SEG0, mask_sh),\ | |
| 259 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_SLOPE_SEG0, mask_sh),\ | |
| 260 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_IN_SEG1, mask_sh),\ | |
| 261 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_BASE_SEG1, mask_sh),\ | |
| 262 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_SLOPE_SEG1, mask_sh),\ | |
| 263 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_IN_SEG2, mask_sh),\ | |
| 264 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_BASE_SEG2, mask_sh),\ | |
| 265 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_SLOPE_SEG2, mask_sh),\ | |
| 266 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_IN_SEG3, mask_sh),\ | |
| 267 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_BASE_SEG3, mask_sh),\ | |
| 268 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_SLOPE_SEG3, mask_sh),\ | |
| 269 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_IN_SEG4, mask_sh),\ | |
| 270 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_BASE_SEG4, mask_sh),\ | |
| 271 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_SLOPE_SEG4, mask_sh),\ | |
| 272 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_IN_SEG5, mask_sh),\ | |
| 273 | + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_BASE_SEG5, mask_sh),\ | |
| 274 | + TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_EN, mask_sh),\ | |
| 275 | + TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_RINGEST_FORCE_EN, mask_sh),\ | |
| 276 | + TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_2TAP_SHARP_FACTOR, mask_sh),\ | |
| 277 | + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF1_EN, mask_sh),\ | |
| 278 | + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_MODE, mask_sh),\ | |
| 279 | + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF3_MODE, mask_sh),\ | |
| 280 | + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT1_GAIN, mask_sh),\ | |
| 281 | + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT2_GAIN, mask_sh),\ | |
| 282 | + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_ROC_GAIN, mask_sh),\ | |
| 283 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_DNTILT_UPTILT, mask_sh),\ | |
| 284 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_UPTILT_MAXVAL, mask_sh),\ | |
| 285 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_DNTILT_SLOPE, mask_sh),\ | |
| 286 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_UPTILT1_SLOPE, mask_sh),\ | |
| 287 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_SLOPE, mask_sh),\ | |
| 288 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_OFFSET, mask_sh),\ | |
| 289 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG1, mask_sh),\ | |
| 290 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG2, mask_sh),\ | |
| 291 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN1, mask_sh),\ | |
| 292 | + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN2, mask_sh),\ | |
| 293 | + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXA, mask_sh),\ | |
| 294 | + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXB, mask_sh),\ | |
| 295 | + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINA, mask_sh),\ | |
| 296 | + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINB, mask_sh),\ | |
| 297 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_IN_SEG0, mask_sh),\ | |
| 298 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_BASE_SEG0, mask_sh),\ | |
| 299 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_SLOPE_SEG0, mask_sh),\ | |
| 300 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_IN_SEG1, mask_sh),\ | |
| 301 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_BASE_SEG1, mask_sh),\ | |
| 302 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_SLOPE_SEG1, mask_sh),\ | |
| 303 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_IN_SEG2, mask_sh),\ | |
| 304 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_BASE_SEG2, mask_sh),\ | |
| 305 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_SLOPE_SEG2, mask_sh),\ | |
| 306 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_IN_SEG3, mask_sh),\ | |
| 307 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_BASE_SEG3, mask_sh),\ | |
| 308 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_SLOPE_SEG3, mask_sh),\ | |
| 309 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_IN_SEG4, mask_sh),\ | |
| 310 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_BASE_SEG4, mask_sh),\ | |
| 311 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_SLOPE_SEG4, mask_sh),\ | |
| 312 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_IN_SEG5, mask_sh),\ | |
| 313 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_BASE_SEG5, mask_sh),\ | |
| 314 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_SLOPE_SEG5, mask_sh),\ | |
| 315 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_IN_SEG6, mask_sh),\ | |
| 316 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_BASE_SEG6, mask_sh),\ | |
| 317 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_SLOPE_SEG6, mask_sh),\ | |
| 318 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_IN_SEG7, mask_sh),\ | |
| 319 | + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_BASE_SEG7, mask_sh),\ | |
| 320 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_IN_SEG0, mask_sh),\ | |
| 321 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_BASE_SEG0, mask_sh),\ | |
| 322 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_SLOPE_SEG0, mask_sh),\ | |
| 323 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_IN_SEG1, mask_sh),\ | |
| 324 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_BASE_SEG1, mask_sh),\ | |
| 325 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_SLOPE_SEG1, mask_sh),\ | |
| 326 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_IN_SEG2, mask_sh),\ | |
| 327 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_BASE_SEG2, mask_sh),\ | |
| 328 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_SLOPE_SEG2, mask_sh),\ | |
| 329 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_IN_SEG3, mask_sh),\ | |
| 330 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_BASE_SEG3, mask_sh),\ | |
| 331 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_SLOPE_SEG3, mask_sh),\ | |
| 332 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_IN_SEG4, mask_sh),\ | |
| 333 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_BASE_SEG4, mask_sh),\ | |
| 334 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_SLOPE_SEG4, mask_sh),\ | |
| 335 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_IN_SEG5, mask_sh),\ | |
| 336 | + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_BASE_SEG5, mask_sh),\ | |
| 337 | + TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C0, mask_sh),\ | |
| 338 | + TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C1, mask_sh),\ | |
| 339 | + TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C2, mask_sh),\ | |
| 340 | + TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C3, mask_sh),\ | |
| 341 | + TF_SF(DSCL0_ISHARP_DELTA_CTRL, ISHARP_DELTA_LUT_HOST_SELECT, mask_sh),\ | |
| 342 | + TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_DIS, mask_sh),\ | |
| 343 | + TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_FORCE, mask_sh),\ | |
| 344 | + TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_STATE, mask_sh),\ | |
| 345 | + TF_SF(DSCL0_ISHARP_DELTA_DATA, ISHARP_DELTA_DATA, mask_sh),\ | |
| 346 | + TF_SF(DSCL0_ISHARP_DELTA_INDEX, ISHARP_DELTA_INDEX, mask_sh),\ | |
| 347 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_EN, mask_sh),\ | |
| 348 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_EN, mask_sh),\ | |
| 349 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_MODE, mask_sh),\ | |
| 350 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_LBA_MODE, mask_sh),\ | |
| 351 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT, mask_sh),\ | |
| 352 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_MODE, mask_sh),\ | |
| 353 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_NORM, mask_sh),\ | |
| 354 | + TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT_CURRENT, mask_sh),\ | |
| 355 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_IN_SEG0, mask_sh),\ | |
| 356 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_BASE_SEG0, mask_sh),\ | |
| 357 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_SLOPE_SEG0, mask_sh), \ | |
| 358 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_IN_SEG1, mask_sh),\ | |
| 359 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_BASE_SEG1, mask_sh),\ | |
| 360 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_SLOPE_SEG1, mask_sh),\ | |
| 361 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_IN_SEG2, mask_sh),\ | |
| 362 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_BASE_SEG2, mask_sh),\ | |
| 363 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_SLOPE_SEG2, mask_sh),\ | |
| 364 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_IN_SEG3, mask_sh),\ | |
| 365 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_BASE_SEG3, mask_sh),\ | |
| 366 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_SLOPE_SEG3, mask_sh),\ | |
| 367 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_IN_SEG4, mask_sh),\ | |
| 368 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_BASE_SEG4, mask_sh),\ | |
| 369 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_SLOPE_SEG4, mask_sh),\ | |
| 370 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_IN_SEG5, mask_sh),\ | |
| 371 | + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_BASE_SEG5, mask_sh),\ | |
| 372 | + TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_UTHRE, mask_sh),\ | |
| 373 | + TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_DTHRE, mask_sh), \ | |
| 374 | + TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_START_IN, mask_sh), \ | |
| 375 | + TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_END_IN, mask_sh), \ | |
| 376 | + TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_SLOPE, mask_sh), \ | |
| 377 | + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_P, mask_sh), \ | |
| 378 | + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_P, mask_sh), \ | |
| 379 | + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_P, mask_sh), \ | |
| 380 | + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_N, mask_sh), \ | |
| 381 | + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_N, mask_sh), \ | |
| 382 | + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_N, mask_sh), \ | |
| 383 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\ | |
| 384 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\ | |
| 385 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ | |
| 386 | + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh) | |
| 387 | + | |
| 388 | +#define DPP_REG_FIELD_LIST_DCN42(type) \ | |
| 389 | + DPP_REG_FIELD_LIST_DCN401(type); \ | |
| 390 | + type CM_HIST_SEL; \ | |
| 391 | + type CM_HIST_CH_EN; \ | |
| 392 | + type CM_HIST_SRC1_SEL; \ | |
| 393 | + type CM_HIST_SRC2_SEL; \ | |
| 394 | + type CM_HIST_SRC3_SEL; \ | |
| 395 | + type CM_HIST_CH1_XBAR; \ | |
| 396 | + type CM_HIST_CH2_XBAR; \ | |
| 397 | + type CM_HIST_CH3_XBAR; \ | |
| 398 | + type CM_HIST_FORMAT; \ | |
| 399 | + type CM_HIST_READ_CHANNEL_MASK; \ | |
| 400 | + type CM_HIST_LOCK; \ | |
| 401 | + type CM_HIST_INDEX; \ | |
| 402 | + type CM_HIST_DATA; \ | |
| 403 | + type CM_HIST_BUFA_RDY_STATUS; \ | |
| 404 | + type CM_HIST_BUFB_RDY_STATUS; \ | |
| 405 | + type CM_HIST_SCALE_SRC1; \ | |
| 406 | + type CM_HIST_COEFA_SRC2; \ | |
| 407 | + type CM_HIST_COEFB_SRC2; \ | |
| 408 | + type CM_HIST_COEFC_SRC2; \ | |
| 409 | + type CM_HIST_SCALE_SRC3; \ | |
| 410 | + type CM_HIST_BIAS_SRC1; \ | |
| 411 | + type CM_HIST_BIAS_SRC2; \ | |
| 412 | + type CM_HIST_BIAS_SRC3 | |
| 413 | + | |
| 414 | + | |
| 415 | +#define DPP_REG_VARIABLE_LIST_DCN42 \ | |
| 416 | + DPP_REG_VARIABLE_LIST_DCN401; \ | |
| 417 | + uint32_t ALPHA_2BIT_LUT01; \ | |
| 418 | + uint32_t ALPHA_2BIT_LUT23; \ | |
| 419 | + uint32_t CM_HIST_CNTL; \ | |
| 420 | + uint32_t CM_HIST_INDEX; \ | |
| 421 | + uint32_t CM_HIST_LOCK; \ | |
| 422 | + uint32_t CM_HIST_DATA; \ | |
| 423 | + uint32_t CM_HIST_STATUS; \ | |
| 424 | + uint32_t CM_HIST_SCALE_SRC1; \ | |
| 425 | + uint32_t CM_HIST_COEFA_SRC2; \ | |
| 426 | + uint32_t CM_HIST_COEFB_SRC2; \ | |
| 427 | + uint32_t CM_HIST_COEFC_SRC2; \ | |
| 428 | + uint32_t CM_HIST_SCALE_SRC3; \ | |
| 429 | + uint32_t CM_HIST_BIAS_SRC1; \ | |
| 430 | + uint32_t CM_HIST_BIAS_SRC2; \ | |
| 431 | + uint32_t CM_HIST_BIAS_SRC3 | |
| 432 | + | |
| 433 | +struct dcn42_dpp_registers { | |
| 434 | + DPP_REG_VARIABLE_LIST_DCN42; | |
| 435 | +}; | |
| 436 | + | |
| 437 | +struct dcn42_dpp_shift { | |
| 438 | + DPP_REG_FIELD_LIST_DCN42(uint8_t); | |
| 439 | +}; | |
| 440 | + | |
| 441 | +struct dcn42_dpp_mask { | |
| 442 | + DPP_REG_FIELD_LIST_DCN42(uint32_t); | |
| 443 | +}; | |
| 444 | +struct dcn42_dpp { | |
| 445 | + struct dpp base; | |
| 446 | + const struct dcn42_dpp_registers *tf_regs; | |
| 447 | + const struct dcn42_dpp_shift *tf_shift; | |
| 448 | + const struct dcn42_dpp_mask *tf_mask; | |
| 449 | + const uint16_t *filter_v; | |
| 450 | + const uint16_t *filter_h; | |
| 451 | + const uint16_t *filter_v_c; | |
| 452 | + const uint16_t *filter_h_c; | |
| 453 | + int lb_pixel_depth_supported; | |
| 454 | + int lb_memory_size; | |
| 455 | + int lb_bits_per_entry; | |
| 456 | + bool is_write_to_ram_a_safe; | |
| 457 | + struct scaler_data scl_data; | |
| 458 | + struct pwl_params pwl_data; | |
| 459 | +}; | |
| 460 | + | |
| 461 | +bool dpp42_construct(struct dcn42_dpp *dpp42, | |
| 462 | + struct dc_context *ctx, | |
| 463 | + uint32_t inst, | |
| 464 | + const struct dcn42_dpp_registers *tf_regs, | |
| 465 | + const struct dcn42_dpp_shift *tf_shift, | |
| 466 | + const struct dcn42_dpp_mask *tf_mask); | |
| 467 | + | |
| 468 | + | |
| 469 | +#endif /* __DCN42_DPP_H__ */ | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | # |
| 2 | −# Copyright 2017 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2017-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -132,3 +132,14 @@ AMD_DAL_GPIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn401/,$(GPIO_DCN401)) · 126 unmodified lines | ||
| 132 | 132 | |
| 133 | 133 | AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN401) |
| 134 | 134 | |
| 135 | +############################################################################### | |
| 136 | +# DCN 4.2 | |
| 137 | +############################################################################### | |
| 138 | + | |
| 139 | +GPIO_DCN42 = hw_translate_dcn42.o hw_factory_dcn42.o | |
| 140 | + | |
| 141 | +AMD_DAL_GPIO_DCN42 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn42/,$(GPIO_DCN42)) | |
| 142 | + | |
| 143 | +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN42) | |
| 144 | + | |
| 145 | + | |
| @@ -0,0 +1,254 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dm_services.h" | |
| 6 | +#include "include/gpio_types.h" | |
| 7 | +#include "../hw_factory.h" | |
| 8 | + | |
| 9 | + | |
| 10 | +#include "../hw_gpio.h" | |
| 11 | +#include "../hw_ddc.h" | |
| 12 | +#include "../hw_hpd.h" | |
| 13 | +#include "../hw_generic.h" | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | +#include "dcn/dcn_4_2_0_offset.h" | |
| 18 | +#include "dcn/dcn_4_2_0_sh_mask.h" | |
| 19 | +#include "dpcs/dpcs_4_0_0_offset.h" | |
| 20 | +#include "dpcs/dpcs_4_0_0_sh_mask.h" | |
| 21 | + | |
| 22 | +#include "reg_helper.h" | |
| 23 | +#include "../hpd_regs.h" | |
| 24 | +#include "hw_factory_dcn42.h" | |
| 25 | + | |
| 26 | +#define DCN_BASE__INST0_SEG2 0x000034C0 | |
| 27 | + | |
| 28 | +/* begin ********************* | |
| 29 | + * macros to expend register list macro defined in HW object header file */ | |
| 30 | + | |
| 31 | +/* DCN */ | |
| 32 | +#define block HPD | |
| 33 | +#define reg_num 0 | |
| 34 | + | |
| 35 | +#undef BASE_INNER | |
| 36 | +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg | |
| 37 | + | |
| 38 | +#define BASE(seg) BASE_INNER(seg) | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | +#define REG(reg_name)\ | |
| 43 | + (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name) | |
| 44 | + | |
| 45 | +#define SF_HPD(reg_name, field_name, post_fix)\ | |
| 46 | + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix | |
| 47 | + | |
| 48 | +#define REGI(reg_name, block, id)\ | |
| 49 | + (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ | |
| 50 | + reg ## block ## id ## _ ## reg_name) | |
| 51 | + | |
| 52 | +#define SF(reg_name, field_name, post_fix)\ | |
| 53 | + .field_name = reg_name ## __ ## field_name ## post_fix | |
| 54 | + | |
| 55 | +/* macros to expend register list macro defined in HW object header file | |
| 56 | + * end *********************/ | |
| 57 | + | |
| 58 | +// DC_GPIO_HPD_* registers are gone. | |
| 59 | +#undef HPD_REG_LIST | |
| 60 | +#define HPD_REG_LIST(id) \ | |
| 61 | + .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\ | |
| 62 | + .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id) | |
| 63 | + | |
| 64 | +#define hpd_regs(id) \ | |
| 65 | +{\ | |
| 66 | + HPD_REG_LIST(id)\ | |
| 67 | +} | |
| 68 | + | |
| 69 | +static const struct hpd_registers hpd_regs[] = { | |
| 70 | + hpd_regs(0), | |
| 71 | + hpd_regs(1), | |
| 72 | + hpd_regs(2), | |
| 73 | + hpd_regs(3), | |
| 74 | + hpd_regs(4), | |
| 75 | +}; | |
| 76 | + | |
| 77 | +static const struct hpd_sh_mask hpd_shift = { | |
| 78 | + HPD_MASK_SH_LIST(__SHIFT) | |
| 79 | +}; | |
| 80 | + | |
| 81 | +static const struct hpd_sh_mask hpd_mask = { | |
| 82 | + HPD_MASK_SH_LIST(_MASK) | |
| 83 | +}; | |
| 84 | + | |
| 85 | +#include "../ddc_regs.h" | |
| 86 | + | |
| 87 | + /* set field name */ | |
| 88 | +#define SF_DDC(reg_name, field_name, post_fix)\ | |
| 89 | + .field_name = reg_name ## __ ## field_name ## post_fix | |
| 90 | + | |
| 91 | +static const struct ddc_registers ddc_data_regs_dcn[] = { | |
| 92 | + ddc_data_regs_dcn2(1), | |
| 93 | + ddc_data_regs_dcn2(2), | |
| 94 | + ddc_data_regs_dcn2(3), | |
| 95 | + ddc_data_regs_dcn2(4), | |
| 96 | + ddc_data_regs_dcn2(5), | |
| 97 | + { | |
| 98 | + // add a dummy entry for cases no such port | |
| 99 | + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, | |
| 100 | + .ddc_setup = 0, | |
| 101 | + .phy_aux_cntl = 0, | |
| 102 | + .dc_gpio_aux_ctrl_5 = 0 | |
| 103 | + }, | |
| 104 | + { | |
| 105 | + DDC_GPIO_VGA_REG_LIST(DATA), | |
| 106 | + .ddc_setup = 0, | |
| 107 | + .phy_aux_cntl = 0, | |
| 108 | + .dc_gpio_aux_ctrl_5 = 0 | |
| 109 | + } | |
| 110 | +}; | |
| 111 | + | |
| 112 | +static const struct ddc_registers ddc_clk_regs_dcn[] = { | |
| 113 | + ddc_clk_regs_dcn2(1), | |
| 114 | + ddc_clk_regs_dcn2(2), | |
| 115 | + ddc_clk_regs_dcn2(3), | |
| 116 | + ddc_clk_regs_dcn2(4), | |
| 117 | + ddc_clk_regs_dcn2(5), | |
| 118 | + { | |
| 119 | + // add a dummy entry for cases no such port | |
| 120 | + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, | |
| 121 | + .ddc_setup = 0, | |
| 122 | + .phy_aux_cntl = 0, | |
| 123 | + .dc_gpio_aux_ctrl_5 = 0 | |
| 124 | + }, | |
| 125 | + { | |
| 126 | + DDC_GPIO_VGA_REG_LIST(CLK), | |
| 127 | + .ddc_setup = 0, | |
| 128 | + .phy_aux_cntl = 0, | |
| 129 | + .dc_gpio_aux_ctrl_5 = 0 | |
| 130 | + } | |
| 131 | +}; | |
| 132 | + | |
| 133 | +static const struct ddc_sh_mask ddc_shift[] = { | |
| 134 | + DDC_MASK_SH_LIST_DCN2(__SHIFT, 1), | |
| 135 | + DDC_MASK_SH_LIST_DCN2(__SHIFT, 2), | |
| 136 | + DDC_MASK_SH_LIST_DCN2(__SHIFT, 3), | |
| 137 | + DDC_MASK_SH_LIST_DCN2(__SHIFT, 4), | |
| 138 | + DDC_MASK_SH_LIST_DCN2(__SHIFT, 5), | |
| 139 | + DDC_MASK_SH_LIST_DCN2(__SHIFT, 6), | |
| 140 | + DDC_MASK_SH_LIST_DCN2_VGA(__SHIFT) | |
| 141 | +}; | |
| 142 | + | |
| 143 | +static const struct ddc_sh_mask ddc_mask[] = { | |
| 144 | + DDC_MASK_SH_LIST_DCN2(_MASK, 1), | |
| 145 | + DDC_MASK_SH_LIST_DCN2(_MASK, 2), | |
| 146 | + DDC_MASK_SH_LIST_DCN2(_MASK, 3), | |
| 147 | + DDC_MASK_SH_LIST_DCN2(_MASK, 4), | |
| 148 | + DDC_MASK_SH_LIST_DCN2(_MASK, 5), | |
| 149 | + DDC_MASK_SH_LIST_DCN2(_MASK, 6), | |
| 150 | + DDC_MASK_SH_LIST_DCN2_VGA(_MASK) | |
| 151 | +}; | |
| 152 | + | |
| 153 | +#include "../generic_regs.h" | |
| 154 | + | |
| 155 | +/* set field name */ | |
| 156 | +#define SF_GENERIC(reg_name, field_name, post_fix)\ | |
| 157 | + .field_name = 0 | |
| 158 | + | |
| 159 | +static const struct generic_registers generic_regs[] = { | |
| 160 | + {{ 0 }}, | |
| 161 | + {{ 0 }}, | |
| 162 | +}; | |
| 163 | + | |
| 164 | +static const struct generic_sh_mask generic_shift[] = { | |
| 165 | + { 0 }, | |
| 166 | + { 0 }, | |
| 167 | +}; | |
| 168 | + | |
| 169 | +static const struct generic_sh_mask generic_mask[] = { | |
| 170 | + { 0 }, | |
| 171 | + { 0 }, | |
| 172 | +}; | |
| 173 | + | |
| 174 | +static void define_generic_registers(struct hw_gpio_pin *pin, uint32_t en) | |
| 175 | +{ | |
| 176 | + struct hw_generic *generic = HW_GENERIC_FROM_BASE(pin); | |
| 177 | + | |
| 178 | + generic->regs = &generic_regs[en]; | |
| 179 | + generic->shifts = &generic_shift[en]; | |
| 180 | + generic->masks = &generic_mask[en]; | |
| 181 | + generic->base.regs = &generic_regs[en].gpio; | |
| 182 | +} | |
| 183 | + | |
| 184 | +static void define_ddc_registers( | |
| 185 | + struct hw_gpio_pin *pin, | |
| 186 | + uint32_t en) | |
| 187 | +{ | |
| 188 | + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); | |
| 189 | + | |
| 190 | + switch (pin->id) { | |
| 191 | + case GPIO_ID_DDC_DATA: | |
| 192 | + ddc->regs = &ddc_data_regs_dcn[en]; | |
| 193 | + ddc->base.regs = &ddc_data_regs_dcn[en].gpio; | |
| 194 | + break; | |
| 195 | + case GPIO_ID_DDC_CLOCK: | |
| 196 | + ddc->regs = &ddc_clk_regs_dcn[en]; | |
| 197 | + ddc->base.regs = &ddc_clk_regs_dcn[en].gpio; | |
| 198 | + break; | |
| 199 | + default: | |
| 200 | + ASSERT_CRITICAL(false); | |
| 201 | + return; | |
| 202 | + } | |
| 203 | + | |
| 204 | + ddc->shifts = &ddc_shift[en]; | |
| 205 | + ddc->masks = &ddc_mask[en]; | |
| 206 | + | |
| 207 | +} | |
| 208 | + | |
| 209 | +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) | |
| 210 | +{ | |
| 211 | + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); | |
| 212 | + | |
| 213 | + hpd->regs = &hpd_regs[en]; | |
| 214 | + hpd->shifts = &hpd_shift; | |
| 215 | + hpd->masks = &hpd_mask; | |
| 216 | + hpd->base.regs = &hpd_regs[en].gpio; | |
| 217 | +} | |
| 218 | + | |
| 219 | + | |
| 220 | +/* function table */ | |
| 221 | +static const struct hw_factory_funcs funcs = { | |
| 222 | + .init_ddc_data = dal_hw_ddc_init, | |
| 223 | + .init_generic = dal_hw_generic_init, | |
| 224 | + .init_hpd = dal_hw_hpd_init, | |
| 225 | + .get_ddc_pin = dal_hw_ddc_get_pin, | |
| 226 | + .get_hpd_pin = dal_hw_hpd_get_pin, | |
| 227 | + .get_generic_pin = dal_hw_generic_get_pin, | |
| 228 | + .define_hpd_registers = define_hpd_registers, | |
| 229 | + .define_ddc_registers = define_ddc_registers, | |
| 230 | + .define_generic_registers = define_generic_registers | |
| 231 | +}; | |
| 232 | + | |
| 233 | +/* | |
| 234 | + * dal_hw_factory_dcn42_init | |
| 235 | + * | |
| 236 | + * @brief | |
| 237 | + * Initialize HW factory function pointers and pin info | |
| 238 | + * | |
| 239 | + * @param | |
| 240 | + * struct hw_factory *factory - [out] struct of function pointers | |
| 241 | + */ | |
| 242 | +void dal_hw_factory_dcn42_init(struct hw_factory *factory) | |
| 243 | +{ | |
| 244 | + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; | |
| 245 | + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; | |
| 246 | + factory->number_of_pins[GPIO_ID_GENERIC] = 4; | |
| 247 | + factory->number_of_pins[GPIO_ID_HPD] = 5; | |
| 248 | + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 28; | |
| 249 | + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; | |
| 250 | + factory->number_of_pins[GPIO_ID_SYNC] = 0; | |
| 251 | + factory->number_of_pins[GPIO_ID_GSL] = 0;/*add this*/ | |
| 252 | + | |
| 253 | + factory->funcs = &funcs; | |
| 254 | +} | |
| @@ -0,0 +1,31 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +#ifndef __DAL_HW_FACTORY_DCN42_H__ | |
| 26 | +#define __DAL_HW_FACTORY_DCN42_H__ | |
| 27 | + | |
| 28 | +/* Initialize HW factory function pointers and pin info */ | |
| 29 | +void dal_hw_factory_dcn42_init(struct hw_factory *factory); | |
| 30 | + | |
| 31 | +#endif /* __DAL_HW_FACTORY_DCN42_H__ */ | |
| @@ -0,0 +1,205 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "hw_translate_dcn42.h" | |
| 6 | + | |
| 7 | +#include "dm_services.h" | |
| 8 | +#include "include/gpio_types.h" | |
| 9 | +#include "../hw_translate.h" | |
| 10 | + | |
| 11 | + | |
| 12 | +#include "dcn/dcn_4_2_0_offset.h" | |
| 13 | +#include "dcn/dcn_4_2_0_sh_mask.h" | |
| 14 | +#include "dpcs/dpcs_4_0_0_offset.h" | |
| 15 | +#include "dpcs/dpcs_4_0_0_sh_mask.h" | |
| 16 | + | |
| 17 | +#define DCN_BASE__INST0_SEG2 0x000034C0 | |
| 18 | + | |
| 19 | +/* begin ********************* | |
| 20 | + * macros to expend register list macro defined in HW object header file */ | |
| 21 | + | |
| 22 | +/* DCN */ | |
| 23 | +#define block HPD | |
| 24 | +#define reg_num 0 | |
| 25 | + | |
| 26 | +#undef BASE_INNER | |
| 27 | +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg | |
| 28 | + | |
| 29 | +#define BASE(seg) BASE_INNER(seg) | |
| 30 | + | |
| 31 | +#undef REG | |
| 32 | +#define REG(reg_name)\ | |
| 33 | + (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name) | |
| 34 | +#define SF_HPD(reg_name, field_name, post_fix)\ | |
| 35 | + .field_name = reg_name ## __ ## field_name ## post_fix | |
| 36 | + | |
| 37 | + | |
| 38 | +/* macros to expend register list macro defined in HW object header file | |
| 39 | + * end *********************/ | |
| 40 | + | |
| 41 | + | |
| 42 | +static bool offset_to_id( | |
| 43 | + uint32_t offset, | |
| 44 | + uint32_t mask, | |
| 45 | + enum gpio_id *id, | |
| 46 | + uint32_t *en) | |
| 47 | +{ | |
| 48 | + switch (offset) { | |
| 49 | + /* HPD */ | |
| 50 | + case REG(HPD0_DC_HPD_INT_STATUS): | |
| 51 | + *id = GPIO_ID_HPD; | |
| 52 | + *en = GPIO_HPD_1; | |
| 53 | + return true; | |
| 54 | + case REG(HPD1_DC_HPD_INT_STATUS): | |
| 55 | + *id = GPIO_ID_HPD; | |
| 56 | + *en = GPIO_HPD_2; | |
| 57 | + return true; | |
| 58 | + case REG(HPD2_DC_HPD_INT_STATUS): | |
| 59 | + *id = GPIO_ID_HPD; | |
| 60 | + *en = GPIO_HPD_3; | |
| 61 | + return true; | |
| 62 | + case REG(HPD3_DC_HPD_INT_STATUS): | |
| 63 | + *id = GPIO_ID_HPD; | |
| 64 | + *en = GPIO_HPD_4; | |
| 65 | + return true; | |
| 66 | + case REG(HPD4_DC_HPD_INT_STATUS): | |
| 67 | + *id = GPIO_ID_HPD; | |
| 68 | + *en = GPIO_HPD_5; | |
| 69 | + return true; | |
| 70 | + /* DDC */ | |
| 71 | + /* we don't care about the GPIO_ID for DDC | |
| 72 | + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK | |
| 73 | + * directly in the create method | |
| 74 | + */ | |
| 75 | + case REG(DC_GPIO_DDC1_A): | |
| 76 | + *en = GPIO_DDC_LINE_DDC1; | |
| 77 | + return true; | |
| 78 | + case REG(DC_GPIO_DDC2_A): | |
| 79 | + *en = GPIO_DDC_LINE_DDC2; | |
| 80 | + return true; | |
| 81 | + case REG(DC_GPIO_DDC3_A): | |
| 82 | + *en = GPIO_DDC_LINE_DDC3; | |
| 83 | + return true; | |
| 84 | + case REG(DC_GPIO_DDC4_A): | |
| 85 | + *en = GPIO_DDC_LINE_DDC4; | |
| 86 | + return true; | |
| 87 | + case REG(DC_GPIO_DDC5_A): | |
| 88 | + *en = GPIO_DDC_LINE_DDC5; | |
| 89 | + return true; | |
| 90 | + case REG(DC_GPIO_DDCVGA_A): | |
| 91 | + *en = GPIO_DDC_LINE_DDC_VGA; | |
| 92 | + return true; | |
| 93 | + default: | |
| 94 | + ASSERT_CRITICAL(false); | |
| 95 | + return false; | |
| 96 | + } | |
| 97 | +} | |
| 98 | + | |
| 99 | + | |
| 100 | +static bool id_to_offset( | |
| 101 | + enum gpio_id id, | |
| 102 | + uint32_t en, | |
| 103 | + struct gpio_pin_info *info) | |
| 104 | +{ | |
| 105 | + bool result = true; | |
| 106 | + | |
| 107 | + switch (id) { | |
| 108 | + case GPIO_ID_DDC_DATA: | |
| 109 | + info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK; | |
| 110 | + switch (en) { | |
| 111 | + case GPIO_DDC_LINE_DDC1: | |
| 112 | + info->offset = REG(DC_GPIO_DDC1_A); | |
| 113 | + break; | |
| 114 | + case GPIO_DDC_LINE_DDC2: | |
| 115 | + info->offset = REG(DC_GPIO_DDC2_A); | |
| 116 | + break; | |
| 117 | + case GPIO_DDC_LINE_DDC3: | |
| 118 | + info->offset = REG(DC_GPIO_DDC3_A); | |
| 119 | + break; | |
| 120 | + case GPIO_DDC_LINE_DDC4: | |
| 121 | + info->offset = REG(DC_GPIO_DDC4_A); | |
| 122 | + break; | |
| 123 | + case GPIO_DDC_LINE_DDC5: | |
| 124 | + info->offset = REG(DC_GPIO_DDC5_A); | |
| 125 | + break; | |
| 126 | + case GPIO_DDC_LINE_DDC_VGA: | |
| 127 | + info->offset = REG(DC_GPIO_DDCVGA_A); | |
| 128 | + break; | |
| 129 | + case GPIO_DDC_LINE_I2C_PAD: | |
| 130 | + default: | |
| 131 | + ASSERT_CRITICAL(false); | |
| 132 | + result = false; | |
| 133 | + } | |
| 134 | + break; | |
| 135 | + case GPIO_ID_DDC_CLOCK: | |
| 136 | + info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK; | |
| 137 | + switch (en) { | |
| 138 | + case GPIO_DDC_LINE_DDC1: | |
| 139 | + info->offset = REG(DC_GPIO_DDC1_A); | |
| 140 | + break; | |
| 141 | + case GPIO_DDC_LINE_DDC2: | |
| 142 | + info->offset = REG(DC_GPIO_DDC2_A); | |
| 143 | + break; | |
| 144 | + case GPIO_DDC_LINE_DDC3: | |
| 145 | + info->offset = REG(DC_GPIO_DDC3_A); | |
| 146 | + break; | |
| 147 | + case GPIO_DDC_LINE_DDC4: | |
| 148 | + info->offset = REG(DC_GPIO_DDC4_A); | |
| 149 | + break; | |
| 150 | + case GPIO_DDC_LINE_DDC5: | |
| 151 | + info->offset = REG(DC_GPIO_DDC5_A); | |
| 152 | + break; | |
| 153 | + case GPIO_DDC_LINE_DDC_VGA: | |
| 154 | + info->offset = REG(DC_GPIO_DDCVGA_A); | |
| 155 | + break; | |
| 156 | + case GPIO_DDC_LINE_I2C_PAD: | |
| 157 | + default: | |
| 158 | + ASSERT_CRITICAL(false); | |
| 159 | + result = false; | |
| 160 | + } | |
| 161 | + break; | |
| 162 | + case GPIO_ID_SYNC: | |
| 163 | + case GPIO_ID_VIP_PAD: | |
| 164 | + default: | |
| 165 | + ASSERT_CRITICAL(false); | |
| 166 | + result = false; | |
| 167 | + } | |
| 168 | + | |
| 169 | + if (result) { | |
| 170 | + info->offset_y = info->offset + 2; | |
| 171 | + info->offset_en = info->offset + 1; | |
| 172 | + info->offset_mask = info->offset - 1; | |
| 173 | + | |
| 174 | + info->mask_y = info->mask; | |
| 175 | + info->mask_en = info->mask; | |
| 176 | + info->mask_mask = info->mask; | |
| 177 | + } | |
| 178 | + | |
| 179 | + return result; | |
| 180 | +} | |
| 181 | + | |
| 182 | + | |
| 183 | +/* function table */ | |
| 184 | +static const struct hw_translate_funcs funcs = { | |
| 185 | + .offset_to_id = offset_to_id, | |
| 186 | + .id_to_offset = id_to_offset, | |
| 187 | +}; | |
| 188 | + | |
| 189 | + | |
| 190 | +/* | |
| 191 | + * dal_hw_translate_dcn42_init | |
| 192 | + * | |
| 193 | + * @brief | |
| 194 | + * Initialize Hw translate function pointers. | |
| 195 | + * | |
| 196 | + * @param | |
| 197 | + * struct hw_translate *tr - [out] struct of function pointers | |
| 198 | + * | |
| 199 | + */ | |
| 200 | +void dal_hw_translate_dcn42_init(struct hw_translate *tr) | |
| 201 | +{ | |
| 202 | + tr->funcs = &funcs; | |
| 203 | +} | |
| 204 | + | |
| 205 | + | |
| @@ -0,0 +1,36 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + */ | |
| 24 | + | |
| 25 | +#ifndef __DAL_HW_TRANSLATE_DCN42_H__ | |
| 26 | +#define __DAL_HW_TRANSLATE_DCN42_H__ | |
| 27 | + | |
| 28 | +struct hw_translate; | |
| 29 | + | |
| 30 | +/* Initialize Hw translate function pointers */ | |
| 31 | +void dal_hw_translate_dcn42_init(struct hw_translate *tr); | |
| 32 | +#ifdef DAL_EMULATION_SUPPORTED | |
| 33 | +void dal_emulated_hw_translate_dcn42_init(struct hw_translate *tr); | |
| 34 | +#endif | |
| 35 | + | |
| 36 | +#endif /* __DAL_HW_TRANSLATE_DCN42_H__ */ | |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | #include "dcn315/hw_factory_dcn315.h" |
| 54 | 54 | #include "dcn32/hw_factory_dcn32.h" |
| 55 | 55 | #include "dcn401/hw_factory_dcn401.h" |
| 56 | +#include "dcn42/hw_factory_dcn42.h" | |
| 56 | 57 | |
| 57 | 58 | bool dal_hw_factory_init( |
| 58 | 59 | struct hw_factory *factory, |
| @@ -118,6 +119,9 @@ bool dal_hw_factory_init( · 59 unmodified lines | ||
| 118 | 119 | case DCN_VERSION_4_01: |
| 119 | 120 | dal_hw_factory_dcn401_init(factory); |
| 120 | 121 | return true; |
| 122 | + case DCN_VERSION_4_2: | |
| 123 | + dal_hw_factory_dcn42_init(factory); | |
| 124 | + return true; | |
| 121 | 125 | default: |
| 122 | 126 | ASSERT_CRITICAL(false); |
| 123 | 127 | return false; |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | #include "dcn315/hw_translate_dcn315.h" |
| 54 | 54 | #include "dcn32/hw_translate_dcn32.h" |
| 55 | 55 | #include "dcn401/hw_translate_dcn401.h" |
| 56 | +#include "dcn42/hw_translate_dcn42.h" | |
| 56 | 57 | |
| 57 | 58 | /* |
| 58 | 59 | * This unit |
| @@ -119,6 +120,9 @@ bool dal_hw_translate_init( · 60 unmodified lines | ||
| 119 | 120 | case DCN_VERSION_4_01: |
| 120 | 121 | dal_hw_translate_dcn401_init(translate); |
| 121 | 122 | return true; |
| 123 | + case DCN_VERSION_4_2: | |
| 124 | + dal_hw_translate_dcn42_init(translate); | |
| 125 | + return true; | |
| 122 | 126 | default: |
| 123 | 127 | BREAK_TO_DEBUGGER(); |
| 124 | 128 | return false; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | # |
| 2 | −# Copyright 2020 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2020-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -47,4 +47,13 @@ HPO_DCN32 = dcn32_hpo_dp_link_encoder.o · 41 unmodified lines | ||
| 47 | 47 | AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32)) |
| 48 | 48 | |
| 49 | 49 | AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN32) |
| 50 | + | |
| 51 | +############################################################################### | |
| 52 | +# DCN42 | |
| 53 | +############################################################################### | |
| 54 | +HPO_DCN42 = dcn42_hpo_dp_link_encoder.o | |
| 55 | + | |
| 56 | +AMD_DAL_HPO_DCN42 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn42/,$(HPO_DCN42)) | |
| 57 | + | |
| 58 | +AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN42) | |
| 50 | 59 | endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2019 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2019-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -208,17 +208,24 @@ · 202 unmodified lines | ||
| 208 | 208 | type CRC_CONT_MODE_ENABLE;\ |
| 209 | 209 | type HBLANK_MINIMUM_SYMBOL_WIDTH |
| 210 | 210 | |
| 211 | +#define DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \ | |
| 212 | + type DP_STREAM_ENC_APG_CLOCK_EN | |
| 211 | 213 | |
| 214 | +#define DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\ | |
| 215 | + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh),\ | |
| 216 | + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_APG_CLOCK_EN, mask_sh) | |
| 212 | 217 | struct dcn31_hpo_dp_stream_encoder_registers { |
| 213 | 218 | DCN3_1_HPO_DP_STREAM_ENC_REGS; |
| 214 | 219 | }; |
| 215 | 220 | |
| 216 | 221 | struct dcn31_hpo_dp_stream_encoder_shift { |
| 217 | 222 | DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t); |
| 223 | + DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t); | |
| 218 | 224 | }; |
| 219 | 225 | |
| 220 | 226 | struct dcn31_hpo_dp_stream_encoder_mask { |
| 221 | 227 | DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t); |
| 228 | + DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t); | |
| 222 | 229 | }; |
| 223 | 230 | |
| 224 | 231 | struct dcn31_hpo_dp_stream_encoder { |
| @@ -241,5 +248,4 @@ void dcn31_hpo_dp_stream_encoder_construct( · 16 unmodified lines | ||
| 241 | 248 | const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, |
| 242 | 249 | const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask); |
| 243 | 250 | |
| 244 | − | |
| 245 | 251 | #endif // __DAL_DCN31_HPO_STREAM_ENCODER_H__ |
| @@ -0,0 +1,93 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dc_bios_types.h" | |
| 6 | +#include "dcn31/dcn31_hpo_dp_link_encoder.h" | |
| 7 | +#include "dcn32/dcn32_hpo_dp_link_encoder.h" | |
| 8 | +#include "dcn42_hpo_dp_link_encoder.h" | |
| 9 | +#include "reg_helper.h" | |
| 10 | +#include "stream_encoder.h" | |
| 11 | + | |
| 12 | +#define DC_LOGGER \ | |
| 13 | + enc3->base.ctx->logger | |
| 14 | + | |
| 15 | +#define REG(reg)\ | |
| 16 | + (enc3->regs->reg) | |
| 17 | + | |
| 18 | +#undef FN | |
| 19 | +#define FN(reg_name, field_name) \ | |
| 20 | + enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name | |
| 21 | + | |
| 22 | + | |
| 23 | +#define CTX \ | |
| 24 | + enc3->base.ctx | |
| 25 | + | |
| 26 | + | |
| 27 | +static void dcn42_hpo_dp_link_enc_read_state( | |
| 28 | + struct hpo_dp_link_encoder *enc, | |
| 29 | + struct hpo_dp_link_enc_state *state) | |
| 30 | +{ | |
| 31 | + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); | |
| 32 | + | |
| 33 | + ASSERT(state); | |
| 34 | + | |
| 35 | + REG_GET(DP_DPHY_SYM32_STATUS, | |
| 36 | + STATUS, &state->link_enc_enabled); | |
| 37 | + REG_GET(DP_DPHY_SYM32_CONTROL, | |
| 38 | + NUM_LANES, &state->lane_count); | |
| 39 | + REG_GET(DP_DPHY_SYM32_CONTROL, | |
| 40 | + MODE, (uint32_t *)&state->link_mode); | |
| 41 | + | |
| 42 | + REG_GET_2(DP_DPHY_SYM32_SAT_VC0, | |
| 43 | + SAT_STREAM_SOURCE, &state->stream_src[0], | |
| 44 | + SAT_SLOT_COUNT, &state->slot_count[0]); | |
| 45 | + REG_GET_2(DP_DPHY_SYM32_SAT_VC1, | |
| 46 | + SAT_STREAM_SOURCE, &state->stream_src[1], | |
| 47 | + SAT_SLOT_COUNT, &state->slot_count[1]); | |
| 48 | + REG_GET_2(DP_DPHY_SYM32_SAT_VC2, | |
| 49 | + SAT_STREAM_SOURCE, &state->stream_src[2], | |
| 50 | + SAT_SLOT_COUNT, &state->slot_count[2]); | |
| 51 | + | |
| 52 | + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, | |
| 53 | + STREAM_VC_RATE_X, &state->vc_rate_x[0], | |
| 54 | + STREAM_VC_RATE_Y, &state->vc_rate_y[0]); | |
| 55 | + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, | |
| 56 | + STREAM_VC_RATE_X, &state->vc_rate_x[1], | |
| 57 | + STREAM_VC_RATE_Y, &state->vc_rate_y[1]); | |
| 58 | + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, | |
| 59 | + STREAM_VC_RATE_X, &state->vc_rate_x[2], | |
| 60 | + STREAM_VC_RATE_Y, &state->vc_rate_y[2]); | |
| 61 | +} | |
| 62 | + | |
| 63 | +static struct hpo_dp_link_encoder_funcs dcn42_hpo_dp_link_encoder_funcs = { | |
| 64 | + .enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output, | |
| 65 | + .disable_link_phy = dcn31_hpo_dp_link_enc_disable_output, | |
| 66 | + .link_enable = dcn31_hpo_dp_link_enc_enable, | |
| 67 | + .link_disable = dcn31_hpo_dp_link_enc_disable, | |
| 68 | + .set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern, | |
| 69 | + .update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table, | |
| 70 | + .set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size, | |
| 71 | + .is_in_alt_mode = dcn32_hpo_dp_link_enc_is_in_alt_mode, | |
| 72 | + .read_state = dcn42_hpo_dp_link_enc_read_state, | |
| 73 | + .set_ffe = dcn31_hpo_dp_link_enc_set_ffe, | |
| 74 | +}; | |
| 75 | + | |
| 76 | +void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31, | |
| 77 | + struct dc_context *ctx, | |
| 78 | + uint32_t inst, | |
| 79 | + const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs, | |
| 80 | + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, | |
| 81 | + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask) | |
| 82 | +{ | |
| 83 | + enc31->base.ctx = ctx; | |
| 84 | + | |
| 85 | + enc31->base.inst = inst; | |
| 86 | + enc31->base.funcs = &dcn42_hpo_dp_link_encoder_funcs; | |
| 87 | + enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN; | |
| 88 | + enc31->base.transmitter = TRANSMITTER_UNKNOWN; | |
| 89 | + | |
| 90 | + enc31->regs = hpo_le_regs; | |
| 91 | + enc31->hpo_le_shift = hpo_le_shift; | |
| 92 | + enc31->hpo_le_mask = hpo_le_mask; | |
| 93 | +} | |
| @@ -0,0 +1,17 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* Copyright 2026 Advanced Micro Devices, Inc. */ | |
| 3 | + | |
| 4 | + | |
| 5 | +#ifndef __DAL_DCN42_HPO_DP_LINK_ENCODER_H__ | |
| 6 | +#define __DAL_DCN42_HPO_DP_LINK_ENCODER_H__ | |
| 7 | + | |
| 8 | +#include "link_encoder.h" | |
| 9 | + | |
| 10 | +void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31, | |
| 11 | + struct dc_context *ctx, | |
| 12 | + uint32_t inst, | |
| 13 | + const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs, | |
| 14 | + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, | |
| 15 | + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask); | |
| 16 | + | |
| 17 | +#endif // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__ | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | |
| 2 | −# Copyright 2022 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -101,4 +101,12 @@ AMD_DAL_HUBBUB_DCN401 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn401/,$(HUBBUB_DCN · 95 unmodified lines | ||
| 101 | 101 | AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN401) |
| 102 | 102 | |
| 103 | 103 | ############################################################################### |
| 104 | +# DCN42 | |
| 105 | +############################################################################### | |
| 106 | +HUBBUB_DCN42 = dcn42_hubbub.o | |
| 107 | + | |
| 108 | +AMD_DAL_HUBBUB_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn42/,$(HUBBUB_DCN42)) | |
| 109 | + | |
| 110 | +AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN42) | |
| 111 | + | |
| 104 | 112 | endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2016 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2016-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -441,6 +441,8 @@ struct dcn_hubbub_registers { · 435 unmodified lines | ||
| 441 | 441 | type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE;\ |
| 442 | 442 | type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE |
| 443 | 443 | |
| 444 | +#define HUBBUB_REG_FIELD_LIST_DCN4_2(type) \ | |
| 445 | + type URGENT_ZERO_SIZE_REQ_EN | |
| 444 | 446 | struct dcn_hubbub_shift { |
| 445 | 447 | DCN_HUBBUB_REG_FIELD_LIST(uint8_t); |
| 446 | 448 | HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t); |
| @@ -449,6 +451,7 @@ struct dcn_hubbub_shift { · 2 unmodified lines | ||
| 449 | 451 | HUBBUB_REG_FIELD_LIST_DCN32(uint8_t); |
| 450 | 452 | HUBBUB_REG_FIELD_LIST_DCN35(uint8_t); |
| 451 | 453 | HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t); |
| 454 | + HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t); | |
| 452 | 455 | |
| 453 | 456 | }; |
| 454 | 457 | |
| @@ -460,6 +463,7 @@ struct dcn_hubbub_mask { · 5 unmodified lines | ||
| 460 | 463 | HUBBUB_REG_FIELD_LIST_DCN32(uint32_t); |
| 461 | 464 | HUBBUB_REG_FIELD_LIST_DCN35(uint32_t); |
| 462 | 465 | HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t); |
| 466 | + HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t); | |
| 463 | 467 | |
| 464 | 468 | }; |
| 465 | 469 | |
| @@ -0,0 +1,539 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dcn30/dcn30_hubbub.h" | |
| 6 | +#include "dcn31/dcn31_hubbub.h" | |
| 7 | +#include "dcn32/dcn32_hubbub.h" | |
| 8 | +#include "dcn35/dcn35_hubbub.h" | |
| 9 | +#include "dcn42/dcn42_hubbub.h" | |
| 10 | +#include "dm_services.h" | |
| 11 | +#include "reg_helper.h" | |
| 12 | + | |
| 13 | +#define DCN42_CRB_SEGMENT_SIZE_KB 64 | |
| 14 | + | |
| 15 | +#define CTX \ | |
| 16 | + hubbub2->base.ctx | |
| 17 | +#define DC_LOGGER \ | |
| 18 | + hubbub2->base.ctx->logger | |
| 19 | +#define REG(reg)\ | |
| 20 | + hubbub2->regs->reg | |
| 21 | + | |
| 22 | +#undef FN | |
| 23 | +#define FN(reg_name, field_name) \ | |
| 24 | + hubbub2->shifts->field_name, hubbub2->masks->field_name | |
| 25 | + | |
| 26 | +static bool hubbub42_program_urgent_watermarks( | |
| 27 | + struct hubbub *hubbub, | |
| 28 | + union dcn_watermark_set *watermarks, | |
| 29 | + bool safe_to_lower) | |
| 30 | +{ | |
| 31 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 32 | + bool wm_pending = false; | |
| 33 | + | |
| 34 | + /* Repeat for water mark set A, B, C and D. */ | |
| 35 | + /* clock state A */ | |
| 36 | + if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) { | |
| 37 | + hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent; | |
| 38 | + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, | |
| 39 | + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent); | |
| 40 | + } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent) | |
| 41 | + wm_pending = true; | |
| 42 | + | |
| 43 | + /* determine the transfer time for a quantity of data for a particular requestor.*/ | |
| 44 | + if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) { | |
| 45 | + hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip; | |
| 46 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0, | |
| 47 | + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip); | |
| 48 | + } else if (watermarks->dcn4x.a.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) | |
| 49 | + wm_pending = true; | |
| 50 | + | |
| 51 | + if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) { | |
| 52 | + hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom; | |
| 53 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0, | |
| 54 | + DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom); | |
| 55 | + } else if (watermarks->dcn4x.a.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) | |
| 56 | + wm_pending = true; | |
| 57 | + | |
| 58 | + if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) { | |
| 59 | + hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem; | |
| 60 | + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, | |
| 61 | + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem); | |
| 62 | + } else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) | |
| 63 | + wm_pending = true; | |
| 64 | + | |
| 65 | + /* clock state B */ | |
| 66 | + if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) { | |
| 67 | + hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent; | |
| 68 | + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, | |
| 69 | + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent); | |
| 70 | + } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent) | |
| 71 | + wm_pending = true; | |
| 72 | + | |
| 73 | + /* determine the transfer time for a quantity of data for a particular requestor.*/ | |
| 74 | + if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) { | |
| 75 | + hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip; | |
| 76 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0, | |
| 77 | + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip); | |
| 78 | + } else if (watermarks->dcn4x.b.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) | |
| 79 | + wm_pending = true; | |
| 80 | + | |
| 81 | + if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) { | |
| 82 | + hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom; | |
| 83 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0, | |
| 84 | + DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom); | |
| 85 | + } else if (watermarks->dcn4x.b.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) | |
| 86 | + wm_pending = true; | |
| 87 | + | |
| 88 | + if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) { | |
| 89 | + hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem; | |
| 90 | + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, | |
| 91 | + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem); | |
| 92 | + } else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) | |
| 93 | + wm_pending = true; | |
| 94 | + | |
| 95 | + /* clock state C */ | |
| 96 | + if (safe_to_lower || watermarks->dcn4x.c.urgent > hubbub2->watermarks.dcn4x.c.urgent) { | |
| 97 | + hubbub2->watermarks.dcn4x.c.urgent = watermarks->dcn4x.c.urgent; | |
| 98 | + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, | |
| 99 | + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, watermarks->dcn4x.c.urgent); | |
| 100 | + } else if (watermarks->dcn4x.c.urgent < hubbub2->watermarks.dcn4x.c.urgent) | |
| 101 | + wm_pending = true; | |
| 102 | + | |
| 103 | + /* determine the transfer time for a quantity of data for a particular requestor.*/ | |
| 104 | + if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) { | |
| 105 | + hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip = watermarks->dcn4x.c.frac_urg_bw_flip; | |
| 106 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0, | |
| 107 | + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->dcn4x.c.frac_urg_bw_flip); | |
| 108 | + } else if (watermarks->dcn4x.c.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) | |
| 109 | + wm_pending = true; | |
| 110 | + | |
| 111 | + if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) { | |
| 112 | + hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom = watermarks->dcn4x.c.frac_urg_bw_nom; | |
| 113 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0, | |
| 114 | + DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->dcn4x.c.frac_urg_bw_nom); | |
| 115 | + } else if (watermarks->dcn4x.c.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) | |
| 116 | + wm_pending = true; | |
| 117 | + | |
| 118 | + if (safe_to_lower || watermarks->dcn4x.c.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) { | |
| 119 | + hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem = watermarks->dcn4x.c.refcyc_per_trip_to_mem; | |
| 120 | + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0, | |
| 121 | + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, watermarks->dcn4x.c.refcyc_per_trip_to_mem); | |
| 122 | + } else if (watermarks->dcn4x.c.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) | |
| 123 | + wm_pending = true; | |
| 124 | + | |
| 125 | + /* clock state D */ | |
| 126 | + if (safe_to_lower || watermarks->dcn4x.d.urgent > hubbub2->watermarks.dcn4x.d.urgent) { | |
| 127 | + hubbub2->watermarks.dcn4x.d.urgent = watermarks->dcn4x.d.urgent; | |
| 128 | + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, | |
| 129 | + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, watermarks->dcn4x.d.urgent); | |
| 130 | + } else if (watermarks->dcn4x.d.urgent < hubbub2->watermarks.dcn4x.d.urgent) | |
| 131 | + wm_pending = true; | |
| 132 | + | |
| 133 | + /* determine the transfer time for a quantity of data for a particular requestor.*/ | |
| 134 | + if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) { | |
| 135 | + hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip = watermarks->dcn4x.d.frac_urg_bw_flip; | |
| 136 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0, | |
| 137 | + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->dcn4x.d.frac_urg_bw_flip); | |
| 138 | + } else if (watermarks->dcn4x.d.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) | |
| 139 | + wm_pending = true; | |
| 140 | + | |
| 141 | + if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) { | |
| 142 | + hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom = watermarks->dcn4x.d.frac_urg_bw_nom; | |
| 143 | + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0, | |
| 144 | + DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->dcn4x.d.frac_urg_bw_nom); | |
| 145 | + } else if (watermarks->dcn4x.d.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) | |
| 146 | + wm_pending = true; | |
| 147 | + | |
| 148 | + if (safe_to_lower || watermarks->dcn4x.d.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) { | |
| 149 | + hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem = watermarks->dcn4x.d.refcyc_per_trip_to_mem; | |
| 150 | + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0, | |
| 151 | + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, watermarks->dcn4x.d.refcyc_per_trip_to_mem); | |
| 152 | + } else if (watermarks->dcn4x.d.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) | |
| 153 | + wm_pending = true; | |
| 154 | + | |
| 155 | + return wm_pending; | |
| 156 | +} | |
| 157 | + | |
| 158 | +static bool hubbub42_program_stutter_watermarks( | |
| 159 | + struct hubbub *hubbub, | |
| 160 | + union dcn_watermark_set *watermarks, | |
| 161 | + bool safe_to_lower) | |
| 162 | +{ | |
| 163 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 164 | + bool wm_pending = false; | |
| 165 | + | |
| 166 | + /* clock state A */ | |
| 167 | + if (safe_to_lower || watermarks->dcn4x.a.sr_enter > hubbub2->watermarks.dcn4x.a.sr_enter) { | |
| 168 | + hubbub2->watermarks.dcn4x.a.sr_enter = watermarks->dcn4x.a.sr_enter; | |
| 169 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, | |
| 170 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter); | |
| 171 | + } else if (watermarks->dcn4x.a.sr_enter < hubbub2->watermarks.dcn4x.a.sr_enter) | |
| 172 | + wm_pending = true; | |
| 173 | + | |
| 174 | + if (safe_to_lower || watermarks->dcn4x.a.sr_exit > hubbub2->watermarks.dcn4x.a.sr_exit) { | |
| 175 | + hubbub2->watermarks.dcn4x.a.sr_exit = watermarks->dcn4x.a.sr_exit; | |
| 176 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, | |
| 177 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit); | |
| 178 | + } else if (watermarks->dcn4x.a.sr_exit < hubbub2->watermarks.dcn4x.a.sr_exit) | |
| 179 | + wm_pending = true; | |
| 180 | + | |
| 181 | + /* clock state B */ | |
| 182 | + if (safe_to_lower || watermarks->dcn4x.b.sr_enter > hubbub2->watermarks.dcn4x.b.sr_enter) { | |
| 183 | + hubbub2->watermarks.dcn4x.b.sr_enter = watermarks->dcn4x.b.sr_enter; | |
| 184 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, | |
| 185 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter); | |
| 186 | + } else if (watermarks->dcn4x.b.sr_enter < hubbub2->watermarks.dcn4x.b.sr_enter) | |
| 187 | + wm_pending = true; | |
| 188 | + | |
| 189 | + if (safe_to_lower || watermarks->dcn4x.b.sr_exit > hubbub2->watermarks.dcn4x.b.sr_exit) { | |
| 190 | + hubbub2->watermarks.dcn4x.b.sr_exit = watermarks->dcn4x.b.sr_exit; | |
| 191 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, | |
| 192 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit); | |
| 193 | + } else if (watermarks->dcn4x.b.sr_exit < hubbub2->watermarks.dcn4x.b.sr_exit) | |
| 194 | + wm_pending = true; | |
| 195 | + | |
| 196 | + /* clock state C */ | |
| 197 | + if (safe_to_lower || watermarks->dcn4x.c.sr_enter > hubbub2->watermarks.dcn4x.c.sr_enter) { | |
| 198 | + hubbub2->watermarks.dcn4x.c.sr_enter = watermarks->dcn4x.c.sr_enter; | |
| 199 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0, | |
| 200 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, watermarks->dcn4x.c.sr_enter); | |
| 201 | + } else if (watermarks->dcn4x.c.sr_enter < hubbub2->watermarks.dcn4x.c.sr_enter) | |
| 202 | + wm_pending = true; | |
| 203 | + | |
| 204 | + if (safe_to_lower || watermarks->dcn4x.c.sr_exit > hubbub2->watermarks.dcn4x.c.sr_exit) { | |
| 205 | + hubbub2->watermarks.dcn4x.c.sr_exit = watermarks->dcn4x.c.sr_exit; | |
| 206 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0, | |
| 207 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, watermarks->dcn4x.c.sr_exit); | |
| 208 | + } else if (watermarks->dcn4x.c.sr_exit < hubbub2->watermarks.dcn4x.c.sr_exit) | |
| 209 | + wm_pending = true; | |
| 210 | + | |
| 211 | + /* clock state D */ | |
| 212 | + if (safe_to_lower || watermarks->dcn4x.d.sr_enter > hubbub2->watermarks.dcn4x.d.sr_enter) { | |
| 213 | + hubbub2->watermarks.dcn4x.d.sr_enter = watermarks->dcn4x.d.sr_enter; | |
| 214 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0, | |
| 215 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, watermarks->dcn4x.d.sr_enter); | |
| 216 | + } else if (watermarks->dcn4x.d.sr_enter < hubbub2->watermarks.dcn4x.d.sr_enter) | |
| 217 | + wm_pending = true; | |
| 218 | + | |
| 219 | + if (safe_to_lower || watermarks->dcn4x.d.sr_exit > hubbub2->watermarks.dcn4x.d.sr_exit) { | |
| 220 | + hubbub2->watermarks.dcn4x.d.sr_exit = watermarks->dcn4x.d.sr_exit; | |
| 221 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0, | |
| 222 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, watermarks->dcn4x.d.sr_exit); | |
| 223 | + } else if (watermarks->dcn4x.d.sr_exit < hubbub2->watermarks.dcn4x.d.sr_exit) | |
| 224 | + wm_pending = true; | |
| 225 | + | |
| 226 | + return wm_pending; | |
| 227 | +} | |
| 228 | + | |
| 229 | +static bool hubbub42_program_pstate_watermarks( | |
| 230 | + struct hubbub *hubbub, | |
| 231 | + union dcn_watermark_set *watermarks, | |
| 232 | + bool safe_to_lower) | |
| 233 | +{ | |
| 234 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 235 | + bool wm_pending = false; | |
| 236 | + | |
| 237 | + /* Section for UCLK_PSTATE_CHANGE_WATERMARKS */ | |
| 238 | + /* UCLK state A */ | |
| 239 | + if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate > hubbub2->watermarks.dcn4x.a.uclk_pstate) { | |
| 240 | + hubbub2->watermarks.dcn4x.a.uclk_pstate = watermarks->dcn4x.a.uclk_pstate; | |
| 241 | + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0, | |
| 242 | + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate); | |
| 243 | + } else if (watermarks->dcn4x.a.uclk_pstate < hubbub2->watermarks.dcn4x.a.uclk_pstate) | |
| 244 | + wm_pending = true; | |
| 245 | + | |
| 246 | + /* UCLK state B */ | |
| 247 | + if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate > hubbub2->watermarks.dcn4x.b.uclk_pstate) { | |
| 248 | + hubbub2->watermarks.dcn4x.b.uclk_pstate = watermarks->dcn4x.b.uclk_pstate; | |
| 249 | + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0, | |
| 250 | + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate); | |
| 251 | + } else if (watermarks->dcn4x.b.uclk_pstate < hubbub2->watermarks.dcn4x.b.uclk_pstate) | |
| 252 | + wm_pending = true; | |
| 253 | + | |
| 254 | + /* UCLK state C */ | |
| 255 | + if (safe_to_lower || watermarks->dcn4x.c.uclk_pstate > hubbub2->watermarks.dcn4x.c.uclk_pstate) { | |
| 256 | + hubbub2->watermarks.dcn4x.c.uclk_pstate = watermarks->dcn4x.c.uclk_pstate; | |
| 257 | + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0, | |
| 258 | + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.uclk_pstate); | |
| 259 | + } else if (watermarks->dcn4x.c.uclk_pstate < hubbub2->watermarks.dcn4x.c.uclk_pstate) | |
| 260 | + wm_pending = true; | |
| 261 | + | |
| 262 | + /* UCLK state D */ | |
| 263 | + if (safe_to_lower || watermarks->dcn4x.d.uclk_pstate > hubbub2->watermarks.dcn4x.d.uclk_pstate) { | |
| 264 | + hubbub2->watermarks.dcn4x.d.uclk_pstate = watermarks->dcn4x.d.uclk_pstate; | |
| 265 | + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0, | |
| 266 | + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.uclk_pstate); | |
| 267 | + } else if (watermarks->dcn4x.d.uclk_pstate < hubbub2->watermarks.dcn4x.d.uclk_pstate) | |
| 268 | + wm_pending = true; | |
| 269 | + | |
| 270 | + /* Section for FCLK_PSTATE_CHANGE_WATERMARKS */ | |
| 271 | + /* FCLK state A */ | |
| 272 | + if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate > hubbub2->watermarks.dcn4x.a.fclk_pstate) { | |
| 273 | + hubbub2->watermarks.dcn4x.a.fclk_pstate = watermarks->dcn4x.a.fclk_pstate; | |
| 274 | + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0, | |
| 275 | + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate); | |
| 276 | + } else if (watermarks->dcn4x.a.fclk_pstate < hubbub2->watermarks.dcn4x.a.fclk_pstate) | |
| 277 | + wm_pending = true; | |
| 278 | + | |
| 279 | + /* FCLK state B */ | |
| 280 | + if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate > hubbub2->watermarks.dcn4x.b.fclk_pstate) { | |
| 281 | + hubbub2->watermarks.dcn4x.b.fclk_pstate = watermarks->dcn4x.b.fclk_pstate; | |
| 282 | + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0, | |
| 283 | + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate); | |
| 284 | + } else if (watermarks->dcn4x.b.fclk_pstate < hubbub2->watermarks.dcn4x.b.fclk_pstate) | |
| 285 | + wm_pending = true; | |
| 286 | + | |
| 287 | + /* FCLK state C */ | |
| 288 | + if (safe_to_lower || watermarks->dcn4x.c.fclk_pstate > hubbub2->watermarks.dcn4x.c.fclk_pstate) { | |
| 289 | + hubbub2->watermarks.dcn4x.c.fclk_pstate = watermarks->dcn4x.c.fclk_pstate; | |
| 290 | + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0, | |
| 291 | + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.fclk_pstate); | |
| 292 | + } else if (watermarks->dcn4x.c.fclk_pstate < hubbub2->watermarks.dcn4x.c.fclk_pstate) | |
| 293 | + wm_pending = true; | |
| 294 | + | |
| 295 | + /* FCLK state D */ | |
| 296 | + if (safe_to_lower || watermarks->dcn4x.d.fclk_pstate > hubbub2->watermarks.dcn4x.d.fclk_pstate) { | |
| 297 | + hubbub2->watermarks.dcn4x.d.fclk_pstate = watermarks->dcn4x.d.fclk_pstate; | |
| 298 | + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0, | |
| 299 | + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.fclk_pstate); | |
| 300 | + } else if (watermarks->dcn4x.d.fclk_pstate < hubbub2->watermarks.dcn4x.d.fclk_pstate) | |
| 301 | + wm_pending = true; | |
| 302 | + | |
| 303 | + return wm_pending; | |
| 304 | +} | |
| 305 | + | |
| 306 | +static bool hubbub42_program_usr_watermarks( | |
| 307 | + struct hubbub *hubbub, | |
| 308 | + union dcn_watermark_set *watermarks, | |
| 309 | + bool safe_to_lower) | |
| 310 | +{ | |
| 311 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 312 | + bool wm_pending = false; | |
| 313 | + | |
| 314 | + /* clock state A */ | |
| 315 | + if (safe_to_lower || watermarks->dcn4x.a.usr > hubbub2->watermarks.dcn4x.a.usr) { | |
| 316 | + hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr; | |
| 317 | + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0, | |
| 318 | + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr); | |
| 319 | + } else if (watermarks->dcn4x.a.usr < hubbub2->watermarks.dcn4x.a.usr) | |
| 320 | + wm_pending = true; | |
| 321 | + | |
| 322 | + /* clock state B */ | |
| 323 | + if (safe_to_lower || watermarks->dcn4x.b.usr > hubbub2->watermarks.dcn4x.b.usr) { | |
| 324 | + hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr; | |
| 325 | + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0, | |
| 326 | + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr); | |
| 327 | + } else if (watermarks->dcn4x.b.usr < hubbub2->watermarks.dcn4x.b.usr) | |
| 328 | + wm_pending = true; | |
| 329 | + | |
| 330 | + /* clock state C */ | |
| 331 | + if (safe_to_lower || watermarks->dcn4x.c.usr > hubbub2->watermarks.dcn4x.c.usr) { | |
| 332 | + hubbub2->watermarks.dcn4x.c.usr = watermarks->dcn4x.c.usr; | |
| 333 | + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0, | |
| 334 | + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, watermarks->dcn4x.c.usr); | |
| 335 | + } else if (watermarks->dcn4x.c.usr < hubbub2->watermarks.dcn4x.c.usr) | |
| 336 | + wm_pending = true; | |
| 337 | + | |
| 338 | + /* clock state D */ | |
| 339 | + if (safe_to_lower || watermarks->dcn4x.d.usr > hubbub2->watermarks.dcn4x.d.usr) { | |
| 340 | + hubbub2->watermarks.dcn4x.d.usr = watermarks->dcn4x.d.usr; | |
| 341 | + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0, | |
| 342 | + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, watermarks->dcn4x.d.usr); | |
| 343 | + } else if (watermarks->dcn4x.d.usr < hubbub2->watermarks.dcn4x.d.usr) | |
| 344 | + wm_pending = true; | |
| 345 | + | |
| 346 | + return wm_pending; | |
| 347 | +} | |
| 348 | + | |
| 349 | +static bool hubbub42_program_stutter_z8_watermarks( | |
| 350 | + struct hubbub *hubbub, | |
| 351 | + union dcn_watermark_set *watermarks, | |
| 352 | + bool safe_to_lower) | |
| 353 | +{ | |
| 354 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 355 | + bool wm_pending = false; | |
| 356 | + | |
| 357 | + /* clock state A */ | |
| 358 | + if (safe_to_lower || watermarks->dcn4x.a.sr_enter_z8 > hubbub2->watermarks.dcn4x.a.sr_enter_z8) { | |
| 359 | + hubbub2->watermarks.dcn4x.a.sr_enter_z8 = watermarks->dcn4x.a.sr_enter_z8; | |
| 360 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0, | |
| 361 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_enter_z8); | |
| 362 | + } else if (watermarks->dcn4x.a.sr_enter_z8 < hubbub2->watermarks.dcn4x.a.sr_enter_z8) | |
| 363 | + wm_pending = true; | |
| 364 | + | |
| 365 | + if (safe_to_lower || watermarks->dcn4x.a.sr_exit_z8 > hubbub2->watermarks.dcn4x.a.sr_exit_z8) { | |
| 366 | + hubbub2->watermarks.dcn4x.a.sr_exit_z8 = watermarks->dcn4x.a.sr_exit_z8; | |
| 367 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0, | |
| 368 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_exit_z8); | |
| 369 | + } else if (watermarks->dcn4x.a.sr_exit_z8 < hubbub2->watermarks.dcn4x.a.sr_exit_z8) | |
| 370 | + wm_pending = true; | |
| 371 | + | |
| 372 | + /* clock state B */ | |
| 373 | + if (safe_to_lower || watermarks->dcn4x.b.sr_enter_z8 > hubbub2->watermarks.dcn4x.b.sr_enter_z8) { | |
| 374 | + hubbub2->watermarks.dcn4x.b.sr_enter_z8 = watermarks->dcn4x.b.sr_enter_z8; | |
| 375 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0, | |
| 376 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_enter_z8); | |
| 377 | + } else if (watermarks->dcn4x.b.sr_enter_z8 < hubbub2->watermarks.dcn4x.b.sr_enter_z8) | |
| 378 | + wm_pending = true; | |
| 379 | + | |
| 380 | + if (safe_to_lower || watermarks->dcn4x.b.sr_exit_z8 > hubbub2->watermarks.dcn4x.b.sr_exit_z8) { | |
| 381 | + hubbub2->watermarks.dcn4x.b.sr_exit_z8 = watermarks->dcn4x.b.sr_exit_z8; | |
| 382 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0, | |
| 383 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_exit_z8); | |
| 384 | + } else if (watermarks->dcn4x.b.sr_exit_z8 < hubbub2->watermarks.dcn4x.b.sr_exit_z8) | |
| 385 | + wm_pending = true; | |
| 386 | + | |
| 387 | + /* clock state C */ | |
| 388 | + if (safe_to_lower || watermarks->dcn4x.c.sr_enter_z8 > hubbub2->watermarks.dcn4x.c.sr_enter_z8) { | |
| 389 | + hubbub2->watermarks.dcn4x.c.sr_enter_z8 = watermarks->dcn4x.c.sr_enter_z8; | |
| 390 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0, | |
| 391 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_enter_z8); | |
| 392 | + } else if (watermarks->dcn4x.c.sr_enter_z8 < hubbub2->watermarks.dcn4x.c.sr_enter_z8) | |
| 393 | + wm_pending = true; | |
| 394 | + | |
| 395 | + if (safe_to_lower || watermarks->dcn4x.c.sr_exit_z8 > hubbub2->watermarks.dcn4x.c.sr_exit_z8) { | |
| 396 | + hubbub2->watermarks.dcn4x.c.sr_exit_z8 = watermarks->dcn4x.c.sr_exit_z8; | |
| 397 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0, | |
| 398 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_exit_z8); | |
| 399 | + } else if (watermarks->dcn4x.c.sr_exit_z8 < hubbub2->watermarks.dcn4x.c.sr_exit_z8) | |
| 400 | + wm_pending = true; | |
| 401 | + | |
| 402 | + /* clock state D */ | |
| 403 | + if (safe_to_lower || watermarks->dcn4x.d.sr_enter_z8 > hubbub2->watermarks.dcn4x.d.sr_enter_z8) { | |
| 404 | + hubbub2->watermarks.dcn4x.d.sr_enter_z8 = watermarks->dcn4x.d.sr_enter_z8; | |
| 405 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0, | |
| 406 | + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_enter_z8); | |
| 407 | + } else if (watermarks->dcn4x.d.sr_enter_z8 < hubbub2->watermarks.dcn4x.d.sr_enter_z8) | |
| 408 | + wm_pending = true; | |
| 409 | + | |
| 410 | + if (safe_to_lower || watermarks->dcn4x.d.sr_exit_z8 > hubbub2->watermarks.dcn4x.d.sr_exit_z8) { | |
| 411 | + hubbub2->watermarks.dcn4x.d.sr_exit_z8 = watermarks->dcn4x.d.sr_exit_z8; | |
| 412 | + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0, | |
| 413 | + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_exit_z8); | |
| 414 | + } else if (watermarks->dcn4x.d.sr_exit_z8 < hubbub2->watermarks.dcn4x.d.sr_exit_z8) | |
| 415 | + wm_pending = true; | |
| 416 | + | |
| 417 | + return wm_pending; | |
| 418 | +} | |
| 419 | + | |
| 420 | +static void hubbub42_allow_self_refresh_control(struct hubbub *hubbub, bool allow) | |
| 421 | +{ | |
| 422 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 423 | + | |
| 424 | + /* | |
| 425 | + * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter | |
| 426 | + * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter | |
| 427 | + */ | |
| 428 | + | |
| 429 | + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, | |
| 430 | + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, | |
| 431 | + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow); | |
| 432 | + | |
| 433 | + if (!allow && hubbub->ctx->dc->debug.disable_stutter) {/*controlled by registry key*/ | |
| 434 | + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, | |
| 435 | + DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, 0, | |
| 436 | + DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, 1); | |
| 437 | + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, | |
| 438 | + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, | |
| 439 | + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); | |
| 440 | + } | |
| 441 | +} | |
| 442 | +static void hubbub42_set_sdp_control(struct hubbub *hubbub, bool dc_control) | |
| 443 | +{ | |
| 444 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 445 | + | |
| 446 | + REG_UPDATE(DCHUBBUB_SDPIF_CFG0, | |
| 447 | + SDPIF_PORT_CONTROL, dc_control); | |
| 448 | +} | |
| 449 | + | |
| 450 | +static bool hubbub42_program_watermarks( | |
| 451 | + struct hubbub *hubbub, | |
| 452 | + union dcn_watermark_set *watermarks, | |
| 453 | + unsigned int refclk_mhz, | |
| 454 | + bool safe_to_lower) | |
| 455 | +{ | |
| 456 | + bool wm_pending = false; | |
| 457 | + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); | |
| 458 | + | |
| 459 | + if (!safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) { | |
| 460 | + /* before raising watermarks, SDP control give to DF, stutter must be disabled */ | |
| 461 | + wm_pending = true; | |
| 462 | + hubbub42_set_sdp_control(hubbub, false); | |
| 463 | + hubbub42_allow_self_refresh_control(hubbub, false); | |
| 464 | + } | |
| 465 | + if (hubbub42_program_urgent_watermarks(hubbub, watermarks, safe_to_lower)) | |
| 466 | + wm_pending = true; | |
| 467 | + | |
| 468 | + if (hubbub42_program_stutter_watermarks(hubbub, watermarks, safe_to_lower)) | |
| 469 | + wm_pending = true; | |
| 470 | + | |
| 471 | + if (hubbub42_program_pstate_watermarks(hubbub, watermarks, safe_to_lower)) | |
| 472 | + wm_pending = true; | |
| 473 | + | |
| 474 | + if (hubbub42_program_usr_watermarks(hubbub, watermarks, safe_to_lower)) | |
| 475 | + wm_pending = true; | |
| 476 | + | |
| 477 | + if (hubbub42_program_stutter_z8_watermarks(hubbub, watermarks, safe_to_lower)) | |
| 478 | + wm_pending = true; | |
| 479 | + | |
| 480 | + REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, | |
| 481 | + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); | |
| 482 | + REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, | |
| 483 | + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF, | |
| 484 | + DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ | |
| 485 | + REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); | |
| 486 | + | |
| 487 | + if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) | |
| 488 | + hubbub42_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | |
| 489 | + if (safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) { | |
| 490 | + hubbub42_set_sdp_control(hubbub, true); | |
| 491 | + } | |
| 492 | + hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); | |
| 493 | + | |
| 494 | + return wm_pending; | |
| 495 | +} | |
| 496 | + | |
| 497 | +static const struct hubbub_funcs hubbub42_funcs = { | |
| 498 | + .update_dchub = hubbub2_update_dchub, | |
| 499 | + .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, | |
| 500 | + .init_vm_ctx = hubbub2_init_vm_ctx, | |
| 501 | + .dcc_support_swizzle = hubbub3_dcc_support_swizzle, | |
| 502 | + .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, | |
| 503 | + .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap, | |
| 504 | + .wm_read_state = hubbub35_wm_read_state, | |
| 505 | + .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq, | |
| 506 | + .program_watermarks = hubbub42_program_watermarks, | |
| 507 | + .allow_self_refresh_control = hubbub42_allow_self_refresh_control, | |
| 508 | + .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, | |
| 509 | + .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes, | |
| 510 | + .force_pstate_change_control = hubbub3_force_pstate_change_control, | |
| 511 | + .init_watermarks = hubbub35_init_watermarks, | |
| 512 | + .program_det_size = dcn32_program_det_size, | |
| 513 | + .program_compbuf_size = dcn35_program_compbuf_size, | |
| 514 | + .init_crb = dcn35_init_crb, | |
| 515 | + .hubbub_read_state = hubbub2_read_state, | |
| 516 | + .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, | |
| 517 | + .dchubbub_init = hubbub35_init, | |
| 518 | + .dchvm_init = dcn35_dchvm_init, | |
| 519 | +}; | |
| 520 | + | |
| 521 | +void hubbub42_construct(struct dcn20_hubbub *hubbub2, | |
| 522 | + struct dc_context *ctx, | |
| 523 | + const struct dcn_hubbub_registers *hubbub_regs, | |
| 524 | + const struct dcn_hubbub_shift *hubbub_shift, | |
| 525 | + const struct dcn_hubbub_mask *hubbub_mask, | |
| 526 | + int det_size_kb, | |
| 527 | + int pixel_chunk_size_kb, | |
| 528 | + int config_return_buffer_size_kb) | |
| 529 | +{ | |
| 530 | + hubbub2->base.ctx = ctx; | |
| 531 | + hubbub2->base.funcs = &hubbub42_funcs; | |
| 532 | + hubbub2->regs = hubbub_regs; | |
| 533 | + hubbub2->shifts = hubbub_shift; | |
| 534 | + hubbub2->masks = hubbub_mask; | |
| 535 | + | |
| 536 | + hubbub2->detile_buf_size = det_size_kb * 1024; | |
| 537 | + hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024; | |
| 538 | + hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN42_CRB_SEGMENT_SIZE_KB; | |
| 539 | +} | |
| @@ -0,0 +1,268 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + * Authors: AMD | |
| 24 | + * | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef __DC_HUBBUB_DCN42_H__ | |
| 28 | +#define __DC_HUBBUB_DCN42_H__ | |
| 29 | + | |
| 30 | +#include "dcn32/dcn32_hubbub.h" | |
| 31 | + | |
| 32 | +#define DCN42_CRB_SIZE_KB 1792 | |
| 33 | +#define DCN42_DEFAULT_DET_SIZE 320 | |
| 34 | +#define DCN42_CRB_SEGMENT_SIZE_KB 64 | |
| 35 | + | |
| 36 | +#define HUBBUB_REG_LIST_DCN42(id)\ | |
| 37 | + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ | |
| 38 | + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ | |
| 39 | + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ | |
| 40 | + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ | |
| 41 | + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ | |
| 42 | + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ | |
| 43 | + SR(DCHUBBUB_ARB_SAT_LEVEL),\ | |
| 44 | + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ | |
| 45 | + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ | |
| 46 | + SR(DCHUBBUB_SOFT_RESET),\ | |
| 47 | + SR(DCHUBBUB_CRC_CTRL), \ | |
| 48 | + SR(DCN_VM_FB_LOCATION_BASE),\ | |
| 49 | + SR(DCN_VM_FB_LOCATION_TOP),\ | |
| 50 | + SR(DCN_VM_FB_OFFSET),\ | |
| 51 | + SR(DCN_VM_AGP_BOT),\ | |
| 52 | + SR(DCN_VM_AGP_TOP),\ | |
| 53 | + SR(DCN_VM_AGP_BASE),\ | |
| 54 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ | |
| 55 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ | |
| 56 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ | |
| 57 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ | |
| 58 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ | |
| 59 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ | |
| 60 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ | |
| 61 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ | |
| 62 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A),\ | |
| 63 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B),\ | |
| 64 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C),\ | |
| 65 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D),\ | |
| 66 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A),\ | |
| 67 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\ | |
| 68 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\ | |
| 69 | + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\ | |
| 70 | + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\ | |
| 71 | + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\ | |
| 72 | + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\ | |
| 73 | + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D),\ | |
| 74 | + SR(DCHUBBUB_DET0_CTRL),\ | |
| 75 | + SR(DCHUBBUB_DET1_CTRL),\ | |
| 76 | + SR(DCHUBBUB_DET2_CTRL),\ | |
| 77 | + SR(DCHUBBUB_DET3_CTRL),\ | |
| 78 | + SR(DCHUBBUB_COMPBUF_CTRL),\ | |
| 79 | + SR(COMPBUF_RESERVED_SPACE),\ | |
| 80 | + SR(DCHUBBUB_DEBUG_CTRL_0),\ | |
| 81 | + SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL),\ | |
| 82 | + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A),\ | |
| 83 | + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B),\ | |
| 84 | + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C),\ | |
| 85 | + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D),\ | |
| 86 | + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A),\ | |
| 87 | + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B),\ | |
| 88 | + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C),\ | |
| 89 | + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D),\ | |
| 90 | + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A),\ | |
| 91 | + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B),\ | |
| 92 | + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C),\ | |
| 93 | + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D),\ | |
| 94 | + SR(DCN_VM_FAULT_ADDR_MSB),\ | |
| 95 | + SR(DCN_VM_FAULT_ADDR_LSB),\ | |
| 96 | + SR(DCN_VM_FAULT_CNTL),\ | |
| 97 | + SR(DCN_VM_FAULT_STATUS),\ | |
| 98 | + SR(SDPIF_REQUEST_RATE_LIMIT),\ | |
| 99 | + SR(DCHUBBUB_CLOCK_CNTL),\ | |
| 100 | + SR(DCHUBBUB_SDPIF_CFG0),\ | |
| 101 | + SR(DCHUBBUB_SDPIF_CFG1),\ | |
| 102 | + SR(DCHUBBUB_MEM_PWR_MODE_CTRL),\ | |
| 103 | + SR(DCHUBBUB_ARB_HOSTVM_CNTL),\ | |
| 104 | + SR(DCHVM_CTRL0),\ | |
| 105 | + SR(DCHVM_MEM_CTRL),\ | |
| 106 | + SR(DCHVM_CLK_CTRL),\ | |
| 107 | + SR(DCHVM_RIOMMU_CTRL0),\ | |
| 108 | + SR(DCHVM_RIOMMU_STAT0),\ | |
| 109 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A),\ | |
| 110 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A),\ | |
| 111 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B),\ | |
| 112 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B),\ | |
| 113 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C),\ | |
| 114 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C),\ | |
| 115 | + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D),\ | |
| 116 | + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D),\ | |
| 117 | + SR(DCHUBBUB_ARB_QOS_FORCE) | |
| 118 | + | |
| 119 | +#define HUBBUB_MASK_SH_LIST_DCN4_2(mask_sh)\ | |
| 120 | + HUBBUB_MASK_SH_LIST_DCN32(mask_sh), \ | |
| 121 | + HUBBUB_SF(DCHVM_CTRL0, HOSTVM_INIT_REQ, mask_sh),\ | |
| 122 | + HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, mask_sh),\ | |
| 123 | + HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_FORCE_REQ, mask_sh),\ | |
| 124 | + HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_POWER_STATUS, mask_sh),\ | |
| 125 | + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_R_GATE_DIS, mask_sh),\ | |
| 126 | + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_G_GATE_DIS, mask_sh),\ | |
| 127 | + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_R_GATE_DIS, mask_sh),\ | |
| 128 | + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_G_GATE_DIS, mask_sh),\ | |
| 129 | + HUBBUB_SF(DCHVM_CLK_CTRL, TR_REQ_REQCLKREQ_MODE, mask_sh),\ | |
| 130 | + HUBBUB_SF(DCHVM_CLK_CTRL, TW_RSP_COMPCLKREQ_MODE, mask_sh),\ | |
| 131 | + HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, mask_sh),\ | |
| 132 | + HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, mask_sh),\ | |
| 133 | + HUBBUB_SF(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, mask_sh),\ | |
| 134 | + HUBBUB_SF(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, mask_sh),\ | |
| 135 | + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\ | |
| 136 | + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\ | |
| 137 | + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\ | |
| 138 | + HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\ | |
| 139 | + HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\ | |
| 140 | + HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, mask_sh),\ | |
| 141 | + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ | |
| 142 | + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \ | |
| 143 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \ | |
| 144 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \ | |
| 145 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \ | |
| 146 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \ | |
| 147 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, mask_sh), \ | |
| 148 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, mask_sh), \ | |
| 149 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, mask_sh), \ | |
| 150 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, mask_sh), \ | |
| 151 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, mask_sh), \ | |
| 152 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, mask_sh), \ | |
| 153 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, mask_sh), \ | |
| 154 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, mask_sh), \ | |
| 155 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_CSTATE_DEEPSLEEP_LEGACY_MODE, mask_sh), \ | |
| 156 | + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ | |
| 157 | + HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \ | |
| 158 | + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ | |
| 159 | + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ | |
| 160 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ | |
| 161 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ | |
| 162 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, mask_sh), \ | |
| 163 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, mask_sh), \ | |
| 164 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \ | |
| 165 | + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \ | |
| 166 | + HUBBUB_SF(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, mask_sh),\ | |
| 167 | + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, mask_sh),\ | |
| 168 | + HUBBUB_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ | |
| 169 | + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ | |
| 170 | + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \ | |
| 171 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \ | |
| 172 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \ | |
| 173 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \ | |
| 174 | + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \ | |
| 175 | + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ | |
| 176 | + HUBBUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE, mask_sh), \ | |
| 177 | + HUBBUB_SF(DCN_VM_FB_LOCATION_TOP, FB_TOP, mask_sh), \ | |
| 178 | + HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \ | |
| 179 | + HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \ | |
| 180 | + HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \ | |
| 181 | + HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \ | |
| 182 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, mask_sh), \ | |
| 183 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, mask_sh), \ | |
| 184 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, mask_sh), \ | |
| 185 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, mask_sh), \ | |
| 186 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, mask_sh), \ | |
| 187 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, mask_sh), \ | |
| 188 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, mask_sh), \ | |
| 189 | + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, mask_sh), \ | |
| 190 | + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, mask_sh), \ | |
| 191 | + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, mask_sh), \ | |
| 192 | + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, mask_sh), \ | |
| 193 | + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, mask_sh), \ | |
| 194 | + HUBBUB_SF(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, mask_sh),\ | |
| 195 | + HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE, mask_sh),\ | |
| 196 | + HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, mask_sh),\ | |
| 197 | + HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE, mask_sh),\ | |
| 198 | + HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, mask_sh),\ | |
| 199 | + HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE, mask_sh),\ | |
| 200 | + HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, mask_sh),\ | |
| 201 | + HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE, mask_sh),\ | |
| 202 | + HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, mask_sh),\ | |
| 203 | + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\ | |
| 204 | + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\ | |
| 205 | + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\ | |
| 206 | + HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\ | |
| 207 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE, mask_sh),\ | |
| 208 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE, mask_sh),\ | |
| 209 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PSTATE_CHANGE_REQUEST, mask_sh),\ | |
| 210 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PRE_CSTATE, mask_sh),\ | |
| 211 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, mask_sh), \ | |
| 212 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, mask_sh), \ | |
| 213 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, mask_sh), \ | |
| 214 | + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, mask_sh), \ | |
| 215 | + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\ | |
| 216 | + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\ | |
| 217 | + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\ | |
| 218 | + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\ | |
| 219 | + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\ | |
| 220 | + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\ | |
| 221 | + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\ | |
| 222 | + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\ | |
| 223 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \ | |
| 224 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, mask_sh), \ | |
| 225 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, mask_sh), \ | |
| 226 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, mask_sh), \ | |
| 227 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \ | |
| 228 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \ | |
| 229 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \ | |
| 230 | + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \ | |
| 231 | + HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \ | |
| 232 | + HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \ | |
| 233 | + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \ | |
| 234 | + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \ | |
| 235 | + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \ | |
| 236 | + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \ | |
| 237 | + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \ | |
| 238 | + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \ | |
| 239 | + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \ | |
| 240 | + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \ | |
| 241 | + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \ | |
| 242 | + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh),\ | |
| 243 | + HUBBUB_SF(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, mask_sh),\ | |
| 244 | + HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DISPCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\ | |
| 245 | + HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\ | |
| 246 | + HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\ | |
| 247 | + HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\ | |
| 248 | + HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\ | |
| 249 | + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_ERROR_STATUS, mask_sh),\ | |
| 250 | + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\ | |
| 251 | + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\ | |
| 252 | + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\ | |
| 253 | + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\ | |
| 254 | + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\ | |
| 255 | + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\ | |
| 256 | + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\ | |
| 257 | + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, URGENT_ZERO_SIZE_REQ_EN, mask_sh),\ | |
| 258 | + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh) | |
| 259 | + | |
| 260 | +void hubbub42_construct(struct dcn20_hubbub *hubbub2, | |
| 261 | + struct dc_context *ctx, | |
| 262 | + const struct dcn_hubbub_registers *hubbub_regs, | |
| 263 | + const struct dcn_hubbub_shift *hubbub_shift, | |
| 264 | + const struct dcn_hubbub_mask *hubbub_mask, | |
| 265 | + int det_size_kb, | |
| 266 | + int pixel_chunk_size_kb, | |
| 267 | + int config_return_buffer_size_kb); | |
| 268 | +#endif | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | |
| 2 | −# Copyright 2022 Advanced Micro Devices, Inc. | |
| 2 | +# Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | # |
| 4 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -94,4 +94,12 @@ AMD_DAL_HUBP_DCN401 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn401/,$(HUBP_DCN401)) · 88 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN401) |
| 96 | 96 | |
| 97 | +############################################################################### | |
| 98 | + | |
| 99 | +HUBP_DCN42 = dcn42_hubp.o | |
| 100 | + | |
| 101 | +AMD_DAL_HUBP_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn42/,$(HUBP_DCN42)) | |
| 102 | + | |
| 103 | +AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN42) | |
| 104 | + | |
| 97 | 105 | endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2012-17 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2012-2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -288,16 +288,22 @@ · 282 unmodified lines | ||
| 288 | 288 | type MCACHEID_MALL_PREF_2H_P1;\ |
| 289 | 289 | type HUBP_FGCG_REP_DIS |
| 290 | 290 | |
| 291 | +#define DCN42_HUBP_REG_FIELD_VARIABLE_LIST(type) \ | |
| 292 | + type HUBP_3DLUT_CROSSBAR_SEL_G;\ | |
| 293 | + type HUBP_3DLUT_CROSSBAR_SEL_B;\ | |
| 294 | + type HUBP_3DLUT_CROSSBAR_SEL_R | |
| 291 | 295 | struct dcn_hubp2_registers { |
| 292 | 296 | DCN401_HUBP_REG_COMMON_VARIABLE_LIST; |
| 293 | 297 | }; |
| 294 | 298 | |
| 295 | 299 | struct dcn_hubp2_shift { |
| 296 | 300 | DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); |
| 301 | + DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); | |
| 297 | 302 | }; |
| 298 | 303 | |
| 299 | 304 | struct dcn_hubp2_mask { |
| 300 | 305 | DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); |
| 306 | + DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); | |
| 301 | 307 | }; |
| 302 | 308 | |
| 303 | 309 | struct dcn20_hubp { |
| @@ -0,0 +1,643 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dcn401/dcn401_hubp.h" | |
| 6 | +#include "dcn42_hubp.h" | |
| 7 | +#include "reg_helper.h" | |
| 8 | + | |
| 9 | +#define REG(reg) \ | |
| 10 | + hubp2->hubp_regs->reg | |
| 11 | + | |
| 12 | +#define CTX \ | |
| 13 | + hubp2->base.ctx | |
| 14 | + | |
| 15 | +#undef FN | |
| 16 | +#define FN(reg_name, field_name) \ | |
| 17 | + hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name | |
| 18 | + | |
| 19 | +static void hubp42_set_fgcg(struct hubp *hubp, bool enable) | |
| 20 | +{ | |
| 21 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 22 | + | |
| 23 | + REG_UPDATE(HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, !enable); | |
| 24 | +} | |
| 25 | + | |
| 26 | +static void hubp42_init(struct hubp *hubp) | |
| 27 | +{ | |
| 28 | + hubp3_init(hubp); | |
| 29 | + | |
| 30 | + hubp42_set_fgcg(hubp, hubp->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dchub); | |
| 31 | + | |
| 32 | + /*do nothing for now for dcn3.5 or later*/ | |
| 33 | +} | |
| 34 | + | |
| 35 | +static void hubp42_program_pixel_format( | |
| 36 | + struct hubp *hubp, | |
| 37 | + enum surface_pixel_format format) | |
| 38 | +{ | |
| 39 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 40 | + uint32_t green_bar = 1; | |
| 41 | + uint32_t red_bar = 3; | |
| 42 | + uint32_t blue_bar = 2; | |
| 43 | + | |
| 44 | + /* swap for ABGR format */ | |
| 45 | + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 | |
| 46 | + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 | |
| 47 | + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS | |
| 48 | + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 | |
| 49 | + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { | |
| 50 | + red_bar = 2; | |
| 51 | + blue_bar = 3; | |
| 52 | + } | |
| 53 | + | |
| 54 | + REG_UPDATE_3(HUBPRET_CONTROL, | |
| 55 | + CROSSBAR_SRC_Y_G, green_bar, | |
| 56 | + CROSSBAR_SRC_CB_B, blue_bar, | |
| 57 | + CROSSBAR_SRC_CR_R, red_bar); | |
| 58 | + | |
| 59 | + /* Mapping is same as ipp programming (cnvc) */ | |
| 60 | + | |
| 61 | + switch (format) { | |
| 62 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: | |
| 63 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 64 | + SURFACE_PIXEL_FORMAT, 1); | |
| 65 | + break; | |
| 66 | + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: | |
| 67 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 68 | + SURFACE_PIXEL_FORMAT, 3); | |
| 69 | + break; | |
| 70 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: | |
| 71 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: | |
| 72 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 73 | + SURFACE_PIXEL_FORMAT, 8); | |
| 74 | + break; | |
| 75 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: | |
| 76 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: | |
| 77 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: | |
| 78 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 79 | + SURFACE_PIXEL_FORMAT, 10); | |
| 80 | + break; | |
| 81 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: | |
| 82 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /* we use crossbar already */ | |
| 83 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 84 | + SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */ | |
| 85 | + break; | |
| 86 | + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: | |
| 87 | + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ | |
| 88 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 89 | + SURFACE_PIXEL_FORMAT, 24); | |
| 90 | + break; | |
| 91 | + | |
| 92 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: | |
| 93 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 94 | + SURFACE_PIXEL_FORMAT, 65); | |
| 95 | + break; | |
| 96 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: | |
| 97 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 98 | + SURFACE_PIXEL_FORMAT, 64); | |
| 99 | + break; | |
| 100 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: | |
| 101 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 102 | + SURFACE_PIXEL_FORMAT, 67); | |
| 103 | + break; | |
| 104 | + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: | |
| 105 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 106 | + SURFACE_PIXEL_FORMAT, 66); | |
| 107 | + break; | |
| 108 | + case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: | |
| 109 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 110 | + SURFACE_PIXEL_FORMAT, 12); | |
| 111 | + break; | |
| 112 | + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: | |
| 113 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 114 | + SURFACE_PIXEL_FORMAT, 112); | |
| 115 | + break; | |
| 116 | + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: | |
| 117 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 118 | + SURFACE_PIXEL_FORMAT, 113); | |
| 119 | + break; | |
| 120 | + case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: | |
| 121 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 122 | + SURFACE_PIXEL_FORMAT, 114); | |
| 123 | + break; | |
| 124 | + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: | |
| 125 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 126 | + SURFACE_PIXEL_FORMAT, 118); | |
| 127 | + break; | |
| 128 | + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: | |
| 129 | + REG_UPDATE(DCSURF_SURFACE_CONFIG, | |
| 130 | + SURFACE_PIXEL_FORMAT, 119); | |
| 131 | + break; | |
| 132 | + case SURFACE_PIXEL_FORMAT_GRPH_RGBE: | |
| 133 | + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, | |
| 134 | + SURFACE_PIXEL_FORMAT, 116, | |
| 135 | + ALPHA_PLANE_EN, 0); | |
| 136 | + break; | |
| 137 | + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: | |
| 138 | + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, | |
| 139 | + SURFACE_PIXEL_FORMAT, 116, | |
| 140 | + ALPHA_PLANE_EN, 1); | |
| 141 | + break; | |
| 142 | + default: | |
| 143 | + BREAK_TO_DEBUGGER(); | |
| 144 | + break; | |
| 145 | + } | |
| 146 | + | |
| 147 | + /* don't see the need of program the xbar in DCN 1.0 */ | |
| 148 | +} | |
| 149 | + | |
| 150 | +void hubp42_program_deadline( | |
| 151 | + struct hubp *hubp, | |
| 152 | + struct dml2_display_dlg_regs *dlg_attr, | |
| 153 | + struct dml2_display_ttu_regs *ttu_attr) | |
| 154 | +{ | |
| 155 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 156 | + | |
| 157 | + /* DLG - Per hubp */ | |
| 158 | + REG_SET_2(BLANK_OFFSET_0, 0, | |
| 159 | + REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, | |
| 160 | + DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); | |
| 161 | + | |
| 162 | + REG_SET(BLANK_OFFSET_1, 0, | |
| 163 | + MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); | |
| 164 | + | |
| 165 | + REG_SET(DST_DIMENSIONS, 0, | |
| 166 | + REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); | |
| 167 | + | |
| 168 | + REG_SET_2(DST_AFTER_SCALER, 0, | |
| 169 | + REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, | |
| 170 | + DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); | |
| 171 | + | |
| 172 | + REG_SET(REF_FREQ_TO_PIX_FREQ, 0, | |
| 173 | + REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); | |
| 174 | + | |
| 175 | + /* DLG - Per luma/chroma */ | |
| 176 | + REG_SET(VBLANK_PARAMETERS_1, 0, | |
| 177 | + REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); | |
| 178 | + | |
| 179 | + if (REG(NOM_PARAMETERS_0)) | |
| 180 | + REG_SET(NOM_PARAMETERS_0, 0, | |
| 181 | + DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); | |
| 182 | + | |
| 183 | + if (REG(NOM_PARAMETERS_1)) | |
| 184 | + REG_SET(NOM_PARAMETERS_1, 0, | |
| 185 | + REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); | |
| 186 | + | |
| 187 | + REG_SET(NOM_PARAMETERS_4, 0, | |
| 188 | + DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); | |
| 189 | + | |
| 190 | + REG_SET(NOM_PARAMETERS_5, 0, | |
| 191 | + REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); | |
| 192 | + | |
| 193 | + REG_SET_2(PER_LINE_DELIVERY, 0, | |
| 194 | + REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, | |
| 195 | + REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); | |
| 196 | + | |
| 197 | + REG_SET(VBLANK_PARAMETERS_2, 0, | |
| 198 | + REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); | |
| 199 | + | |
| 200 | + if (REG(NOM_PARAMETERS_2)) | |
| 201 | + REG_SET(NOM_PARAMETERS_2, 0, | |
| 202 | + DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); | |
| 203 | + | |
| 204 | + if (REG(NOM_PARAMETERS_3)) | |
| 205 | + REG_SET(NOM_PARAMETERS_3, 0, | |
| 206 | + REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); | |
| 207 | + | |
| 208 | + REG_SET(NOM_PARAMETERS_6, 0, | |
| 209 | + DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); | |
| 210 | + | |
| 211 | + REG_SET(NOM_PARAMETERS_7, 0, | |
| 212 | + REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); | |
| 213 | + | |
| 214 | + /* TTU - per hubp */ | |
| 215 | + REG_SET_2(DCN_TTU_QOS_WM, 0, | |
| 216 | + QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, | |
| 217 | + QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); | |
| 218 | + | |
| 219 | + /* TTU - per luma/chroma */ | |
| 220 | + /* Assumed surf0 is luma and 1 is chroma */ | |
| 221 | + | |
| 222 | + REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, | |
| 223 | + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, | |
| 224 | + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, | |
| 225 | + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); | |
| 226 | + | |
| 227 | + REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, | |
| 228 | + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, | |
| 229 | + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, | |
| 230 | + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); | |
| 231 | + | |
| 232 | + REG_SET_3(DCN_CUR0_TTU_CNTL0, 0, | |
| 233 | + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0, | |
| 234 | + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0, | |
| 235 | + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0); | |
| 236 | + | |
| 237 | + REG_SET(FLIP_PARAMETERS_1, 0, | |
| 238 | + REFCYC_PER_PTE_GROUP_FLIP_L, dlg_attr->refcyc_per_pte_group_flip_l); | |
| 239 | + REG_SET(HUBP_3DLUT_DLG_PARAM, 0, REFCYC_PER_3DLUT_GROUP, dlg_attr->refcyc_per_tdlut_group); | |
| 240 | + | |
| 241 | + REG_UPDATE(DCN_DMDATA_VM_CNTL, | |
| 242 | + REFCYC_PER_VM_DMDATA, dlg_attr->refcyc_per_vm_dmdata); | |
| 243 | +} | |
| 244 | + | |
| 245 | +void hubp42_setup( | |
| 246 | + struct hubp *hubp, | |
| 247 | + struct dml2_dchub_per_pipe_register_set *pipe_regs, | |
| 248 | + union dml2_global_sync_programming *pipe_global_sync, | |
| 249 | + struct dc_crtc_timing *timing) | |
| 250 | +{ | |
| 251 | + /* otg is locked when this func is called. Register are double buffered. | |
| 252 | + * disable the requestors is not needed | |
| 253 | + */ | |
| 254 | + hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing); | |
| 255 | + hubp401_program_requestor(hubp, &pipe_regs->rq_regs); | |
| 256 | + hubp42_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs); | |
| 257 | +} | |
| 258 | +static void hubp42_program_surface_config( | |
| 259 | + struct hubp *hubp, | |
| 260 | + enum surface_pixel_format format, | |
| 261 | + struct dc_tiling_info *tiling_info, | |
| 262 | + struct plane_size *plane_size, | |
| 263 | + enum dc_rotation_angle rotation, | |
| 264 | + struct dc_plane_dcc_param *dcc, | |
| 265 | + bool horizontal_mirror, | |
| 266 | + unsigned int compat_level) | |
| 267 | +{ | |
| 268 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 269 | + | |
| 270 | + hubp3_dcc_control_sienna_cichlid(hubp, dcc); | |
| 271 | + hubp3_program_tiling(hubp2, tiling_info, format); | |
| 272 | + hubp2_program_size(hubp, format, plane_size, dcc); | |
| 273 | + hubp2_program_rotation(hubp, rotation, horizontal_mirror); | |
| 274 | + hubp42_program_pixel_format(hubp, format); | |
| 275 | +} | |
| 276 | + | |
| 277 | +void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp, | |
| 278 | + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r, | |
| 279 | + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g, | |
| 280 | + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b) | |
| 281 | +{ | |
| 282 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 283 | + | |
| 284 | + REG_UPDATE_3(HUBP_3DLUT_CONTROL, | |
| 285 | + HUBP_3DLUT_CROSSBAR_SEL_R, bit_slice_r, | |
| 286 | + HUBP_3DLUT_CROSSBAR_SEL_G, bit_slice_g, | |
| 287 | + HUBP_3DLUT_CROSSBAR_SEL_B, bit_slice_b); | |
| 288 | +} | |
| 289 | + | |
| 290 | +static bool hubp42_program_surface_flip_and_addr( | |
| 291 | + struct hubp *hubp, | |
| 292 | + const struct dc_plane_address *address, | |
| 293 | + bool flip_immediate) | |
| 294 | +{ | |
| 295 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 296 | + | |
| 297 | + //program flip type | |
| 298 | + REG_UPDATE(DCSURF_FLIP_CONTROL, | |
| 299 | + SURFACE_FLIP_TYPE, flip_immediate); | |
| 300 | + | |
| 301 | + // Program VMID reg | |
| 302 | + if (flip_immediate == 0) | |
| 303 | + REG_UPDATE(VMID_SETTINGS_0, | |
| 304 | + VMID, address->vmid); | |
| 305 | + | |
| 306 | + if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) { | |
| 307 | + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0); | |
| 308 | + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1); | |
| 309 | + | |
| 310 | + } else { | |
| 311 | + // turn off stereo if not in stereo | |
| 312 | + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0); | |
| 313 | + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0); | |
| 314 | + } | |
| 315 | + | |
| 316 | + /* HW automatically latch rest of address register on write to | |
| 317 | + * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used | |
| 318 | + * | |
| 319 | + * program high first and then the low addr, order matters! | |
| 320 | + */ | |
| 321 | + switch (address->type) { | |
| 322 | + case PLN_ADDR_TYPE_GRAPHICS: | |
| 323 | + /* DCN1.0 does not support const color | |
| 324 | + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 | |
| 325 | + * base on address->grph.dcc_const_color | |
| 326 | + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma | |
| 327 | + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma | |
| 328 | + */ | |
| 329 | + | |
| 330 | + if (address->grph.addr.quad_part == 0) | |
| 331 | + break; | |
| 332 | + | |
| 333 | + REG_UPDATE_2(DCSURF_SURFACE_CONTROL, | |
| 334 | + PRIMARY_SURFACE_TMZ, address->tmz_surface, | |
| 335 | + PRIMARY_META_SURFACE_TMZ, address->tmz_surface); | |
| 336 | + | |
| 337 | + if (address->grph.meta_addr.quad_part != 0) { | |
| 338 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, | |
| 339 | + PRIMARY_META_SURFACE_ADDRESS_HIGH, | |
| 340 | + address->grph.meta_addr.high_part); | |
| 341 | + | |
| 342 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, | |
| 343 | + PRIMARY_META_SURFACE_ADDRESS, | |
| 344 | + address->grph.meta_addr.low_part); | |
| 345 | + } | |
| 346 | + | |
| 347 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, | |
| 348 | + PRIMARY_SURFACE_ADDRESS_HIGH, | |
| 349 | + address->grph.addr.high_part); | |
| 350 | + | |
| 351 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, | |
| 352 | + PRIMARY_SURFACE_ADDRESS, | |
| 353 | + address->grph.addr.low_part); | |
| 354 | + break; | |
| 355 | + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: | |
| 356 | + if (address->video_progressive.luma_addr.quad_part == 0 | |
| 357 | + || address->video_progressive.chroma_addr.quad_part == 0) | |
| 358 | + break; | |
| 359 | + | |
| 360 | + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, | |
| 361 | + PRIMARY_SURFACE_TMZ, address->tmz_surface, | |
| 362 | + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, | |
| 363 | + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, | |
| 364 | + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); | |
| 365 | + | |
| 366 | + if (address->video_progressive.luma_meta_addr.quad_part != 0) { | |
| 367 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, | |
| 368 | + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, | |
| 369 | + address->video_progressive.chroma_meta_addr.high_part); | |
| 370 | + | |
| 371 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, | |
| 372 | + PRIMARY_META_SURFACE_ADDRESS_C, | |
| 373 | + address->video_progressive.chroma_meta_addr.low_part); | |
| 374 | + | |
| 375 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, | |
| 376 | + PRIMARY_META_SURFACE_ADDRESS_HIGH, | |
| 377 | + address->video_progressive.luma_meta_addr.high_part); | |
| 378 | + | |
| 379 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, | |
| 380 | + PRIMARY_META_SURFACE_ADDRESS, | |
| 381 | + address->video_progressive.luma_meta_addr.low_part); | |
| 382 | + } | |
| 383 | + | |
| 384 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, | |
| 385 | + PRIMARY_SURFACE_ADDRESS_HIGH_C, | |
| 386 | + address->video_progressive.chroma_addr.high_part); | |
| 387 | + | |
| 388 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, | |
| 389 | + PRIMARY_SURFACE_ADDRESS_C, | |
| 390 | + address->video_progressive.chroma_addr.low_part); | |
| 391 | + | |
| 392 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, | |
| 393 | + PRIMARY_SURFACE_ADDRESS_HIGH, | |
| 394 | + address->video_progressive.luma_addr.high_part); | |
| 395 | + | |
| 396 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, | |
| 397 | + PRIMARY_SURFACE_ADDRESS, | |
| 398 | + address->video_progressive.luma_addr.low_part); | |
| 399 | + break; | |
| 400 | + case PLN_ADDR_TYPE_GRPH_STEREO: | |
| 401 | + if (address->grph_stereo.left_addr.quad_part == 0) | |
| 402 | + break; | |
| 403 | + if (address->grph_stereo.right_addr.quad_part == 0) | |
| 404 | + break; | |
| 405 | + | |
| 406 | + REG_UPDATE_8(DCSURF_SURFACE_CONTROL, | |
| 407 | + PRIMARY_SURFACE_TMZ, address->tmz_surface, | |
| 408 | + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, | |
| 409 | + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, | |
| 410 | + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface, | |
| 411 | + SECONDARY_SURFACE_TMZ, address->tmz_surface, | |
| 412 | + SECONDARY_SURFACE_TMZ_C, address->tmz_surface, | |
| 413 | + SECONDARY_META_SURFACE_TMZ, address->tmz_surface, | |
| 414 | + SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface); | |
| 415 | + | |
| 416 | + if (address->grph_stereo.right_meta_addr.quad_part != 0) { | |
| 417 | + | |
| 418 | + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, 0, | |
| 419 | + SECONDARY_META_SURFACE_ADDRESS_HIGH_C, | |
| 420 | + address->grph_stereo.right_alpha_meta_addr.high_part); | |
| 421 | + | |
| 422 | + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, 0, | |
| 423 | + SECONDARY_META_SURFACE_ADDRESS_C, | |
| 424 | + address->grph_stereo.right_alpha_meta_addr.low_part); | |
| 425 | + | |
| 426 | + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, | |
| 427 | + SECONDARY_META_SURFACE_ADDRESS_HIGH, | |
| 428 | + address->grph_stereo.right_meta_addr.high_part); | |
| 429 | + | |
| 430 | + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, | |
| 431 | + SECONDARY_META_SURFACE_ADDRESS, | |
| 432 | + address->grph_stereo.right_meta_addr.low_part); | |
| 433 | + } | |
| 434 | + if (address->grph_stereo.left_meta_addr.quad_part != 0) { | |
| 435 | + | |
| 436 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, | |
| 437 | + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, | |
| 438 | + address->grph_stereo.left_alpha_meta_addr.high_part); | |
| 439 | + | |
| 440 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, | |
| 441 | + PRIMARY_META_SURFACE_ADDRESS_C, | |
| 442 | + address->grph_stereo.left_alpha_meta_addr.low_part); | |
| 443 | + | |
| 444 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, | |
| 445 | + PRIMARY_META_SURFACE_ADDRESS_HIGH, | |
| 446 | + address->grph_stereo.left_meta_addr.high_part); | |
| 447 | + | |
| 448 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, | |
| 449 | + PRIMARY_META_SURFACE_ADDRESS, | |
| 450 | + address->grph_stereo.left_meta_addr.low_part); | |
| 451 | + } | |
| 452 | + | |
| 453 | + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, 0, | |
| 454 | + SECONDARY_SURFACE_ADDRESS_HIGH_C, | |
| 455 | + address->grph_stereo.right_alpha_addr.high_part); | |
| 456 | + | |
| 457 | + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_C, 0, | |
| 458 | + SECONDARY_SURFACE_ADDRESS_C, | |
| 459 | + address->grph_stereo.right_alpha_addr.low_part); | |
| 460 | + | |
| 461 | + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, | |
| 462 | + SECONDARY_SURFACE_ADDRESS_HIGH, | |
| 463 | + address->grph_stereo.right_addr.high_part); | |
| 464 | + | |
| 465 | + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, | |
| 466 | + SECONDARY_SURFACE_ADDRESS, | |
| 467 | + address->grph_stereo.right_addr.low_part); | |
| 468 | + | |
| 469 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, | |
| 470 | + PRIMARY_SURFACE_ADDRESS_HIGH_C, | |
| 471 | + address->grph_stereo.left_alpha_addr.high_part); | |
| 472 | + | |
| 473 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, | |
| 474 | + PRIMARY_SURFACE_ADDRESS_C, | |
| 475 | + address->grph_stereo.left_alpha_addr.low_part); | |
| 476 | + | |
| 477 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, | |
| 478 | + PRIMARY_SURFACE_ADDRESS_HIGH, | |
| 479 | + address->grph_stereo.left_addr.high_part); | |
| 480 | + | |
| 481 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, | |
| 482 | + PRIMARY_SURFACE_ADDRESS, | |
| 483 | + address->grph_stereo.left_addr.low_part); | |
| 484 | + break; | |
| 485 | + case PLN_ADDR_TYPE_RGBEA: | |
| 486 | + if (address->rgbea.addr.quad_part == 0 | |
| 487 | + || address->rgbea.alpha_addr.quad_part == 0) | |
| 488 | + break; | |
| 489 | + | |
| 490 | + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, | |
| 491 | + PRIMARY_SURFACE_TMZ, address->tmz_surface, | |
| 492 | + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, | |
| 493 | + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, | |
| 494 | + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); | |
| 495 | + | |
| 496 | + if (address->rgbea.meta_addr.quad_part != 0) { | |
| 497 | + | |
| 498 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, | |
| 499 | + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, | |
| 500 | + address->rgbea.alpha_meta_addr.high_part); | |
| 501 | + | |
| 502 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, | |
| 503 | + PRIMARY_META_SURFACE_ADDRESS_C, | |
| 504 | + address->rgbea.alpha_meta_addr.low_part); | |
| 505 | + | |
| 506 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, | |
| 507 | + PRIMARY_META_SURFACE_ADDRESS_HIGH, | |
| 508 | + address->rgbea.meta_addr.high_part); | |
| 509 | + | |
| 510 | + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, | |
| 511 | + PRIMARY_META_SURFACE_ADDRESS, | |
| 512 | + address->rgbea.meta_addr.low_part); | |
| 513 | + } | |
| 514 | + | |
| 515 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, | |
| 516 | + PRIMARY_SURFACE_ADDRESS_HIGH_C, | |
| 517 | + address->rgbea.alpha_addr.high_part); | |
| 518 | + | |
| 519 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, | |
| 520 | + PRIMARY_SURFACE_ADDRESS_C, | |
| 521 | + address->rgbea.alpha_addr.low_part); | |
| 522 | + | |
| 523 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, | |
| 524 | + PRIMARY_SURFACE_ADDRESS_HIGH, | |
| 525 | + address->rgbea.addr.high_part); | |
| 526 | + | |
| 527 | + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, | |
| 528 | + PRIMARY_SURFACE_ADDRESS, | |
| 529 | + address->rgbea.addr.low_part); | |
| 530 | + break; | |
| 531 | + default: | |
| 532 | + BREAK_TO_DEBUGGER(); | |
| 533 | + break; | |
| 534 | + } | |
| 535 | + | |
| 536 | + hubp->request_address = *address; | |
| 537 | + | |
| 538 | + return true; | |
| 539 | +} | |
| 540 | + | |
| 541 | +struct hubp_funcs dcn42_hubp_funcs = { | |
| 542 | + .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer, | |
| 543 | + .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled, | |
| 544 | + .hubp_program_surface_flip_and_addr = hubp42_program_surface_flip_and_addr, | |
| 545 | + .hubp_program_surface_config = hubp42_program_surface_config, | |
| 546 | + .hubp_is_flip_pending = hubp2_is_flip_pending, | |
| 547 | + .hubp_setup2 = hubp42_setup, | |
| 548 | + .hubp_setup_interdependent2 = hubp401_setup_interdependent, | |
| 549 | + .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings, | |
| 550 | + .set_blank = hubp2_set_blank, | |
| 551 | + .dcc_control = hubp3_dcc_control, | |
| 552 | + .hubp_reset = hubp_reset, | |
| 553 | + .mem_program_viewport = min_set_viewport, | |
| 554 | + .set_cursor_attributes = hubp32_cursor_set_attributes, | |
| 555 | + .set_cursor_position = hubp401_cursor_set_position, | |
| 556 | + .hubp_clk_cntl = hubp2_clk_cntl, | |
| 557 | + .hubp_vtg_sel = hubp2_vtg_sel, | |
| 558 | + .dmdata_set_attributes = hubp3_dmdata_set_attributes, | |
| 559 | + .dmdata_load = hubp2_dmdata_load, | |
| 560 | + .dmdata_status_done = hubp2_dmdata_status_done, | |
| 561 | + .hubp_read_state = hubp42_read_state, | |
| 562 | + .hubp_clear_underflow = hubp2_clear_underflow, | |
| 563 | + .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl, | |
| 564 | + .hubp_init = hubp42_init, | |
| 565 | + .set_unbounded_requesting = hubp31_set_unbounded_requesting, | |
| 566 | + .hubp_soft_reset = hubp31_soft_reset, | |
| 567 | + .hubp_set_flip_int = hubp1_set_flip_int, | |
| 568 | + .hubp_in_blank = hubp1_in_blank, | |
| 569 | + .program_extended_blank = hubp31_program_extended_blank_value, | |
| 570 | + .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale, | |
| 571 | + .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode, | |
| 572 | + .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format, | |
| 573 | + .hubp_program_3dlut_fl_addr = hubp401_program_3dlut_fl_addr, | |
| 574 | + .hubp_program_3dlut_fl_dlg_param = hubp401_program_3dlut_fl_dlg_param, | |
| 575 | + .hubp_enable_3dlut_fl = hubp401_enable_3dlut_fl, | |
| 576 | + .hubp_program_3dlut_fl_addressing_mode = hubp401_program_3dlut_fl_addressing_mode, | |
| 577 | + .hubp_program_3dlut_fl_width = hubp401_program_3dlut_fl_width, | |
| 578 | + .hubp_program_3dlut_fl_tmz_protected = hubp401_program_3dlut_fl_tmz_protected, | |
| 579 | + .hubp_program_3dlut_fl_crossbar = hubp42_program_3dlut_fl_crossbar, | |
| 580 | + .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done, | |
| 581 | + .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config, | |
| 582 | + .hubp_read_reg_state = hubp3_read_reg_state | |
| 583 | +}; | |
| 584 | + | |
| 585 | +bool hubp42_construct( | |
| 586 | + struct dcn20_hubp *hubp2, | |
| 587 | + struct dc_context *ctx, | |
| 588 | + uint32_t inst, | |
| 589 | + const struct dcn_hubp2_registers *hubp_regs, | |
| 590 | + const struct dcn_hubp2_shift *hubp_shift, | |
| 591 | + const struct dcn_hubp2_mask *hubp_mask) | |
| 592 | +{ | |
| 593 | + hubp2->base.funcs = &dcn42_hubp_funcs; | |
| 594 | + hubp2->base.ctx = ctx; | |
| 595 | + hubp2->hubp_regs = hubp_regs; | |
| 596 | + hubp2->hubp_shift = hubp_shift; | |
| 597 | + hubp2->hubp_mask = hubp_mask; | |
| 598 | + hubp2->base.inst = inst; | |
| 599 | + hubp2->base.opp_id = OPP_ID_INVALID; | |
| 600 | + hubp2->base.mpcc_id = 0xf; | |
| 601 | + | |
| 602 | + return true; | |
| 603 | +} | |
| 604 | + | |
| 605 | + | |
| 606 | +void hubp42_read_state(struct hubp *hubp) | |
| 607 | +{ | |
| 608 | + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | |
| 609 | + struct dcn_hubp_state *s = &hubp2->state; | |
| 610 | + struct dcn_fl_regs_st *fl_regs = &s->fl_regs; | |
| 611 | + | |
| 612 | + hubp401_read_state(hubp); | |
| 613 | + | |
| 614 | + /* CONTROL */ | |
| 615 | + REG_GET_5(HUBP_3DLUT_CONTROL, | |
| 616 | + HUBP_3DLUT_ENABLE, &fl_regs->lut_enable, | |
| 617 | + HUBP_3DLUT_DONE, &fl_regs->lut_done, | |
| 618 | + HUBP_3DLUT_ADDRESSING_MODE, &fl_regs->lut_addr_mode, | |
| 619 | + HUBP_3DLUT_WIDTH, &fl_regs->lut_width, | |
| 620 | + HUBP_3DLUT_MPC_WIDTH, &fl_regs->lut_mpc_width); | |
| 621 | + | |
| 622 | + REG_GET_4(HUBP_3DLUT_CONTROL, | |
| 623 | + HUBP_3DLUT_TMZ, &fl_regs->lut_tmz, | |
| 624 | + HUBP_3DLUT_CROSSBAR_SEL_R, &fl_regs->lut_crossbar_sel_r, | |
| 625 | + HUBP_3DLUT_CROSSBAR_SEL_G, &fl_regs->lut_crossbar_sel_g, | |
| 626 | + HUBP_3DLUT_CROSSBAR_SEL_B, &fl_regs->lut_crossbar_sel_b); | |
| 627 | + | |
| 628 | + /* ADDR */ | |
| 629 | + REG_GET(HUBP_3DLUT_ADDRESS_HIGH, | |
| 630 | + HUBP_3DLUT_ADDRESS_HIGH, &fl_regs->lut_addr_hi); | |
| 631 | + REG_GET(HUBP_3DLUT_ADDRESS_LOW, | |
| 632 | + HUBP_3DLUT_ADDRESS_LOW, &fl_regs->lut_addr_lo); | |
| 633 | + /* CLK */ | |
| 634 | + REG_GET(HUBP_3DLUT_DLG_PARAM, | |
| 635 | + REFCYC_PER_3DLUT_GROUP, &fl_regs->refcyc_3dlut_group); | |
| 636 | + /* FL */ | |
| 637 | + REG_GET_2(_3DLUT_FL_BIAS_SCALE, | |
| 638 | + HUBP0_3DLUT_FL_BIAS, &fl_regs->lut_fl_bias, | |
| 639 | + HUBP0_3DLUT_FL_SCALE, &fl_regs->lut_fl_scale); | |
| 640 | + REG_GET_2(_3DLUT_FL_CONFIG, | |
| 641 | + HUBP0_3DLUT_FL_MODE, &fl_regs->lut_fl_mode, | |
| 642 | + HUBP0_3DLUT_FL_FORMAT, &fl_regs->lut_fl_format); | |
| 643 | +} | |
| @@ -0,0 +1,79 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + * Authors: AMD | |
| 24 | + * | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef __DC_HUBP_DCN42_H__ | |
| 28 | +#define __DC_HUBP_DCN42_H__ | |
| 29 | + | |
| 30 | +#include "dcn35/dcn35_hubp.h" | |
| 31 | + | |
| 32 | +#define HUBP_MASK_SH_LIST_DCN42(mask_sh)\ | |
| 33 | + HUBP_MASK_SH_LIST_DCN35(mask_sh),\ | |
| 34 | + HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mask_sh),\ | |
| 35 | + HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, mask_sh),\ | |
| 36 | + HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, mask_sh),\ | |
| 37 | + HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_SCALE, mask_sh),\ | |
| 38 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ENABLE, mask_sh),\ | |
| 39 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_DONE, mask_sh),\ | |
| 40 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, mask_sh),\ | |
| 41 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, mask_sh),\ | |
| 42 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_MPC_WIDTH, mask_sh),\ | |
| 43 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, mask_sh),\ | |
| 44 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_B, mask_sh),\ | |
| 45 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_G, mask_sh),\ | |
| 46 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_R, mask_sh),\ | |
| 47 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, mask_sh),\ | |
| 48 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_LOW, HUBP_3DLUT_ADDRESS_LOW, mask_sh),\ | |
| 49 | + HUBP_SF(CURSOR0_0_HUBP_3DLUT_DLG_PARAM, REFCYC_PER_3DLUT_GROUP, mask_sh) | |
| 50 | + | |
| 51 | +bool hubp42_construct( | |
| 52 | + struct dcn20_hubp *hubp2, | |
| 53 | + struct dc_context *ctx, | |
| 54 | + uint32_t inst, | |
| 55 | + const struct dcn_hubp2_registers *hubp_regs, | |
| 56 | + const struct dcn_hubp2_shift *hubp_shift, | |
| 57 | + const struct dcn_hubp2_mask *hubp_mask); | |
| 58 | + | |
| 59 | +void hubp42_program_3dlut_fl_crossbar( | |
| 60 | + struct hubp *hubp, | |
| 61 | + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r, | |
| 62 | + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g, | |
| 63 | + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b); | |
| 64 | + | |
| 65 | +void hubp42_read_state(struct hubp *hubp); | |
| 66 | + | |
| 67 | +void hubp42_setup( | |
| 68 | + struct hubp *hubp, | |
| 69 | + struct dml2_dchub_per_pipe_register_set *pipe_regs, | |
| 70 | + union dml2_global_sync_programming *pipe_global_sync, | |
| 71 | + struct dc_crtc_timing *timing); | |
| 72 | + | |
| 73 | +void hubp42_program_deadline( | |
| 74 | + struct hubp *hubp, | |
| 75 | + struct dml2_display_dlg_regs *dlg_attr, | |
| 76 | + struct dml2_display_ttu_regs *ttu_attr); | |
| 77 | + | |
| 78 | + | |
| 79 | +#endif /* __DC_HUBP_DCN42_H__ */ | |
| @@ -1,5 +1,4 @@ | ||
| 1 | − | |
| 2 | −# Copyright 2022 Advanced Micro Devices, Inc. | |
| 1 | +# Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 3 | 2 | # |
| 4 | 3 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 4 | # copy of this software and associated documentation files (the "Software"), |
| @@ -199,4 +198,13 @@ HWSS_DCN401 = dcn401_hwseq.o dcn401_init.o · 193 unmodified lines | ||
| 199 | 198 | AMD_DAL_HWSS_DCN401 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn401/,$(HWSS_DCN401)) |
| 200 | 199 | |
| 201 | 200 | AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN401) |
| 201 | + | |
| 202 | +############################################################################### | |
| 203 | + | |
| 204 | +HWSS_DCN42 = dcn42_hwseq.o dcn42_init.o | |
| 205 | + | |
| 206 | +AMD_DAL_HWSS_DCN42 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn42/,$(HWSS_DCN42)) | |
| 207 | + | |
| 208 | +AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN42) | |
| 209 | + | |
| 202 | 210 | endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2016 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2016, 2026 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -700,6 +700,8 @@ struct dce_hwseq_registers { · 694 unmodified lines | ||
| 700 | 700 | uint32_t DOMAIN23_PG_STATUS; |
| 701 | 701 | uint32_t DOMAIN24_PG_STATUS; |
| 702 | 702 | uint32_t DOMAIN25_PG_STATUS; |
| 703 | + uint32_t DOMAIN26_PG_CONFIG; | |
| 704 | + uint32_t DOMAIN26_PG_STATUS; | |
| 703 | 705 | }; |
| 704 | 706 | /* set field name */ |
| 705 | 707 | #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ |
| @@ -1245,6 +1247,13 @@ struct dce_hwseq_registers { · 539 unmodified lines | ||
| 1245 | 1247 | type DOMAIN25_PGFSM_PWR_STATUS; \ |
| 1246 | 1248 | type DOMAIN_DESIRED_PWR_STATE; |
| 1247 | 1249 | |
| 1250 | +#define HWSEQ_DCN42_REG_FIELD_LIST(type) \ | |
| 1251 | + type DPIASYMCLK4_GATE_DISABLE;\ | |
| 1252 | + type DPIASYMCLK5_GATE_DISABLE;\ | |
| 1253 | + type DOMAIN26_POWER_FORCEON; \ | |
| 1254 | + type DOMAIN26_POWER_GATE; \ | |
| 1255 | + type DOMAIN26_PGFSM_PWR_STATUS; | |
| 1256 | + | |
| 1248 | 1257 | struct dce_hwseq_shift { |
| 1249 | 1258 | HWSEQ_REG_FIELD_LIST(uint8_t) |
| 1250 | 1259 | HWSEQ_DCN_REG_FIELD_LIST(uint8_t) |
| @@ -1253,6 +1262,7 @@ struct dce_hwseq_shift { · 2 unmodified lines | ||
| 1253 | 1262 | HWSEQ_DCN31_REG_FIELD_LIST(uint8_t) |
| 1254 | 1263 | HWSEQ_DCN35_REG_FIELD_LIST(uint8_t) |
| 1255 | 1264 | HWSEQ_DCN401_REG_FIELD_LIST(uint8_t) |
| 1265 | + HWSEQ_DCN42_REG_FIELD_LIST(uint8_t) | |
| 1256 | 1266 | }; |
| 1257 | 1267 | |
| 1258 | 1268 | struct dce_hwseq_mask { |
| @@ -1263,6 +1273,7 @@ struct dce_hwseq_mask { · 4 unmodified lines | ||
| 1263 | 1273 | HWSEQ_DCN31_REG_FIELD_LIST(uint32_t) |
| 1264 | 1274 | HWSEQ_DCN35_REG_FIELD_LIST(uint32_t) |
| 1265 | 1275 | HWSEQ_DCN401_REG_FIELD_LIST(uint32_t) |
| 1276 | + HWSEQ_DCN42_REG_FIELD_LIST(uint32_t) | |
| 1266 | 1277 | }; |
| 1267 | 1278 | |
| 1268 | 1279 | |
| @@ -660,6 +660,60 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) · 659 unmodified lines | ||
| 660 | 660 | } |
| 661 | 661 | } |
| 662 | 662 | |
| 663 | +static void | |
| 664 | +dce110_external_encoder_control(enum bp_external_encoder_control_action action, | |
| 665 | + struct dc_link *link, | |
| 666 | + struct dc_crtc_timing *timing) | |
| 667 | +{ | |
| 668 | + struct dc *dc = link->ctx->dc; | |
| 669 | + struct dc_bios *bios = link->ctx->dc_bios; | |
| 670 | + const struct dc_link_settings *link_settings = &link->cur_link_settings; | |
| 671 | + enum bp_result bp_result = BP_RESULT_OK; | |
| 672 | + struct bp_external_encoder_control ext_cntl = { | |
| 673 | + .action = action, | |
| 674 | + .connector_obj_id = link->link_enc->connector, | |
| 675 | + .encoder_id = link->ext_enc_id, | |
| 676 | + .lanes_number = link_settings->lane_count, | |
| 677 | + .link_rate = link_settings->link_rate, | |
| 678 | + | |
| 679 | + /* Use signal type of the real link encoder, ie. DP */ | |
| 680 | + .signal = link->connector_signal, | |
| 681 | + | |
| 682 | + /* We don't know the timing yet when executing the SETUP action, | |
| 683 | + * so use a reasonably high default value. It seems that ENABLE | |
| 684 | + * can change the actual pixel clock but doesn't work with higher | |
| 685 | + * pixel clocks than what SETUP was called with. | |
| 686 | + */ | |
| 687 | + .pixel_clock = timing ? timing->pix_clk_100hz / 10 : 300000, | |
| 688 | + .color_depth = timing ? timing->display_color_depth : COLOR_DEPTH_888, | |
| 689 | + }; | |
| 690 | + DC_LOGGER_INIT(); | |
| 691 | + | |
| 692 | + bp_result = bios->funcs->external_encoder_control(bios, &ext_cntl); | |
| 693 | + | |
| 694 | + if (bp_result != BP_RESULT_OK) | |
| 695 | + DC_LOG_ERROR("Failed to execute external encoder action: 0x%x\n", action); | |
| 696 | +} | |
| 697 | + | |
| 698 | +static void | |
| 699 | +dce110_prepare_ddc(struct dc_link *link) | |
| 700 | +{ | |
| 701 | + if (link->ext_enc_id.id) | |
| 702 | + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_DDC_SETUP, link, NULL); | |
| 703 | +} | |
| 704 | + | |
| 705 | +static bool | |
| 706 | +dce110_dac_load_detect(struct dc_link *link) | |
| 707 | +{ | |
| 708 | + struct dc_bios *bios = link->ctx->dc_bios; | |
| 709 | + struct link_encoder *link_enc = link->link_enc; | |
| 710 | + enum bp_result bp_result; | |
| 711 | + | |
| 712 | + bp_result = bios->funcs->dac_load_detection( | |
| 713 | + bios, link_enc->analog_engine, link->ext_enc_id); | |
| 714 | + return bp_result == BP_RESULT_OK; | |
| 715 | +} | |
| 716 | + | |
| 663 | 717 | void dce110_enable_stream(struct pipe_ctx *pipe_ctx) |
| 664 | 718 | { |
| 665 | 719 | enum dc_lane_count lane_count = |
| @@ -690,6 +744,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) · 24 unmodified lines | ||
| 690 | 744 | |
| 691 | 745 | tg->funcs->set_early_control(tg, early_control); |
| 692 | 746 | |
| 747 | + if (link->ext_enc_id.id) | |
| 748 | + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_ENABLE, link, timing); | |
| 693 | 749 | } |
| 694 | 750 | |
| 695 | 751 | static enum bp_result link_transmitter_control( |
| @@ -1183,6 +1239,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) · 487 unmodified lines | ||
| 1183 | 1239 | dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| 1184 | 1240 | link_enc->transmitter - TRANSMITTER_UNIPHY_A); |
| 1185 | 1241 | } |
| 1242 | + | |
| 1243 | + if (link->ext_enc_id.id) | |
| 1244 | + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_DISABLE, link, NULL); | |
| 1186 | 1245 | } |
| 1187 | 1246 | |
| 1188 | 1247 | void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, |
| @@ -3317,6 +3376,11 @@ void dce110_enable_dp_link_output( · 2128 unmodified lines | ||
| 3317 | 3376 | } |
| 3318 | 3377 | } |
| 3319 | 3378 | |
| 3379 | + if (link->ext_enc_id.id) { | |
| 3380 | + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_INIT, link, NULL); | |
| 3381 | + dce110_external_encoder_control(EXTERNAL_ENCODER_CONTROL_SETUP, link, NULL); | |
| 3382 | + } | |
| 3383 | + | |
| 3320 | 3384 | if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { |
| 3321 | 3385 | if (dc->clk_mgr->funcs->notify_link_rate_change) |
| 3322 | 3386 | dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); |
| @@ -3409,6 +3473,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { · 86 unmodified lines | ||
| 3409 | 3473 | .enable_dp_link_output = dce110_enable_dp_link_output, |
| 3410 | 3474 | .enable_analog_link_output = dce110_enable_analog_link_output, |
| 3411 | 3475 | .disable_link_output = dce110_disable_link_output, |
| 3476 | + .dac_load_detect = dce110_dac_load_detect, | |
| 3477 | + .prepare_ddc = dce110_prepare_ddc, | |
| 3412 | 3478 | }; |
| 3413 | 3479 | |
| 3414 | 3480 | static const struct hwseq_private_funcs dce110_private_funcs = { |
| @@ -72,7 +72,11 @@ void dcn401_initialize_min_clocks(struct dc *dc) · 71 unmodified lines | ||
| 72 | 72 | * audio corruption. Read current DISPCLK from DENTIST and request the same |
| 73 | 73 | * freq to ensure that the timing is valid and unchanged. |
| 74 | 74 | */ |
| 75 | − clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr); | |
| 75 | + if (dc->clk_mgr->funcs->get_dispclk_from_dentist) { | |
| 76 | + clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr); | |
| 77 | + } else { | |
| 78 | + clocks->dispclk_khz = dc->clk_mgr->boot_snapshot.dispclk * 1000; | |
| 79 | + } | |
| 76 | 80 | } |
| 77 | 81 | clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; |
| 78 | 82 | clocks->fclk_p_state_change_support = true; |
| @@ -1202,6 +1206,25 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) · 1123 unmodified lines | ||
| 1202 | 1206 | x_pos = pos_cpy.x - param.recout.x; |
| 1203 | 1207 | y_pos = pos_cpy.y - param.recout.y; |
| 1204 | 1208 | |
| 1209 | + /** | |
| 1210 | + * If the cursor position is negative after recout adjustment, we need | |
| 1211 | + * to shift the hotspot to compensate and clamp position to 0. This | |
| 1212 | + * handles the case where cursor straddles the left/top edge of an | |
| 1213 | + * overlay plane - the cursor is partially visible and needs correct | |
| 1214 | + * hotspot adjustment to render the visible portion. | |
| 1215 | + */ | |
| 1216 | + if (x_pos < 0) { | |
| 1217 | + pos_cpy.x_hotspot -= x_pos; | |
| 1218 | + if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION) | |
| 1219 | + adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy); | |
| 1220 | + x_pos = 0; | |
| 1221 | + } | |
| 1222 | + | |
| 1223 | + if (y_pos < 0) { | |
| 1224 | + pos_cpy.y_hotspot -= y_pos; | |
| 1225 | + y_pos = 0; | |
| 1226 | + } | |
| 1227 | + | |
| 1205 | 1228 | recout_x_pos = x_pos - pos_cpy.x_hotspot; |
| 1206 | 1229 | recout_y_pos = y_pos - pos_cpy.y_hotspot; |
| 1207 | 1230 | |
| @@ -1464,7 +1487,7 @@ void dcn401_optimize_bandwidth( · 256 unmodified lines | ||
| 1464 | 1487 | dc->clk_mgr, |
| 1465 | 1488 | context, |
| 1466 | 1489 | true); |
| 1467 | − if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) { | |
| 1490 | + if (context->bw_ctx.bw.dcn.clk.zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW) { | |
| 1468 | 1491 | for (i = 0; i < dc->res_pool->pipe_count; ++i) { |
| 1469 | 1492 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
| 1470 | 1493 | |
| @@ -1472,7 +1495,7 @@ void dcn401_optimize_bandwidth( · 1 unmodified line | ||
| 1472 | 1495 | && pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max |
| 1473 | 1496 | && pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total) |
| 1474 | 1497 | pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp, |
| 1475 | − pipe_ctx->dlg_regs.min_dst_y_next_start); | |
| 1498 | + pipe_ctx->hubp_regs.dlg_regs.min_dst_y_next_start); | |
| 1476 | 1499 | } |
| 1477 | 1500 | } |
| 1478 | 1501 | } |
| @@ -0,0 +1,1472 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +// | |
| 3 | +// Copyright 2026 Advanced Micro Devices, Inc. | |
| 4 | + | |
| 5 | +#include "dm_services.h" | |
| 6 | +#include "dm_helpers.h" | |
| 7 | +#include "core_types.h" | |
| 8 | +#include "resource.h" | |
| 9 | +#include "dccg.h" | |
| 10 | +#include "dce/dce_hwseq.h" | |
| 11 | +#include "dcn30/dcn30_cm_common.h" | |
| 12 | +#include "reg_helper.h" | |
| 13 | +#include "abm.h" | |
| 14 | +#include "hubp.h" | |
| 15 | +#include "dchubbub.h" | |
| 16 | +#include "timing_generator.h" | |
| 17 | +#include "opp.h" | |
| 18 | +#include "ipp.h" | |
| 19 | +#include "mpc.h" | |
| 20 | +#include "mcif_wb.h" | |
| 21 | +#include "dc_dmub_srv.h" | |
| 22 | +#include "link_hwss.h" | |
| 23 | +#include "dpcd_defs.h" | |
| 24 | +#include "dcn401/dcn401_hwseq.h" | |
| 25 | +#include "dcn42_hwseq.h" | |
| 26 | +#include "clk_mgr.h" | |
| 27 | +#include "dsc.h" | |
| 28 | +#include "dcn20/dcn20_optc.h" | |
| 29 | +#include "dce/dmub_hw_lock_mgr.h" | |
| 30 | +#include "dcn42/dcn42_resource.h" | |
| 31 | +#include "link_service.h" | |
| 32 | +#include "../dcn10/dcn10_hwseq.h" | |
| 33 | +#include "../dcn20/dcn20_hwseq.h" | |
| 34 | +#include "dc_state_priv.h" | |
| 35 | +#include "dc_stream_priv.h" | |
| 36 | +#include "dcn35/dcn35_hwseq.h" | |
| 37 | +#include "dcn42/dcn42_hwseq.h" | |
| 38 | +#include "dce/dmub_hw_lock_mgr.h" | |
| 39 | +#include "dio/dcn10/dcn10_dio.h" | |
| 40 | + | |
| 41 | +#define DC_LOGGER \ | |
| 42 | + ctx->logger | |
| 43 | + | |
| 44 | +#define CTX \ | |
| 45 | + hws->ctx | |
| 46 | + | |
| 47 | +#define REG(reg)\ | |
| 48 | + hws->regs->reg | |
| 49 | + | |
| 50 | +#undef FN | |
| 51 | +#define FN(reg_name, field_name) \ | |
| 52 | + hws->shifts->field_name, hws->masks->field_name | |
| 53 | + | |
| 54 | + | |
| 55 | +static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log) | |
| 56 | +{ | |
| 57 | + if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) { | |
| 58 | + if (dc->res_pool->pg_cntl->funcs->print_pg_status) | |
| 59 | + dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log); | |
| 60 | + } | |
| 61 | +} | |
| 62 | +void dcn42_init_hw(struct dc *dc) | |
| 63 | +{ | |
| 64 | + struct abm **abms = dc->res_pool->multiple_abms; | |
| 65 | + struct dce_hwseq *hws = dc->hwseq; | |
| 66 | + struct dc_bios *dcb = dc->ctx->dc_bios; | |
| 67 | + struct resource_pool *res_pool = dc->res_pool; | |
| 68 | + int i; | |
| 69 | + int edp_num; | |
| 70 | + uint32_t backlight = MAX_BACKLIGHT_LEVEL; | |
| 71 | + uint32_t user_level = MAX_BACKLIGHT_LEVEL; | |
| 72 | + int current_dchub_ref_freq = 0; | |
| 73 | + | |
| 74 | + if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) { | |
| 75 | + dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); | |
| 76 | + | |
| 77 | + // mark dcmode limits present if any clock has distinct AC and DC values from SMU | |
| 78 | + dc->caps.dcmode_power_limits_present = dc->clk_mgr->funcs->is_dc_mode_present && | |
| 79 | + dc->clk_mgr->funcs->is_dc_mode_present(dc->clk_mgr); | |
| 80 | + } | |
| 81 | + | |
| 82 | + // Initialize the dccg | |
| 83 | + if (res_pool->dccg->funcs->dccg_init) | |
| 84 | + res_pool->dccg->funcs->dccg_init(res_pool->dccg); | |
| 85 | + | |
| 86 | + // Disable DMUB Initialization until IPS state programming is finalized | |
| 87 | + //if (!dcb->funcs->is_accelerated_mode(dcb)) { | |
| 88 | + // hws->funcs.bios_golden_init(dc); | |
| 89 | + //} | |
| 90 | + | |
| 91 | + // Set default OPTC memory power states | |
| 92 | + if (dc->debug.enable_mem_low_power.bits.optc) { | |
| 93 | + // Shutdown when unassigned and light sleep in VBLANK | |
| 94 | + REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1); | |
| 95 | + } | |
| 96 | + | |
| 97 | + if (dc->debug.enable_mem_low_power.bits.vga) { | |
| 98 | + // Power down VGA memory | |
| 99 | + REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1); | |
| 100 | + } | |
| 101 | + | |
| 102 | + if (dc->ctx->dc_bios->fw_info_valid) { | |
| 103 | + res_pool->ref_clocks.xtalin_clock_inKhz = | |
| 104 | + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; | |
| 105 | + | |
| 106 | + if (res_pool->hubbub) { | |
| 107 | + (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, | |
| 108 | + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, | |
| 109 | + &res_pool->ref_clocks.dccg_ref_clock_inKhz); | |
| 110 | + | |
| 111 | + current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000; | |
| 112 | + | |
| 113 | + (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, | |
| 114 | + res_pool->ref_clocks.dccg_ref_clock_inKhz, | |
| 115 | + &res_pool->ref_clocks.dchub_ref_clock_inKhz); | |
| 116 | + } else { | |
| 117 | + // Not all ASICs have DCCG sw component | |
| 118 | + res_pool->ref_clocks.dccg_ref_clock_inKhz = | |
| 119 | + res_pool->ref_clocks.xtalin_clock_inKhz; | |
| 120 | + res_pool->ref_clocks.dchub_ref_clock_inKhz = | |
| 121 | + res_pool->ref_clocks.xtalin_clock_inKhz; | |
| 122 | + } | |
1350 more lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 413 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 722 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 1122 lines aren’t shown here.
This diff is large: its 1007 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 199 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 649 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 2338 lines aren’t shown here.
This diff is large: its 589 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 753 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17873 lines aren’t shown here.
This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.