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 | Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com> | 219 | Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com> |
| 220 | David Brownell <david-b@pacbell.net> | 220 | David Brownell <david-b@pacbell.net> |
| 221 | David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org> | 221 | David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org> |
| 222 | David Gow <david@davidgow.net> <davidgow@google.com> | ||
| 222 | David Heidelberg <david@ixit.cz> <d.okias@gmail.com> | 223 | David Heidelberg <david@ixit.cz> <d.okias@gmail.com> |
| 223 | David Hildenbrand <david@kernel.org> <david@redhat.com> | 224 | David Hildenbrand <david@kernel.org> <david@redhat.com> |
| 224 | David Rheinsberg <david@readahead.eu> <dh.herrmann@gmail.com> | 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 | Jason Gunthorpe <jgg@ziepe.ca> <jgg@mellanox.com> | 354 | Jason Gunthorpe <jgg@ziepe.ca> <jgg@mellanox.com> |
| 354 | Jason Gunthorpe <jgg@ziepe.ca> <jgg@nvidia.com> | 355 | Jason Gunthorpe <jgg@ziepe.ca> <jgg@nvidia.com> |
| 355 | Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com> | 356 | Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com> |
| 357 | Jason Xing <kerneljasonxing@gmail.com> <kernelxing@tencent.com> | ||
| 356 | <javier@osg.samsung.com> <javier.martinez@collabora.co.uk> | 358 | <javier@osg.samsung.com> <javier.martinez@collabora.co.uk> |
| 357 | Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com> | 359 | Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com> |
| 358 | Jayachandran C <c.jayachandran@gmail.com> <jayachandranc@netlogicmicro.com> | 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 | Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com> | 403 | Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com> |
| 402 | Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com> | 404 | Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com> |
| 403 | Jishnu Prakash <quic_jprakash@quicinc.com> <jprakash@codeaurora.org> | 405 | Jishnu Prakash <quic_jprakash@quicinc.com> <jprakash@codeaurora.org> |
| 406 | Joe Damato <joe@dama.to> <jdamato@fastly.com> | ||
| 404 | Joel Granados <joel.granados@kernel.org> <j.granados@samsung.com> | 407 | Joel Granados <joel.granados@kernel.org> <j.granados@samsung.com> |
| 405 | Johan Hovold <johan@kernel.org> <jhovold@gmail.com> | 408 | Johan Hovold <johan@kernel.org> <jhovold@gmail.com> |
| 406 | Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com> | 409 | Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com> |
| @@ -1242,6 +1242,10 @@ N: Veaceslav Falico · 1241 unmodified lines | |||
| 1242 | E: vfalico@gmail.com | 1242 | E: vfalico@gmail.com |
| 1243 | D: Co-maintainer and co-author of the network bonding driver. | 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 | N: János Farkas | 1249 | N: János Farkas |
| 1246 | E: chexum@shadow.banki.hu | 1250 | E: chexum@shadow.banki.hu |
| 1247 | D: romfs, various (mostly networking) fixes | 1251 | D: romfs, various (mostly networking) fixes |
| @@ -2415,6 +2419,10 @@ S: Am Muehlenweg 38 · 1167 unmodified lines | |||
| 2415 | S: D53424 Remagen | 2419 | S: D53424 Remagen |
| 2416 | S: Germany | 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 | N: Colin Leroy | 2426 | N: Colin Leroy |
| 2419 | E: colin@colino.net | 2427 | E: colin@colino.net |
| 2420 | W: http://www.geekounet.org/ | 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 | Date: November 2025 | 2 | Date: November 2025 |
| 3 | KernelVersion: 6.19 | 3 | KernelVersion: 6.19 |
| 4 | Contact: Armin Wolf <W_Armin@gmx.de> | 4 | Contact: Armin Wolf <W_Armin@gmx.de> |
| @@ -8,15 +8,15 @@ Description: · 3 unmodified lines | |||
| 8 | 8 | ||
| 9 | Reading this file returns the current enable status of the FN lock functionality. | 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 | Date: November 2025 | 12 | Date: November 2025 |
| 13 | KernelVersion: 6.19 | 13 | KernelVersion: 6.19 |
| 14 | Contact: Armin Wolf <W_Armin@gmx.de> | 14 | Contact: Armin Wolf <W_Armin@gmx.de> |
| 15 | Description: | 15 | Description: |
| 16 | Allows userspace applications to enable/disable the super key functionality | 16 | Allows userspace applications to enable/disable the super key of the integrated |
| 17 | of the integrated keyboard by writing "1"/"0" into this file. | 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 | What: /sys/bus/platform/devices/INOU0000:XX/touchpad_toggle_enable | 21 | What: /sys/bus/platform/devices/INOU0000:XX/touchpad_toggle_enable |
| 22 | Date: November 2025 | 22 | Date: November 2025 |
| @@ -74,6 +74,7 @@ · 73 unmodified lines | |||
| 74 | TPM TPM drivers are enabled. | 74 | TPM TPM drivers are enabled. |
| 75 | UMS USB Mass Storage support is enabled. | 75 | UMS USB Mass Storage support is enabled. |
| 76 | USB USB support is enabled. | 76 | USB USB support is enabled. |
| 77 | NVME NVMe support is enabled | ||
| 77 | USBHID USB Human Interface Device support is enabled. | 78 | USBHID USB Human Interface Device support is enabled. |
| 78 | V4L Video For Linux support is enabled. | 79 | V4L Video For Linux support is enabled. |
| 79 | VGA The VGA console has been enabled. | 80 | VGA The VGA console has been enabled. |
| @@ -4787,6 +4788,18 @@ Kernel parameters · 4707 unmodified lines | |||
| 4787 | This can be set from sysctl after boot. | 4788 | This can be set from sysctl after boot. |
| 4788 | See Documentation/admin-guide/sysctl/vm.rst for details. | 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 | ohci1394_dma=early [HW,EARLY] enable debugging via the ohci1394 driver. | 4803 | ohci1394_dma=early [HW,EARLY] enable debugging via the ohci1394 driver. |
| 4791 | See Documentation/core-api/debugging-via-ohci1394.rst for more | 4804 | See Documentation/core-api/debugging-via-ohci1394.rst for more |
| 4792 | info. | 4805 | info. |
| @@ -24,7 +24,7 @@ Keyboard settings · 23 unmodified lines | |||
| 24 | 24 | ||
| 25 | The ``uniwill-laptop`` driver allows the user to enable/disable: | 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 | - the touchpad toggle functionality of the integrated touchpad | 28 | - the touchpad toggle functionality of the integrated touchpad |
| 29 | 29 | ||
| 30 | See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details. | 30 | See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details. |
| @@ -16,7 +16,6 @@ description: | · 15 unmodified lines | |||
| 16 | properties: | 16 | properties: |
| 17 | compatible: | 17 | compatible: |
| 18 | enum: | 18 | enum: |
| 19 | - kontron,sa67mcu-hwmon | ||
| 20 | - kontron,sl28cpld-fan | 19 | - kontron,sl28cpld-fan |
| 21 | 20 | ||
| 22 | reg: | 21 | reg: |
| @@ -87,6 +87,7 @@ required: · 86 unmodified lines | |||
| 87 | 87 | ||
| 88 | allOf: | 88 | allOf: |
| 89 | - $ref: can-controller.yaml# | 89 | - $ref: can-controller.yaml# |
| 90 | - $ref: /schemas/memory-controllers/mc-peripheral-props.yaml | ||
| 90 | - if: | 91 | - if: |
| 91 | properties: | 92 | properties: |
| 92 | compatible: | 93 | compatible: |
| @@ -23,6 +23,7 @@ properties: · 22 unmodified lines | |||
| 23 | enum: | 23 | enum: |
| 24 | - nvidia,tegra210-audio-graph-card | 24 | - nvidia,tegra210-audio-graph-card |
| 25 | - nvidia,tegra186-audio-graph-card | 25 | - nvidia,tegra186-audio-graph-card |
| 26 | - nvidia,tegra238-audio-graph-card | ||
| 26 | - nvidia,tegra264-audio-graph-card | 27 | - nvidia,tegra264-audio-graph-card |
| 27 | 28 | ||
| 28 | clocks: | 29 | clocks: |
| @@ -20,6 +20,7 @@ properties: · 19 unmodified lines | |||
| 20 | - renesas,r9a07g044-ssi # RZ/G2{L,LC} | 20 | - renesas,r9a07g044-ssi # RZ/G2{L,LC} |
| 21 | - renesas,r9a07g054-ssi # RZ/V2L | 21 | - renesas,r9a07g054-ssi # RZ/V2L |
| 22 | - renesas,r9a08g045-ssi # RZ/G3S | 22 | - renesas,r9a08g045-ssi # RZ/G3S |
| 23 | - renesas,r9a08g046-ssi # RZ/G3L | ||
| 23 | - const: renesas,rz-ssi | 24 | - const: renesas,rz-ssi |
| 24 | 25 | ||
| 25 | reg: | 26 | reg: |
| @@ -57,7 +57,7 @@ Supported chips: · 56 unmodified lines | |||
| 57 | - https://ww1.microchip.com/downloads/en/DeviceDoc/EMC1438%20DS%20Rev.%201.0%20(04-29-10).pdf | 57 | - https://ww1.microchip.com/downloads/en/DeviceDoc/EMC1438%20DS%20Rev.%201.0%20(04-29-10).pdf |
| 58 | 58 | ||
| 59 | Author: | 59 | Author: |
| 60 | Kalhan Trisal <kalhan.trisal@intel.com | 60 | Kalhan Trisal <kalhan.trisal@intel.com> |
| 61 | 61 | ||
| 62 | 62 | ||
| 63 | Description | 63 | Description |
| @@ -220,7 +220,6 @@ Hardware Monitoring Kernel Drivers · 219 unmodified lines | |||
| 220 | q54sj108a2 | 220 | q54sj108a2 |
| 221 | qnap-mcu-hwmon | 221 | qnap-mcu-hwmon |
| 222 | raspberrypi-hwmon | 222 | raspberrypi-hwmon |
| 223 | sa67 | ||
| 224 | sbrmi | 223 | sbrmi |
| 225 | sbtsi_temp | 224 | sbtsi_temp |
| 226 | sch5627 | 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 | - compound-ops | 152 | - compound-ops |
| 153 | - | 153 | - |
| 154 | name: threads-set | 154 | name: threads-set |
| 155 | doc: set the number of running threads | 155 | doc: set the maximum number of running threads |
| 156 | attribute-set: server | 156 | attribute-set: server |
| 157 | flags: [admin-perm] | 157 | flags: [admin-perm] |
| 158 | do: | 158 | do: |
| @@ -165,7 +165,7 @@ operations: · 6 unmodified lines | |||
| 165 | - min-threads | 165 | - min-threads |
| 166 | - | 166 | - |
| 167 | name: threads-get | 167 | name: threads-get |
| 168 | doc: get the number of running threads | 168 | doc: get the maximum number of running threads |
| 169 | attribute-set: server | 169 | attribute-set: server |
| 170 | do: | 170 | do: |
| 171 | reply: | 171 | reply: |
| @@ -2372,6 +2372,10 @@ quirk_flags · 2371 unmodified lines | |||
| 2372 | audible volume | 2372 | audible volume |
| 2373 | * bit 25: ``mixer_capture_min_mute`` | 2373 | * bit 25: ``mixer_capture_min_mute`` |
| 2374 | Similar to bit 24 but for capture streams | 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 | This module supports multiple devices, autoprobe and hotplugging. | 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 | F: drivers/thermal/thermal_mmio.c | 993 | F: drivers/thermal/thermal_mmio.c |
| 994 | 994 | ||
| 995 | AMAZON ETHERNET DRIVERS | 995 | AMAZON ETHERNET DRIVERS |
| 996 | M: Shay Agroskin <shayagr@amazon.com> | ||
| 997 | M: Arthur Kiyanovski <akiyano@amazon.com> | 996 | M: Arthur Kiyanovski <akiyano@amazon.com> |
| 998 | R: David Arinzon <darinzon@amazon.com> | 997 | M: David Arinzon <darinzon@amazon.com> |
| 999 | R: Saeed Bishara <saeedb@amazon.com> | ||
| 1000 | L: netdev@vger.kernel.org | 998 | L: netdev@vger.kernel.org |
| 1001 | S: Maintained | 999 | S: Maintained |
| 1002 | F: Documentation/networking/device_drivers/ethernet/amazon/ena.rst | 1000 | F: Documentation/networking/device_drivers/ethernet/amazon/ena.rst |
| @@ -4617,7 +4615,6 @@ F: drivers/bluetooth/ · 3614 unmodified lines | |||
| 4617 | 4615 | ||
| 4618 | BLUETOOTH SUBSYSTEM | 4616 | BLUETOOTH SUBSYSTEM |
| 4619 | M: Marcel Holtmann <marcel@holtmann.org> | 4617 | M: Marcel Holtmann <marcel@holtmann.org> |
| 4620 | M: Johan Hedberg <johan.hedberg@gmail.com> | ||
| 4621 | M: Luiz Augusto von Dentz <luiz.dentz@gmail.com> | 4618 | M: Luiz Augusto von Dentz <luiz.dentz@gmail.com> |
| 4622 | L: linux-bluetooth@vger.kernel.org | 4619 | L: linux-bluetooth@vger.kernel.org |
| 4623 | S: Supported | 4620 | S: Supported |
| @@ -10187,8 +10184,8 @@ F: drivers/i2c/busses/i2c-cpm.c · 5563 unmodified lines | |||
| 10187 | 10184 | ||
| 10188 | FREESCALE IMX / MXC FEC DRIVER | 10185 | FREESCALE IMX / MXC FEC DRIVER |
| 10189 | M: Wei Fang <wei.fang@nxp.com> | 10186 | M: Wei Fang <wei.fang@nxp.com> |
| 10187 | R: Frank Li <frank.li@nxp.com> | ||
| 10190 | R: Shenwei Wang <shenwei.wang@nxp.com> | 10188 | R: Shenwei Wang <shenwei.wang@nxp.com> |
| 10191 | R: Clark Wang <xiaoning.wang@nxp.com> | ||
| 10192 | L: imx@lists.linux.dev | 10189 | L: imx@lists.linux.dev |
| 10193 | L: netdev@vger.kernel.org | 10190 | L: netdev@vger.kernel.org |
| 10194 | S: Maintained | 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 | F: Documentation/trace/ftrace* | 10497 | F: Documentation/trace/ftrace* |
| 10501 | F: arch/*/*/*/*ftrace* | 10498 | F: arch/*/*/*/*ftrace* |
| 10502 | F: arch/*/*/*ftrace* | 10499 | F: arch/*/*/*ftrace* |
| 10503 | F: include/*/ftrace.h | 10500 | F: include/*/*ftrace* |
| 10504 | F: kernel/trace/fgraph.c | 10501 | F: kernel/trace/fgraph.c |
| 10505 | F: kernel/trace/ftrace* | 10502 | F: kernel/trace/ftrace* |
| 10506 | F: samples/ftrace | 10503 | F: samples/ftrace |
| @@ -12233,7 +12230,6 @@ IBM Power SRIOV Virtual NIC Device Driver · 1726 unmodified lines | |||
| 12233 | M: Haren Myneni <haren@linux.ibm.com> | 12230 | M: Haren Myneni <haren@linux.ibm.com> |
| 12234 | M: Rick Lindsley <ricklind@linux.ibm.com> | 12231 | M: Rick Lindsley <ricklind@linux.ibm.com> |
| 12235 | R: Nick Child <nnac123@linux.ibm.com> | 12232 | R: Nick Child <nnac123@linux.ibm.com> |
| 12236 | R: Thomas Falcon <tlfalcon@linux.ibm.com> | ||
| 12237 | L: netdev@vger.kernel.org | 12233 | L: netdev@vger.kernel.org |
| 12238 | S: Maintained | 12234 | S: Maintained |
| 12239 | F: drivers/net/ethernet/ibm/ibmvnic.* | 12235 | F: drivers/net/ethernet/ibm/ibmvnic.* |
| @@ -13958,7 +13954,7 @@ F: fs/smb/server/ · 1718 unmodified lines | |||
| 13958 | 13954 | ||
| 13959 | KERNEL UNIT TESTING FRAMEWORK (KUnit) | 13955 | KERNEL UNIT TESTING FRAMEWORK (KUnit) |
| 13960 | M: Brendan Higgins <brendan.higgins@linux.dev> | 13956 | M: Brendan Higgins <brendan.higgins@linux.dev> |
| 13961 | M: David Gow <davidgow@google.com> | 13957 | M: David Gow <david@davidgow.net> |
| 13962 | R: Rae Moar <raemoar63@gmail.com> | 13958 | R: Rae Moar <raemoar63@gmail.com> |
| 13963 | L: linux-kselftest@vger.kernel.org | 13959 | L: linux-kselftest@vger.kernel.org |
| 13964 | L: kunit-dev@googlegroups.com | 13960 | L: kunit-dev@googlegroups.com |
| @@ -14778,7 +14774,7 @@ F: drivers/misc/lis3lv02d/ · 813 unmodified lines | |||
| 14778 | F: drivers/platform/x86/hp/hp_accel.c | 14774 | F: drivers/platform/x86/hp/hp_accel.c |
| 14779 | 14775 | ||
| 14780 | LIST KUNIT TEST | 14776 | LIST KUNIT TEST |
| 14781 | M: David Gow <davidgow@google.com> | 14777 | M: David Gow <david@davidgow.net> |
| 14782 | L: linux-kselftest@vger.kernel.org | 14778 | L: linux-kselftest@vger.kernel.org |
| 14783 | L: kunit-dev@googlegroups.com | 14779 | L: kunit-dev@googlegroups.com |
| 14784 | S: Maintained | 14780 | S: Maintained |
| @@ -15391,10 +15387,8 @@ F: drivers/crypto/marvell/ · 606 unmodified lines | |||
| 15391 | F: include/linux/soc/marvell/octeontx2/ | 15387 | F: include/linux/soc/marvell/octeontx2/ |
| 15392 | 15388 | ||
| 15393 | MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) | 15389 | MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) |
| 15394 | M: Mirko Lindner <mlindner@marvell.com> | ||
| 15395 | M: Stephen Hemminger <stephen@networkplumber.org> | ||
| 15396 | L: netdev@vger.kernel.org | 15390 | L: netdev@vger.kernel.org |
| 15397 | S: Odd fixes | 15391 | S: Orphan |
| 15398 | F: drivers/net/ethernet/marvell/sk* | 15392 | F: drivers/net/ethernet/marvell/sk* |
| 15399 | 15393 | ||
| 15400 | MARVELL LIBERTAS WIRELESS DRIVER | 15394 | MARVELL LIBERTAS WIRELESS DRIVER |
| @@ -15491,7 +15485,6 @@ MARVELL OCTEONTX2 RVU ADMIN FUNCTION DRIVER · 90 unmodified lines | |||
| 15491 | M: Sunil Goutham <sgoutham@marvell.com> | 15485 | M: Sunil Goutham <sgoutham@marvell.com> |
| 15492 | M: Linu Cherian <lcherian@marvell.com> | 15486 | M: Linu Cherian <lcherian@marvell.com> |
| 15493 | M: Geetha sowjanya <gakula@marvell.com> | 15487 | M: Geetha sowjanya <gakula@marvell.com> |
| 15494 | M: Jerin Jacob <jerinj@marvell.com> | ||
| 15495 | M: hariprasad <hkelam@marvell.com> | 15488 | M: hariprasad <hkelam@marvell.com> |
| 15496 | M: Subbaraya Sundeep <sbhatta@marvell.com> | 15489 | M: Subbaraya Sundeep <sbhatta@marvell.com> |
| 15497 | L: netdev@vger.kernel.org | 15490 | L: netdev@vger.kernel.org |
| @@ -15506,7 +15499,7 @@ S: Supported · 8 unmodified lines | |||
| 15506 | F: drivers/perf/marvell_pem_pmu.c | 15499 | F: drivers/perf/marvell_pem_pmu.c |
| 15507 | 15500 | ||
| 15508 | MARVELL PRESTERA ETHERNET SWITCH DRIVER | 15501 | MARVELL PRESTERA ETHERNET SWITCH DRIVER |
| 15509 | M: Taras Chornyi <taras.chornyi@plvision.eu> | 15502 | M: Elad Nachman <enachman@marvell.com> |
| 15510 | S: Supported | 15503 | S: Supported |
| 15511 | W: https://github.com/Marvell-switching/switchdev-prestera | 15504 | W: https://github.com/Marvell-switching/switchdev-prestera |
| 15512 | F: drivers/net/ethernet/marvell/prestera/ | 15505 | F: drivers/net/ethernet/marvell/prestera/ |
| @@ -16180,7 +16173,6 @@ F: drivers/dma/mediatek/ · 667 unmodified lines | |||
| 16180 | 16173 | ||
| 16181 | MEDIATEK ETHERNET DRIVER | 16174 | MEDIATEK ETHERNET DRIVER |
| 16182 | M: Felix Fietkau <nbd@nbd.name> | 16175 | M: Felix Fietkau <nbd@nbd.name> |
| 16183 | M: Sean Wang <sean.wang@mediatek.com> | ||
| 16184 | M: Lorenzo Bianconi <lorenzo@kernel.org> | 16176 | M: Lorenzo Bianconi <lorenzo@kernel.org> |
| 16185 | L: netdev@vger.kernel.org | 16177 | L: netdev@vger.kernel.org |
| 16186 | S: Maintained | 16178 | S: Maintained |
| @@ -16373,8 +16365,6 @@ F: include/soc/mediatek/smi.h · 186 unmodified lines | |||
| 16373 | MEDIATEK SWITCH DRIVER | 16365 | MEDIATEK SWITCH DRIVER |
| 16374 | M: Chester A. Unal <chester.a.unal@arinc9.com> | 16366 | M: Chester A. Unal <chester.a.unal@arinc9.com> |
| 16375 | M: Daniel Golle <daniel@makrotopia.org> | 16367 | M: Daniel Golle <daniel@makrotopia.org> |
| 16376 | M: DENG Qingfang <dqfext@gmail.com> | ||
| 16377 | M: Sean Wang <sean.wang@mediatek.com> | ||
| 16378 | L: netdev@vger.kernel.org | 16368 | L: netdev@vger.kernel.org |
| 16379 | S: Maintained | 16369 | S: Maintained |
| 16380 | F: drivers/net/dsa/mt7530-mdio.c | 16370 | F: drivers/net/dsa/mt7530-mdio.c |
| @@ -19242,8 +19232,6 @@ F: tools/objtool/ · 2861 unmodified lines | |||
| 19242 | 19232 | ||
| 19243 | OCELOT ETHERNET SWITCH DRIVER | 19233 | OCELOT ETHERNET SWITCH DRIVER |
| 19244 | M: Vladimir Oltean <vladimir.oltean@nxp.com> | 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 | M: UNGLinuxDriver@microchip.com | 19235 | M: UNGLinuxDriver@microchip.com |
| 19248 | L: netdev@vger.kernel.org | 19236 | L: netdev@vger.kernel.org |
| 19249 | S: Supported | 19237 | S: Supported |
| @@ -19829,7 +19817,6 @@ F: arch/*/boot/dts/ · 579 unmodified lines | |||
| 19829 | F: include/dt-bindings/ | 19817 | F: include/dt-bindings/ |
| 19830 | 19818 | ||
| 19831 | OPENCOMPUTE PTP CLOCK DRIVER | 19819 | OPENCOMPUTE PTP CLOCK DRIVER |
| 19832 | M: Jonathan Lemon <jonathan.lemon@gmail.com> | ||
| 19833 | M: Vadim Fedorenko <vadim.fedorenko@linux.dev> | 19820 | M: Vadim Fedorenko <vadim.fedorenko@linux.dev> |
| 19834 | L: netdev@vger.kernel.org | 19821 | L: netdev@vger.kernel.org |
| 19835 | S: Maintained | 19822 | S: Maintained |
| @@ -20137,9 +20124,8 @@ F: Documentation/devicetree/bindings/pci/marvell,armada-3700-pcie.yaml · 301 unmodified lines | |||
| 20137 | F: drivers/pci/controller/pci-aardvark.c | 20124 | F: drivers/pci/controller/pci-aardvark.c |
| 20138 | 20125 | ||
| 20139 | PCI DRIVER FOR ALTERA PCIE IP | 20126 | PCI DRIVER FOR ALTERA PCIE IP |
| 20140 | M: Joyce Ooi <joyce.ooi@intel.com> | ||
| 20141 | L: linux-pci@vger.kernel.org | 20127 | L: linux-pci@vger.kernel.org |
| 20142 | S: Supported | 20128 | S: Orphan |
| 20143 | F: Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml | 20129 | F: Documentation/devicetree/bindings/pci/altr,pcie-root-port.yaml |
| 20144 | F: drivers/pci/controller/pcie-altera.c | 20130 | F: drivers/pci/controller/pcie-altera.c |
| 20145 | 20131 | ||
| @@ -20384,9 +20370,8 @@ S: Supported · 238 unmodified lines | |||
| 20384 | F: Documentation/PCI/pci-error-recovery.rst | 20370 | F: Documentation/PCI/pci-error-recovery.rst |
| 20385 | 20371 | ||
| 20386 | PCI MSI DRIVER FOR ALTERA MSI IP | 20372 | PCI MSI DRIVER FOR ALTERA MSI IP |
| 20387 | M: Joyce Ooi <joyce.ooi@intel.com> | ||
| 20388 | L: linux-pci@vger.kernel.org | 20373 | L: linux-pci@vger.kernel.org |
| 20389 | S: Supported | 20374 | S: Orphan |
| 20390 | F: Documentation/devicetree/bindings/interrupt-controller/altr,msi-controller.yaml | 20375 | F: Documentation/devicetree/bindings/interrupt-controller/altr,msi-controller.yaml |
| 20391 | F: drivers/pci/controller/pcie-altera-msi.c | 20376 | F: drivers/pci/controller/pcie-altera-msi.c |
| 20392 | 20377 | ||
| @@ -21473,9 +21458,8 @@ S: Supported · 1080 unmodified lines | |||
| 21473 | F: drivers/scsi/qedi/ | 21458 | F: drivers/scsi/qedi/ |
| 21474 | 21459 | ||
| 21475 | QLOGIC QL4xxx ETHERNET DRIVER | 21460 | QLOGIC QL4xxx ETHERNET DRIVER |
| 21476 | M: Manish Chopra <manishc@marvell.com> | ||
| 21477 | L: netdev@vger.kernel.org | 21461 | L: netdev@vger.kernel.org |
| 21478 | S: Maintained | 21462 | S: Orphan |
| 21479 | F: drivers/net/ethernet/qlogic/qed/ | 21463 | F: drivers/net/ethernet/qlogic/qed/ |
| 21480 | F: drivers/net/ethernet/qlogic/qede/ | 21464 | F: drivers/net/ethernet/qlogic/qede/ |
| 21481 | F: include/linux/qed/ | 21465 | F: include/linux/qed/ |
| @@ -24353,7 +24337,6 @@ F: Documentation/devicetree/bindings/interrupt-controller/kontron,sl28cpld-intc. · 2871 unmodified lines | |||
| 24353 | F: Documentation/devicetree/bindings/pwm/kontron,sl28cpld-pwm.yaml | 24337 | F: Documentation/devicetree/bindings/pwm/kontron,sl28cpld-pwm.yaml |
| 24354 | F: Documentation/devicetree/bindings/watchdog/kontron,sl28cpld-wdt.yaml | 24338 | F: Documentation/devicetree/bindings/watchdog/kontron,sl28cpld-wdt.yaml |
| 24355 | F: drivers/gpio/gpio-sl28cpld.c | 24339 | F: drivers/gpio/gpio-sl28cpld.c |
| 24356 | F: drivers/hwmon/sa67mcu-hwmon.c | ||
| 24357 | F: drivers/hwmon/sl28cpld-hwmon.c | 24340 | F: drivers/hwmon/sl28cpld-hwmon.c |
| 24358 | F: drivers/irqchip/irq-sl28cpld.c | 24341 | F: drivers/irqchip/irq-sl28cpld.c |
| 24359 | F: drivers/pwm/pwm-sl28cpld.c | 24342 | F: drivers/pwm/pwm-sl28cpld.c |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 7 | 2 | VERSION = 7 |
| 3 | PATCHLEVEL = 0 | 3 | PATCHLEVEL = 0 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc2 | 5 | EXTRAVERSION = -rc3 |
| 6 | NAME = Baby Opossum Posse | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -1497,13 +1497,13 @@ ifneq ($(wildcard $(resolve_btfids_O)),) · 1488 unmodified lines | |||
| 1497 | $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean | 1497 | $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean |
| 1498 | endif | 1498 | endif |
| 1499 | 1499 | ||
| 1500 | PHONY += objtool_clean | 1500 | PHONY += objtool_clean objtool_mrproper |
| 1501 | 1501 | ||
| 1502 | objtool_O = $(abspath $(objtree))/tools/objtool | 1502 | objtool_O = $(abspath $(objtree))/tools/objtool |
| 1503 | 1503 | ||
| 1504 | objtool_clean: | 1504 | objtool_clean objtool_mrproper: |
| 1505 | ifneq ($(wildcard $(objtool_O)),) | 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 | endif | 1507 | endif |
| 1508 | 1508 | ||
| 1509 | tools/: FORCE | 1509 | tools/: FORCE |
| @@ -1686,7 +1686,7 @@ PHONY += $(mrproper-dirs) mrproper · 176 unmodified lines | |||
| 1686 | $(mrproper-dirs): | 1686 | $(mrproper-dirs): |
| 1687 | $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) | 1687 | $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) |
| 1688 | 1688 | ||
| 1689 | mrproper: clean $(mrproper-dirs) | 1689 | mrproper: clean objtool_mrproper $(mrproper-dirs) |
| 1690 | $(call cmd,rmfiles) | 1690 | $(call cmd,rmfiles) |
| 1691 | @find . $(RCS_FIND_IGNORE) \ | 1691 | @find . $(RCS_FIND_IGNORE) \ |
| 1692 | \( -name '*.rmeta' \) \ | 1692 | \( -name '*.rmeta' \) \ |
| @@ -71,6 +71,7 @@ SECTIONS · 70 unmodified lines | |||
| 71 | 71 | ||
| 72 | STABS_DEBUG | 72 | STABS_DEBUG |
| 73 | DWARF_DEBUG | 73 | DWARF_DEBUG |
| 74 | MODINFO | ||
| 74 | ELF_DETAILS | 75 | ELF_DETAILS |
| 75 | 76 | ||
| 76 | DISCARDS | 77 | DISCARDS |
| @@ -123,6 +123,7 @@ SECTIONS · 122 unmodified lines | |||
| 123 | _end = . ; | 123 | _end = . ; |
| 124 | 124 | ||
| 125 | STABS_DEBUG | 125 | STABS_DEBUG |
| 126 | MODINFO | ||
| 126 | ELF_DETAILS | 127 | ELF_DETAILS |
| 127 | DISCARDS | 128 | DISCARDS |
| 128 | 129 | ||
| @@ -21,6 +21,7 @@ SECTIONS · 20 unmodified lines | |||
| 21 | COMMON_DISCARDS | 21 | COMMON_DISCARDS |
| 22 | *(.ARM.exidx*) | 22 | *(.ARM.exidx*) |
| 23 | *(.ARM.extab*) | 23 | *(.ARM.extab*) |
| 24 | *(.modinfo) | ||
| 24 | *(.note.*) | 25 | *(.note.*) |
| 25 | *(.rel.*) | 26 | *(.rel.*) |
| 26 | *(.printk_index) | 27 | *(.printk_index) |
| @@ -154,6 +154,7 @@ SECTIONS · 153 unmodified lines | |||
| 154 | 154 | ||
| 155 | STABS_DEBUG | 155 | STABS_DEBUG |
| 156 | DWARF_DEBUG | 156 | DWARF_DEBUG |
| 157 | MODINFO | ||
| 157 | ARM_DETAILS | 158 | ARM_DETAILS |
| 158 | 159 | ||
| 159 | ARM_ASSERTS | 160 | ARM_ASSERTS |
| @@ -153,6 +153,7 @@ SECTIONS · 152 unmodified lines | |||
| 153 | 153 | ||
| 154 | STABS_DEBUG | 154 | STABS_DEBUG |
| 155 | DWARF_DEBUG | 155 | DWARF_DEBUG |
| 156 | MODINFO | ||
| 156 | ARM_DETAILS | 157 | ARM_DETAILS |
| 157 | 158 | ||
| 158 | ARM_ASSERTS | 159 | ARM_ASSERTS |
| @@ -91,8 +91,9 @@ __XCHG_GEN(_mb) · 90 unmodified lines | |||
| 91 | #define __xchg_wrapper(sfx, ptr, x) \ | 91 | #define __xchg_wrapper(sfx, ptr, x) \ |
| 92 | ({ \ | 92 | ({ \ |
| 93 | __typeof__(*(ptr)) __ret; \ | 93 | __typeof__(*(ptr)) __ret; \ |
| 94 | __ret = (__typeof__(*(ptr))) \ | 94 | __ret = (__force __typeof__(*(ptr))) \ |
| 95 | __arch_xchg##sfx((unsigned long)(x), (ptr), sizeof(*(ptr))); \ | 95 | __arch_xchg##sfx((__force unsigned long)(x), (ptr), \ |
| 96 | sizeof(*(ptr))); \ | ||
| 96 | __ret; \ | 97 | __ret; \ |
| 97 | }) | 98 | }) |
| 98 | 99 | ||
| @@ -175,9 +176,10 @@ __CMPXCHG_GEN(_mb) · 76 unmodified lines | |||
| 175 | #define __cmpxchg_wrapper(sfx, ptr, o, n) \ | 176 | #define __cmpxchg_wrapper(sfx, ptr, o, n) \ |
| 176 | ({ \ | 177 | ({ \ |
| 177 | __typeof__(*(ptr)) __ret; \ | 178 | __typeof__(*(ptr)) __ret; \ |
| 178 | __ret = (__typeof__(*(ptr))) \ | 179 | __ret = (__force __typeof__(*(ptr))) \ |
| 179 | __cmpxchg##sfx((ptr), (unsigned long)(o), \ | 180 | __cmpxchg##sfx((ptr), (__force unsigned long)(o), \ |
| 180 | (unsigned long)(n), sizeof(*(ptr))); \ | 181 | (__force unsigned long)(n), \ |
| 182 | sizeof(*(ptr))); \ | ||
| 181 | __ret; \ | 183 | __ret; \ |
| 182 | }) | 184 | }) |
| 183 | 185 | ||
| @@ -50,11 +50,11 @@ · 49 unmodified lines | |||
| 50 | 50 | ||
| 51 | #define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) | 51 | #define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) |
| 52 | 52 | ||
| 53 | #define _PAGE_KERNEL (PROT_NORMAL) | 53 | #define _PAGE_KERNEL (PROT_NORMAL | PTE_DIRTY) |
| 54 | #define _PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) | 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) | 55 | #define _PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY | PTE_DIRTY) |
| 56 | #define _PAGE_KERNEL_EXEC (PROT_NORMAL & ~PTE_PXN) | 56 | #define _PAGE_KERNEL_EXEC ((PROT_NORMAL & ~PTE_PXN) | PTE_DIRTY) |
| 57 | #define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT) | 57 | #define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT | PTE_DIRTY) |
| 58 | 58 | ||
| 59 | #define _PAGE_SHARED (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) | 59 | #define _PAGE_SHARED (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) |
| 60 | #define _PAGE_SHARED_EXEC (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE) | 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 | #ifndef _ASM_RUNTIME_CONST_H | 2 | #ifndef _ASM_RUNTIME_CONST_H |
| 3 | #define _ASM_RUNTIME_CONST_H | 3 | #define _ASM_RUNTIME_CONST_H |
| 4 | 4 | ||
| 5 | #ifdef MODULE | ||
| 6 | #error "Cannot use runtime-const infrastructure from modules" | ||
| 7 | #endif | ||
| 8 | |||
| 5 | #include <asm/cacheflush.h> | 9 | #include <asm/cacheflush.h> |
| 6 | 10 | ||
| 7 | /* Sigh. You can still run arm64 in BE mode */ | 11 | /* Sigh. You can still run arm64 in BE mode */ |
| @@ -349,6 +349,7 @@ SECTIONS · 348 unmodified lines | |||
| 349 | 349 | ||
| 350 | STABS_DEBUG | 350 | STABS_DEBUG |
| 351 | DWARF_DEBUG | 351 | DWARF_DEBUG |
| 352 | MODINFO | ||
| 352 | ELF_DETAILS | 353 | ELF_DETAILS |
| 353 | 354 | ||
| 354 | HEAD_SYMBOLS | 355 | HEAD_SYMBOLS |
| @@ -599,6 +599,27 @@ void contpte_clear_young_dirty_ptes(struct vm_area_struct *vma, · 598 unmodified lines | |||
| 599 | } | 599 | } |
| 600 | EXPORT_SYMBOL_GPL(contpte_clear_young_dirty_ptes); | 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 | int contpte_ptep_set_access_flags(struct vm_area_struct *vma, | 623 | int contpte_ptep_set_access_flags(struct vm_area_struct *vma, |
| 603 | unsigned long addr, pte_t *ptep, | 624 | unsigned long addr, pte_t *ptep, |
| 604 | pte_t entry, int dirty) | 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 | int i; | 629 | int i; |
| 609 | 630 | ||
| 610 | /* | 631 | /* |
| 611 | * Gather the access/dirty bits for the contiguous range. If nothing has | 632 | * Check whether all sub-PTEs in the CONT block already match the |
| 612 | * changed, its a noop. | 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)); | 655 | if (contpte_all_subptes_match_access_flags(ptep, entry)) |
| 615 | if (pte_val(orig_pte) == pte_val(entry)) | ||
| 616 | return 0; | 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 | * We can fix up access/dirty bits without having to unfold the contig | 664 | * We can fix up access/dirty bits without having to unfold the contig |
| 620 | * range. But if the write bit is changing, we must unfold. | 665 | * range. But if the write bit is changing, we must unfold. |
| @@ -109,6 +109,7 @@ SECTIONS · 108 unmodified lines | |||
| 109 | 109 | ||
| 110 | STABS_DEBUG | 110 | STABS_DEBUG |
| 111 | DWARF_DEBUG | 111 | DWARF_DEBUG |
| 112 | MODINFO | ||
| 112 | ELF_DETAILS | 113 | ELF_DETAILS |
| 113 | 114 | ||
| 114 | DISCARDS | 115 | DISCARDS |
| @@ -62,6 +62,7 @@ SECTIONS · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | STABS_DEBUG | 63 | STABS_DEBUG |
| 64 | DWARF_DEBUG | 64 | DWARF_DEBUG |
| 65 | MODINFO | ||
| 65 | ELF_DETAILS | 66 | ELF_DETAILS |
| 66 | .hexagon.attributes 0 : { *(.hexagon.attributes) } | 67 | .hexagon.attributes 0 : { *(.hexagon.attributes) } |
| 67 | 68 | ||
| @@ -147,6 +147,7 @@ SECTIONS · 146 unmodified lines | |||
| 147 | 147 | ||
| 148 | STABS_DEBUG | 148 | STABS_DEBUG |
| 149 | DWARF_DEBUG | 149 | DWARF_DEBUG |
| 150 | MODINFO | ||
| 150 | ELF_DETAILS | 151 | ELF_DETAILS |
| 151 | 152 | ||
| 152 | #ifdef CONFIG_EFI_STUB | 153 | #ifdef CONFIG_EFI_STUB |
| @@ -85,6 +85,7 @@ SECTIONS { · 84 unmodified lines | |||
| 85 | _end = .; | 85 | _end = .; |
| 86 | 86 | ||
| 87 | STABS_DEBUG | 87 | STABS_DEBUG |
| 88 | MODINFO | ||
| 88 | ELF_DETAILS | 89 | ELF_DETAILS |
| 89 | 90 | ||
| 90 | /* Sections to be discarded */ | 91 | /* Sections to be discarded */ |
| @@ -58,6 +58,7 @@ SECTIONS · 57 unmodified lines | |||
| 58 | _end = . ; | 58 | _end = . ; |
| 59 | 59 | ||
| 60 | STABS_DEBUG | 60 | STABS_DEBUG |
| 61 | MODINFO | ||
| 61 | ELF_DETAILS | 62 | ELF_DETAILS |
| 62 | 63 | ||
| 63 | /* Sections to be discarded */ | 64 | /* Sections to be discarded */ |
| @@ -51,6 +51,7 @@ __init_begin = .; · 50 unmodified lines | |||
| 51 | _end = . ; | 51 | _end = . ; |
| 52 | 52 | ||
| 53 | STABS_DEBUG | 53 | STABS_DEBUG |
| 54 | MODINFO | ||
| 54 | ELF_DETAILS | 55 | ELF_DETAILS |
| 55 | 56 | ||
| 56 | /* Sections to be discarded */ | 57 | /* Sections to be discarded */ |
| @@ -217,6 +217,7 @@ SECTIONS · 216 unmodified lines | |||
| 217 | 217 | ||
| 218 | STABS_DEBUG | 218 | STABS_DEBUG |
| 219 | DWARF_DEBUG | 219 | DWARF_DEBUG |
| 220 | MODINFO | ||
| 220 | ELF_DETAILS | 221 | ELF_DETAILS |
| 221 | 222 | ||
| 222 | /* These must appear regardless of . */ | 223 | /* These must appear regardless of . */ |
| @@ -57,6 +57,7 @@ SECTIONS · 56 unmodified lines | |||
| 57 | 57 | ||
| 58 | STABS_DEBUG | 58 | STABS_DEBUG |
| 59 | DWARF_DEBUG | 59 | DWARF_DEBUG |
| 60 | MODINFO | ||
| 60 | ELF_DETAILS | 61 | ELF_DETAILS |
| 61 | 62 | ||
| 62 | DISCARDS | 63 | DISCARDS |
| @@ -101,6 +101,7 @@ SECTIONS · 100 unmodified lines | |||
| 101 | /* Throw in the debugging sections */ | 101 | /* Throw in the debugging sections */ |
| 102 | STABS_DEBUG | 102 | STABS_DEBUG |
| 103 | DWARF_DEBUG | 103 | DWARF_DEBUG |
| 104 | MODINFO | ||
| 104 | ELF_DETAILS | 105 | ELF_DETAILS |
| 105 | 106 | ||
| 106 | /* Sections to be discarded -- must be last */ | 107 | /* Sections to be discarded -- must be last */ |
| @@ -90,6 +90,7 @@ SECTIONS · 89 unmodified lines | |||
| 90 | /* Sections to be discarded */ | 90 | /* Sections to be discarded */ |
| 91 | DISCARDS | 91 | DISCARDS |
| 92 | /DISCARD/ : { | 92 | /DISCARD/ : { |
| 93 | *(.modinfo) | ||
| 93 | #ifdef CONFIG_64BIT | 94 | #ifdef CONFIG_64BIT |
| 94 | /* temporary hack until binutils is fixed to not emit these | 95 | /* temporary hack until binutils is fixed to not emit these |
| 95 | * for static binaries | 96 | * for static binaries |
| @@ -85,7 +85,7 @@ extern void __update_cache(pte_t pte); · 84 unmodified lines | |||
| 85 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e)) | 85 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e)) |
| 86 | 86 | ||
| 87 | /* This is the size of the initially mapped kernel memory */ | 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 | #define KERNEL_INITIAL_ORDER 26 /* 1<<26 = 64MB */ | 89 | #define KERNEL_INITIAL_ORDER 26 /* 1<<26 = 64MB */ |
| 90 | #else | 90 | #else |
| 91 | #define KERNEL_INITIAL_ORDER 25 /* 1<<25 = 32MB */ | 91 | #define KERNEL_INITIAL_ORDER 25 /* 1<<25 = 32MB */ |
| @@ -56,6 +56,7 @@ ENTRY(parisc_kernel_start) · 55 unmodified lines | |||
| 56 | 56 | ||
| 57 | .import __bss_start,data | 57 | .import __bss_start,data |
| 58 | .import __bss_stop,data | 58 | .import __bss_stop,data |
| 59 | .import __end,data | ||
| 59 | 60 | ||
| 60 | load32 PA(__bss_start),%r3 | 61 | load32 PA(__bss_start),%r3 |
| 61 | load32 PA(__bss_stop),%r4 | 62 | load32 PA(__bss_stop),%r4 |
| @@ -149,7 +150,11 @@ $cpu_ok: · 87 unmodified lines | |||
| 149 | * everything ... it will get remapped correctly later */ | 150 | * everything ... it will get remapped correctly later */ |
| 150 | ldo 0+_PAGE_KERNEL_RWX(%r0),%r3 /* Hardwired 0 phys addr start */ | 151 | ldo 0+_PAGE_KERNEL_RWX(%r0),%r3 /* Hardwired 0 phys addr start */ |
| 151 | load32 (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */ | 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 | $pgt_fill_loop: | 159 | $pgt_fill_loop: |
| 155 | STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1) | 160 | STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1) |
| @@ -120,14 +120,6 @@ void __init setup_arch(char **cmdline_p) · 119 unmodified lines | |||
| 120 | #endif | 120 | #endif |
| 121 | printk(KERN_CONT ".\n"); | 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 | #ifdef CONFIG_64BIT | 123 | #ifdef CONFIG_64BIT |
| 132 | if(parisc_narrow_firmware) { | 124 | if(parisc_narrow_firmware) { |
| 133 | printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n"); | 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 | int ret, cpunum; | 271 | int ret, cpunum; |
| 280 | struct pdc_coproc_cfg coproc_cfg; | 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 | /* check QEMU/SeaBIOS marker in PAGE0 */ | 286 | /* check QEMU/SeaBIOS marker in PAGE0 */ |
| 283 | running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0); | 287 | running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0); |
| 284 | 288 | ||
| @@ -165,6 +165,7 @@ SECTIONS · 164 unmodified lines | |||
| 165 | _end = . ; | 165 | _end = . ; |
| 166 | 166 | ||
| 167 | STABS_DEBUG | 167 | STABS_DEBUG |
| 168 | MODINFO | ||
| 168 | ELF_DETAILS | 169 | ELF_DETAILS |
| 169 | .note 0 : { *(.note) } | 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 | dev->error_state = pci_channel_io_normal; | 212 | dev->error_state = pci_channel_io_normal; |
| 213 | dev->dma_mask = 0xffffffff; | 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 | /* Early fixups, before probing the BARs */ | 222 | /* Early fixups, before probing the BARs */ |
| 216 | pci_fixup_device(pci_fixup_early, dev); | 223 | pci_fixup_device(pci_fixup_early, dev); |
| 217 | 224 | ||
| @@ -397,6 +397,7 @@ SECTIONS · 396 unmodified lines | |||
| 397 | _end = . ; | 397 | _end = . ; |
| 398 | 398 | ||
| 399 | DWARF_DEBUG | 399 | DWARF_DEBUG |
| 400 | MODINFO | ||
| 400 | ELF_DETAILS | 401 | ELF_DETAILS |
| 401 | 402 | ||
| 402 | DISCARDS | 403 | DISCARDS |
| @@ -170,6 +170,7 @@ SECTIONS · 169 unmodified lines | |||
| 170 | 170 | ||
| 171 | STABS_DEBUG | 171 | STABS_DEBUG |
| 172 | DWARF_DEBUG | 172 | DWARF_DEBUG |
| 173 | MODINFO | ||
| 173 | ELF_DETAILS | 174 | ELF_DETAILS |
| 174 | .riscv.attributes 0 : { *(.riscv.attributes) } | 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 | " j 4f\n" | 159 | " j 4f\n" |
| 160 | "3: mvc 8(1,%[addr]),0(%[addr])\n" | 160 | "3: mvc 8(1,%[addr]),0(%[addr])\n" |
| 161 | "4:" | 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 | : [poison] "d" (poison) | 163 | : [poison] "d" (poison) |
| 164 | : "memory", "cc" | 164 | : "memory", "cc" |
| 165 | ); | 165 | ); |
| @@ -221,6 +221,7 @@ SECTIONS · 220 unmodified lines | |||
| 221 | /* Debugging sections. */ | 221 | /* Debugging sections. */ |
| 222 | STABS_DEBUG | 222 | STABS_DEBUG |
| 223 | DWARF_DEBUG | 223 | DWARF_DEBUG |
| 224 | MODINFO | ||
| 224 | ELF_DETAILS | 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 | " j 3f\n" | 28 | " j 3f\n" |
| 29 | "2: xc 0(1,%1),0(%2)\n" | 29 | "2: xc 0(1,%1),0(%2)\n" |
| 30 | "3:" | 30 | "3:" |
| 31 | : : "d" (bytes), "a" (p1), "a" (p2) | 31 | : "+a" (bytes), "+a" (p1), "+a" (p2) |
| 32 | : "0", "cc", "memory"); | 32 | : : "0", "cc", "memory"); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | static void xor_xc_3(unsigned long bytes, unsigned long * __restrict p1, | 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 | "2: xc 0(1,%1),0(%2)\n" | 54 | "2: xc 0(1,%1),0(%2)\n" |
| 55 | "3: xc 0(1,%1),0(%3)\n" | 55 | "3: xc 0(1,%1),0(%3)\n" |
| 56 | "4:" | 56 | "4:" |
| 57 | : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3) | 57 | : "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3) |
| 58 | : : "0", "cc", "memory"); | 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 | "3: xc 0(1,%1),0(%3)\n" | 85 | "3: xc 0(1,%1),0(%3)\n" |
| 86 | "4: xc 0(1,%1),0(%4)\n" | 86 | "4: xc 0(1,%1),0(%4)\n" |
| 87 | "5:" | 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 | : : "0", "cc", "memory"); | 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 | const unsigned long * __restrict p5) | 96 | const unsigned long * __restrict p5) |
| 97 | { | 97 | { |
| 98 | asm volatile( | 98 | asm volatile( |
| 99 | " larl 1,2f\n" | ||
| 100 | " aghi %0,-1\n" | 99 | " aghi %0,-1\n" |
| 101 | " jm 6f\n" | 100 | " jm 6f\n" |
| 102 | " srlg 0,%0,8\n" | 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 | "4: xc 0(1,%1),0(%4)\n" | 121 | "4: xc 0(1,%1),0(%4)\n" |
| 123 | "5: xc 0(1,%1),0(%5)\n" | 122 | "5: xc 0(1,%1),0(%5)\n" |
| 124 | "6:" | 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 | "+a" (p5) | 125 | "+a" (p5) |
| 127 | : : "0", "cc", "memory"); | 126 | : : "0", "cc", "memory"); |
| 128 | } | 127 | } |
| @@ -89,6 +89,7 @@ SECTIONS · 88 unmodified lines | |||
| 89 | 89 | ||
| 90 | STABS_DEBUG | 90 | STABS_DEBUG |
| 91 | DWARF_DEBUG | 91 | DWARF_DEBUG |
| 92 | MODINFO | ||
| 92 | ELF_DETAILS | 93 | ELF_DETAILS |
| 93 | 94 | ||
| 94 | DISCARDS | 95 | DISCARDS |
| @@ -355,6 +355,13 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, · 354 unmodified lines | |||
| 355 | dev->error_state = pci_channel_io_normal; | 355 | dev->error_state = pci_channel_io_normal; |
| 356 | dev->dma_mask = 0xffffffff; | 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 | if (of_node_name_eq(node, "pci")) { | 365 | if (of_node_name_eq(node, "pci")) { |
| 359 | /* a PCI-PCI bridge */ | 366 | /* a PCI-PCI bridge */ |
| 360 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | 367 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; |
| @@ -191,6 +191,7 @@ SECTIONS · 190 unmodified lines | |||
| 191 | 191 | ||
| 192 | STABS_DEBUG | 192 | STABS_DEBUG |
| 193 | DWARF_DEBUG | 193 | DWARF_DEBUG |
| 194 | MODINFO | ||
| 194 | ELF_DETAILS | 195 | ELF_DETAILS |
| 195 | 196 | ||
| 196 | DISCARDS | 197 | DISCARDS |
| @@ -172,6 +172,7 @@ SECTIONS · 171 unmodified lines | |||
| 172 | 172 | ||
| 173 | STABS_DEBUG | 173 | STABS_DEBUG |
| 174 | DWARF_DEBUG | 174 | DWARF_DEBUG |
| 175 | MODINFO | ||
| 175 | ELF_DETAILS | 176 | ELF_DETAILS |
| 176 | 177 | ||
| 177 | DISCARDS | 178 | DISCARDS |
| @@ -113,6 +113,7 @@ SECTIONS · 112 unmodified lines | |||
| 113 | 113 | ||
| 114 | STABS_DEBUG | 114 | STABS_DEBUG |
| 115 | DWARF_DEBUG | 115 | DWARF_DEBUG |
| 116 | MODINFO | ||
| 116 | ELF_DETAILS | 117 | ELF_DETAILS |
| 117 | 118 | ||
| 118 | DISCARDS | 119 | DISCARDS |
| @@ -113,6 +113,7 @@ vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o · 112 unmodified lines | |||
| 113 | 113 | ||
| 114 | ifdef CONFIG_EFI_SBAT | 114 | ifdef CONFIG_EFI_SBAT |
| 115 | $(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE) | 115 | $(obj)/sbat.o: $(CONFIG_EFI_SBAT_FILE) |
| 116 | AFLAGS_sbat.o += -I $(srctree) | ||
| 116 | endif | 117 | endif |
| 117 | 118 | ||
| 118 | $(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE | 119 | $(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE |
| @@ -28,17 +28,17 @@ · 27 unmodified lines | |||
| 28 | #include "sev.h" | 28 | #include "sev.h" |
| 29 | 29 | ||
| 30 | static struct ghcb boot_ghcb_page __aligned(PAGE_SIZE); | 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 | #undef __init | 33 | #undef __init |
| 34 | #define __init | 34 | #define __init |
| 35 | 35 | ||
| 36 | #define __BOOT_COMPRESSED | 36 | #define __BOOT_COMPRESSED |
| 37 | 37 | ||
| 38 | u8 snp_vmpl; | 38 | u8 snp_vmpl __section(".data"); |
| 39 | u16 ghcb_version; | 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 | /* Include code for early handlers */ | 43 | /* Include code for early handlers */ |
| 44 | #include "../../boot/startup/sev-shared.c" | 44 | #include "../../boot/startup/sev-shared.c" |
| @@ -188,6 +188,7 @@ bool sev_es_check_ghcb_fault(unsigned long address) · 143 unmodified lines | |||
| 188 | MSR_AMD64_SNP_RESERVED_BIT13 | \ | 188 | MSR_AMD64_SNP_RESERVED_BIT13 | \ |
| 189 | MSR_AMD64_SNP_RESERVED_BIT15 | \ | 189 | MSR_AMD64_SNP_RESERVED_BIT15 | \ |
| 190 | MSR_AMD64_SNP_SECURE_AVIC | \ | 190 | MSR_AMD64_SNP_SECURE_AVIC | \ |
| 191 | MSR_AMD64_SNP_RESERVED_BITS19_22 | \ | ||
| 191 | MSR_AMD64_SNP_RESERVED_MASK) | 192 | MSR_AMD64_SNP_RESERVED_MASK) |
| 192 | 193 | ||
| 193 | #ifdef CONFIG_AMD_SECURE_AVIC | 194 | #ifdef CONFIG_AMD_SECURE_AVIC |
| @@ -88,7 +88,7 @@ SECTIONS · 87 unmodified lines | |||
| 88 | /DISCARD/ : { | 88 | /DISCARD/ : { |
| 89 | *(.dynamic) *(.dynsym) *(.dynstr) *(.dynbss) | 89 | *(.dynamic) *(.dynsym) *(.dynstr) *(.dynbss) |
| 90 | *(.hash) *(.gnu.hash) | 90 | *(.hash) *(.gnu.hash) |
| 91 | *(.note.*) | 91 | *(.note.*) *(.modinfo) |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | .got.plt (INFO) : { | 94 | .got.plt (INFO) : { |
| @@ -31,7 +31,7 @@ static u32 cpuid_std_range_max __ro_after_init; · 30 unmodified lines | |||
| 31 | static u32 cpuid_hyp_range_max __ro_after_init; | 31 | static u32 cpuid_hyp_range_max __ro_after_init; |
| 32 | static u32 cpuid_ext_range_max __ro_after_init; | 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 | void __noreturn | 36 | void __noreturn |
| 37 | sev_es_terminate(unsigned int set, unsigned int reason) | 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 | [MSR_AMD64_SNP_VMSA_REG_PROT_BIT] = "VMSARegProt", | 89 | [MSR_AMD64_SNP_VMSA_REG_PROT_BIT] = "VMSARegProt", |
| 90 | [MSR_AMD64_SNP_SMT_PROT_BIT] = "SMTProt", | 90 | [MSR_AMD64_SNP_SMT_PROT_BIT] = "SMTProt", |
| 91 | [MSR_AMD64_SNP_SECURE_AVIC_BIT] = "SecureAVIC", | 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 | #endif | 35 | #endif |
| 36 | .endm | 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 | .text | 66 | .text |
| 39 | .globl __kernel_sigreturn | 67 | .globl __kernel_sigreturn |
| 40 | .type __kernel_sigreturn,@function | 68 | .type __kernel_sigreturn,@function |
| 69 | nop /* libgcc hack: see comment above */ | ||
| 41 | ALIGN | 70 | ALIGN |
| 42 | __kernel_sigreturn: | 71 | __kernel_sigreturn: |
| 43 | STARTPROC_SIGNAL_FRAME IA32_SIGFRAME_sigcontext | 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 | .globl __kernel_rt_sigreturn | 82 | .globl __kernel_rt_sigreturn |
| 54 | .type __kernel_rt_sigreturn,@function | 83 | .type __kernel_rt_sigreturn,@function |
| 84 | nop /* libgcc hack: see comment above */ | ||
| 55 | ALIGN | 85 | ALIGN |
| 56 | __kernel_rt_sigreturn: | 86 | __kernel_rt_sigreturn: |
| 57 | STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext | 87 | STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext |
| @@ -138,7 +138,7 @@ extern void __init efi_apply_memmap_quirks(void); · 137 unmodified lines | |||
| 138 | extern int __init efi_reuse_config(u64 tables, int nr_tables); | 138 | extern int __init efi_reuse_config(u64 tables, int nr_tables); |
| 139 | extern void efi_delete_dummy_variable(void); | 139 | extern void efi_delete_dummy_variable(void); |
| 140 | extern void efi_crash_gracefully_on_page_fault(unsigned long phys_addr); | 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 | void arch_efi_call_virt_setup(void); | 143 | void arch_efi_call_virt_setup(void); |
| 144 | void arch_efi_call_virt_teardown(void); | 144 | void arch_efi_call_virt_teardown(void); |
| @@ -740,7 +740,10 @@ · 739 unmodified lines | |||
| 740 | #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT) | 740 | #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT) |
| 741 | #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18 | 741 | #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18 |
| 742 | #define MSR_AMD64_SNP_SECURE_AVIC BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT) | 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 | #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT) | 747 | #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT) |
| 745 | #define MSR_AMD64_SAVIC_CONTROL 0xc0010138 | 748 | #define MSR_AMD64_SAVIC_CONTROL 0xc0010138 |
| 746 | #define MSR_AMD64_SAVIC_EN_BIT 0 | 749 | #define MSR_AMD64_SAVIC_EN_BIT 0 |
| @@ -22,6 +22,7 @@ extern int numa_off; · 21 unmodified lines | |||
| 22 | */ | 22 | */ |
| 23 | extern s16 __apicid_to_node[MAX_LOCAL_APIC]; | 23 | extern s16 __apicid_to_node[MAX_LOCAL_APIC]; |
| 24 | extern nodemask_t numa_nodes_parsed __initdata; | 24 | extern nodemask_t numa_nodes_parsed __initdata; |
| 25 | extern nodemask_t numa_phys_nodes_parsed __initdata; | ||
| 25 | 26 | ||
| 26 | static inline void set_apicid_to_node(int apicid, s16 node) | 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 | extern void numa_add_cpu(unsigned int cpu); | 49 | extern void numa_add_cpu(unsigned int cpu); |
| 49 | extern void numa_remove_cpu(unsigned int cpu); | 50 | extern void numa_remove_cpu(unsigned int cpu); |
| 50 | extern void init_gi_nodes(void); | 51 | extern void init_gi_nodes(void); |
| 52 | extern int num_phys_nodes(void); | ||
| 51 | #else /* CONFIG_NUMA */ | 53 | #else /* CONFIG_NUMA */ |
| 52 | static inline void numa_set_node(int cpu, int node) { } | 54 | static inline void numa_set_node(int cpu, int node) { } |
| 53 | static inline void numa_clear_node(int cpu) { } | 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 | static inline void numa_add_cpu(unsigned int cpu) { } | 57 | static inline void numa_add_cpu(unsigned int cpu) { } |
| 56 | static inline void numa_remove_cpu(unsigned int cpu) { } | 58 | static inline void numa_remove_cpu(unsigned int cpu) { } |
| 57 | static inline void init_gi_nodes(void) { } | 59 | static inline void init_gi_nodes(void) { } |
| 60 | static inline int num_phys_nodes(void) | ||
| 61 | { | ||
| 62 | return 1; | ||
| 63 | } | ||
| 58 | #endif /* CONFIG_NUMA */ | 64 | #endif /* CONFIG_NUMA */ |
| 59 | 65 | ||
| 60 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS | 66 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS |
| @@ -19,10 +19,8 @@ · 18 unmodified lines | |||
| 19 | extern p4d_t level4_kernel_pgt[512]; | 19 | extern p4d_t level4_kernel_pgt[512]; |
| 20 | extern p4d_t level4_ident_pgt[512]; | 20 | extern p4d_t level4_ident_pgt[512]; |
| 21 | extern pud_t level3_kernel_pgt[512]; | 21 | extern pud_t level3_kernel_pgt[512]; |
| 22 | extern pud_t level3_ident_pgt[512]; | ||
| 23 | extern pmd_t level2_kernel_pgt[512]; | 22 | extern pmd_t level2_kernel_pgt[512]; |
| 24 | extern pmd_t level2_fixmap_pgt[512]; | 23 | extern pmd_t level2_fixmap_pgt[512]; |
| 25 | extern pmd_t level2_ident_pgt[512]; | ||
| 26 | extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM]; | 24 | extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM]; |
| 27 | extern pgd_t init_top_pgt[]; | 25 | extern pgd_t init_top_pgt[]; |
| 28 | 26 | ||
| @@ -155,6 +155,7 @@ extern unsigned int __max_logical_packages; · 154 unmodified lines | |||
| 155 | extern unsigned int __max_threads_per_core; | 155 | extern unsigned int __max_threads_per_core; |
| 156 | extern unsigned int __num_threads_per_package; | 156 | extern unsigned int __num_threads_per_package; |
| 157 | extern unsigned int __num_cores_per_package; | 157 | extern unsigned int __num_cores_per_package; |
| 158 | extern unsigned int __num_nodes_per_package; | ||
| 158 | 159 | ||
| 159 | const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c); | 160 | const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c); |
| 160 | enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c); | 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 | return __num_threads_per_package; | 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 | #ifdef CONFIG_X86_LOCAL_APIC | 188 | #ifdef CONFIG_X86_LOCAL_APIC |
| 183 | int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level); | 189 | int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level); |
| 184 | #else | 190 | #else |
| @@ -95,6 +95,9 @@ EXPORT_SYMBOL(__max_dies_per_package); · 94 unmodified lines | |||
| 95 | unsigned int __max_logical_packages __ro_after_init = 1; | 95 | unsigned int __max_logical_packages __ro_after_init = 1; |
| 96 | EXPORT_SYMBOL(__max_logical_packages); | 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 | unsigned int __num_cores_per_package __ro_after_init = 1; | 101 | unsigned int __num_cores_per_package __ro_after_init = 1; |
| 99 | EXPORT_SYMBOL(__num_cores_per_package); | 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 | msr_clear_bit(MSR_RMID_SNC_CONFIG, 0); | 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 | static const struct x86_cpu_id snc_cpu_ids[] __initconst = { | 368 | static const struct x86_cpu_id snc_cpu_ids[] __initconst = { |
| 369 | X86_MATCH_VFM(INTEL_ICELAKE_X, 0), | 369 | X86_MATCH_VFM(INTEL_ICELAKE_X, 0), |
| 370 | X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, 0), | 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 | static __init int snc_get_config(void) | 378 | static __init int snc_get_config(void) |
| 389 | { | 379 | { |
| 390 | struct cacheinfo *ci = get_cpu_cacheinfo_level(0, RESCTRL_L3_CACHE); | 380 | int ret = topology_num_nodes_per_package(); |
| 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; | ||
| 397 | 381 | ||
| 398 | cpus_read_lock(); | 382 | if (ret > 1 && !x86_match_cpu(snc_cpu_ids)) { |
| 399 | if (num_online_cpus() != num_present_cpus()) | 383 | pr_warn("CoD enabled system? Resctrl not supported\n"); |
| 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) | ||
| 409 | return 1; | 384 | return 1; |
| 410 | 385 | } | |
| 411 | ret = cpus_per_l3 / cpus_per_node; | ||
| 412 | 386 | ||
| 413 | /* sanity check: Only valid results are 1, 2, 3, 4, 6 */ | 387 | /* sanity check: Only valid results are 1, 2, 3, 4, 6 */ |
| 414 | switch (ret) { | 388 | switch (ret) { |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #include <asm/mpspec.h> | 31 | #include <asm/mpspec.h> |
| 32 | #include <asm/msr.h> | 32 | #include <asm/msr.h> |
| 33 | #include <asm/smp.h> | 33 | #include <asm/smp.h> |
| 34 | #include <asm/numa.h> | ||
| 34 | 35 | ||
| 35 | #include "cpu.h" | 36 | #include "cpu.h" |
| 36 | 37 | ||
| @@ -492,11 +493,19 @@ void __init topology_init_possible_cpus(void) · 455 unmodified lines | |||
| 492 | set_nr_cpu_ids(allowed); | 493 | set_nr_cpu_ids(allowed); |
| 493 | 494 | ||
| 494 | cnta = domain_weight(TOPO_PKG_DOMAIN); | 495 | cnta = domain_weight(TOPO_PKG_DOMAIN); |
| 495 | cntb = domain_weight(TOPO_DIE_DOMAIN); | ||
| 496 | __max_logical_packages = cnta; | 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 | __max_dies_per_package = 1U << (get_count_order(cntb) - get_count_order(cnta)); | 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 | pr_info("Max. logical dies: %3u\n", cntb); | 509 | pr_info("Max. logical dies: %3u\n", cntb); |
| 501 | pr_info("Max. dies per package: %3u\n", __max_dies_per_package); | 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 | .data | 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 | SYM_DATA_START_PTI_ALIGNED(init_top_pgt) | 619 | SYM_DATA_START_PTI_ALIGNED(init_top_pgt) |
| 647 | .fill 512,8,0 | 620 | .fill 512,8,0 |
| 648 | .fill PTI_USER_PGD_FILL,8,0 | 621 | .fill PTI_USER_PGD_FILL,8,0 |
| 649 | SYM_DATA_END(init_top_pgt) | 622 | SYM_DATA_END(init_top_pgt) |
| 650 | #endif | ||
| 651 | 623 | ||
| 652 | SYM_DATA_START_PAGE_ALIGNED(level4_kernel_pgt) | 624 | SYM_DATA_START_PAGE_ALIGNED(level4_kernel_pgt) |
| 653 | .fill 511,8,0 | 625 | .fill 511,8,0 |
| @@ -468,13 +468,6 @@ static int x86_cluster_flags(void) · 467 unmodified lines | |||
| 468 | } | 468 | } |
| 469 | #endif | 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 | static struct sched_domain_topology_level x86_topology[] = { | 471 | static struct sched_domain_topology_level x86_topology[] = { |
| 479 | SDTL_INIT(tl_smt_mask, cpu_smt_flags, SMT), | 472 | SDTL_INIT(tl_smt_mask, cpu_smt_flags, SMT), |
| 480 | #ifdef CONFIG_SCHED_CLUSTER | 473 | #ifdef CONFIG_SCHED_CLUSTER |
| @@ -496,7 +489,7 @@ static void __init build_sched_topology(void) · 15 unmodified lines | |||
| 496 | * PKG domain since the NUMA domains will auto-magically create the | 489 | * PKG domain since the NUMA domains will auto-magically create the |
| 497 | * right spanning domains based on the SLIT. | 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 | unsigned int pkgdom = ARRAY_SIZE(x86_topology) - 2; | 493 | unsigned int pkgdom = ARRAY_SIZE(x86_topology) - 2; |
| 501 | 494 | ||
| 502 | memset(&x86_topology[pkgdom], 0, sizeof(x86_topology[pkgdom])); | 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 | #ifdef CONFIG_NUMA | 508 | #ifdef CONFIG_NUMA |
| 516 | static int sched_avg_remote_distance; | 509 | /* |
| 517 | static int avg_remote_numa_distance(void) | 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; | 515 | int u = topology_num_nodes_per_package(); |
| 520 | int distance, nr_remote, total_distance; | 516 | |
| 521 | 517 | for (int k = 0; k < u; k++) { | |
| 522 | if (sched_avg_remote_distance > 0) | 518 | for (int l = k; l < u; l++) { |
| 523 | return sched_avg_remote_distance; | 519 | if (node_distance(N + k, N + l) != |
| 524 | 520 | node_distance(N + l, N + k)) | |
| 525 | nr_remote = 0; | 521 | return false; |
| 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 | } | ||
| 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 | int arch_sched_node_distance(int from, int to) | 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 | switch (boot_cpu_data.x86_vfm) { | 658 | switch (boot_cpu_data.x86_vfm) { |
| 550 | case INTEL_GRANITERAPIDS_X: | 659 | case INTEL_GRANITERAPIDS_X: |
| 551 | case INTEL_ATOM_DARKMONT_X: | 660 | case INTEL_ATOM_DARKMONT_X: |
| 552 | 661 | if (topology_max_packages() == 1 || | |
| 553 | if (!x86_has_numa_in_package || topology_max_packages() == 1 || | 662 | topology_num_nodes_per_package() < 3) |
| 554 | d < REMOTE_DISTANCE) | ||
| 555 | return d; | 663 | return d; |
| 556 | 664 | ||
| 557 | /* | 665 | /* |
| 558 | * With SNC enabled, there could be too many levels of remote | 666 | * Handle SNC-3 asymmetries. |
| 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. | ||
| 573 | */ | 667 | */ |
| 574 | WARN_ONCE(topology_max_packages() > 2, | 668 | return slit_cluster_distance(from, to); |
| 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(); | ||
| 580 | } | 669 | } |
| 581 | return d; | 670 | return d; |
| 582 | } | 671 | } |
| @@ -606,7 +695,7 @@ void set_cpu_sibling_map(int cpu) · 23 unmodified lines | |||
| 606 | o = &cpu_data(i); | 695 | o = &cpu_data(i); |
| 607 | 696 | ||
| 608 | if (match_pkg(c, o) && !topology_same_node(c, o)) | 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 | if ((i == cpu) || (has_smt && match_smt(c, o))) | 700 | if ((i == cpu) || (has_smt && match_smt(c, o))) |
| 612 | link_mask(topology_sibling_cpumask, cpu, i); | 701 | link_mask(topology_sibling_cpumask, cpu, i); |
| @@ -427,6 +427,7 @@ SECTIONS · 426 unmodified lines | |||
| 427 | .llvm_bb_addr_map : { *(.llvm_bb_addr_map) } | 427 | .llvm_bb_addr_map : { *(.llvm_bb_addr_map) } |
| 428 | #endif | 428 | #endif |
| 429 | 429 | ||
| 430 | MODINFO | ||
| 430 | ELF_DETAILS | 431 | ELF_DETAILS |
| 431 | 432 | ||
| 432 | DISCARDS | 433 | DISCARDS |
| @@ -48,6 +48,8 @@ s16 __apicid_to_node[MAX_LOCAL_APIC] = { · 47 unmodified lines | |||
| 48 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE | 48 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | nodemask_t numa_phys_nodes_parsed __initdata; | ||
| 52 | |||
| 51 | int numa_cpu_node(int cpu) | 53 | int numa_cpu_node(int cpu) |
| 52 | { | 54 | { |
| 53 | u32 apicid = early_per_cpu(x86_cpu_to_apicid, cpu); | 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 | return NUMA_NO_NODE; | 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 | cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; | 67 | cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; |
| 61 | EXPORT_SYMBOL(node_to_cpumask_map); | 68 | EXPORT_SYMBOL(node_to_cpumask_map); |
| 62 | 69 | ||
| @@ -210,6 +217,7 @@ static int __init dummy_numa_init(void) · 147 unmodified lines | |||
| 210 | 0LLU, PFN_PHYS(max_pfn) - 1); | 217 | 0LLU, PFN_PHYS(max_pfn) - 1); |
| 211 | 218 | ||
| 212 | node_set(0, numa_nodes_parsed); | 219 | node_set(0, numa_nodes_parsed); |
| 220 | node_set(0, numa_phys_nodes_parsed); | ||
| 213 | numa_add_memblk(0, 0, PFN_PHYS(max_pfn)); | 221 | numa_add_memblk(0, 0, PFN_PHYS(max_pfn)); |
| 214 | 222 | ||
| 215 | return 0; | 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 | set_apicid_to_node(apic_id, node); | 58 | set_apicid_to_node(apic_id, node); |
| 59 | node_set(node, numa_nodes_parsed); | 59 | node_set(node, numa_nodes_parsed); |
| 60 | node_set(node, numa_phys_nodes_parsed); | ||
| 60 | pr_debug("SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", pxm, apic_id, node); | 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 | set_apicid_to_node(apic_id, node); | 99 | set_apicid_to_node(apic_id, node); |
| 99 | node_set(node, numa_nodes_parsed); | 100 | node_set(node, numa_nodes_parsed); |
| 101 | node_set(node, numa_phys_nodes_parsed); | ||
| 100 | pr_debug("SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", pxm, apic_id, node); | 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 | efi_check_for_embedded_firmwares(); | 838 | efi_check_for_embedded_firmwares(); |
| 839 | efi_free_boot_services(); | 839 | efi_unmap_boot_services(); |
| 840 | 840 | ||
| 841 | if (!efi_is_mixed()) | 841 | if (!efi_is_mixed()) |
| 842 | efi_native_runtime_setup(); | 842 | efi_native_runtime_setup(); |
| @@ -341,7 +341,7 @@ void __init efi_reserve_boot_services(void) · 340 unmodified lines | |||
| 341 | 341 | ||
| 342 | /* | 342 | /* |
| 343 | * Because the following memblock_reserve() is paired | 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 | * efi_free_boot_services(), we must be extremely | 345 | * efi_free_boot_services(), we must be extremely |
| 346 | * careful not to reserve, and subsequently free, | 346 | * careful not to reserve, and subsequently free, |
| 347 | * critical regions of memory (like the kernel image) or | 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 | pr_err("Failed to unmap VA mapping for 0x%llx\n", va); | 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 | struct efi_memory_map_data data = { 0 }; | 416 | struct efi_memory_map_data data = { 0 }; |
| 410 | efi_memory_desc_t *md; | 417 | efi_memory_desc_t *md; |
| 411 | int num_entries = 0; | 418 | int num_entries = 0; |
| 419 | int idx = 0; | ||
| 420 | size_t sz; | ||
| 412 | void *new, *new_md; | 421 | void *new, *new_md; |
| 413 | 422 | ||
| 414 | /* Keep all regions for /sys/kernel/debug/efi */ | 423 | /* Keep all regions for /sys/kernel/debug/efi */ |
| 415 | if (efi_enabled(EFI_DBG)) | 424 | if (efi_enabled(EFI_DBG)) |
| 416 | return; | 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 | for_each_efi_memory_desc(md) { | 434 | for_each_efi_memory_desc(md) { |
| 419 | unsigned long long start = md->phys_addr; | 435 | unsigned long long start = md->phys_addr; |
| 420 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 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 | start = SZ_1M; | 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 | if (!num_entries) | 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 | * A number of config table entries get remapped to virtual addresses | 565 | * A number of config table entries get remapped to virtual addresses |
| 517 | * after entering EFI virtual mode. However, the kexec kernel requires | 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 | const unsigned int __initconst pvh_start_info_sz = sizeof(pvh_start_info); | 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 | * Xen guests are able to obtain the memory map from the hypervisor via the | 29 | * Xen guests are able to obtain the memory map from the hypervisor via the |
| 35 | * HYPERVISOR_memory_op hypercall. | 30 | * HYPERVISOR_memory_op hypercall. |
| @@ -95,7 +90,7 @@ static void __init init_pvh_bootparams(bool xen_guest) · 59 unmodified lines | |||
| 95 | pvh_bootparams.hdr.version = (2 << 8) | 12; | 90 | pvh_bootparams.hdr.version = (2 << 8) | 12; |
| 96 | pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0; | 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 | * Xen PV would need some work to support PCID: CR3 handling as well | 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 | setup_clear_cpu_cap(X86_FEATURE_PCID); | 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 | static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; | 105 | static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; |
| 106 | #endif | 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 | * Protects atomic reservation decrease/increase against concurrent increases. | 112 | * Protects atomic reservation decrease/increase against concurrent increases. |
| 110 | * Also protects non-atomic updates of current_pages and balloon lists. | 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 | /* Zap identity mapping */ | 1780 | /* Zap identity mapping */ |
| 1778 | init_top_pgt[0] = __pgd(0); | 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 | /* Pre-constructed entries are in pfn, so convert to mfn */ | 1789 | /* Pre-constructed entries are in pfn, so convert to mfn */ |
| 1781 | /* L4[273] -> level3_ident_pgt */ | 1790 | /* L4[273] -> level3_ident_pgt */ |
| 1782 | /* L4[511] -> level3_kernel_pgt */ | 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 | if (op_is_write(op)) | 398 | if (op_is_write(op)) |
| 399 | memcpy(page_address(page), p, bytes); | 399 | memcpy(page_address(page), p, bytes); |
| 400 | 400 | ||
| 401 | if (bio_add_page(bio, page, bytes, 0) < bytes) | 401 | __bio_add_page(bio, page, bytes, 0); |
| 402 | break; | ||
| 403 | 402 | ||
| 404 | len -= bytes; | 403 | len -= bytes; |
| 405 | p += bytes; | 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, | 4796 | static struct blk_mq_tags **blk_mq_prealloc_tag_set_tags( |
| 4797 | int new_nr_hw_queues) | 4797 | struct blk_mq_tag_set *set, |
| 4798 | int new_nr_hw_queues) | ||
| 4798 | { | 4799 | { |
| 4799 | struct blk_mq_tags **new_tags; | 4800 | struct blk_mq_tags **new_tags; |
| 4800 | int i; | 4801 | int i; |
| 4801 | 4802 | ||
| 4802 | if (set->nr_hw_queues >= new_nr_hw_queues) | 4803 | if (set->nr_hw_queues >= new_nr_hw_queues) |
| 4803 | goto done; | 4804 | return NULL; |
| 4804 | 4805 | ||
| 4805 | new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *), | 4806 | new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *), |
| 4806 | GFP_KERNEL, set->numa_node); | 4807 | GFP_KERNEL, set->numa_node); |
| 4807 | if (!new_tags) | 4808 | if (!new_tags) |
| 4808 | return -ENOMEM; | 4809 | return ERR_PTR(-ENOMEM); |
| 4809 | 4810 | ||
| 4810 | if (set->tags) | 4811 | if (set->tags) |
| 4811 | memcpy(new_tags, set->tags, set->nr_hw_queues * | 4812 | memcpy(new_tags, set->tags, set->nr_hw_queues * |
| 4812 | sizeof(*set->tags)); | 4813 | sizeof(*set->tags)); |
| 4813 | kfree(set->tags); | ||
| 4814 | set->tags = new_tags; | ||
| 4815 | 4814 | ||
| 4816 | for (i = set->nr_hw_queues; i < new_nr_hw_queues; i++) { | 4815 | for (i = set->nr_hw_queues; i < new_nr_hw_queues; i++) { |
| 4817 | if (!__blk_mq_alloc_map_and_rqs(set, i)) { | 4816 | if (blk_mq_is_shared_tags(set->flags)) { |
| 4818 | while (--i >= set->nr_hw_queues) | 4817 | new_tags[i] = set->shared_tags; |
| 4819 | __blk_mq_free_map_and_rqs(set, i); | 4818 | } else { |
| 4820 | return -ENOMEM; | 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 | cond_resched(); | 4824 | cond_resched(); |
| 4823 | } | 4825 | } |
| 4824 | 4826 | ||
| 4825 | done: | 4827 | return new_tags; |
| 4826 | set->nr_hw_queues = new_nr_hw_queues; | 4828 | out_unwind: |
| 4827 | return 0; | 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 | unsigned int memflags; | 5120 | unsigned int memflags; |
| 5114 | int i; | 5121 | int i; |
| 5115 | struct xarray elv_tbl; | 5122 | struct xarray elv_tbl; |
| 5123 | struct blk_mq_tags **new_tags; | ||
| 5116 | bool queues_frozen = false; | 5124 | bool queues_frozen = false; |
| 5117 | 5125 | ||
| 5118 | lockdep_assert_held(&set->tag_list_lock); | 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 | if (blk_mq_elv_switch_none(q, &elv_tbl)) | 5155 | if (blk_mq_elv_switch_none(q, &elv_tbl)) |
| 5148 | goto switch_back; | 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 | list_for_each_entry(q, &set->tag_list, tag_set_list) | 5162 | list_for_each_entry(q, &set->tag_list, tag_set_list) |
| 5151 | blk_mq_freeze_queue_nomemsave(q); | 5163 | blk_mq_freeze_queue_nomemsave(q); |
| 5152 | queues_frozen = true; | 5164 | queues_frozen = true; |
| 5153 | if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0) | 5165 | if (new_tags) { |
| 5154 | goto switch_back; | 5166 | kfree(set->tags); |
| 5167 | set->tags = new_tags; | ||
| 5168 | } | ||
| 5169 | set->nr_hw_queues = nr_hw_queues; | ||
| 5155 | 5170 | ||
| 5156 | fallback: | 5171 | fallback: |
| 5157 | blk_mq_update_queue_map(set); | 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 | * Serialize updating nr_requests with concurrent queue_requests_store() | 79 | * Serialize updating nr_requests with concurrent queue_requests_store() |
| 80 | * and switching elevator. | 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 | if (nr == q->nr_requests) | 90 | if (nr == q->nr_requests) |
| 85 | goto unlock; | 91 | goto unlock; |
| @@ -807,7 +807,16 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf, · 806 unmodified lines | |||
| 807 | elv_iosched_load_module(ctx.name); | 807 | elv_iosched_load_module(ctx.name); |
| 808 | ctx.type = elevator_find_get(ctx.name); | 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 | if (!blk_queue_no_elv_switch(q)) { | 820 | if (!blk_queue_no_elv_switch(q)) { |
| 812 | ret = elevator_change(q, &ctx); | 821 | ret = elevator_change(q, &ctx); |
| 813 | if (!ret) | 822 | if (!ret) |
| @@ -817,6 +826,7 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf, · 3 unmodified lines | |||
| 817 | } | 826 | } |
| 818 | up_read(&set->update_nr_hwq_lock); | 827 | up_read(&set->update_nr_hwq_lock); |
| 819 | 828 | ||
| 829 | out: | ||
| 820 | if (ctx.type) | 830 | if (ctx.type) |
| 821 | elevator_put(ctx.type); | 831 | elevator_put(ctx.type); |
| 822 | return ret; | 832 | return ret; |
| @@ -876,8 +876,6 @@ config CRYPTO_BLAKE2B · 875 unmodified lines | |||
| 876 | - blake2b-384 | 876 | - blake2b-384 |
| 877 | - blake2b-512 | 877 | - blake2b-512 |
| 878 | 878 | ||
| 879 | Used by the btrfs filesystem. | ||
| 880 | |||
| 881 | See https://blake2.net for further information. | 879 | See https://blake2.net for further information. |
| 882 | 880 | ||
| 883 | config CRYPTO_CMAC | 881 | config CRYPTO_CMAC |
| @@ -965,7 +963,6 @@ config CRYPTO_SHA256 · 81 unmodified lines | |||
| 965 | 10118-3), including HMAC support. | 963 | 10118-3), including HMAC support. |
| 966 | 964 | ||
| 967 | This is required for IPsec AH (XFRM_AH) and IPsec ESP (XFRM_ESP). | 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 | config CRYPTO_SHA512 | 967 | config CRYPTO_SHA512 |
| 971 | tristate "SHA-384 and SHA-512" | 968 | tristate "SHA-384 and SHA-512" |
| @@ -1039,8 +1036,6 @@ config CRYPTO_XXHASH · 67 unmodified lines | |||
| 1039 | 1036 | ||
| 1040 | Extremely fast, working at speeds close to RAM limits. | 1037 | Extremely fast, working at speeds close to RAM limits. |
| 1041 | 1038 | ||
| 1042 | Used by the btrfs filesystem. | ||
| 1043 | |||
| 1044 | endmenu | 1039 | endmenu |
| 1045 | 1040 | ||
| 1046 | menu "CRCs (cyclic redundancy checks)" | 1041 | menu "CRCs (cyclic redundancy checks)" |
| @@ -1058,8 +1053,6 @@ config CRYPTO_CRC32C · 11 unmodified lines | |||
| 1058 | on Communications, Vol. 41, No. 6, June 1993, selected for use with | 1053 | on Communications, Vol. 41, No. 6, June 1993, selected for use with |
| 1059 | iSCSI. | 1054 | iSCSI. |
| 1060 | 1055 | ||
| 1061 | Used by btrfs, ext4, jbd2, NVMeoF/TCP, and iSCSI. | ||
| 1062 | |||
| 1063 | config CRYPTO_CRC32 | 1056 | config CRYPTO_CRC32 |
| 1064 | tristate "CRC32" | 1057 | tristate "CRC32" |
| 1065 | select CRYPTO_HASH | 1058 | select CRYPTO_HASH |
| @@ -1067,8 +1060,6 @@ config CRYPTO_CRC32 · 1 unmodified line | |||
| 1067 | help | 1060 | help |
| 1068 | CRC32 CRC algorithm (IEEE 802.3) | 1061 | CRC32 CRC algorithm (IEEE 802.3) |
| 1069 | 1062 | ||
| 1070 | Used by RoCEv2 and f2fs. | ||
| 1071 | |||
| 1072 | endmenu | 1063 | endmenu |
| 1073 | 1064 | ||
| 1074 | menu "Compression" | 1065 | menu "Compression" |
| @@ -4132,7 +4132,7 @@ static const struct alg_test_desc alg_test_descs[] = { · 4131 unmodified lines | |||
| 4132 | .fips_allowed = 1, | 4132 | .fips_allowed = 1, |
| 4133 | }, { | 4133 | }, { |
| 4134 | .alg = "authenc(hmac(sha224),cbc(aes))", | 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 | .test = alg_test_aead, | 4136 | .test = alg_test_aead, |
| 4137 | .suite = { | 4137 | .suite = { |
| 4138 | .aead = __VECS(hmac_sha224_aes_cbc_tv_temp) | 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 | .fips_allowed = 1, | 4194 | .fips_allowed = 1, |
| 4195 | }, { | 4195 | }, { |
| 4196 | .alg = "authenc(hmac(sha384),cbc(aes))", | 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 | .test = alg_test_aead, | 4198 | .test = alg_test_aead, |
| 4199 | .suite = { | 4199 | .suite = { |
| 4200 | .aead = __VECS(hmac_sha384_aes_cbc_tv_temp) | 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 | cmd_abo = job->cmd_bo; | 186 | cmd_abo = job->cmd_bo; |
| 187 | 187 | ||
| 188 | if (unlikely(job->job_timeout)) { | 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 | ret = -EINVAL; | 190 | ret = -EINVAL; |
| 191 | goto out; | 191 | goto out; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | if (unlikely(!data) || unlikely(size != sizeof(u32))) { | 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 | ret = -EINVAL; | 196 | ret = -EINVAL; |
| 197 | goto out; | 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 | if (status == AIE2_STATUS_SUCCESS) | 202 | if (status == AIE2_STATUS_SUCCESS) |
| 203 | amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED); | 203 | amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED); |
| 204 | else | 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 | out: | 207 | out: |
| 208 | aie2_sched_notify(job); | 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 | cmd_abo = job->cmd_bo; | 244 | cmd_abo = job->cmd_bo; |
| 245 | 245 | ||
| 246 | if (unlikely(job->job_timeout)) { | 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 | ret = -EINVAL; | 248 | ret = -EINVAL; |
| 249 | goto out; | 249 | goto out; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | if (unlikely(!data) || unlikely(size != sizeof(u32) * 3)) { | 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 | ret = -EINVAL; | 254 | ret = -EINVAL; |
| 255 | goto out; | 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 | fail_cmd_idx, fail_cmd_status); | 270 | fail_cmd_idx, fail_cmd_status); |
| 271 | 271 | ||
| 272 | if (fail_cmd_status == AIE2_STATUS_SUCCESS) { | 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 | ret = -EINVAL; | 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 | out: | 279 | out: |
| 287 | aie2_sched_notify(job); | 280 | aie2_sched_notify(job); |
| 288 | return ret; | 281 | return ret; |
| @@ -40,11 +40,8 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev, · 39 unmodified lines | |||
| 40 | return -ENODEV; | 40 | return -ENODEV; |
| 41 | 41 | ||
| 42 | ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg); | 42 | ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg); |
| 43 | if (ret == -ETIME) { | 43 | if (ret == -ETIME) |
| 44 | xdna_mailbox_stop_channel(ndev->mgmt_chann); | 44 | aie2_destroy_mgmt_chann(ndev); |
| 45 | xdna_mailbox_destroy_channel(ndev->mgmt_chann); | ||
| 46 | ndev->mgmt_chann = NULL; | ||
| 47 | } | ||
| 48 | 45 | ||
| 49 | if (!ret && *hdl->status != AIE2_STATUS_SUCCESS) { | 46 | if (!ret && *hdl->status != AIE2_STATUS_SUCCESS) { |
| 50 | XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x", | 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 | intr_reg = i2x.mb_head_ptr_reg + 4; | 295 | intr_reg = i2x.mb_head_ptr_reg + 4; |
| 299 | hwctx->priv->mbox_chann = xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x, | 296 | hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox); |
| 300 | intr_reg, ret); | ||
| 301 | if (!hwctx->priv->mbox_chann) { | 297 | if (!hwctx->priv->mbox_chann) { |
| 302 | XDNA_ERR(xdna, "Not able to create channel"); | 298 | XDNA_ERR(xdna, "Not able to create channel"); |
| 303 | ret = -EINVAL; | 299 | ret = -EINVAL; |
| 304 | goto del_ctx_req; | 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 | ndev->hwctx_num++; | 310 | ndev->hwctx_num++; |
| 307 | 311 | ||
| 308 | XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, resp.msix_id); | 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 | return 0; | 315 | return 0; |
| 312 | 316 | ||
| 317 | free_channel: | ||
| 318 | xdna_mailbox_free_channel(hwctx->priv->mbox_chann); | ||
| 313 | del_ctx_req: | 319 | del_ctx_req: |
| 314 | aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); | 320 | aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); |
| 315 | return ret; | 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 | xdna_mailbox_stop_channel(hwctx->priv->mbox_chann); | 332 | xdna_mailbox_stop_channel(hwctx->priv->mbox_chann); |
| 327 | ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); | 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 | XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id); | 335 | XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id); |
| 330 | hwctx->priv->mbox_chann = NULL; | 336 | hwctx->priv->mbox_chann = NULL; |
| 331 | hwctx->fw_ctx_id = -1; | 337 | hwctx->fw_ctx_id = -1; |
| @@ -914,6 +920,20 @@ void aie2_msg_init(struct amdxdna_dev_hdl *ndev) · 582 unmodified lines | |||
| 914 | ndev->exec_msg_ops = &legacy_exec_message_ops; | 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 | static inline struct amdxdna_gem_obj * | 937 | static inline struct amdxdna_gem_obj * |
| 918 | aie2_cmdlist_get_cmd_buf(struct amdxdna_sched_job *job) | 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 | aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL); | 332 | aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL); |
| 333 | aie2_mgmt_fw_fini(ndev); | 333 | aie2_mgmt_fw_fini(ndev); |
| 334 | xdna_mailbox_stop_channel(ndev->mgmt_chann); | 334 | aie2_destroy_mgmt_chann(ndev); |
| 335 | xdna_mailbox_destroy_channel(ndev->mgmt_chann); | ||
| 336 | ndev->mgmt_chann = NULL; | ||
| 337 | drmm_kfree(&xdna->ddev, ndev->mbox); | 335 | drmm_kfree(&xdna->ddev, ndev->mbox); |
| 338 | ndev->mbox = NULL; | 336 | ndev->mbox = NULL; |
| 339 | aie2_psp_stop(ndev->psp_hdl); | 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 | pci_set_master(pdev); | 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 | ret = aie2_smu_init(ndev); | 384 | ret = aie2_smu_init(ndev); |
| 368 | if (ret) { | 385 | if (ret) { |
| 369 | XDNA_ERR(xdna, "failed to init smu, ret %d", ret); | 386 | XDNA_ERR(xdna, "failed to init smu, ret %d", ret); |
| 370 | goto disable_dev; | 387 | goto free_channel; |
| 371 | } | 388 | } |
| 372 | 389 | ||
| 373 | ret = aie2_psp_start(ndev->psp_hdl); | 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 | goto stop_psp; | 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 | mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx); | 402 | mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx); |
| 398 | if (mgmt_mb_irq < 0) { | 403 | if (mgmt_mb_irq < 0) { |
| 399 | ret = mgmt_mb_irq; | 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 | xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4; | 409 | xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4; |
| 405 | ndev->mgmt_chann = xdna_mailbox_create_channel(ndev->mbox, | 410 | ret = xdna_mailbox_start_channel(ndev->mgmt_chann, |
| 406 | &ndev->mgmt_x2i, | 411 | &ndev->mgmt_x2i, |
| 407 | &ndev->mgmt_i2x, | 412 | &ndev->mgmt_i2x, |
| 408 | xdna_mailbox_intr_reg, | 413 | xdna_mailbox_intr_reg, |
| 409 | mgmt_mb_irq); | 414 | mgmt_mb_irq); |
| 410 | if (!ndev->mgmt_chann) { | 415 | if (ret) { |
| 411 | XDNA_ERR(xdna, "failed to create management mailbox channel"); | 416 | XDNA_ERR(xdna, "failed to start management mailbox channel"); |
| 412 | ret = -EINVAL; | 417 | ret = -EINVAL; |
| 413 | goto stop_psp; | 418 | goto stop_psp; |
| 414 | } | 419 | } |
| @@ -416,38 +421,41 @@ static int aie2_hw_start(struct amdxdna_dev *xdna) · 1 unmodified line | |||
| 416 | ret = aie2_mgmt_fw_init(ndev); | 421 | ret = aie2_mgmt_fw_init(ndev); |
| 417 | if (ret) { | 422 | if (ret) { |
| 418 | XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret); | 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 | ret = aie2_pm_init(ndev); | 427 | ret = aie2_pm_init(ndev); |
| 423 | if (ret) { | 428 | if (ret) { |
| 424 | XDNA_ERR(xdna, "failed to init pm, ret %d", ret); | 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 | ret = aie2_mgmt_fw_query(ndev); | 433 | ret = aie2_mgmt_fw_query(ndev); |
| 429 | if (ret) { | 434 | if (ret) { |
| 430 | XDNA_ERR(xdna, "failed to query fw, ret %d", ret); | 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 | ret = aie2_error_async_events_alloc(ndev); | 439 | ret = aie2_error_async_events_alloc(ndev); |
| 435 | if (ret) { | 440 | if (ret) { |
| 436 | XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret); | 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 | ndev->dev_status = AIE2_DEV_START; | 445 | ndev->dev_status = AIE2_DEV_START; |
| 441 | 446 | ||
| 442 | return 0; | 447 | return 0; |
| 443 | 448 | ||
| 444 | destroy_mgmt_chann: | 449 | stop_fw: |
| 450 | aie2_suspend_fw(ndev); | ||
| 445 | xdna_mailbox_stop_channel(ndev->mgmt_chann); | 451 | xdna_mailbox_stop_channel(ndev->mgmt_chann); |
| 446 | xdna_mailbox_destroy_channel(ndev->mgmt_chann); | ||
| 447 | stop_psp: | 452 | stop_psp: |
| 448 | aie2_psp_stop(ndev->psp_hdl); | 453 | aie2_psp_stop(ndev->psp_hdl); |
| 449 | fini_smu: | 454 | fini_smu: |
| 450 | aie2_smu_fini(ndev); | 455 | aie2_smu_fini(ndev); |
| 456 | free_channel: | ||
| 457 | xdna_mailbox_free_channel(ndev->mgmt_chann); | ||
| 458 | ndev->mgmt_chann = NULL; | ||
| 451 | disable_dev: | 459 | disable_dev: |
| 452 | pci_disable_device(pdev); | 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 | /* aie2_message.c */ | 332 | /* aie2_message.c */ |
| 333 | void aie2_msg_init(struct amdxdna_dev_hdl *ndev); | 333 | void aie2_msg_init(struct amdxdna_dev_hdl *ndev); |
| 334 | void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev); | ||
| 334 | int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev); | 335 | int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev); |
| 335 | int aie2_resume_fw(struct amdxdna_dev_hdl *ndev); | 336 | int aie2_resume_fw(struct amdxdna_dev_hdl *ndev); |
| 336 | int aie2_set_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 value); | 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 | return INVALID_CU_IDX; | 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 | * This should be called in close() and remove(). DO NOT call in other syscalls. | 166 | * This should be called in close() and remove(). DO NOT call in other syscalls. |
| 140 | * This guarantee that when hwctx and resources will be released, if user | 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 | void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size); | 168 | void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size); |
| 169 | u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo); | 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 | void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job); | 174 | void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job); |
| 172 | void amdxdna_hwctx_remove_all(struct amdxdna_client *client); | 175 | void amdxdna_hwctx_remove_all(struct amdxdna_client *client); |
| @@ -460,26 +460,49 @@ msg_id_failed: · 459 unmodified lines | |||
| 460 | return ret; | 460 | return ret; |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | struct mailbox_channel * | 463 | struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb) |
| 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) | ||
| 469 | { | 464 | { |
| 470 | struct mailbox_channel *mb_chann; | 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 | mb_chann = kzalloc_obj(*mb_chann); | 467 | mb_chann = kzalloc_obj(*mb_chann); |
| 479 | if (!mb_chann) | 468 | if (!mb_chann) |
| 480 | return NULL; | 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 | mb_chann->mb = mb; | 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 | mb_chann->msix_irq = mb_irq; | 506 | mb_chann->msix_irq = mb_irq; |
| 484 | mb_chann->iohub_int_addr = iohub_int_addr; | 507 | mb_chann->iohub_int_addr = iohub_int_addr; |
| 485 | memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i)); | 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 | mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I); | 512 | mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I); |
| 490 | mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X); | 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 | /* Everything look good. Time to enable irq handler */ | 515 | /* Everything look good. Time to enable irq handler */ |
| 500 | ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, mb_chann); | 516 | ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, mb_chann); |
| 501 | if (ret) { | 517 | if (ret) { |
| 502 | MB_ERR(mb_chann, "Failed to request irq %d ret %d", mb_irq, ret); | 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 | mb_chann->bad_state = false; | 522 | mb_chann->bad_state = false; |
| 507 | mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0); | 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); | 525 | MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", mb_chann->msix_irq); |
| 510 | return mb_chann; | 526 | return 0; |
| 511 | |||
| 512 | destroy_wq: | ||
| 513 | destroy_workqueue(mb_chann->work_q); | ||
| 514 | free_and_out: | ||
| 515 | kfree(mb_chann); | ||
| 516 | return NULL; | ||
| 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 | struct mailbox_msg *mb_msg; | 531 | struct mailbox_msg *mb_msg; |
| 522 | unsigned long msg_id; | 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 | free_irq(mb_chann->msix_irq, mb_chann); | 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 | xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg) | 541 | xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg) |
| 530 | mailbox_release_msg(mb_chann, mb_msg); | 542 | mailbox_release_msg(mb_chann, mb_msg); |
| 531 | |||
| 532 | xa_destroy(&mb_chann->chan_xa); | 543 | xa_destroy(&mb_chann->chan_xa); |
| 533 | 544 | ||
| 534 | MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", mb_chann->msix_irq); | 545 | MB_DBG(mb_chann, "Mailbox channel stopped, 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"); | ||
| 547 | } | 546 | } |
| 548 | 547 | ||
| 549 | struct mailbox *xdnam_mailbox_create(struct drm_device *ddev, | 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 | const struct xdna_mailbox_res *res); | 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 | * @x2i: host to firmware mailbox resources | 87 | * @x2i: host to firmware mailbox resources |
| 81 | * @i2x: firmware to host mailbox resources | 88 | * @i2x: firmware to host mailbox resources |
| 82 | * @xdna_mailbox_intr_reg: register addr of MSI-X interrupt | 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 | * Return: If success, return a handle of mailbox channel. Otherwise, return NULL. | 92 | * Return: If success, return a handle of mailbox channel. Otherwise, return NULL. |
| 86 | */ | 93 | */ |
| 87 | struct mailbox_channel * | 94 | int |
| 88 | xdna_mailbox_create_channel(struct mailbox *mailbox, | 95 | xdna_mailbox_start_channel(struct mailbox_channel *mb_chann, |
| 89 | const struct xdna_mailbox_chann_res *x2i, | 96 | const struct xdna_mailbox_chann_res *x2i, |
| 90 | const struct xdna_mailbox_chann_res *i2x, | 97 | const struct xdna_mailbox_chann_res *i2x, |
| 91 | u32 xdna_mailbox_intr_reg, | 98 | u32 xdna_mailbox_intr_reg, |
| 92 | int mb_irq); | 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 | * @mailbox_chann: the handle return from xdna_mailbox_create_channel() | 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 | * xdna_mailbox_stop_channel() -- stop mailbox channel | 109 | * xdna_mailbox_stop_channel() -- stop mailbox channel |
| 105 | * | 110 | * |
| 106 | * @mailbox_chann: the handle return from xdna_mailbox_create_channel() | 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 | void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann); | 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 | static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = { | 68 | static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = { |
| 69 | { .major = 5, .min_minor = 7 }, | 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 | { 0 } | 71 | { 0 } |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| @@ -245,11 +245,14 @@ static int calc_sizes(struct drm_device *ddev, · 244 unmodified lines | |||
| 245 | ((st->ifm.stride_kernel >> 1) & 0x1) + 1; | 245 | ((st->ifm.stride_kernel >> 1) & 0x1) + 1; |
| 246 | u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) + | 246 | u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) + |
| 247 | (st->ifm.stride_kernel & 0x1) + 1; | 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 | st->ifm.height[2] - (st->ifm.pad_top + st->ifm.pad_bottom); | 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 | st->ifm.width - (st->ifm.pad_left + st->ifm.pad_right); | 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 | len = feat_matrix_length(info, &st->ifm, ifm_width, | 256 | len = feat_matrix_length(info, &st->ifm, ifm_width, |
| 254 | ifm_height, st->ifm.depth); | 257 | ifm_height, st->ifm.depth); |
| 255 | dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n", | 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 | return ret; | 420 | return ret; |
| 418 | break; | 421 | break; |
| 419 | case NPU_OP_ELEMENTWISE: | 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 | (param == 6) || (param == 7) || (param == 0x24)); | 427 | (param == 6) || (param == 7) || (param == 0x24)); |
| 422 | use_ifm = st.ifm.broadcast != 8; | 428 | use_ifm = st.ifm.broadcast != 8; |
| 423 | ret = calc_sizes_elemwise(ddev, info, cmd, &st, use_ifm, use_ifm2); | 429 | ret = calc_sizes_elemwise(ddev, info, cmd, &st, use_ifm, use_ifm2); |
| @@ -143,23 +143,29 @@ out: · 142 unmodified lines | |||
| 143 | return ret; | 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 | static void ethosu_job_cleanup(struct kref *ref) | 158 | static void ethosu_job_cleanup(struct kref *ref) |
| 147 | { | 159 | { |
| 148 | struct ethosu_job *job = container_of(ref, struct ethosu_job, | 160 | struct ethosu_job *job = container_of(ref, struct ethosu_job, |
| 149 | refcount); | 161 | refcount); |
| 150 | unsigned int i; | ||
| 151 | 162 | ||
| 152 | pm_runtime_put_autosuspend(job->dev->base.dev); | 163 | pm_runtime_put_autosuspend(job->dev->base.dev); |
| 153 | 164 | ||
| 154 | dma_fence_put(job->done_fence); | 165 | dma_fence_put(job->done_fence); |
| 155 | dma_fence_put(job->inference_done_fence); | 166 | dma_fence_put(job->inference_done_fence); |
| 156 | 167 | ||
| 157 | for (i = 0; i < job->region_cnt; i++) | 168 | ethosu_job_err_cleanup(job); |
| 158 | drm_gem_object_put(job->region_bo[i]); | ||
| 159 | |||
| 160 | drm_gem_object_put(job->cmd_bo); | ||
| 161 | |||
| 162 | kfree(job); | ||
| 163 | } | 169 | } |
| 164 | 170 | ||
| 165 | static void ethosu_job_put(struct ethosu_job *job) | 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 | ret = ethosu_job_push(ejob); | 462 | ret = ethosu_job_push(ejob); |
| 463 | if (!ret) { | ||
| 464 | ethosu_job_put(ejob); | ||
| 465 | return 0; | ||
| 466 | } | ||
| 457 | 467 | ||
| 458 | out_cleanup_job: | 468 | out_cleanup_job: |
| 459 | if (ret) | 469 | if (ret) |
| 460 | drm_sched_job_cleanup(&ejob->base); | 470 | drm_sched_job_cleanup(&ejob->base); |
| 461 | out_put_job: | 471 | out_put_job: |
| 462 | ethosu_job_put(ejob); | 472 | ethosu_job_err_cleanup(ejob); |
| 463 | 473 | ||
| 464 | return ret; | 474 | return ret; |
| 465 | } | 475 | } |
| @@ -379,8 +379,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { · 378 unmodified lines | |||
| 379 | 379 | ||
| 380 | {{"_CPC", METHOD_0ARGS, | 380 | {{"_CPC", METHOD_0ARGS, |
| 381 | METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */ | 381 | METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */ |
| 382 | PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, | 382 | PACKAGE_INFO(ACPI_PTYPE1_VAR, |
| 383 | 0, 0, 0), | 383 | ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | |
| 384 | ACPI_RTYPE_PACKAGE, 0, 0, 0, 0), | ||
| 384 | 385 | ||
| 385 | {{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */ | 386 | {{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */ |
| 386 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, | 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 | if (!adev || !acpi_match_device_ids(adev, special_pm_ids)) | 1456 | if (!adev || !acpi_match_device_ids(adev, special_pm_ids)) |
| 1457 | return 0; | 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 | * Only attach the power domain to the first device if the | 1460 | * Only attach the power domain to the first device if the |
| 1470 | * companion is shared by multiple. This is to prevent doing power | 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 | ATA_QUIRK_FIRMWARE_WARN }, | 4189 | ATA_QUIRK_FIRMWARE_WARN }, |
| 4190 | 4190 | ||
| 4191 | /* Seagate disks with LPM issues */ | 4191 | /* Seagate disks with LPM issues */ |
| 4192 | { "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM }, | ||
| 4192 | { "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM }, | 4193 | { "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM }, |
| 4193 | 4194 | ||
| 4194 | /* drives which fail FPDMA_AA activation (some may freeze afterwards) | 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 | /* Devices that do not need bridging limits applied */ | 4232 | /* Devices that do not need bridging limits applied */ |
| 4232 | { "MTRON MSP-SATA*", NULL, ATA_QUIRK_BRIDGE_OK }, | 4233 | { "MTRON MSP-SATA*", NULL, ATA_QUIRK_BRIDGE_OK }, |
| 4233 | { "BUFFALO HD-QSU2/R5", NULL, ATA_QUIRK_BRIDGE_OK }, | 4234 | { "BUFFALO HD-QSU2/R5", NULL, ATA_QUIRK_BRIDGE_OK }, |
| 4235 | { "QEMU HARDDISK", "2.5+", ATA_QUIRK_BRIDGE_OK }, | ||
| 4234 | 4236 | ||
| 4235 | /* Devices which aren't very happy with higher link speeds */ | 4237 | /* Devices which aren't very happy with higher link speeds */ |
| 4236 | { "WD My Book", NULL, ATA_QUIRK_1_5_GBPS }, | 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 | break; | 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 | * This is a deferred command that timed out while | 652 | * This is a deferred command that timed out while |
| 653 | * waiting for the command queue to drain. Since the qc | 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 | WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE); | 660 | WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE); |
| 661 | ap->deferred_qc = NULL; | 661 | ap->deferred_qc = NULL; |
| 662 | cancel_work(&ap->deferred_qc_work); | ||
| 662 | set_host_byte(scmd, DID_TIME_OUT); | 663 | set_host_byte(scmd, DID_TIME_OUT); |
| 663 | scsi_eh_finish_cmd(scmd, &ap->eh_done_q); | 664 | scsi_eh_finish_cmd(scmd, &ap->eh_done_q); |
| 664 | } else if (i < ATA_MAX_QUEUE) { | 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 | scmd = qc->scsicmd; | 1700 | scmd = qc->scsicmd; |
| 1701 | ap->deferred_qc = NULL; | 1701 | ap->deferred_qc = NULL; |
| 1702 | cancel_work(&ap->deferred_qc_work); | ||
| 1702 | ata_qc_free(qc); | 1703 | ata_qc_free(qc); |
| 1703 | scmd->result = (DID_SOFT_ERROR << 16); | 1704 | scmd->result = (DID_SOFT_ERROR << 16); |
| 1704 | scsi_done(scmd); | 1705 | scsi_done(scmd); |
| @@ -179,19 +179,10 @@ void device_release_driver_internal(struct device *dev, const struct device_driv · 178 unmodified lines | |||
| 179 | void driver_detach(const struct device_driver *drv); | 179 | void driver_detach(const struct device_driver *drv); |
| 180 | void driver_deferred_probe_del(struct device *dev); | 180 | void driver_deferred_probe_del(struct device *dev); |
| 181 | void device_set_deferred_probe_reason(const struct device *dev, struct va_format *vaf); | 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 | static inline int driver_match_device(const struct device_driver *drv, | 182 | static inline int driver_match_device(const struct device_driver *drv, |
| 191 | struct device *dev) | 183 | struct device *dev) |
| 192 | { | 184 | { |
| 193 | guard(device)(dev); | 185 | return drv->bus->match ? drv->bus->match(dev, drv) : 1; |
| 194 | return driver_match_device_locked(drv, dev); | ||
| 195 | } | 186 | } |
| 196 | 187 | ||
| 197 | static inline void dev_sync_state(struct device *dev) | 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 | bool async_allowed; | 928 | bool async_allowed; |
| 929 | int ret; | 929 | int ret; |
| 930 | 930 | ||
| 931 | ret = driver_match_device_locked(drv, dev); | 931 | ret = driver_match_device(drv, dev); |
| 932 | if (ret == 0) { | 932 | if (ret == 0) { |
| 933 | /* no match */ | 933 | /* no match */ |
| 934 | return 0; | 934 | return 0; |
| @@ -52,9 +52,10 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data, · 51 unmodified lines | |||
| 52 | rng->priv = 0; | 52 | rng->priv = 0; |
| 53 | } else { | 53 | } else { |
| 54 | work_data = kmalloc_obj(*work_data, GFP_ATOMIC); | 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 | return -ENOMEM; | 57 | return -ENOMEM; |
| 57 | 58 | } | |
| 58 | work_data->ctx = i2c_priv; | 59 | work_data->ctx = i2c_priv; |
| 59 | work_data->client = i2c_priv->client; | 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 | return; | 378 | return; |
| 379 | 379 | ||
| 380 | error_exit: | 380 | error_exit: |
| 381 | kfree(t); | ||
| 382 | pr_err("Failed to enable SEV-TIO: ret=%d en=%d initdone=%d SEV=%d\n", | 381 | pr_err("Failed to enable SEV-TIO: ret=%d en=%d initdone=%d SEV=%d\n", |
| 383 | ret, t->tio_en, t->tio_init_done, boot_cpu_has(X86_FEATURE_SEV)); | 382 | ret, t->tio_en, t->tio_init_done, boot_cpu_has(X86_FEATURE_SEV)); |
| 383 | kfree(t); | ||
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | void sev_tsm_uninit(struct sev_device *sev) | 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 | struct psp_device *psp_master = psp_get_master_device(); | 1106 | struct psp_device *psp_master = psp_get_master_device(); |
| 1107 | struct snp_hv_fixed_pages_entry *entry; | 1107 | struct snp_hv_fixed_pages_entry *entry; |
| 1108 | struct sev_device *sev; | ||
| 1109 | unsigned int order; | 1108 | unsigned int order; |
| 1110 | struct page *page; | 1109 | struct page *page; |
| 1111 | 1110 | ||
| 1112 | if (!psp_master || !psp_master->sev_data) | 1111 | if (!psp_master) |
| 1113 | return NULL; | 1112 | return NULL; |
| 1114 | 1113 | ||
| 1115 | sev = psp_master->sev_data; | ||
| 1116 | |||
| 1117 | order = get_order(PMD_SIZE * num_2mb_pages); | 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 | * This API uses SNP_INIT_EX to transition allocated pages to HV_Fixed | 1123 | * This API uses SNP_INIT_EX to transition allocated pages to HV_Fixed |
| 1127 | * page state, fail if SNP is already initialized. | 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 | return NULL; | 1128 | return NULL; |
| 1131 | 1129 | ||
| 1132 | /* Re-use freed pages that match the request */ | 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 | struct psp_device *psp_master = psp_get_master_device(); | 1160 | struct psp_device *psp_master = psp_get_master_device(); |
| 1163 | struct snp_hv_fixed_pages_entry *entry, *nentry; | 1161 | struct snp_hv_fixed_pages_entry *entry, *nentry; |
| 1164 | 1162 | ||
| 1165 | if (!psp_master || !psp_master->sev_data) | 1163 | if (!psp_master) |
| 1166 | return; | 1164 | return; |
| 1167 | 1165 | ||
| 1168 | /* | 1166 | /* |
| @@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj; · 84 unmodified lines | |||
| 85 | * as an alternative to ordinary EFI variables, due to platform-dependent | 85 | * as an alternative to ordinary EFI variables, due to platform-dependent |
| 86 | * limitations. The memory occupied by this table is marked as reserved. | 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 | * to guarantee that it can mark the table as reserved. | 89 | * to guarantee that it can mark the table as reserved. |
| 90 | * | 90 | * |
| 91 | * Implicit inputs: | 91 | * Implicit inputs: |
| @@ -47,7 +47,7 @@ subdir-ccflags-$(CONFIG_DRM_AMDGPU_WERROR) += -Werror · 46 unmodified lines | |||
| 47 | amdgpu-y := amdgpu_drv.o | 47 | amdgpu-y := amdgpu_drv.o |
| 48 | 48 | ||
| 49 | # add KMS driver | 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 | amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ | 51 | amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ |
| 52 | atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ | 52 | atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ |
| 53 | amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ | 53 | amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ |
| @@ -81,6 +81,7 @@ · 80 unmodified lines | |||
| 81 | #include "amdgpu_sdma.h" | 81 | #include "amdgpu_sdma.h" |
| 82 | #include "amdgpu_lsdma.h" | 82 | #include "amdgpu_lsdma.h" |
| 83 | #include "amdgpu_nbio.h" | 83 | #include "amdgpu_nbio.h" |
| 84 | #include "amdgpu_reg_access.h" | ||
| 84 | #include "amdgpu_hdp.h" | 85 | #include "amdgpu_hdp.h" |
| 85 | #include "amdgpu_dm.h" | 86 | #include "amdgpu_dm.h" |
| 86 | #include "amdgpu_virt.h" | 87 | #include "amdgpu_virt.h" |
| @@ -217,9 +218,7 @@ extern struct amdgpu_watchdog_timer amdgpu_watchdog_timer; · 130 unmodified lines | |||
| 217 | extern int amdgpu_async_gfx_ring; | 218 | extern int amdgpu_async_gfx_ring; |
| 218 | extern int amdgpu_mcbp; | 219 | extern int amdgpu_mcbp; |
| 219 | extern int amdgpu_discovery; | 220 | extern int amdgpu_discovery; |
| 220 | extern int amdgpu_mes; | ||
| 221 | extern int amdgpu_mes_log_enable; | 221 | extern int amdgpu_mes_log_enable; |
| 222 | extern int amdgpu_mes_kiq; | ||
| 223 | extern int amdgpu_uni_mes; | 222 | extern int amdgpu_uni_mes; |
| 224 | extern int amdgpu_noretry; | 223 | extern int amdgpu_noretry; |
| 225 | extern int amdgpu_force_asic_type; | 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 | * Core structure, functions and helpers. | 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 | struct amdgpu_mmio_remap { | 682 | struct amdgpu_mmio_remap { |
| 699 | u32 reg_offset; | 683 | u32 reg_offset; |
| 700 | resource_size_t bus_addr; | 684 | resource_size_t bus_addr; |
| @@ -791,6 +775,12 @@ struct amd_powerplay { · 90 unmodified lines | |||
| 791 | (rid == 0x01) || \ | 775 | (rid == 0x01) || \ |
| 792 | (rid == 0x10)))) | 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 | struct amdgpu_mqd_prop { | 784 | struct amdgpu_mqd_prop { |
| 795 | uint64_t mqd_gpu_addr; | 785 | uint64_t mqd_gpu_addr; |
| 796 | uint64_t hqd_base_gpu_addr; | 786 | uint64_t hqd_base_gpu_addr; |
| @@ -811,6 +801,10 @@ struct amdgpu_mqd_prop { · 14 unmodified lines | |||
| 811 | uint64_t fence_address; | 801 | uint64_t fence_address; |
| 812 | bool tmz_queue; | 802 | bool tmz_queue; |
| 813 | bool kernel_queue; | 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 | struct amdgpu_mqd { | 810 | struct amdgpu_mqd { |
| @@ -906,42 +900,8 @@ struct amdgpu_device { · 89 unmodified lines | |||
| 906 | /* protects concurrent MM_INDEX/DATA based register access */ | 900 | /* protects concurrent MM_INDEX/DATA based register access */ |
| 907 | spinlock_t mmio_idx_lock; | 901 | spinlock_t mmio_idx_lock; |
| 908 | struct amdgpu_mmio_remap rmmio_remap; | 902 | struct amdgpu_mmio_remap rmmio_remap; |
| 909 | /* protects concurrent SMC based register access */ | 903 | /* Indirect register access blocks */ |
| 910 | spinlock_t smc_idx_lock; | 904 | struct amdgpu_reg_access reg; |
| 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; | ||
| 945 | struct amdgpu_doorbell doorbell; | 905 | struct amdgpu_doorbell doorbell; |
| 946 | 906 | ||
| 947 | /* clock/pll info */ | 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 | void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, | 1258 | void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, |
| 1299 | void *buf, size_t size, bool write); | 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 | u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev); | 1260 | u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev); |
| 1337 | bool amdgpu_device_asic_has_dc_support(struct pci_dev *pdev, | 1261 | bool amdgpu_device_asic_has_dc_support(struct pci_dev *pdev, |
| 1338 | enum amd_asic_type asic_type); | 1262 | enum amd_asic_type asic_type); |
| @@ -1372,28 +1296,30 @@ int emu_soc_asic_init(struct amdgpu_device *adev); · 33 unmodified lines | |||
| 1372 | #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) | 1296 | #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) |
| 1373 | #define RREG32_XCC(reg, inst) amdgpu_device_xcc_rreg(adev, (reg), 0, inst) | 1297 | #define RREG32_XCC(reg, inst) amdgpu_device_xcc_rreg(adev, (reg), 0, inst) |
| 1374 | #define WREG32_XCC(reg, v, inst) amdgpu_device_xcc_wreg(adev, (reg), (v), 0, inst) | 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)) | 1299 | #define RREG32_PCIE(reg) amdgpu_reg_pcie_rd32(adev, (reg)) |
| 1376 | #define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v)) | 1300 | #define WREG32_PCIE(reg, v) amdgpu_reg_pcie_wr32(adev, (reg), (v)) |
| 1377 | #define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg)) | 1301 | #define RREG32_PCIE_PORT(reg) amdgpu_reg_pciep_rd32(adev, (reg)) |
| 1378 | #define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v)) | 1302 | #define WREG32_PCIE_PORT(reg, v) amdgpu_reg_pciep_wr32(adev, (reg), (v)) |
| 1379 | #define RREG32_PCIE_EXT(reg) adev->pcie_rreg_ext(adev, (reg)) | 1303 | #define RREG32_PCIE_EXT(reg) amdgpu_reg_pcie_ext_rd32(adev, (reg)) |
| 1380 | #define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v)) | 1304 | #define WREG32_PCIE_EXT(reg, v) amdgpu_reg_pcie_ext_wr32(adev, (reg), (v)) |
| 1381 | #define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg)) | 1305 | #define RREG64_PCIE(reg) amdgpu_reg_pcie_rd64(adev, (reg)) |
| 1382 | #define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v)) | 1306 | #define WREG64_PCIE(reg, v) amdgpu_reg_pcie_wr64(adev, (reg), (v)) |
| 1383 | #define RREG64_PCIE_EXT(reg) adev->pcie_rreg64_ext(adev, (reg)) | 1307 | #define RREG64_PCIE_EXT(reg) amdgpu_reg_pcie_ext_rd64(adev, (reg)) |
| 1384 | #define WREG64_PCIE_EXT(reg, v) adev->pcie_wreg64_ext(adev, (reg), (v)) | 1308 | #define WREG64_PCIE_EXT(reg, v) amdgpu_reg_pcie_ext_wr64(adev, (reg), (v)) |
| 1385 | #define RREG32_SMC(reg) adev->smc_rreg(adev, (reg)) | 1309 | #define RREG32_SMC(reg) amdgpu_reg_smc_rd32(adev, (reg)) |
| 1386 | #define WREG32_SMC(reg, v) adev->smc_wreg(adev, (reg), (v)) | 1310 | #define WREG32_SMC(reg, v) amdgpu_reg_smc_wr32(adev, (reg), (v)) |
| 1387 | #define RREG32_UVD_CTX(reg) adev->uvd_ctx_rreg(adev, (reg)) | 1311 | #define RREG32_UVD_CTX(reg) amdgpu_reg_uvd_ctx_rd32(adev, (reg)) |
| 1388 | #define WREG32_UVD_CTX(reg, v) adev->uvd_ctx_wreg(adev, (reg), (v)) | 1312 | #define WREG32_UVD_CTX(reg, v) amdgpu_reg_uvd_ctx_wr32(adev, (reg), (v)) |
| 1389 | #define RREG32_DIDT(reg) adev->didt_rreg(adev, (reg)) | 1313 | #define RREG32_DIDT(reg) amdgpu_reg_didt_rd32(adev, (reg)) |
| 1390 | #define WREG32_DIDT(reg, v) adev->didt_wreg(adev, (reg), (v)) | 1314 | #define WREG32_DIDT(reg, v) amdgpu_reg_didt_wr32(adev, (reg), (v)) |
| 1391 | #define RREG32_GC_CAC(reg) adev->gc_cac_rreg(adev, (reg)) | 1315 | #define RREG32_GC_CAC(reg) amdgpu_reg_gc_cac_rd32(adev, (reg)) |
| 1392 | #define WREG32_GC_CAC(reg, v) adev->gc_cac_wreg(adev, (reg), (v)) | 1316 | #define WREG32_GC_CAC(reg, v) amdgpu_reg_gc_cac_wr32(adev, (reg), (v)) |
| 1393 | #define RREG32_SE_CAC(reg) adev->se_cac_rreg(adev, (reg)) | 1317 | #define RREG32_SE_CAC(reg) amdgpu_reg_se_cac_rd32(adev, (reg)) |
| 1394 | #define WREG32_SE_CAC(reg, v) adev->se_cac_wreg(adev, (reg), (v)) | 1318 | #define WREG32_SE_CAC(reg, v) amdgpu_reg_se_cac_wr32(adev, (reg), (v)) |
| 1395 | #define RREG32_AUDIO_ENDPT(block, reg) adev->audio_endpt_rreg(adev, (block), (reg)) | 1319 | #define RREG32_AUDIO_ENDPT(block, reg) \ |
| 1396 | #define WREG32_AUDIO_ENDPT(block, reg, v) adev->audio_endpt_wreg(adev, (block), (reg), (v)) | 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 | #define WREG32_P(reg, val, mask) \ | 1323 | #define WREG32_P(reg, val, mask) \ |
| 1398 | do { \ | 1324 | do { \ |
| 1399 | uint32_t tmp_ = RREG32(reg); \ | 1325 | uint32_t tmp_ = RREG32(reg); \ |
| @@ -1523,10 +1449,6 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev, · 123 unmodified lines | |||
| 1523 | struct amdgpu_ring *ring); | 1449 | struct amdgpu_ring *ring); |
| 1524 | 1450 | ||
| 1525 | void amdgpu_device_halt(struct amdgpu_device *adev); | 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 | struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev); | 1452 | struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev); |
| 1531 | struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, | 1453 | struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, |
| 1532 | struct dma_fence *gang); | 1454 | struct dma_fence *gang); |
| @@ -1536,6 +1458,8 @@ struct dma_fence *amdgpu_device_enforce_isolation(struct amdgpu_device *adev, · 3 unmodified lines | |||
| 1536 | bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev); | 1458 | bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev); |
| 1537 | ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring); | 1459 | ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring); |
| 1538 | ssize_t amdgpu_show_reset_mask(char *buf, uint32_t supported_reset); | 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 | /* atpx handler */ | 1464 | /* atpx handler */ |
| 1541 | #if defined(CONFIG_VGA_SWITCHEROO) | 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 | *process_info = info; | 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 | /* Validate page directory and attach eviction fence */ | 1447 | /* Validate page directory and attach eviction fence */ |
| 1445 | ret = amdgpu_bo_reserve(vm->root.bo, true); | 1448 | ret = amdgpu_bo_reserve(vm->root.bo, true); |
| @@ -1479,6 +1482,7 @@ validate_pd_fail: · 33 unmodified lines | |||
| 1479 | amdgpu_bo_unreserve(vm->root.bo); | 1482 | amdgpu_bo_unreserve(vm->root.bo); |
| 1480 | reserve_pd_fail: | 1483 | reserve_pd_fail: |
| 1481 | vm->process_info = NULL; | 1484 | vm->process_info = NULL; |
| 1485 | already_acquired: | ||
| 1482 | if (info) { | 1486 | if (info) { |
| 1483 | dma_fence_put(&info->eviction_fence->base); | 1487 | dma_fence_put(&info->eviction_fence->base); |
| 1484 | *process_info = NULL; | 1488 | *process_info = NULL; |
| @@ -35,6 +35,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, · 34 unmodified lines | |||
| 35 | struct dma_fence *fence; | 35 | struct dma_fence *fence; |
| 36 | int i, r; | 36 | int i, r; |
| 37 | 37 | ||
| 38 | mutex_lock(&adev->mman.default_entity.lock); | ||
| 38 | stime = ktime_get(); | 39 | stime = ktime_get(); |
| 39 | for (i = 0; i < n; i++) { | 40 | for (i = 0; i < n; i++) { |
| 40 | r = amdgpu_copy_buffer(adev, &adev->mman.default_entity, | 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 | exit_do_move: | 52 | exit_do_move: |
| 53 | mutex_unlock(&adev->mman.default_entity.lock); | ||
| 52 | etime = ktime_get(); | 54 | etime = ktime_get(); |
| 53 | *time_ms = ktime_ms_delta(etime, stime); | 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 | if (r) | 84 | if (r) |
| 85 | return r; | 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 | /* Check if we can add this IB to some existing job */ | 87 | /* Check if we can add this IB to some existing job */ |
| 95 | for (i = 0; i < p->gang_size; ++i) | 88 | for (i = 0; i < p->gang_size; ++i) |
| 96 | if (p->entities[i] == entity) | 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 | } else { | 231 | } else { |
| 232 | struct amdgpu_fpriv *fpriv; | 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 | r = amdgpu_xcp_select_scheds(adev, hw_ip, hw_prio, fpriv, | 236 | r = amdgpu_xcp_select_scheds(adev, hw_ip, hw_prio, fpriv, |
| 236 | &num_scheds, &scheds); | 237 | &num_scheds, &scheds); |
| 237 | if (r) | 238 | if (r) |
| 238 | goto error_free_entity; | 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 | /* disable load balance if the hw engine retains context among dependent jobs */ | 247 | /* disable load balance if the hw engine retains context among dependent jobs */ |
| 242 | if (hw_ip == AMDGPU_HW_IP_VCN_ENC || | 248 | if (hw_ip == AMDGPU_HW_IP_VCN_ENC || |
| 243 | hw_ip == AMDGPU_HW_IP_VCN_DEC || | 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 | else | 354 | else |
| 349 | ctx->stable_pstate = current_stable_pstate; | 355 | ctx->stable_pstate = current_stable_pstate; |
| 350 | 356 | ||
| 351 | ctx->ctx_mgr = &(fpriv->ctx_mgr); | ||
| 352 | return 0; | 357 | return 0; |
| 353 | } | 358 | } |
| 354 | 359 | ||
| @@ -44,20 +44,19 @@ struct amdgpu_ctx_entity { · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | struct amdgpu_ctx { | 45 | struct amdgpu_ctx { |
| 46 | struct kref refcount; | 46 | struct kref refcount; |
| 47 | struct amdgpu_ctx_mgr *mgr; | 47 | spinlock_t ring_lock; |
| 48 | unsigned reset_counter; | 48 | unsigned reset_counter; |
| 49 | unsigned reset_counter_query; | 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 | int32_t init_priority; | 50 | int32_t init_priority; |
| 55 | int32_t override_priority; | 51 | int32_t override_priority; |
| 52 | uint32_t stable_pstate; | ||
| 56 | atomic_t guilty; | 53 | atomic_t guilty; |
| 54 | bool preamble_presented; | ||
| 55 | uint64_t generation; | ||
| 57 | unsigned long ras_counter_ce; | 56 | unsigned long ras_counter_ce; |
| 58 | unsigned long ras_counter_ue; | 57 | unsigned long ras_counter_ue; |
| 59 | uint32_t stable_pstate; | 58 | struct amdgpu_ctx_mgr *mgr; |
| 60 | struct amdgpu_ctx_mgr *ctx_mgr; | 59 | struct amdgpu_ctx_entity *entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM]; |
| 61 | }; | 60 | }; |
| 62 | 61 | ||
| 63 | struct amdgpu_ctx_mgr { | 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 | if (size & 0x3 || *pos & 0x3) | 638 | if (size & 0x3 || *pos & 0x3) |
| 639 | return -EINVAL; | 639 | return -EINVAL; |
| 640 | 640 | ||
| 641 | if (!adev->didt_rreg) | 641 | if (!adev->reg.didt.rreg) |
| 642 | return -EOPNOTSUPP; | 642 | return -EOPNOTSUPP; |
| 643 | 643 | ||
| 644 | r = pm_runtime_get_sync(adev_to_drm(adev)->dev); | 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 | if (size & 0x3 || *pos & 0x3) | 696 | if (size & 0x3 || *pos & 0x3) |
| 697 | return -EINVAL; | 697 | return -EINVAL; |
| 698 | 698 | ||
| 699 | if (!adev->didt_wreg) | 699 | if (!adev->reg.didt.wreg) |
| 700 | return -EOPNOTSUPP; | 700 | return -EOPNOTSUPP; |
| 701 | 701 | ||
| 702 | r = pm_runtime_get_sync(adev_to_drm(adev)->dev); | 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 | ssize_t result = 0; | 752 | ssize_t result = 0; |
| 753 | int r; | 753 | int r; |
| 754 | 754 | ||
| 755 | if (!adev->smc_rreg) | 755 | if (!adev->reg.smc.rreg) |
| 756 | return -EOPNOTSUPP; | 756 | return -EOPNOTSUPP; |
| 757 | 757 | ||
| 758 | if (size & 0x3 || *pos & 0x3) | 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 | ssize_t result = 0; | 810 | ssize_t result = 0; |
| 811 | int r; | 811 | int r; |
| 812 | 812 | ||
| 813 | if (!adev->smc_wreg) | 813 | if (!adev->reg.smc.wreg) |
| 814 | return -EOPNOTSUPP; | 814 | return -EOPNOTSUPP; |
| 815 | 815 | ||
| 816 | if (size & 0x3 || *pos & 0x3) | 816 | if (size & 0x3 || *pos & 0x3) |
| @@ -846,558 +846,6 @@ bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev) · 845 unmodified lines | |||
| 846 | return false; | 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 | * amdgpu_device_get_rev_id - query device rev_id | 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 | return adev->nbio.funcs->get_rev_id(adev); | 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 | static uint32_t amdgpu_device_get_vbios_flags(struct amdgpu_device *adev) | 861 | static uint32_t amdgpu_device_get_vbios_flags(struct amdgpu_device *adev) |
| 1557 | { | 862 | { |
| 1558 | if (hweight32(adev->aid_mask) && (adev->flags & AMD_IS_APU)) | 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 | if (r) | 2461 | if (r) |
| 3157 | goto init_failed; | 2462 | goto init_failed; |
| 3158 | 2463 | ||
| 3159 | if (adev->mman.buffer_funcs_ring && | 2464 | amdgpu_ttm_set_buffer_funcs_status(adev, true); |
| 3160 | adev->mman.buffer_funcs_ring->sched.ready) | ||
| 3161 | amdgpu_ttm_set_buffer_funcs_status(adev, true); | ||
| 3162 | 2465 | ||
| 3163 | /* Don't init kfd if whole hive need to be reset during init */ | 2466 | /* Don't init kfd if whole hive need to be reset during init */ |
| 3164 | if (adev->init_lvl->level != AMDGPU_INIT_LEVEL_MINIMAL_XGMI) { | 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 | r = amdgpu_device_ip_resume_phase2(adev); | 3351 | r = amdgpu_device_ip_resume_phase2(adev); |
| 4049 | 3352 | ||
| 4050 | if (adev->mman.buffer_funcs_ring->sched.ready) | 3353 | amdgpu_ttm_set_buffer_funcs_status(adev, true); |
| 4051 | amdgpu_ttm_set_buffer_funcs_status(adev, true); | ||
| 4052 | 3354 | ||
| 4053 | if (r) | 3355 | if (r) |
| 4054 | return r; | 3356 | return r; |
| @@ -4108,17 +3410,6 @@ bool amdgpu_device_asic_has_dc_support(struct pci_dev *pdev, · 53 unmodified lines | |||
| 4108 | case CHIP_VERDE: | 3410 | case CHIP_VERDE: |
| 4109 | case CHIP_OLAND: | 3411 | case CHIP_OLAND: |
| 4110 | return amdgpu_dc != 0 && IS_ENABLED(CONFIG_DRM_AMD_DC_SI); | 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 | default: | 3413 | default: |
| 4123 | return amdgpu_dc != 0; | 3414 | return amdgpu_dc != 0; |
| 4124 | #else | 3415 | #else |
| @@ -4396,26 +3687,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 271 unmodified lines | |||
| 4396 | adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS); | 3687 | adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS); |
| 4397 | bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); | 3688 | bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); |
| 4398 | 3689 | ||
| 4399 | adev->smc_rreg = &amdgpu_invalid_rreg; | 3690 | amdgpu_reg_access_init(adev); |
| 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; | ||
| 4419 | 3691 | ||
| 4420 | dev_info( | 3692 | dev_info( |
| 4421 | adev->dev, | 3693 | adev->dev, |
| @@ -4460,13 +3732,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 38 unmodified lines | |||
| 4460 | return r; | 3732 | return r; |
| 4461 | 3733 | ||
| 4462 | spin_lock_init(&adev->mmio_idx_lock); | 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 | spin_lock_init(&adev->mm_stats.lock); | 3735 | spin_lock_init(&adev->mm_stats.lock); |
| 4471 | spin_lock_init(&adev->virt.rlcg_reg_lock); | 3736 | spin_lock_init(&adev->virt.rlcg_reg_lock); |
| 4472 | spin_lock_init(&adev->wb.lock); | 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 | return 0; | 4460 | return 0; |
| 5196 | 4461 | ||
| 5197 | unwind_evict: | 4462 | unwind_evict: |
| 5198 | if (adev->mman.buffer_funcs_ring->sched.ready) | 4463 | amdgpu_ttm_set_buffer_funcs_status(adev, true); |
| 5199 | amdgpu_ttm_set_buffer_funcs_status(adev, true); | ||
| 5200 | amdgpu_fence_driver_hw_init(adev); | 4464 | amdgpu_fence_driver_hw_init(adev); |
| 5201 | 4465 | ||
| 5202 | unwind_userq: | 4466 | unwind_userq: |
| @@ -5930,8 +5194,7 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context) · 727 unmodified lines | |||
| 5930 | if (r) | 5194 | if (r) |
| 5931 | goto out; | 5195 | goto out; |
| 5932 | 5196 | ||
| 5933 | if (tmp_adev->mman.buffer_funcs_ring->sched.ready) | 5197 | amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true); |
| 5934 | amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true); | ||
| 5935 | 5198 | ||
| 5936 | r = amdgpu_device_ip_resume_phase3(tmp_adev); | 5199 | r = amdgpu_device_ip_resume_phase3(tmp_adev); |
| 5937 | if (r) | 5200 | if (r) |
| @@ -6309,7 +5572,7 @@ static void amdgpu_device_halt_activities(struct amdgpu_device *adev, · 371 unmodified lines | |||
| 6309 | if (!amdgpu_ring_sched_ready(ring)) | 5572 | if (!amdgpu_ring_sched_ready(ring)) |
| 6310 | continue; | 5573 | continue; |
| 6311 | 5574 | ||
| 6312 | drm_sched_stop(&ring->sched, job ? &job->base : NULL); | 5575 | drm_sched_wqueue_stop(&ring->sched); |
| 6313 | 5576 | ||
| 6314 | if (need_emergency_restart) | 5577 | if (need_emergency_restart) |
| 6315 | amdgpu_job_stop_all_jobs_on_sched(&ring->sched); | 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 | if (!amdgpu_ring_sched_ready(ring)) | 5656 | if (!amdgpu_ring_sched_ready(ring)) |
| 6394 | continue; | 5657 | continue; |
| 6395 | 5658 | ||
| 6396 | drm_sched_start(&ring->sched, 0); | 5659 | drm_sched_wqueue_start(&ring->sched); |
| 6397 | } | 5660 | } |
| 6398 | 5661 | ||
| 6399 | if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) | 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 | pci_wait_for_pending_transaction(pdev); | 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 | * amdgpu_device_get_gang - return a reference to the current gang | 6643 | * amdgpu_device_get_gang - return a reference to the current gang |
| 7414 | * @adev: amdgpu_device pointer | 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 | ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring) | 6824 | ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring) |
| 7625 | { | 6825 | { |
| 7626 | ssize_t size = 0; | 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 | case IP_VERSION(3, 5, 1): | 2298 | case IP_VERSION(3, 5, 1): |
| 2299 | case IP_VERSION(3, 6, 0): | 2299 | case IP_VERSION(3, 6, 0): |
| 2300 | case IP_VERSION(4, 1, 0): | 2300 | case IP_VERSION(4, 1, 0): |
| 2301 | case IP_VERSION(4, 2, 0): | ||
| 2301 | /* TODO: Fix IP version. DC code expects version 4.0.1 */ | 2302 | /* TODO: Fix IP version. DC code expects version 4.0.1 */ |
| 2302 | if (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(4, 1, 0)) | 2303 | if (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(4, 1, 0)) |
| 2303 | adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 0, 1); | 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 | int amdgpu_async_gfx_ring = 1; | 223 | int amdgpu_async_gfx_ring = 1; |
| 224 | int amdgpu_mcbp = -1; | 224 | int amdgpu_mcbp = -1; |
| 225 | int amdgpu_discovery = -1; | 225 | int amdgpu_discovery = -1; |
| 226 | int amdgpu_mes; | ||
| 227 | int amdgpu_mes_log_enable = 0; | 226 | int amdgpu_mes_log_enable = 0; |
| 228 | int amdgpu_mes_kiq; | ||
| 229 | int amdgpu_uni_mes = 1; | 227 | int amdgpu_uni_mes = 1; |
| 230 | int amdgpu_noretry = -1; | 228 | int amdgpu_noretry = -1; |
| 231 | int amdgpu_force_asic_type = -1; | 229 | int amdgpu_force_asic_type = -1; |
| @@ -690,15 +688,6 @@ MODULE_PARM_DESC(discovery, · 458 unmodified lines | |||
| 690 | "Allow driver to discover hardware IPs from IP Discovery table at the top of VRAM"); | 688 | "Allow driver to discover hardware IPs from IP Discovery table at the top of VRAM"); |
| 691 | module_param_named(discovery, amdgpu_discovery, int, 0444); | 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 | * DOC: mes_log_enable (int) | 692 | * DOC: mes_log_enable (int) |
| 704 | * Enable Micro Engine Scheduler log. This is used to enable/disable MES internal log. | 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 | "Enable Micro Engine Scheduler log (0 = disabled (default), 1 = enabled)"); | 697 | "Enable Micro Engine Scheduler log (0 = disabled (default), 1 = enabled)"); |
| 709 | module_param_named(mes_log_enable, amdgpu_mes_log_enable, int, 0444); | 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 | * DOC: uni_mes (int) | 701 | * DOC: uni_mes (int) |
| 722 | * Enable Unified Micro Engine Scheduler. This is a new engine pipe for unified scheduler. | 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 | return seq; | 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 | * amdgpu_fence_emit - emit a fence on the requested ring | 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 | * @flags: flags to pass into the subordinate .emit_fence() call | 97 | * @flags: flags to pass into the subordinate .emit_fence() call |
| 108 | * | 98 | * |
| 109 | * Emits a fence command on the requested ring (all asics). | 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, | 101 | void amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, |
| 113 | unsigned int flags) | 102 | unsigned int flags) |
| 114 | { | 103 | { |
| 115 | struct amdgpu_device *adev = ring->adev; | 104 | struct amdgpu_device *adev = ring->adev; |
| 116 | struct dma_fence *fence; | 105 | struct dma_fence *fence; |
| 117 | struct dma_fence __rcu **ptr; | 106 | struct dma_fence __rcu **ptr; |
| 118 | uint32_t seq; | 107 | uint32_t seq; |
| 119 | int r; | ||
| 120 | 108 | ||
| 121 | fence = &af->base; | 109 | fence = &af->base; |
| 122 | af->ring = ring; | 110 | af->ring = ring; |
| @@ -126,11 +114,9 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, · 3 unmodified lines | |||
| 126 | &ring->fence_drv.lock, | 114 | &ring->fence_drv.lock, |
| 127 | adev->fence_context + ring->idx, seq); | 115 | adev->fence_context + ring->idx, seq); |
| 128 | 116 | ||
| 129 | amdgpu_fence_save_fence_wptr_start(af); | ||
| 130 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, | 117 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, |
| 131 | seq, flags | AMDGPU_FENCE_FLAG_INT); | 118 | seq, flags | AMDGPU_FENCE_FLAG_INT); |
| 132 | amdgpu_fence_save_fence_wptr_end(af); | 119 | |
| 133 | amdgpu_fence_save_wptr(af); | ||
| 134 | pm_runtime_get_noresume(adev_to_drm(adev)->dev); | 120 | pm_runtime_get_noresume(adev_to_drm(adev)->dev); |
| 135 | ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; | 121 | ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; |
| 136 | if (unlikely(rcu_dereference_protected(*ptr, 1))) { | 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 | rcu_read_unlock(); | 127 | rcu_read_unlock(); |
| 142 | 128 | ||
| 143 | if (old) { | 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 | dma_fence_put(old); | 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 | * emitting the fence would mess up the hardware ring buffer. | 143 | * emitting the fence would mess up the hardware ring buffer. |
| 155 | */ | 144 | */ |
| 156 | rcu_assign_pointer(*ptr, dma_fence_get(fence)); | 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 | do { | 229 | do { |
| 243 | struct dma_fence *fence, **ptr; | 230 | struct dma_fence *fence, **ptr; |
| 244 | struct amdgpu_fence *am_fence; | ||
| 245 | 231 | ||
| 246 | ++last_seq; | 232 | ++last_seq; |
| 247 | last_seq &= drv->num_fences_mask; | 233 | last_seq &= drv->num_fences_mask; |
| @@ -254,12 +240,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) · 6 unmodified lines | |||
| 254 | if (!fence) | 240 | if (!fence) |
| 255 | continue; | 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 | dma_fence_signal(fence); | 243 | dma_fence_signal(fence); |
| 264 | dma_fence_put(fence); | 244 | dma_fence_put(fence); |
| 265 | pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); | 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 | struct dma_fence *unprocessed; | 700 | struct dma_fence *unprocessed; |
| 719 | struct dma_fence __rcu **ptr; | 701 | struct dma_fence __rcu **ptr; |
| 720 | struct amdgpu_fence *fence; | 702 | struct amdgpu_fence *fence; |
| 721 | struct amdgpu_ring *ring = af->ring; | ||
| 722 | unsigned long flags; | 703 | unsigned long flags; |
| 723 | u32 seq, last_seq; | 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 | last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; | 709 | last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; |
| 727 | seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask; | 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 | spin_lock_irqsave(&ring->fence_drv.lock, flags); | 714 | spin_lock_irqsave(&ring->fence_drv.lock, flags); |
| 731 | do { | 715 | do { |
| 732 | last_seq++; | 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 | if (unprocessed && !dma_fence_is_signaled_locked(unprocessed)) { | 723 | if (unprocessed && !dma_fence_is_signaled_locked(unprocessed)) { |
| 740 | fence = container_of(unprocessed, struct amdgpu_fence, base); | 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) | 728 | /* mark all fences from the guilty context with an error */ |
| 743 | reemitted = true; | 729 | if (is_guilty_fence) |
| 744 | else if (fence == af) | ||
| 745 | dma_fence_set_error(&fence->base, -ETIME); | 730 | dma_fence_set_error(&fence->base, -ETIME); |
| 746 | else if (fence->context == af->context) | 731 | else if (is_guilty_context) |
| 747 | dma_fence_set_error(&fence->base, -ECANCELED); | 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 | rcu_read_unlock(); | 747 | rcu_read_unlock(); |
| 750 | } while (last_seq != seq); | 748 | } while (last_seq != seq); |
| 751 | spin_unlock_irqrestore(&ring->fence_drv.lock, flags); | 749 | spin_unlock_irqrestore(&ring->fence_drv.lock, flags); |
| 752 | 750 | amdgpu_ring_commit(ring); | |
| 753 | if (reemitted) { | 751 | ring->reemit = false; |
| 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; | ||
| 763 | } | 752 | } |
| 764 | 753 | ||
| 765 | static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring, | 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; | 757 | unsigned int first_idx = af->ib_wptr & ring->buf_mask; |
| 769 | unsigned int last_idx = end_wptr & ring->buf_mask; | 758 | unsigned int dw_size = af->ib_dw_size; |
| 770 | unsigned int i; | 759 | unsigned int i; |
| 771 | 760 | ||
| 761 | af->backup_idx = ring->ring_backup_entries_to_copy; | ||
| 772 | /* Backup the contents of the ring buffer. */ | 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 | ring->ring_backup[ring->ring_backup_entries_to_copy++] = ring->ring[i]; | 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 | struct dma_fence *unprocessed; | 770 | struct dma_fence *unprocessed; |
| 781 | struct dma_fence __rcu **ptr; | 771 | struct dma_fence __rcu **ptr; |
| 782 | struct amdgpu_fence *fence; | 772 | struct amdgpu_fence *fence; |
| 783 | u64 wptr; | ||
| 784 | u32 seq, last_seq; | 773 | u32 seq, last_seq; |
| 785 | 774 | ||
| 786 | last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; | 775 | last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; |
| 787 | seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask; | 776 | seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask; |
| 788 | wptr = ring->fence_drv.signalled_wptr; | ||
| 789 | ring->ring_backup_entries_to_copy = 0; | 777 | ring->ring_backup_entries_to_copy = 0; |
| 790 | 778 | ||
| 791 | do { | 779 | do { |
| @@ -799,21 +787,7 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring, · 7 unmodified lines | |||
| 799 | if (unprocessed && !dma_fence_is_signaled(unprocessed)) { | 787 | if (unprocessed && !dma_fence_is_signaled(unprocessed)) { |
| 800 | fence = container_of(unprocessed, struct amdgpu_fence, base); | 788 | fence = container_of(unprocessed, struct amdgpu_fence, base); |
| 801 | 789 | ||
| 802 | /* save everything if the ring is not guilty, otherwise | 790 | amdgpu_ring_backup_unprocessed_command(ring, fence); |
| 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++; | ||
| 817 | } | 791 | } |
| 818 | rcu_read_unlock(); | 792 | rcu_read_unlock(); |
| 819 | } while (last_seq != seq); | 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 | &ring->mqd_ptr); | 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 | int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id) | 555 | int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id) |
| 507 | { | 556 | { |
| 508 | struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id]; | 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 | int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev, | 583 | int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev, |
| 584 | unsigned mqd_size, int xcc_id); | 584 | unsigned mqd_size, int xcc_id); |
| 585 | void amdgpu_gfx_mqd_sw_fini(struct amdgpu_device *adev, int xcc_id); | 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 | int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id); | 588 | int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id); |
| 587 | int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id); | 589 | int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id); |
| 588 | int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id); | 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 | * translation. Avoid this by doing the invalidation from the SDMA | 742 | * translation. Avoid this by doing the invalidation from the SDMA |
| 743 | * itself at least for GART. | 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 | r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.default_entity.base, | 746 | r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.default_entity.base, |
| 747 | AMDGPU_FENCE_OWNER_UNDEFINED, | 747 | AMDGPU_FENCE_OWNER_UNDEFINED, |
| 748 | 16 * 4, AMDGPU_IB_POOL_IMMEDIATE, | 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 | job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop; | 755 | job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop; |
| 756 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); | 756 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
| 757 | fence = amdgpu_job_submit(job); | 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 | dma_fence_wait(fence, false); | 760 | dma_fence_wait(fence, false); |
| 761 | dma_fence_put(fence); | 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 | return; | 763 | return; |
| 764 | 764 | ||
| 765 | error_alloc: | 765 | error_alloc: |
| 766 | mutex_unlock(&adev->mman.gtt_window_lock); | 766 | mutex_unlock(&adev->mman.default_entity.lock); |
| 767 | dev_err(adev->dev, "Error flushing GPU TLB using the SDMA (%d)!\n", r); | 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 | struct amdgpu_gtt_mgr *mgr = &adev->mman.gtt_mgr; | 325 | struct amdgpu_gtt_mgr *mgr = &adev->mman.gtt_mgr; |
| 326 | struct ttm_resource_manager *man = &mgr->manager; | 326 | struct ttm_resource_manager *man = &mgr->manager; |
| 327 | uint64_t start, size; | ||
| 328 | 327 | ||
| 329 | man->use_tt = true; | 328 | man->use_tt = true; |
| 330 | man->func = &amdgpu_gtt_mgr_func; | 329 | man->func = &amdgpu_gtt_mgr_func; |
| 331 | 330 | ||
| 332 | ttm_resource_manager_init(man, &adev->mman.bdev, gtt_size); | 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; | 333 | drm_mm_init(&mgr->mm, 0, adev->gmc.gart_size >> PAGE_SHIFT); |
| 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); | ||
| 338 | spin_lock_init(&mgr->lock); | 334 | spin_lock_init(&mgr->lock); |
| 339 | 335 | ||
| 340 | ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); | 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 | struct amdgpu_ib *ib = &ibs[0]; | 129 | struct amdgpu_ib *ib = &ibs[0]; |
| 130 | struct dma_fence *tmp = NULL; | 130 | struct dma_fence *tmp = NULL; |
| 131 | struct amdgpu_fence *af; | 131 | struct amdgpu_fence *af; |
| 132 | struct amdgpu_fence *vm_af; | ||
| 132 | bool need_ctx_switch; | 133 | bool need_ctx_switch; |
| 133 | struct amdgpu_vm *vm; | 134 | struct amdgpu_vm *vm; |
| 134 | uint64_t fence_ctx; | 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 | dma_fence_put(tmp); | 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 | if (job) { |
| 219 | ring->funcs->emit_mem_sync(ring); | 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 && | 228 | /* IB sequence */ |
| 222 | ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH) | 229 | af->ib_wptr = ring->wptr; |
| 223 | ring->funcs->emit_wave_limit(ring, true); | 230 | amdgpu_ring_ib_begin(ring); |
| 224 | 231 | ||
| 225 | if (ring->funcs->insert_start) | 232 | if (ring->funcs->insert_start) |
| 226 | ring->funcs->insert_start(ring); | 233 | ring->funcs->insert_start(ring); |
| 227 | 234 | ||
| 228 | if (job) { | 235 | if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync) |
| 229 | r = amdgpu_vm_flush(ring, job, need_pipe_sync); | 236 | ring->funcs->emit_mem_sync(ring); |
| 230 | if (r) { | ||
| 231 | amdgpu_ring_undo(ring); | ||
| 232 | goto free_fence; | ||
| 233 | } | ||
| 234 | } | ||
| 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 | if (ring->funcs->emit_gfx_shadow && adev->gfx.cp_gfx_shadow) | 242 | if (ring->funcs->emit_gfx_shadow && adev->gfx.cp_gfx_shadow) |
| 239 | amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va, | 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 | cond_exec = amdgpu_ring_init_cond_exec(ring, | 247 | cond_exec = amdgpu_ring_init_cond_exec(ring, |
| 244 | ring->cond_exe_gpu_addr); | 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 | amdgpu_device_flush_hdp(adev, ring); | 253 | amdgpu_device_flush_hdp(adev, ring); |
| 247 | 254 | ||
| 248 | if (need_ctx_switch) | 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 | amdgpu_ring_emit_frame_cntl(ring, false, secure); | 288 | amdgpu_ring_emit_frame_cntl(ring, false, secure); |
| 282 | 289 | ||
| 283 | amdgpu_device_invalidate_hdp(adev, ring); | 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 | if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE) | 295 | if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE) |
| 286 | fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY; | 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 | amdgpu_ring_init_cond_exec(ring, ring->cond_exe_gpu_addr); | 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); | 310 | 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 | } | ||
| 308 | *f = &af->base; | 311 | *f = &af->base; |
| 309 | /* get a ref for the job */ | 312 | /* get a ref for the job */ |
| 310 | if (job) | 313 | if (job) |
| @@ -323,15 +326,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, · 12 unmodified lines | |||
| 323 | ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH) | 326 | ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH) |
| 324 | ring->funcs->emit_wave_limit(ring, false); | 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 | amdgpu_ring_ib_end(ring); | 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 | amdgpu_ring_commit(ring); | 333 | amdgpu_ring_commit(ring); |
| 336 | 334 | ||
| 337 | return 0; | 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 | struct drm_wedge_task_info *info = NULL; | 92 | struct drm_wedge_task_info *info = NULL; |
| 93 | struct amdgpu_task_info *ti = NULL; | 93 | struct amdgpu_task_info *ti = NULL; |
| 94 | struct amdgpu_device *adev = ring->adev; | 94 | struct amdgpu_device *adev = ring->adev; |
| 95 | enum drm_gpu_sched_stat status = DRM_GPU_SCHED_STAT_RESET; | ||
| 96 | int idx, r; | 95 | int idx, r; |
| 97 | 96 | ||
| 98 | if (!drm_dev_enter(adev_to_drm(adev), &idx)) { | 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 | ring->sched.name); | 146 | ring->sched.name); |
| 148 | drm_dev_wedged_event(adev_to_drm(adev), | 147 | drm_dev_wedged_event(adev_to_drm(adev), |
| 149 | DRM_WEDGE_RECOVERY_NONE, info); | 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 | goto exit; | 149 | goto exit; |
| 153 | } | 150 | } |
| 154 | dev_err(adev->dev, "Ring %s reset failed\n", ring->sched.name); | 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 | exit: | 181 | exit: |
| 185 | amdgpu_vm_put_task_info(ti); | 182 | amdgpu_vm_put_task_info(ti); |
| 186 | drm_dev_exit(idx); | 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 | int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm, | 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 | #include <linux/debugfs.h> | 25 | #include <linux/debugfs.h> |
| 25 | #include <linux/list.h> | 26 | #include <linux/list.h> |
| 26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| @@ -42,6 +43,7 @@ · 15 unmodified lines | |||
| 42 | #include "amdgpu_reset.h" | 43 | #include "amdgpu_reset.h" |
| 43 | #include "amdgpu_psp.h" | 44 | #include "amdgpu_psp.h" |
| 44 | #include "amdgpu_ras_mgr.h" | 45 | #include "amdgpu_ras_mgr.h" |
| 46 | #include "amdgpu_virt_ras_cmd.h" | ||
| 45 | 47 | ||
| 46 | #ifdef CONFIG_X86_MCE_AMD | 48 | #ifdef CONFIG_X86_MCE_AMD |
| 47 | #include <asm/mce.h> | 49 | #include <asm/mce.h> |
| @@ -228,19 +230,30 @@ static int amdgpu_check_address_validity(struct amdgpu_device *adev, · 180 unmodified lines | |||
| 228 | return 0; | 230 | return 0; |
| 229 | 231 | ||
| 230 | if (amdgpu_sriov_vf(adev)) { | 232 | if (amdgpu_sriov_vf(adev)) { |
| 231 | if (amdgpu_virt_check_vf_critical_region(adev, address, &hit)) | 233 | if (amdgpu_uniras_enabled(adev)) { |
| 232 | return -EPERM; | 234 | if (amdgpu_virt_ras_check_address_validity(adev, address, &hit)) |
| 233 | return hit ? -EACCES : 0; | 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 | if ((address >= adev->gmc.mc_vram_size) || | 245 | if ((address >= adev->gmc.mc_vram_size) || |
| 237 | (address >= RAS_UMC_INJECT_ADDR_LIMIT)) | 246 | (address >= RAS_UMC_INJECT_ADDR_LIMIT)) |
| 238 | return -EFAULT; | 247 | return -EFAULT; |
| 239 | 248 | ||
| 240 | if (amdgpu_uniras_enabled(adev)) | 249 | if (amdgpu_uniras_enabled(adev)) { |
| 241 | count = amdgpu_ras_mgr_lookup_bad_pages_in_a_row(adev, address, | 250 | if (amdgpu_sriov_vf(adev)) |
| 242 | page_pfns, ARRAY_SIZE(page_pfns)); | 251 | count = amdgpu_virt_ras_convert_retired_address(adev, address, |
| 243 | else | 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 | count = amdgpu_umc_lookup_bad_pages_in_a_row(adev, | 257 | count = amdgpu_umc_lookup_bad_pages_in_a_row(adev, |
| 245 | address, page_pfns, ARRAY_SIZE(page_pfns)); | 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 | enum amdgpu_memory_partition nps) | 3131 | enum amdgpu_memory_partition nps) |
| 3119 | { | 3132 | { |
| 3120 | int i = 0; | 3133 | int i = 0; |
| 3134 | uint64_t chan_idx_v2; | ||
| 3121 | enum amdgpu_memory_partition save_nps; | 3135 | enum amdgpu_memory_partition save_nps; |
| 3122 | 3136 | ||
| 3123 | save_nps = (bps[0].retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; | 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 | /*old asics just have pa in eeprom*/ | 3140 | /*old asics just have pa in eeprom*/ |
| 3126 | if (IP_VERSION_MAJ(amdgpu_ip_version(adev, UMC_HWIP, 0)) < 12) { | 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 | for (i = 0; i < adev->umc.retire_unit; i++) | 3147 | for (i = 0; i < adev->umc.retire_unit; i++) |
| 3133 | bps[i].retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); | 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 | if (save_nps == nps) { | 3151 | if (save_nps == nps) { |
| 3137 | if (amdgpu_umc_pages_in_a_row(adev, err_data, | 3152 | if (amdgpu_umc_pages_in_a_row(adev, err_data, |
| 3138 | bps[0].retired_page << AMDGPU_GPU_PAGE_SHIFT)) | 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 | enum amdgpu_memory_partition nps) | 3191 | enum amdgpu_memory_partition nps) |
| 3177 | { | 3192 | { |
| 3178 | int i = 0; | 3193 | int i = 0; |
| 3194 | uint64_t chan_idx_v2; | ||
| 3179 | enum amdgpu_memory_partition save_nps; | 3195 | enum amdgpu_memory_partition save_nps; |
| 3180 | 3196 | ||
| 3181 | if (!amdgpu_ras_smu_eeprom_supported(adev)) { | 3197 | if (!amdgpu_ras_smu_eeprom_supported(adev)) { |
| 3182 | save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; | 3198 | save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK; |
| 3199 | chan_idx_v2 = bps->retired_page & UMC_CHANNEL_IDX_V2; | ||
| 3183 | bps->retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); | 3200 | bps->retired_page &= ~(UMC_NPS_MASK << UMC_NPS_SHIFT); |
| 3184 | } else { | 3201 | } else { |
| 3185 | /* if pmfw manages eeprom, save_nps is not stored on eeprom, | 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 | err_data->err_addr[i].mcumc_id = bps->mcumc_id; | 3218 | err_data->err_addr[i].mcumc_id = bps->mcumc_id; |
| 3202 | } | 3219 | } |
| 3203 | } else { | 3220 | } else { |
| 3204 | if (bps->address) { | 3221 | if (save_nps || chan_idx_v2) { |
| 3205 | if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data)) | 3222 | if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data)) |
| 3206 | return -EINVAL; | 3223 | return -EINVAL; |
| 3207 | } else { | 3224 | } else { |
| 3208 | /* for specific old eeprom data, mca address is not stored, | 3225 | /* for specific old eeprom data, mca address is not stored, |
| 3209 | * calc it from pa | 3226 | * calc it from pa |
| 3210 | */ | 3227 | */ |
| 3211 | if (amdgpu_umc_pa2mca(adev, bps->retired_page << AMDGPU_GPU_PAGE_SHIFT, | 3228 | if (bps->address == 0) |
| 3212 | &(bps->address), AMDGPU_NPS1_PARTITION_MODE)) | 3229 | if (amdgpu_umc_pa2mca(adev, |
| 3213 | return -EINVAL; | 3230 | bps->retired_page << AMDGPU_GPU_PAGE_SHIFT, |
| 3231 | &(bps->address), | ||
| 3232 | AMDGPU_NPS1_PARTITION_MODE)) | ||
| 3233 | return -EINVAL; | ||
| 3214 | 3234 | ||
| 3215 | if (amdgpu_ras_mca2pa(adev, bps, err_data)) | 3235 | if (amdgpu_ras_mca2pa(adev, bps, err_data)) |
| 3216 | return -EOPNOTSUPP; | 3236 | return -EOPNOTSUPP; |
| @@ -5516,11 +5536,11 @@ static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev, · 2299 unmodified lines | |||
| 5516 | * is changed. In such case, replace the aqua_vanjaram implementation | 5536 | * is changed. In such case, replace the aqua_vanjaram implementation |
| 5517 | * with more common helper */ | 5537 | * with more common helper */ |
| 5518 | reg_addr = (mmMP0_SMN_C2PMSG_92 << 2) + | 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 | fw_status = amdgpu_device_indirect_rreg_ext(adev, reg_addr); | 5540 | fw_status = amdgpu_device_indirect_rreg_ext(adev, reg_addr); |
| 5521 | 5541 | ||
| 5522 | reg_addr = (mmMP0_SMN_C2PMSG_126 << 2) + | 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 | boot_error = amdgpu_device_indirect_rreg_ext(adev, reg_addr); | 5544 | boot_error = amdgpu_device_indirect_rreg_ext(adev, reg_addr); |
| 5525 | 5545 | ||
| 5526 | socket_id = AMDGPU_RAS_GPU_ERR_SOCKET_ID(boot_error); | 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 | int retry_loop; | 5606 | int retry_loop; |
| 5587 | 5607 | ||
| 5588 | reg_addr = (mmMP0_SMN_C2PMSG_92 << 2) + | 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 | for (retry_loop = 0; retry_loop < AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT; retry_loop++) { | 5611 | for (retry_loop = 0; retry_loop < AMDGPU_RAS_BOOT_STATUS_POLLING_LIMIT; retry_loop++) { |
| 5592 | reg_data = amdgpu_device_indirect_rreg_ext(adev, reg_addr); | 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 | control->bad_channel_bitmap = 0; | 508 | control->bad_channel_bitmap = 0; |
| 509 | amdgpu_dpm_send_hbm_bad_channel_flag(adev, control->bad_channel_bitmap); | 509 | amdgpu_dpm_send_hbm_bad_channel_flag(adev, control->bad_channel_bitmap); |
| 510 | con->update_channel_flag = false; | 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 | amdgpu_ras_debugfs_set_ret_size(control); | 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 | ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask; | 90 | ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask; |
| 91 | 91 | ||
| 92 | /* Make sure we aren't trying to allocate more space | 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 | if (!ring->reemit) { |
| 96 | return -ENOMEM; | 97 | if (WARN_ON_ONCE(ndw > ring->max_dw)) |
| 98 | return -ENOMEM; | ||
| 99 | } | ||
| 97 | 100 | ||
| 98 | ring->count_dw = ndw; | 101 | ring->count_dw = ndw; |
| 99 | ring->wptr_old = ring->wptr; | 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 | return 0; | 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 | * amdgpu_ring_insert_nop - insert NOP packets | 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 | int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring, | 855 | int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring, |
| 876 | struct amdgpu_fence *guilty_fence) | 856 | struct amdgpu_fence *guilty_fence) |
| 877 | { | 857 | { |
| 878 | unsigned int i; | ||
| 879 | int r; | 858 | int r; |
| 880 | 859 | ||
| 881 | /* verify that the ring is functional */ | 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 | if (r) | 862 | if (r) |
| 884 | return r; | 863 | return r; |
| 885 | 864 | ||
| 886 | /* set an error on all fences from the context */ | 865 | /* set an error on all fences from the context and reemit */ |
| 887 | if (guilty_fence) | 866 | amdgpu_ring_set_fence_errors_and_reemit(ring, guilty_fence); |
| 888 | amdgpu_fence_driver_update_timedout_fence_state(guilty_fence); | 867 | |
| 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 | } | ||
| 896 | return 0; | 868 | return 0; |
| 897 | } | 869 | } |
| 898 | 870 | ||
| @@ -121,7 +121,6 @@ struct amdgpu_fence_driver { · 120 unmodified lines | |||
| 121 | /* sync_seq is protected by ring emission lock */ | 121 | /* sync_seq is protected by ring emission lock */ |
| 122 | uint32_t sync_seq; | 122 | uint32_t sync_seq; |
| 123 | atomic_t last_seq; | 123 | atomic_t last_seq; |
| 124 | u64 signalled_wptr; | ||
| 125 | bool initialized; | 124 | bool initialized; |
| 126 | struct amdgpu_irq_src *irq_src; | 125 | struct amdgpu_irq_src *irq_src; |
| 127 | unsigned irq_type; | 126 | unsigned irq_type; |
| @@ -146,23 +145,23 @@ struct amdgpu_fence { · 18 unmodified lines | |||
| 146 | struct amdgpu_ring *ring; | 145 | struct amdgpu_ring *ring; |
| 147 | ktime_t start_timestamp; | 146 | ktime_t start_timestamp; |
| 148 | 147 | ||
| 149 | /* wptr for the total submission for resets */ | 148 | /* location and size of the IB */ |
| 150 | u64 wptr; | 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 | /* fence context for resets */ | 153 | /* fence context for resets */ |
| 152 | u64 context; | 154 | u64 context; |
| 153 | /* has this fence been reemitted */ | 155 | /* idx for ring backups */ |
| 154 | unsigned int reemitted; | 156 | unsigned int backup_idx; |
| 155 | /* wptr for the fence for the submission */ | ||
| 156 | u64 fence_wptr_start; | ||
| 157 | u64 fence_wptr_end; | ||
| 158 | }; | 157 | }; |
| 159 | 158 | ||
| 160 | extern const struct drm_sched_backend_ops amdgpu_sched_ops; | 159 | extern const struct drm_sched_backend_ops amdgpu_sched_ops; |
| 161 | 160 | ||
| 162 | void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error); | 161 | void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error); |
| 163 | void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); | 162 | void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); |
| 164 | void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af); | 163 | void amdgpu_ring_set_fence_errors_and_reemit(struct amdgpu_ring *ring, |
| 165 | void amdgpu_fence_save_wptr(struct amdgpu_fence *af); | 164 | struct amdgpu_fence *guilty_fence); |
| 166 | 165 | ||
| 167 | int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring); | 166 | int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring); |
| 168 | int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, | 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 | void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev); | 171 | void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev); |
| 173 | int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev); | 172 | int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev); |
| 174 | void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev); | 173 | void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev); |
| 175 | int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, | 174 | void amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, |
| 176 | unsigned int flags); | 175 | unsigned int flags); |
| 177 | int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s, | 176 | int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s, |
| 178 | uint32_t timeout); | 177 | uint32_t timeout); |
| 179 | bool amdgpu_fence_process(struct amdgpu_ring *ring); | 178 | bool amdgpu_fence_process(struct amdgpu_ring *ring); |
| @@ -313,6 +312,7 @@ struct amdgpu_ring { · 133 unmodified lines | |||
| 313 | /* backups for resets */ | 312 | /* backups for resets */ |
| 314 | uint32_t *ring_backup; | 313 | uint32_t *ring_backup; |
| 315 | unsigned int ring_backup_entries_to_copy; | 314 | unsigned int ring_backup_entries_to_copy; |
| 315 | bool reemit; | ||
| 316 | unsigned rptr_offs; | 316 | unsigned rptr_offs; |
| 317 | u64 rptr_gpu_addr; | 317 | u64 rptr_gpu_addr; |
| 318 | u32 *rptr_cpu_addr; | 318 | u32 *rptr_cpu_addr; |
| @@ -522,6 +522,17 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, · 203 unmodified lines | |||
| 522 | ring->count_dw -= count_dw; | 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 | * amdgpu_ring_patch_cond_exec - patch dw count of conditional execute | 537 | * amdgpu_ring_patch_cond_exec - patch dw count of conditional execute |
| 527 | * @ring: amdgpu_ring structure | 538 | * @ring: amdgpu_ring structure |
| @@ -532,18 +543,13 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, · 4 unmodified lines | |||
| 532 | static inline void amdgpu_ring_patch_cond_exec(struct amdgpu_ring *ring, | 543 | static inline void amdgpu_ring_patch_cond_exec(struct amdgpu_ring *ring, |
| 533 | unsigned int offset) | 544 | unsigned int offset) |
| 534 | { | 545 | { |
| 535 | unsigned cur; | ||
| 536 | |||
| 537 | if (!ring->funcs->init_cond_exec) | 546 | if (!ring->funcs->init_cond_exec) |
| 538 | return; | 547 | return; |
| 539 | 548 | ||
| 540 | WARN_ON(offset > ring->buf_mask); | 549 | WARN_ON(offset > ring->buf_mask); |
| 541 | WARN_ON(ring->ring[offset] != 0); | 550 | WARN_ON(ring->ring[offset] != 0); |
| 542 | 551 | ||
| 543 | cur = (ring->wptr - 1) & ring->buf_mask; | 552 | ring->ring[offset] = amdgpu_ring_get_dw_distance(ring, offset, ring->wptr - 1); |
| 544 | if (cur < offset) | ||
| 545 | cur += ring->ring_size >> 2; | ||
| 546 | ring->ring[offset] = cur - offset; | ||
| 547 | } | 553 | } |
| 548 | 554 | ||
| 549 | int amdgpu_ring_test_helper(struct amdgpu_ring *ring); | 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 | static struct dma_fence * | 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 | struct amdgpu_ring *ring; | 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 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); | 172 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
| 172 | WARN_ON(job->ibs[0].length_dw > num_dw); | 173 | WARN_ON(job->ibs[0].length_dw > num_dw); |
| 173 | 174 | ||
| 175 | lockdep_assert_held(&entity->lock); | ||
| 176 | |||
| 174 | return amdgpu_job_submit(job); | 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 | *size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset); | 232 | *size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset); |
| 230 | 233 | ||
| 231 | *addr = adev->gmc.gart_start; | 234 | *addr = amdgpu_compute_gart_address(&adev->gmc, entity, window); |
| 232 | *addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE * | ||
| 233 | AMDGPU_GPU_PAGE_SIZE; | ||
| 234 | *addr += offset; | 235 | *addr += offset; |
| 235 | 236 | ||
| 236 | num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); | 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 | src_addr += job->ibs[0].gpu_addr; | 249 | src_addr += job->ibs[0].gpu_addr; |
| 249 | 250 | ||
| 250 | dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); | 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 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, | 253 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, |
| 253 | dst_addr, num_bytes, 0); | 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 | amdgpu_gart_map_vram_range(adev, pa, 0, num_pages, flags, cpu_addr); | 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 | return 0; | 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 | amdgpu_res_first(src->mem, src->offset, size, &src_mm); | 314 | amdgpu_res_first(src->mem, src->offset, size, &src_mm); |
| 314 | amdgpu_res_first(dst->mem, dst->offset, size, &dst_mm); | 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 | while (src_mm.remaining) { | 318 | while (src_mm.remaining) { |
| 318 | uint64_t from, to, cur_size, tiling_flags; | 319 | uint64_t from, to, cur_size, tiling_flags; |
| 319 | uint32_t num_type, data_format, max_com, write_compress_disable; | 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 | amdgpu_res_next(&dst_mm, cur_size); | 369 | amdgpu_res_next(&dst_mm, cur_size); |
| 369 | } | 370 | } |
| 370 | error: | 371 | error: |
| 371 | mutex_unlock(&adev->mman.gtt_window_lock); | 372 | mutex_unlock(&entity->lock); |
| 372 | *f = fence; | 373 | *f = fence; |
| 373 | return r; | 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 | if (r) | 1581 | if (r) |
| 1581 | goto out; | 1582 | goto out; |
| 1582 | 1583 | ||
| 1583 | mutex_lock(&adev->mman.gtt_window_lock); | 1584 | mutex_lock(&adev->mman.default_entity.lock); |
| 1584 | amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm); | 1585 | amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm); |
| 1585 | src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + | 1586 | src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + |
| 1586 | src_mm.start; | 1587 | src_mm.start; |
| @@ -1591,8 +1592,8 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, · 4 unmodified lines | |||
| 1591 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, | 1592 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, |
| 1592 | PAGE_SIZE, 0); | 1593 | PAGE_SIZE, 0); |
| 1593 | 1594 | ||
| 1594 | fence = amdgpu_ttm_job_submit(adev, job, num_dw); | 1595 | fence = amdgpu_ttm_job_submit(adev, &adev->mman.default_entity, job, num_dw); |
| 1595 | mutex_unlock(&adev->mman.gtt_window_lock); | 1596 | mutex_unlock(&adev->mman.default_entity.lock); |
| 1596 | 1597 | ||
| 1597 | if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout)) | 1598 | if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout)) |
| 1598 | r = -ETIMEDOUT; | 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 | * @adev: amdgpu device | 1913 | * @adev: amdgpu device |
| 1913 | * | 1914 | * |
| 1914 | * Allocates a global BO with backing AMDGPU_PL_MMIO_REMAP when the | 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 | adev->rmmio_remap.bo = NULL; | 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 | * amdgpu_ttm_init - Init the memory management (ttm) as well as various | 2062 | * amdgpu_ttm_init - Init the memory management (ttm) as well as various |
| 2018 | * gtt/vram related fields. | 2063 | * gtt/vram related fields. |
| @@ -2027,8 +2072,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) · 8 unmodified lines | |||
| 2027 | uint64_t gtt_size; | 2072 | uint64_t gtt_size; |
| 2028 | int r; | 2073 | int r; |
| 2029 | 2074 | ||
| 2030 | mutex_init(&adev->mman.gtt_window_lock); | ||
| 2031 | |||
| 2032 | dma_set_max_seg_size(adev->dev, UINT_MAX); | 2075 | dma_set_max_seg_size(adev->dev, UINT_MAX); |
| 2033 | /* No others user of address space so set it to 0 */ | 2076 | /* No others user of address space so set it to 0 */ |
| 2034 | r = ttm_device_init(&adev->mman.bdev, &amdgpu_bo_driver, adev->dev, | 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 | struct amdgpu_ring *ring; | 2356 | struct amdgpu_ring *ring; |
| 2314 | struct drm_gpu_scheduler *sched; | 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 | ring = adev->mman.buffer_funcs_ring; | 2364 | ring = adev->mman.buffer_funcs_ring; |
| 2317 | sched = &ring->sched; | 2365 | sched = &ring->sched; |
| 2318 | r = drm_sched_entity_init(&adev->mman.default_entity.base, | 2366 | r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, |
| 2319 | DRM_SCHED_PRIORITY_KERNEL, &sched, | 2367 | &adev->mman.default_entity, |
| 2320 | 1, NULL); | 2368 | DRM_SCHED_PRIORITY_KERNEL, |
| 2321 | if (r) { | 2369 | &sched, 1, 0); |
| 2370 | if (r < 0) { | ||
| 2322 | dev_err(adev->dev, | 2371 | dev_err(adev->dev, |
| 2323 | "Failed setting up TTM BO move entity (%d)\n", | 2372 | "Failed setting up TTM entity (%d)\n", r); |
| 2324 | r); | ||
| 2325 | return; | 2373 | return; |
| 2326 | } | 2374 | } |
| 2327 | 2375 | ||
| 2328 | r = drm_sched_entity_init(&adev->mman.clear_entity.base, | 2376 | r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, |
| 2329 | DRM_SCHED_PRIORITY_NORMAL, &sched, | 2377 | &adev->mman.clear_entity, |
| 2330 | 1, NULL); | 2378 | DRM_SCHED_PRIORITY_NORMAL, |
| 2331 | if (r) { | 2379 | &sched, 1, 1); |
| 2380 | if (r < 0) { | ||
| 2332 | dev_err(adev->dev, | 2381 | dev_err(adev->dev, |
| 2333 | "Failed setting up TTM BO clear entity (%d)\n", | 2382 | "Failed setting up TTM BO clear entity (%d)\n", r); |
| 2334 | r); | 2383 | goto error_free_default_entity; |
| 2335 | goto error_free_entity; | ||
| 2336 | } | 2384 | } |
| 2337 | 2385 | ||
| 2338 | r = drm_sched_entity_init(&adev->mman.move_entity.base, | 2386 | r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, |
| 2339 | DRM_SCHED_PRIORITY_NORMAL, &sched, | 2387 | &adev->mman.move_entity, |
| 2340 | 1, NULL); | 2388 | DRM_SCHED_PRIORITY_NORMAL, |
| 2341 | if (r) { | 2389 | &sched, 1, 2); |
| 2390 | if (r < 0) { | ||
| 2342 | dev_err(adev->dev, | 2391 | dev_err(adev->dev, |
| 2343 | "Failed setting up TTM BO move entity (%d)\n", | 2392 | "Failed setting up TTM BO move entity (%d)\n", r); |
| 2344 | r); | 2393 | goto error_free_clear_entity; |
| 2345 | drm_sched_entity_destroy(&adev->mman.clear_entity.base); | ||
| 2346 | goto error_free_entity; | ||
| 2347 | } | 2394 | } |
| 2348 | } else { | 2395 | } else { |
| 2349 | drm_sched_entity_destroy(&adev->mman.default_entity.base); | 2396 | amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, |
| 2350 | drm_sched_entity_destroy(&adev->mman.clear_entity.base); | 2397 | &adev->mman.default_entity); |
| 2351 | drm_sched_entity_destroy(&adev->mman.move_entity.base); | 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 | /* Drop all the old fences since re-creating the scheduler entities | 2402 | /* Drop all the old fences since re-creating the scheduler entities |
| 2353 | * will allocate new contexts. | 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 | return; | 2416 | return; |
| 2367 | 2417 | ||
| 2368 | error_free_entity: | 2418 | error_free_clear_entity: |
| 2369 | drm_sched_entity_destroy(&adev->mman.default_entity.base); | 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 | static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev, | 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 | byte_count -= cur_size_in_bytes; | 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 | return 0; | 2499 | return 0; |
| 2446 | 2500 | ||
| @@ -2483,7 +2537,7 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_device *adev, · 36 unmodified lines | |||
| 2483 | byte_count -= cur_size; | 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 | return 0; | 2541 | return 0; |
| 2488 | } | 2542 | } |
| 2489 | 2543 | ||
| @@ -2503,6 +2557,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 13 unmodified lines | |||
| 2503 | struct dma_fence **fence) | 2557 | struct dma_fence **fence) |
| 2504 | { | 2558 | { |
| 2505 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); | 2559 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
| 2560 | struct amdgpu_ttm_buffer_entity *entity; | ||
| 2506 | struct amdgpu_res_cursor cursor; | 2561 | struct amdgpu_res_cursor cursor; |
| 2507 | u64 addr; | 2562 | u64 addr; |
| 2508 | int r = 0; | 2563 | int r = 0; |
| @@ -2513,11 +2568,12 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 4 unmodified lines | |||
| 2513 | if (!fence) | 2568 | if (!fence) |
| 2514 | return -EINVAL; | 2569 | return -EINVAL; |
| 2515 | 2570 | ||
| 2571 | entity = &adev->mman.clear_entity; | ||
| 2516 | *fence = dma_fence_get_stub(); | 2572 | *fence = dma_fence_get_stub(); |
| 2517 | 2573 | ||
| 2518 | amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); | 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 | while (cursor.remaining) { | 2577 | while (cursor.remaining) { |
| 2522 | struct dma_fence *next = NULL; | 2578 | struct dma_fence *next = NULL; |
| 2523 | u64 size; | 2579 | u64 size; |
| @@ -2530,13 +2586,12 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 6 unmodified lines | |||
| 2530 | /* Never clear more than 256MiB at once to avoid timeouts */ | 2586 | /* Never clear more than 256MiB at once to avoid timeouts */ |
| 2531 | size = min(cursor.size, 256ULL << 20); | 2587 | size = min(cursor.size, 256ULL << 20); |
| 2532 | 2588 | ||
| 2533 | r = amdgpu_ttm_map_buffer(&adev->mman.clear_entity, | 2589 | r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &cursor, |
| 2534 | &bo->tbo, bo->tbo.resource, &cursor, | 2590 | 0, false, &size, &addr); |
| 2535 | 1, false, &size, &addr); | ||
| 2536 | if (r) | 2591 | if (r) |
| 2537 | goto err; | 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 | &next, true, | 2595 | &next, true, |
| 2541 | AMDGPU_KERNEL_JOB_ID_TTM_CLEAR_BUFFER); | 2596 | AMDGPU_KERNEL_JOB_ID_TTM_CLEAR_BUFFER); |
| 2542 | if (r) | 2597 | if (r) |
| @@ -2548,7 +2603,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, · 5 unmodified lines | |||
| 2548 | amdgpu_res_next(&cursor, size); | 2603 | amdgpu_res_next(&cursor, size); |
| 2549 | } | 2604 | } |
| 2550 | err: | 2605 | err: |
| 2551 | mutex_unlock(&adev->mman.gtt_window_lock); | 2606 | mutex_unlock(&entity->lock); |
| 2552 | 2607 | ||
| 2553 | return r; | 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 | amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst); | 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 | while (dst.remaining) { | 2632 | while (dst.remaining) { |
| 2578 | struct dma_fence *next; | 2633 | struct dma_fence *next; |
| 2579 | uint64_t cur_size, to; | 2634 | uint64_t cur_size, to; |
| @@ -2582,7 +2637,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, · 2 unmodified lines | |||
| 2582 | cur_size = min(dst.size, 256ULL << 20); | 2637 | cur_size = min(dst.size, 256ULL << 20); |
| 2583 | 2638 | ||
| 2584 | r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &dst, | 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 | if (r) | 2641 | if (r) |
| 2587 | goto error; | 2642 | goto error; |
| 2588 | 2643 | ||
| @@ -2598,7 +2653,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, · 9 unmodified lines | |||
| 2598 | amdgpu_res_next(&dst, cur_size); | 2653 | amdgpu_res_next(&dst, cur_size); |
| 2599 | } | 2654 | } |
| 2600 | error: | 2655 | error: |
| 2601 | mutex_unlock(&adev->mman.gtt_window_lock); | 2656 | mutex_unlock(&entity->lock); |
| 2602 | if (f) | 2657 | if (f) |
| 2603 | *f = dma_fence_get(fence); | 2658 | *f = dma_fence_get(fence); |
| 2604 | dma_fence_put(fence); | 2659 | dma_fence_put(fence); |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | |||
| 29 | #include <drm/ttm/ttm_placement.h> | 29 | #include <drm/ttm/ttm_placement.h> |
| 30 | #include "amdgpu_vram_mgr.h" | 30 | #include "amdgpu_vram_mgr.h" |
| 31 | #include "amdgpu_hmm.h" | 31 | #include "amdgpu_hmm.h" |
| 32 | #include "amdgpu_gmc.h" | ||
| 32 | 33 | ||
| 33 | #define AMDGPU_PL_GDS (TTM_PL_PRIV + 0) | 34 | #define AMDGPU_PL_GDS (TTM_PL_PRIV + 0) |
| 34 | #define AMDGPU_PL_GWS (TTM_PL_PRIV + 1) | 35 | #define AMDGPU_PL_GWS (TTM_PL_PRIV + 1) |
| @@ -38,8 +39,7 @@ · 3 unmodified lines | |||
| 38 | #define AMDGPU_PL_MMIO_REMAP (TTM_PL_PRIV + 5) | 39 | #define AMDGPU_PL_MMIO_REMAP (TTM_PL_PRIV + 5) |
| 39 | #define __AMDGPU_PL_NUM (TTM_PL_PRIV + 6) | 40 | #define __AMDGPU_PL_NUM (TTM_PL_PRIV + 6) |
| 40 | 41 | ||
| 41 | #define AMDGPU_GTT_MAX_TRANSFER_SIZE 512 | 42 | #define AMDGPU_GTT_MAX_TRANSFER_SIZE 1024 |
| 42 | #define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2 | ||
| 43 | 43 | ||
| 44 | extern const struct attribute_group amdgpu_vram_mgr_attr_group; | 44 | extern const struct attribute_group amdgpu_vram_mgr_attr_group; |
| 45 | extern const struct attribute_group amdgpu_gtt_mgr_attr_group; | 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 | struct amdgpu_ttm_buffer_entity { | 55 | struct amdgpu_ttm_buffer_entity { |
| 56 | struct drm_sched_entity base; | 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 | struct amdgpu_mman { | 62 | struct amdgpu_mman { |
| @@ -67,8 +70,7 @@ struct amdgpu_mman { · 7 unmodified lines | |||
| 67 | struct amdgpu_ring *buffer_funcs_ring; | 70 | struct amdgpu_ring *buffer_funcs_ring; |
| 68 | bool buffer_funcs_enabled; | 71 | bool buffer_funcs_enabled; |
| 69 | 72 | ||
| 70 | struct mutex gtt_window_lock; | 73 | /* @default_entity: for workarounds, has no gart windows */ |
| 71 | |||
| 72 | struct amdgpu_ttm_buffer_entity default_entity; | 74 | struct amdgpu_ttm_buffer_entity default_entity; |
| 73 | struct amdgpu_ttm_buffer_entity clear_entity; | 75 | struct amdgpu_ttm_buffer_entity clear_entity; |
| 74 | struct amdgpu_ttm_buffer_entity move_entity; | 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 | #endif | 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 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct amdgpu_hmm_range *range); | 231 | void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct amdgpu_hmm_range *range); |
| 209 | int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo, | 232 | int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo, |
| 210 | uint64_t *user_addr); | 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 | return ret; | 446 | return ret; |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue, | 449 | static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue) |
| 450 | int queue_id) | ||
| 451 | { | 450 | { |
| 452 | struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr; | 451 | struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr; |
| 453 | struct amdgpu_device *adev = uq_mgr->adev; | 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 | uq_funcs->mqd_destroy(queue); | 460 | uq_funcs->mqd_destroy(queue); |
| 462 | amdgpu_userq_fence_driver_free(queue); | 461 | amdgpu_userq_fence_driver_free(queue); |
| 463 | /* Use interrupt-safe locking since IRQ handlers may access these XArrays */ | 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 | xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index); | 463 | xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index); |
| 466 | queue->userq_mgr = NULL; | 464 | queue->userq_mgr = NULL; |
| 467 | list_del(&queue->userq_va_list); | 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 | up_read(&adev->reset_domain->sem); | 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 | void | 471 | void |
| 480 | amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr, | 472 | amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr, |
| 481 | struct amdgpu_eviction_fence_mgr *evf_mgr) | 473 | struct amdgpu_eviction_fence_mgr *evf_mgr) |
| @@ -625,22 +617,13 @@ unref_bo: · 143 unmodified lines | |||
| 625 | } | 617 | } |
| 626 | 618 | ||
| 627 | static int | 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 | struct amdgpu_device *adev = uq_mgr->adev; | 622 | struct amdgpu_device *adev = uq_mgr->adev; |
| 633 | struct amdgpu_usermode_queue *queue; | ||
| 634 | int r = 0; | 623 | int r = 0; |
| 635 | 624 | ||
| 636 | cancel_delayed_work_sync(&uq_mgr->resume_work); | 625 | cancel_delayed_work_sync(&uq_mgr->resume_work); |
| 637 | mutex_lock(&uq_mgr->userq_mutex); | 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 | amdgpu_userq_wait_for_last_fence(queue); | 627 | amdgpu_userq_wait_for_last_fence(queue); |
| 645 | /* Cancel any pending hang detection work and cleanup */ | 628 | /* Cancel any pending hang detection work and cleanup */ |
| 646 | if (queue->hang_detect_fence) { | 629 | if (queue->hang_detect_fence) { |
| @@ -672,7 +655,7 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id) · 25 unmodified lines | |||
| 672 | drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n"); | 655 | drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n"); |
| 673 | queue->state = AMDGPU_USERQ_STATE_HUNG; | 656 | queue->state = AMDGPU_USERQ_STATE_HUNG; |
| 674 | } | 657 | } |
| 675 | amdgpu_userq_cleanup(queue, queue_id); | 658 | amdgpu_userq_cleanup(queue); |
| 676 | mutex_unlock(&uq_mgr->userq_mutex); | 659 | mutex_unlock(&uq_mgr->userq_mutex); |
| 677 | 660 | ||
| 678 | pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); | 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 | return r; | 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 | static int amdgpu_userq_priority_permit(struct drm_file *filp, | 697 | static int amdgpu_userq_priority_permit(struct drm_file *filp, |
| 684 | int priority) | 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 | goto unlock; | 848 | goto unlock; |
| 835 | } | 849 | } |
| 836 | 850 | ||
| 851 | /* drop this refcount during queue destroy */ | ||
| 852 | kref_init(&queue->refcount); | ||
| 853 | |||
| 837 | /* Wait for mode-1 reset to complete */ | 854 | /* Wait for mode-1 reset to complete */ |
| 838 | down_read(&adev->reset_domain->sem); | 855 | down_read(&adev->reset_domain->sem); |
| 839 | r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL)); | 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 | struct drm_file *filp) | 1002 | struct drm_file *filp) |
| 986 | { | 1003 | { |
| 987 | union drm_amdgpu_userq *args = data; | 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 | if (!amdgpu_userq_enabled(dev)) | 1009 | if (!amdgpu_userq_enabled(dev)) |
| 991 | return -ENOTSUPP; | 1010 | return -ENOTSUPP; |
| @@ -1000,11 +1019,16 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data, · 8 unmodified lines | |||
| 1000 | drm_file_err(filp, "Failed to create usermode queue\n"); | 1019 | drm_file_err(filp, "Failed to create usermode queue\n"); |
| 1001 | break; | 1020 | break; |
| 1002 | 1021 | ||
| 1003 | case AMDGPU_USERQ_OP_FREE: | 1022 | case AMDGPU_USERQ_OP_FREE: { |
| 1004 | r = amdgpu_userq_destroy(filp, args->in.queue_id); | 1023 | xa_lock(&fpriv->userq_mgr.userq_xa); |
| 1005 | if (r) | 1024 | queue = __xa_erase(&fpriv->userq_mgr.userq_xa, args->in.queue_id); |
| 1006 | drm_file_err(filp, "Failed to destroy usermode queue\n"); | 1025 | xa_unlock(&fpriv->userq_mgr.userq_xa); |
| 1026 | if (!queue) | ||
| 1027 | return -ENOENT; | ||
| 1028 | |||
| 1029 | amdgpu_userq_put(queue); | ||
| 1007 | break; | 1030 | break; |
| 1031 | } | ||
| 1008 | 1032 | ||
| 1009 | default: | 1033 | default: |
| 1010 | drm_dbg_driver(dev, "Invalid user queue op specified: %d\n", args->in.op); | 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 | /* Resume all the queues for this process */ | 1048 | /* Resume all the queues for this process */ |
| 1025 | xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { | 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 | if (!amdgpu_userq_buffer_vas_mapped(queue)) { | 1054 | if (!amdgpu_userq_buffer_vas_mapped(queue)) { |
| 1027 | drm_file_err(uq_mgr->file, | 1055 | drm_file_err(uq_mgr->file, |
| 1028 | "trying restore queue without va mapping\n"); | 1056 | "trying restore queue without va mapping\n"); |
| 1029 | queue->state = AMDGPU_USERQ_STATE_INVALID_VA; | 1057 | queue->state = AMDGPU_USERQ_STATE_INVALID_VA; |
| 1058 | amdgpu_userq_put(queue); | ||
| 1030 | continue; | 1059 | continue; |
| 1031 | } | 1060 | } |
| 1032 | 1061 | ||
| 1033 | r = amdgpu_userq_restore_helper(queue); | 1062 | r = amdgpu_userq_restore_helper(queue); |
| 1034 | if (r) | 1063 | if (r) |
| 1035 | ret = r; | 1064 | ret = r; |
| 1065 | |||
| 1066 | amdgpu_userq_put(queue); | ||
| 1036 | } | 1067 | } |
| 1037 | 1068 | ||
| 1038 | if (ret) | 1069 | if (ret) |
| @@ -1266,9 +1297,13 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr) · 227 unmodified lines | |||
| 1266 | amdgpu_userq_detect_and_reset_queues(uq_mgr); | 1297 | amdgpu_userq_detect_and_reset_queues(uq_mgr); |
| 1267 | /* Try to unmap all the queues in this process ctx */ | 1298 | /* Try to unmap all the queues in this process ctx */ |
| 1268 | xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { | 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 | r = amdgpu_userq_preempt_helper(queue); | 1303 | r = amdgpu_userq_preempt_helper(queue); |
| 1270 | if (r) | 1304 | if (r) |
| 1271 | ret = r; | 1305 | ret = r; |
| 1306 | amdgpu_userq_put(queue); | ||
| 1272 | } | 1307 | } |
| 1273 | 1308 | ||
| 1274 | if (ret) | 1309 | if (ret) |
| @@ -1301,16 +1336,24 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr) · 26 unmodified lines | |||
| 1301 | int ret; | 1336 | int ret; |
| 1302 | 1337 | ||
| 1303 | xa_for_each(&uq_mgr->userq_xa, queue_id, queue) { | 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 | struct dma_fence *f = queue->last_fence; | 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 | continue; | 1347 | continue; |
| 1348 | } | ||
| 1308 | ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100)); | 1349 | ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100)); |
| 1309 | if (ret <= 0) { | 1350 | if (ret <= 0) { |
| 1310 | drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n", | 1351 | drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n", |
| 1311 | f->context, f->seqno); | 1352 | f->context, f->seqno); |
| 1353 | amdgpu_userq_put(queue); | ||
| 1312 | return -ETIMEDOUT; | 1354 | return -ETIMEDOUT; |
| 1313 | } | 1355 | } |
| 1356 | amdgpu_userq_put(queue); | ||
| 1314 | } | 1357 | } |
| 1315 | 1358 | ||
| 1316 | return 0; | 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 | void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr) | 1404 | void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr) |
| 1362 | { | 1405 | { |
| 1363 | struct amdgpu_usermode_queue *queue; | 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); | 1420 | amdgpu_userq_put(queue); |
| 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); | ||
| 1374 | } | 1421 | } |
| 1375 | 1422 | ||
| 1376 | xa_destroy(&userq_mgr->userq_xa); | 1423 | xa_destroy(&userq_mgr->userq_xa); |
| 1377 | mutex_unlock(&userq_mgr->userq_mutex); | ||
| 1378 | mutex_destroy(&userq_mgr->userq_mutex); | 1424 | mutex_destroy(&userq_mgr->userq_mutex); |
| 1379 | } | 1425 | } |
| 1380 | 1426 | ||
| @@ -74,6 +74,7 @@ struct amdgpu_usermode_queue { · 73 unmodified lines | |||
| 74 | struct dentry *debugfs_queue; | 74 | struct dentry *debugfs_queue; |
| 75 | struct delayed_work hang_detect_work; | 75 | struct delayed_work hang_detect_work; |
| 76 | struct dma_fence *hang_detect_fence; | 76 | struct dma_fence *hang_detect_fence; |
| 77 | struct kref refcount; | ||
| 77 | 78 | ||
| 78 | struct list_head userq_va_list; | 79 | struct list_head userq_va_list; |
| 79 | }; | 80 | }; |
| @@ -81,6 +82,8 @@ struct amdgpu_usermode_queue { · 1 unmodified line | |||
| 81 | struct amdgpu_userq_funcs { | 82 | struct amdgpu_userq_funcs { |
| 82 | int (*mqd_create)(struct amdgpu_usermode_queue *queue, | 83 | int (*mqd_create)(struct amdgpu_usermode_queue *queue, |
| 83 | struct drm_amdgpu_userq_in *args); | 84 | struct drm_amdgpu_userq_in *args); |
| 85 | int (*mqd_update)(struct amdgpu_usermode_queue *queue, | ||
| 86 | struct drm_amdgpu_userq_in *args); | ||
| 84 | void (*mqd_destroy)(struct amdgpu_usermode_queue *uq); | 87 | void (*mqd_destroy)(struct amdgpu_usermode_queue *uq); |
| 85 | int (*unmap)(struct amdgpu_usermode_queue *queue); | 88 | int (*unmap)(struct amdgpu_usermode_queue *queue); |
| 86 | int (*map)(struct amdgpu_usermode_queue *queue); | 89 | int (*map)(struct amdgpu_usermode_queue *queue); |
| @@ -112,6 +115,9 @@ struct amdgpu_db_info { · 25 unmodified lines | |||
| 112 | struct amdgpu_userq_obj *db_obj; | 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 | int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); | 121 | int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); |
| 116 | 122 | ||
| 117 | int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv, | 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 | struct drm_file *filp) | 461 | struct drm_file *filp) |
| 462 | { | 462 | { |
| 463 | struct amdgpu_device *adev = drm_to_adev(dev); | 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 | struct amdgpu_fpriv *fpriv = filp->driver_priv; | 467 | struct amdgpu_fpriv *fpriv = filp->driver_priv; |
| 465 | struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr; | 468 | struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr; |
| 466 | struct drm_amdgpu_userq_signal *args = data; | 469 | struct drm_gem_object **gobj_write, **gobj_read; |
| 467 | struct drm_gem_object **gobj_write = NULL; | 470 | u32 *syncobj_handles, num_syncobj_handles; |
| 468 | struct drm_gem_object **gobj_read = NULL; | ||
| 469 | struct amdgpu_usermode_queue *queue; | ||
| 470 | struct amdgpu_userq_fence *userq_fence; | 471 | struct amdgpu_userq_fence *userq_fence; |
| 472 | struct amdgpu_usermode_queue *queue = NULL; | ||
| 471 | struct drm_syncobj **syncobj = NULL; | 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 | struct dma_fence *fence; | 474 | struct dma_fence *fence; |
| 477 | struct drm_exec exec; | 475 | struct drm_exec exec; |
| 476 | int r, i, entry; | ||
| 478 | u64 wptr; | 477 | u64 wptr; |
| 479 | 478 | ||
| 480 | if (!amdgpu_userq_enabled(dev)) | 479 | if (!amdgpu_userq_enabled(dev)) |
| 481 | return -ENOTSUPP; | 480 | return -ENOTSUPP; |
| 482 | 481 | ||
| 483 | if (args->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES || | 482 | if (args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || |
| 484 | args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || | ||
| 485 | args->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES) | 483 | args->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES) |
| 486 | return -EINVAL; | 484 | return -EINVAL; |
| 487 | 485 | ||
| 488 | num_syncobj_handles = args->num_syncobj_handles; | 486 | num_syncobj_handles = args->num_syncobj_handles; |
| 489 | syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles), | 487 | syncobj_handles = memdup_array_user(u64_to_user_ptr(args->syncobj_handles), |
| 490 | size_mul(sizeof(u32), num_syncobj_handles)); | 488 | num_syncobj_handles, sizeof(u32)); |
| 491 | if (IS_ERR(syncobj_handles)) | 489 | if (IS_ERR(syncobj_handles)) |
| 492 | return PTR_ERR(syncobj_handles); | 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; | 507 | r = drm_gem_objects_lookup(filp, |
| 510 | bo_handles_read = memdup_user(u64_to_user_ptr(args->bo_read_handles), | 508 | u64_to_user_ptr(args->bo_read_handles), |
| 511 | sizeof(u32) * num_read_bo_handles); | 509 | num_read_bo_handles, |
| 512 | if (IS_ERR(bo_handles_read)) { | 510 | &gobj_read); |
| 513 | r = PTR_ERR(bo_handles_read); | 511 | if (r) |
| 514 | goto free_syncobj; | 512 | goto free_syncobj; |
| 515 | } | ||
| 516 | 513 | ||
| 517 | /* Array of pointers to the GEM read objects */ | 514 | r = drm_gem_objects_lookup(filp, |
| 518 | gobj_read = kmalloc_array(num_read_bo_handles, sizeof(*gobj_read), GFP_KERNEL); | 515 | u64_to_user_ptr(args->bo_write_handles), |
| 519 | if (!gobj_read) { | 516 | num_write_bo_handles, |
| 520 | r = -ENOMEM; | 517 | &gobj_write); |
| 521 | goto free_bo_handles_read; | 518 | if (r) |
| 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); | ||
| 537 | goto put_gobj_read; | 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 | /* Retrieve the user queue */ | 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 | if (!queue) { | 523 | if (!queue) { |
| 558 | r = -ENOENT; | 524 | r = -ENOENT; |
| 559 | goto put_gobj_write; | 525 | goto put_gobj_write; |
| @@ -629,17 +595,13 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data, · 69 unmodified lines | |||
| 629 | exec_fini: | 595 | exec_fini: |
| 630 | drm_exec_fini(&exec); | 596 | drm_exec_fini(&exec); |
| 631 | put_gobj_write: | 597 | put_gobj_write: |
| 632 | while (wentry-- > 0) | 598 | for (i = 0; i < num_write_bo_handles; i++) |
| 633 | drm_gem_object_put(gobj_write[wentry]); | 599 | drm_gem_object_put(gobj_write[i]); |
| 634 | kfree(gobj_write); | 600 | kfree(gobj_write); |
| 635 | free_bo_handles_write: | ||
| 636 | kfree(bo_handles_write); | ||
| 637 | put_gobj_read: | 601 | put_gobj_read: |
| 638 | while (rentry-- > 0) | 602 | for (i = 0; i < num_read_bo_handles; i++) |
| 639 | drm_gem_object_put(gobj_read[rentry]); | 603 | drm_gem_object_put(gobj_read[i]); |
| 640 | kfree(gobj_read); | 604 | kfree(gobj_read); |
| 641 | free_bo_handles_read: | ||
| 642 | kfree(bo_handles_read); | ||
| 643 | free_syncobj: | 605 | free_syncobj: |
| 644 | while (entry-- > 0) | 606 | while (entry-- > 0) |
| 645 | if (syncobj[entry]) | 607 | if (syncobj[entry]) |
| @@ -648,98 +610,73 @@ free_syncobj: · 2 unmodified lines | |||
| 648 | free_syncobj_handles: | 610 | free_syncobj_handles: |
| 649 | kfree(syncobj_handles); | 611 | kfree(syncobj_handles); |
| 650 | 612 | ||
| 613 | if (queue) | ||
| 614 | amdgpu_userq_put(queue); | ||
| 615 | |||
| 651 | return r; | 616 | return r; |
| 652 | } | 617 | } |
| 653 | 618 | ||
| 654 | int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, | 619 | int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, |
| 655 | struct drm_file *filp) | 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 | struct drm_amdgpu_userq_wait *wait_info = data; | 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 | struct amdgpu_fpriv *fpriv = filp->driver_priv; | 626 | struct amdgpu_fpriv *fpriv = filp->driver_priv; |
| 662 | struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr; | 627 | struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr; |
| 663 | struct amdgpu_usermode_queue *waitq; | 628 | struct drm_gem_object **gobj_write, **gobj_read; |
| 664 | struct drm_gem_object **gobj_write; | 629 | u32 *timeline_points, *timeline_handles; |
| 665 | struct drm_gem_object **gobj_read; | 630 | struct amdgpu_usermode_queue *waitq = NULL; |
| 631 | u32 *syncobj_handles, num_syncobj; | ||
| 666 | struct dma_fence **fences = NULL; | 632 | struct dma_fence **fences = NULL; |
| 667 | u16 num_points, num_fences = 0; | 633 | u16 num_points, num_fences = 0; |
| 668 | int r, i, rentry, wentry, cnt; | ||
| 669 | struct drm_exec exec; | 634 | struct drm_exec exec; |
| 635 | int r, i, cnt; | ||
| 670 | 636 | ||
| 671 | if (!amdgpu_userq_enabled(dev)) | 637 | if (!amdgpu_userq_enabled(dev)) |
| 672 | return -ENOTSUPP; | 638 | return -ENOTSUPP; |
| 673 | 639 | ||
| 674 | if (wait_info->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES || | 640 | if (wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || |
| 675 | wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES || | ||
| 676 | wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES) | 641 | wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES) |
| 677 | return -EINVAL; | 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 | num_syncobj = wait_info->num_syncobj_handles; | 644 | num_syncobj = wait_info->num_syncobj_handles; |
| 694 | syncobj_handles = memdup_user(u64_to_user_ptr(wait_info->syncobj_handles), | 645 | syncobj_handles = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_handles), |
| 695 | size_mul(sizeof(u32), num_syncobj)); | 646 | num_syncobj, sizeof(u32)); |
| 696 | if (IS_ERR(syncobj_handles)) { | 647 | if (IS_ERR(syncobj_handles)) |
| 697 | r = PTR_ERR(syncobj_handles); | 648 | return PTR_ERR(syncobj_handles); |
| 698 | goto free_bo_handles_write; | 649 | |
| 699 | } | ||
| 700 | 650 | ||
| 701 | num_points = wait_info->num_syncobj_timeline_handles; | 651 | num_points = wait_info->num_syncobj_timeline_handles; |
| 702 | timeline_handles = memdup_user(u64_to_user_ptr(wait_info->syncobj_timeline_handles), | 652 | timeline_handles = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_handles), |
| 703 | sizeof(u32) * num_points); | 653 | num_points, sizeof(u32)); |
| 704 | if (IS_ERR(timeline_handles)) { | 654 | if (IS_ERR(timeline_handles)) { |
| 705 | r = PTR_ERR(timeline_handles); | 655 | r = PTR_ERR(timeline_handles); |
| 706 | goto free_syncobj_handles; | 656 | goto free_syncobj_handles; |
| 707 | } | 657 | } |
| 708 | 658 | ||
| 709 | timeline_points = memdup_user(u64_to_user_ptr(wait_info->syncobj_timeline_points), | 659 | timeline_points = memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_points), |
| 710 | sizeof(u32) * num_points); | 660 | num_points, sizeof(u32)); |
| 661 | |||
| 711 | if (IS_ERR(timeline_points)) { | 662 | if (IS_ERR(timeline_points)) { |
| 712 | r = PTR_ERR(timeline_points); | 663 | r = PTR_ERR(timeline_points); |
| 713 | goto free_timeline_handles; | 664 | goto free_timeline_handles; |
| 714 | } | 665 | } |
| 715 | 666 | ||
| 716 | gobj_read = kmalloc_array(num_read_bo_handles, sizeof(*gobj_read), GFP_KERNEL); | 667 | r = drm_gem_objects_lookup(filp, |
| 717 | if (!gobj_read) { | 668 | u64_to_user_ptr(wait_info->bo_read_handles), |
| 718 | r = -ENOMEM; | 669 | num_read_bo_handles, |
| 670 | &gobj_read); | ||
| 671 | if (r) | ||
| 719 | goto free_timeline_points; | 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); | 674 | r = drm_gem_objects_lookup(filp, |
| 731 | if (!gobj_write) { | 675 | u64_to_user_ptr(wait_info->bo_write_handles), |
| 732 | r = -ENOMEM; | 676 | num_write_bo_handles, |
| 677 | &gobj_write); | ||
| 678 | if (r) | ||
| 733 | goto put_gobj_read; | 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 | drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, | 681 | drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, |
| 745 | (num_read_bo_handles + num_write_bo_handles)); | 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 | num_fences = dma_fence_dedup_array(fences, num_fences); | 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 | if (!waitq) { | 867 | if (!waitq) { |
| 931 | r = -EINVAL; | 868 | r = -EINVAL; |
| 932 | goto free_fences; | 869 | goto free_fences; |
| @@ -983,43 +920,25 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, · 50 unmodified lines | |||
| 983 | r = -EFAULT; | 920 | r = -EFAULT; |
| 984 | goto free_fences; | 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 | free_fences: | 925 | free_fences: |
| 1009 | while (num_fences-- > 0) | 926 | if (fences) { |
| 1010 | dma_fence_put(fences[num_fences]); | 927 | while (num_fences-- > 0) |
| 1011 | kfree(fences); | 928 | dma_fence_put(fences[num_fences]); |
| 929 | kfree(fences); | ||
| 930 | } | ||
| 1012 | free_fence_info: | 931 | free_fence_info: |
| 1013 | kfree(fence_info); | 932 | kfree(fence_info); |
| 1014 | exec_fini: | 933 | exec_fini: |
| 1015 | drm_exec_fini(&exec); | 934 | drm_exec_fini(&exec); |
| 1016 | put_gobj_write: | 935 | put_gobj_write: |
| 1017 | while (wentry-- > 0) | 936 | for (i = 0; i < num_write_bo_handles; i++) |
| 1018 | drm_gem_object_put(gobj_write[wentry]); | 937 | drm_gem_object_put(gobj_write[i]); |
| 1019 | kfree(gobj_write); | 938 | kfree(gobj_write); |
| 1020 | put_gobj_read: | 939 | put_gobj_read: |
| 1021 | while (rentry-- > 0) | 940 | for (i = 0; i < num_read_bo_handles; i++) |
| 1022 | drm_gem_object_put(gobj_read[rentry]); | 941 | drm_gem_object_put(gobj_read[i]); |
| 1023 | kfree(gobj_read); | 942 | kfree(gobj_read); |
| 1024 | free_timeline_points: | 943 | free_timeline_points: |
| 1025 | kfree(timeline_points); | 944 | kfree(timeline_points); |
| @@ -1027,10 +946,9 @@ free_timeline_handles: · 1 unmodified line | |||
| 1027 | kfree(timeline_handles); | 946 | kfree(timeline_handles); |
| 1028 | free_syncobj_handles: | 947 | free_syncobj_handles: |
| 1029 | kfree(syncobj_handles); | 948 | kfree(syncobj_handles); |
| 1030 | free_bo_handles_write: | 949 | |
| 1031 | kfree(bo_handles_write); | 950 | if (waitq) |
| 1032 | free_bo_handles_read: | 951 | amdgpu_userq_put(waitq); |
| 1033 | kfree(bo_handles_read); | ||
| 1034 | 952 | ||
| 1035 | return r; | 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 | * amdgpu_vce_get_create_msg - generate a VCE create msg | 454 | * amdgpu_vce_get_create_msg - generate a VCE create msg |
| 473 | * | 455 | * |
| @@ -52,6 +52,7 @@ struct amdgpu_vce { · 51 unmodified lines | |||
| 52 | uint32_t srbm_soft_reset; | 52 | uint32_t srbm_soft_reset; |
| 53 | unsigned num_rings; | 53 | unsigned num_rings; |
| 54 | uint32_t keyselect; | 54 | uint32_t keyselect; |
| 55 | struct drm_mm_node gart_node; | ||
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | int amdgpu_vce_early_init(struct amdgpu_device *adev); | 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 | int amdgpu_vce_suspend(struct amdgpu_device *adev); | 62 | int amdgpu_vce_suspend(struct amdgpu_device *adev); |
| 62 | int amdgpu_vce_resume(struct amdgpu_device *adev); | 63 | int amdgpu_vce_resume(struct amdgpu_device *adev); |
| 63 | void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp); | 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 | int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, struct amdgpu_job *job, | 65 | int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, struct amdgpu_job *job, |
| 66 | struct amdgpu_ib *ib); | 66 | struct amdgpu_ib *ib); |
| 67 | int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, | 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 | * @need_pipe_sync: is pipe sync needed | 764 | * @need_pipe_sync: is pipe sync needed |
| 765 | * | 765 | * |
| 766 | * Emit a VM flush when it is necessary. | 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, | 768 | void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, |
| 772 | bool need_pipe_sync) | 769 | bool need_pipe_sync) |
| 773 | { | 770 | { |
| 774 | struct amdgpu_device *adev = ring->adev; | 771 | struct amdgpu_device *adev = ring->adev; |
| 775 | struct amdgpu_isolation *isolation = &adev->isolation[ring->xcp_id]; | 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 | bool cleaner_shader_needed = false; | 780 | bool cleaner_shader_needed = false; |
| 784 | bool pasid_mapping_needed = false; | 781 | bool pasid_mapping_needed = false; |
| 785 | struct dma_fence *fence = NULL; | 782 | struct dma_fence *fence = NULL; |
| 786 | unsigned int patch; | 783 | unsigned int patch = 0; |
| 787 | int r; | ||
| 788 | 784 | ||
| 789 | if (amdgpu_vmid_had_gpu_reset(adev, id)) { | 785 | if (amdgpu_vmid_had_gpu_reset(adev, id)) { |
| 790 | gds_switch_needed = true; | 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 | if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync && | 809 | if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync && |
| 814 | !cleaner_shader_needed) | 810 | !cleaner_shader_needed) |
| 815 | return 0; | 811 | return; |
| 816 | 812 | ||
| 817 | amdgpu_ring_ib_begin(ring); | 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 | if (ring->funcs->init_cond_exec) | 825 | if (ring->funcs->init_cond_exec) |
| 819 | patch = amdgpu_ring_init_cond_exec(ring, | 826 | patch = amdgpu_ring_init_cond_exec(ring, |
| 820 | ring->cond_exe_gpu_addr); | 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 | if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) { | 854 | if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) { |
| 848 | r = amdgpu_fence_emit(ring, job->hw_vm_fence, 0); | 855 | amdgpu_fence_emit(ring, job->hw_vm_fence, 0); |
| 849 | if (r) | ||
| 850 | return r; | ||
| 851 | fence = &job->hw_vm_fence->base; | 856 | fence = &job->hw_vm_fence->base; |
| 852 | /* get a ref for the job */ | 857 | /* get a ref for the job */ |
| 853 | dma_fence_get(fence); | 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 | amdgpu_ring_ib_end(ring); | 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 | task_info->process_name, task_info->tgid, | 3214 | task_info->process_name, task_info->tgid, |
| 3211 | task_info->task.comm, task_info->task.pid); | 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 | struct ww_acquire_ctx *ticket, | 513 | struct ww_acquire_ctx *ticket, |
| 514 | int (*callback)(void *p, struct amdgpu_bo *bo), | 514 | int (*callback)(void *p, struct amdgpu_bo *bo), |
| 515 | void *param); | 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 | int amdgpu_vm_update_pdes(struct amdgpu_device *adev, | 517 | int amdgpu_vm_update_pdes(struct amdgpu_device *adev, |
| 518 | struct amdgpu_vm *vm, bool immediate); | 518 | struct amdgpu_vm *vm, bool immediate); |
| 519 | int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | 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 | if (!(adev->aid_mask & BIT(i))) | 338 | if (!(adev->aid_mask & BIT(i))) |
| 339 | return U32_MAX; | 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 | return RREG32_PCIE_EXT(addr); | 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 | u32 xgmi_state_reg_val; | 348 | u32 xgmi_state_reg_val; |
| 349 | 349 | ||
| 350 | if (amdgpu_sriov_vf(adev)) | ||
| 351 | return AMDGPU_XGMI_LINK_NA; | ||
| 352 | |||
| 350 | if (adev->gmc.xgmi.num_physical_nodes <= 1) | 353 | if (adev->gmc.xgmi.num_physical_nodes <= 1) |
| 351 | return -EINVAL; | 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 | static void __xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst, u64 mca_base) | 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 | static void xgmi_v6_4_0_reset_error_count(struct amdgpu_device *adev, int xgmi_inst) | 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 | u64 mca_base, struct ras_err_data *err_data) | 1506 | u64 mca_base, struct ras_err_data *err_data) |
| 1501 | { | 1507 | { |
| 1502 | int xgmi_inst = mcm_info->die_id; | 1508 | int xgmi_inst = mcm_info->die_id; |
| 1509 | uint64_t smn_base; | ||
| 1503 | u64 status = 0; | 1510 | u64 status = 0; |
| 1504 | 1511 | ||
| 1505 | status = RREG64_MCA(xgmi_inst, mca_base, ACA_REG_IDX_STATUS); | 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 | default: | 1523 | default: |
| 1517 | break; | 1524 | break; |
| 1518 | } | 1525 | } |
| 1519 | 1526 | smn_base = amdgpu_reg_get_smn_base64(adev, XGMI_HWIP, xgmi_inst); | |
| 1520 | WREG64_MCA(xgmi_inst, mca_base, ACA_REG_IDX_STATUS, 0ULL); | 1527 | WREG64_MCA(smn_base, mca_base, ACA_REG_IDX_STATUS, 0ULL); |
| 1521 | } | 1528 | } |
| 1522 | 1529 | ||
| 1523 | static void xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, int xgmi_inst, struct ras_err_data *err_data) | 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 | uint32_t hit; | 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 | struct amdsriov_ras_telemetry { | 486 | struct amdsriov_ras_telemetry { |
| 474 | struct amd_sriov_ras_telemetry_header header; | 487 | struct amd_sriov_ras_telemetry_header header; |
| 475 | 488 | union amd_sriov_ras_host_push body; | |
| 476 | union { | 489 | struct amd_sriov_uniras_shared_mem uniras_shared_mem; |
| 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; | ||
| 481 | }; | 490 | }; |
| 482 | 491 | ||
| 483 | /* version data stored in MAILBOX_MSGBUF_RCV_DW1 for future expansion */ | 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 | _Static_assert(AMD_SRIOV_MSG_RESERVE_UCODE > AMD_SRIOV_UCODE_ID__MAX, | 519 | _Static_assert(AMD_SRIOV_MSG_RESERVE_UCODE > AMD_SRIOV_UCODE_ID__MAX, |
| 511 | "AMD_SRIOV_MSG_RESERVE_UCODE must be bigger than AMD_SRIOV_UCODE_ID__MAX"); | 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 | #undef _stringification | 526 | #undef _stringification |
| 514 | #undef stringification | 527 | #undef stringification |
| 515 | #endif | 528 | #endif |
| @@ -58,25 +58,6 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev) · 57 unmodified lines | |||
| 58 | adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1; | 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 | static enum amdgpu_gfx_partition | 61 | static enum amdgpu_gfx_partition |
| 81 | __aqua_vanjaram_calc_xcp_mode(struct amdgpu_xcp_mgr *xcp_mgr) | 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 | uint64_t smn_addr, int i) | 571 | uint64_t smn_addr, int i) |
| 591 | { | 572 | { |
| 592 | regdata->addr = | 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 | regdata->value = RREG32_PCIE_EXT(regdata->addr); | 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 | ctx->vbios_pn[count] = 0; | 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 | static void atom_get_vbios_version(struct atom_context *ctx) | 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 | strscpy(ctx->build_num, str, len); | 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 | struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) | 1545 | struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) |
| 1524 | { | 1546 | { |
| 1525 | int base; | 1547 | int base; |
| @@ -1582,6 +1604,8 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) · 56 unmodified lines | |||
| 1582 | atom_get_vbios_version(ctx); | 1604 | atom_get_vbios_version(ctx); |
| 1583 | atom_get_vbios_build(ctx); | 1605 | atom_get_vbios_build(ctx); |
| 1584 | 1606 | ||
| 1607 | atom_print_vbios_info(ctx); | ||
| 1608 | |||
| 1585 | return ctx; | 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 | unsigned long flags; | 154 | unsigned long flags; |
| 155 | u32 r; | 155 | u32 r; |
| 156 | 156 | ||
| 157 | spin_lock_irqsave(&adev->pcie_idx_lock, flags); | 157 | spin_lock_irqsave(&adev->reg.pcie.lock, flags); |
| 158 | WREG32(mmPCIE_INDEX, reg); | 158 | WREG32(mmPCIE_INDEX, reg); |
| 159 | (void)RREG32(mmPCIE_INDEX); | 159 | (void)RREG32(mmPCIE_INDEX); |
| 160 | r = RREG32(mmPCIE_DATA); | 160 | r = RREG32(mmPCIE_DATA); |
| 161 | spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); | 161 | spin_unlock_irqrestore(&adev->reg.pcie.lock, flags); |
| 162 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmPCIE_INDEX, reg); | 170 | WREG32(mmPCIE_INDEX, reg); |
| 171 | (void)RREG32(mmPCIE_INDEX); | 171 | (void)RREG32(mmPCIE_INDEX); |
| 172 | WREG32(mmPCIE_DATA, v); | 172 | WREG32(mmPCIE_DATA, v); |
| 173 | (void)RREG32(mmPCIE_DATA); | 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 | static u32 cik_smc_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 179 | unsigned long flags; |
| 180 | u32 r; | 180 | u32 r; |
| 181 | 181 | ||
| 182 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | 182 | spin_lock_irqsave(&adev->reg.smc.lock, flags); |
| 183 | WREG32(mmSMC_IND_INDEX_0, (reg)); | 183 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 184 | r = RREG32(mmSMC_IND_DATA_0); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmSMC_IND_INDEX_0, (reg)); | 194 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 195 | WREG32(mmSMC_IND_DATA_0, (v)); | 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 | static u32 cik_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 201 | unsigned long flags; |
| 202 | u32 r; | 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 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); | 205 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 206 | r = RREG32(mmUVD_CTX_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); | 216 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 217 | WREG32(mmUVD_CTX_DATA, (v)); | 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 | static u32 cik_didt_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 223 | unsigned long flags; |
| 224 | u32 r; | 224 | u32 r; |
| 225 | 225 | ||
| 226 | spin_lock_irqsave(&adev->didt_idx_lock, flags); | 226 | spin_lock_irqsave(&adev->reg.didt.lock, flags); |
| 227 | WREG32(mmDIDT_IND_INDEX, (reg)); | 227 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 228 | r = RREG32(mmDIDT_IND_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmDIDT_IND_INDEX, (reg)); | 238 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 239 | WREG32(mmDIDT_IND_DATA, (v)); | 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 | static const u32 bonaire_golden_spm_registers[] = | 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 | dw_ptr = (u32 *)bios; | 1027 | dw_ptr = (u32 *)bios; |
| 1028 | length_dw = ALIGN(length_bytes, 4) / 4; | 1028 | length_dw = ALIGN(length_bytes, 4) / 4; |
| 1029 | /* take the smc lock since we are using the smc index */ | 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 | /* set rom index to 0 */ | 1031 | /* set rom index to 0 */ |
| 1032 | WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX); | 1032 | WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX); |
| 1033 | WREG32(mmSMC_IND_DATA_0, 0); | 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 | WREG32(mmSMC_IND_INDEX_0, ixROM_DATA); | 1035 | WREG32(mmSMC_IND_INDEX_0, ixROM_DATA); |
| 1036 | for (i = 0; i < length_dw; i++) | 1036 | for (i = 0; i < length_dw; i++) |
| 1037 | dw_ptr[i] = RREG32(mmSMC_IND_DATA_0); | 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 | return true; | 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 | struct amdgpu_device *adev = ip_block->adev; | 1985 | struct amdgpu_device *adev = ip_block->adev; |
| 1986 | 1986 | ||
| 1987 | adev->smc_rreg = &cik_smc_rreg; | 1987 | adev->reg.smc.rreg = cik_smc_rreg; |
| 1988 | adev->smc_wreg = &cik_smc_wreg; | 1988 | adev->reg.smc.wreg = cik_smc_wreg; |
| 1989 | adev->pcie_rreg = &cik_pcie_rreg; | 1989 | adev->reg.pcie.rreg = &cik_pcie_rreg; |
| 1990 | adev->pcie_wreg = &cik_pcie_wreg; | 1990 | adev->reg.pcie.wreg = &cik_pcie_wreg; |
| 1991 | adev->uvd_ctx_rreg = &cik_uvd_ctx_rreg; | 1991 | adev->reg.uvd_ctx.rreg = &cik_uvd_ctx_rreg; |
| 1992 | adev->uvd_ctx_wreg = &cik_uvd_ctx_wreg; | 1992 | adev->reg.uvd_ctx.wreg = &cik_uvd_ctx_wreg; |
| 1993 | adev->didt_rreg = &cik_didt_rreg; | 1993 | adev->reg.didt.rreg = &cik_didt_rreg; |
| 1994 | adev->didt_wreg = &cik_didt_wreg; | 1994 | adev->reg.didt.wreg = &cik_didt_wreg; |
| 1995 | 1995 | ||
| 1996 | adev->asic_funcs = &cik_asic_funcs; | 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 | static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev); | 53 | static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev); |
| 54 | static void cik_sdma_set_irq_funcs(struct amdgpu_device *adev); | 54 | static void cik_sdma_set_irq_funcs(struct amdgpu_device *adev); |
| 55 | static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static int cik_sdma_soft_reset(struct amdgpu_ip_block *ip_block); | 56 | static int cik_sdma_soft_reset(struct amdgpu_ip_block *ip_block); |
| 58 | 57 | ||
| 59 | u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev); | 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 | static int cik_sdma_early_init(struct amdgpu_ip_block *ip_block) | 929 | static int cik_sdma_early_init(struct amdgpu_ip_block *ip_block) |
| 923 | { | 930 | { |
| 924 | struct amdgpu_device *adev = ip_block->adev; | 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 | cik_sdma_set_ring_funcs(adev); | 940 | cik_sdma_set_ring_funcs(adev); |
| 934 | cik_sdma_set_irq_funcs(adev); | 941 | cik_sdma_set_irq_funcs(adev); |
| 935 | cik_sdma_set_buffer_funcs(adev); | 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 | return 0; | 945 | return 0; |
| 939 | } | 946 | } |
| @@ -1337,26 +1344,6 @@ static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev) · 397 unmodified lines | |||
| 1337 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version cik_sdma_ip_block = | 1347 | const struct amdgpu_ip_block_version cik_sdma_ip_block = |
| 1361 | { | 1348 | { |
| 1362 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 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 | unsigned long flags; | 175 | unsigned long flags; |
| 176 | u32 r; | 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 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | 179 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 180 | r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | 192 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 193 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset, v); | 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 | static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) | 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 | struct amdgpu_device *adev = ip_block->adev; | 2751 | struct amdgpu_device *adev = ip_block->adev; |
| 2752 | 2752 | ||
| 2753 | adev->audio_endpt_rreg = &dce_v10_0_audio_endpt_rreg; | 2753 | adev->reg.audio_endpt.rreg = &dce_v10_0_audio_endpt_rreg; |
| 2754 | adev->audio_endpt_wreg = &dce_v10_0_audio_endpt_wreg; | 2754 | adev->reg.audio_endpt.wreg = &dce_v10_0_audio_endpt_wreg; |
| 2755 | 2755 | ||
| 2756 | dce_v10_0_set_display_funcs(adev); | 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 | unsigned long flags; | 138 | unsigned long flags; |
| 139 | u32 r; | 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 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | 142 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 143 | r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, | 155 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, |
| 156 | reg | AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_WRITE_EN_MASK); | 156 | reg | AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_WRITE_EN_MASK); |
| 157 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset, v); | 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 | static u32 dce_v6_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) | 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 | struct amdgpu_device *adev = ip_block->adev; | 2698 | struct amdgpu_device *adev = ip_block->adev; |
| 2699 | 2699 | ||
| 2700 | adev->audio_endpt_rreg = &dce_v6_0_audio_endpt_rreg; | 2700 | adev->reg.audio_endpt.rreg = &dce_v6_0_audio_endpt_rreg; |
| 2701 | adev->audio_endpt_wreg = &dce_v6_0_audio_endpt_wreg; | 2701 | adev->reg.audio_endpt.wreg = &dce_v6_0_audio_endpt_wreg; |
| 2702 | 2702 | ||
| 2703 | dce_v6_0_set_display_funcs(adev); | 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 | unsigned long flags; | 126 | unsigned long flags; |
| 127 | u32 r; | 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 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | 130 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 131 | r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); | 143 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); |
| 144 | WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset, v); | 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 | static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) | 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 | struct amdgpu_device *adev = ip_block->adev; | 2656 | struct amdgpu_device *adev = ip_block->adev; |
| 2657 | 2657 | ||
| 2658 | adev->audio_endpt_rreg = &dce_v8_0_audio_endpt_rreg; | 2658 | adev->reg.audio_endpt.rreg = &dce_v8_0_audio_endpt_rreg; |
| 2659 | adev->audio_endpt_wreg = &dce_v8_0_audio_endpt_wreg; | 2659 | adev->reg.audio_endpt.wreg = &dce_v8_0_audio_endpt_wreg; |
| 2660 | 2660 | ||
| 2661 | dce_v8_0_set_display_funcs(adev); | 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 | address = adev->nbio.funcs->get_pcie_index_offset(adev); | 51 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 52 | data = adev->nbio.funcs->get_pcie_data_offset(adev); | 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 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3); | 55 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3); |
| 56 | WREG32(data, ficaa_val); | 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 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3); | 61 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3); |
| 62 | ficadh_val = RREG32(data); | 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 | return (((ficadh_val & 0xFFFFFFFFFFFFFFFF) << 32) | ficadl_val); | 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 | address = adev->nbio.funcs->get_pcie_index_offset(adev); | 74 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 75 | data = adev->nbio.funcs->get_pcie_data_offset(adev); | 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 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3); | 78 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3); |
| 79 | WREG32(data, ficaa_val); | 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 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3); | 84 | WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3); |
| 85 | WREG32(data, ficadh_val); | 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 | address = adev->nbio.funcs->get_pcie_index_offset(adev); | 102 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 103 | data = adev->nbio.funcs->get_pcie_data_offset(adev); | 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 | WREG32(address, lo_addr); | 106 | WREG32(address, lo_addr); |
| 107 | *lo_val = RREG32(data); | 107 | *lo_val = RREG32(data); |
| 108 | WREG32(address, hi_addr); | 108 | WREG32(address, hi_addr); |
| 109 | *hi_val = RREG32(data); | 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 | address = adev->nbio.funcs->get_pcie_index_offset(adev); | 124 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 125 | data = adev->nbio.funcs->get_pcie_data_offset(adev); | 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 | WREG32(address, lo_addr); | 128 | WREG32(address, lo_addr); |
| 129 | WREG32(data, lo_val); | 129 | WREG32(data, lo_val); |
| 130 | WREG32(address, hi_addr); | 130 | WREG32(address, hi_addr); |
| 131 | WREG32(data, hi_val); | 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 | /* same as perfmon_wreg but return status on write value check */ | 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 | address = adev->nbio.funcs->get_pcie_index_offset(adev); | 143 | address = adev->nbio.funcs->get_pcie_index_offset(adev); |
| 144 | data = adev->nbio.funcs->get_pcie_data_offset(adev); | 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 | WREG32(address, lo_addr); | 147 | WREG32(address, lo_addr); |
| 148 | WREG32(data, lo_val); | 148 | WREG32(data, lo_val); |
| 149 | WREG32(address, hi_addr); | 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 | lo_val_rb = RREG32(data); | 153 | lo_val_rb = RREG32(data); |
| 154 | WREG32(address, hi_addr); | 154 | WREG32(address, hi_addr); |
| 155 | hi_val_rb = RREG32(data); | 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 | if (!(lo_val == lo_val_rb && hi_val == hi_val_rb)) | 158 | if (!(lo_val == lo_val_rb && hi_val == hi_val_rb)) |
| 159 | return -EBUSY; | 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 | return gfx_v11_0_cp_gfx_start(adev); | 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 | static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, | 4272 | static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, |
| 4242 | struct amdgpu_mqd_prop *prop) | 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 | /* set UQ fenceaddress */ | 4403 | /* set UQ fenceaddress */ |
| 4373 | mqd->fence_address_lo = lower_32_bits(prop->fence_address); | 4404 | mqd->fence_address_lo = lower_32_bits(prop->fence_address); |
| 4374 | mqd->fence_address_hi = upper_32_bits(prop->fence_address); | 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 | return 0; | 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 | return gfx_v12_0_cp_gfx_start(adev); | 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 | static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, | 3143 | static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, |
| 3113 | struct amdgpu_mqd_prop *prop) | 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 | /* set UQ fenceaddress */ | 3273 | /* set UQ fenceaddress */ |
| 3243 | mqd->fence_address_lo = lower_32_bits(prop->fence_address); | 3274 | mqd->fence_address_lo = lower_32_bits(prop->fence_address); |
| 3244 | mqd->fence_address_hi = upper_32_bits(prop->fence_address); | 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 | return 0; | 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 | * Configure apertures: | 1406 | * Configure apertures: |
| 1407 | * LDS: 0x20000000'00000000 - 0x20000001'00000000 (4GB) | 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 | sh_mem_bases = REG_SET_FIELD(0, SH_MEM_BASES, PRIVATE_BASE, | 1410 | sh_mem_bases = REG_SET_FIELD(0, SH_MEM_BASES, PRIVATE_BASE, |
| 1411 | (adev->gmc.private_aperture_start >> 58)); | 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 | adev->gmc.shared_aperture_start = 0x2000000000000000ULL; | 654 | adev->gmc.shared_aperture_start = 0x2000000000000000ULL; |
| 655 | adev->gmc.shared_aperture_end = | 655 | adev->gmc.shared_aperture_end = |
| 656 | adev->gmc.shared_aperture_start + (4ULL << 30) - 1; | 656 | adev->gmc.shared_aperture_start + (4ULL << 30) - 1; |
| 657 | |||
| 657 | adev->gmc.private_aperture_start = 0x1000000000000000ULL; | 658 | adev->gmc.private_aperture_start = 0x1000000000000000ULL; |
| 658 | adev->gmc.private_aperture_end = | 659 | if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0)) |
| 659 | adev->gmc.private_aperture_start + (4ULL << 30) - 1; | 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 | adev->gmc.noretry_flags = AMDGPU_VM_NORETRY_FLAGS_TF; | 666 | adev->gmc.noretry_flags = AMDGPU_VM_NORETRY_FLAGS_TF; |
| 661 | 667 | ||
| 662 | return 0; | 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 | return; | 345 | return; |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | mutex_lock(&adev->mman.gtt_window_lock); | ||
| 349 | gmc_v12_1_flush_vm_hub(adev, vmid, vmhub, 0); | 348 | gmc_v12_1_flush_vm_hub(adev, vmid, vmhub, 0); |
| 350 | mutex_unlock(&adev->mman.gtt_window_lock); | ||
| 351 | return; | 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 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); | 283 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 284 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); | 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 | WREG32(address, (reg)); | 287 | WREG32(address, (reg)); |
| 288 | r = RREG32(data); | 288 | r = RREG32(data); |
| 289 | spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | 289 | spin_unlock_irqrestore(&adev->reg.didt.lock, flags); |
| 290 | return r; | 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 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); | 297 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 298 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); | 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 | WREG32(address, (reg)); | 301 | WREG32(address, (reg)); |
| 302 | WREG32(data, (v)); | 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 | static u32 nv_get_config_memsize(struct amdgpu_device *adev) | 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 | struct amdgpu_device *adev = ip_block->adev; | 635 | struct amdgpu_device *adev = ip_block->adev; |
| 636 | 636 | ||
| 637 | adev->nbio.funcs->set_reg_remap(adev); | 637 | adev->nbio.funcs->set_reg_remap(adev); |
| 638 | adev->smc_rreg = NULL; | 638 | adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; |
| 639 | adev->smc_wreg = NULL; | 639 | adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; |
| 640 | adev->pcie_rreg = &amdgpu_device_indirect_rreg; | 640 | adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; |
| 641 | adev->pcie_wreg = &amdgpu_device_indirect_wreg; | 641 | adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; |
| 642 | adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | 642 | adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; |
| 643 | adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | 643 | adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; |
| 644 | adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | 644 | |
| 645 | adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | 645 | adev->reg.didt.rreg = &nv_didt_rreg; |
| 646 | 646 | adev->reg.didt.wreg = &nv_didt_wreg; | |
| 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; | ||
| 653 | 647 | ||
| 654 | adev->asic_funcs = &nv_asic_funcs; | 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 | bl_status_reg = | 166 | bl_status_reg = |
| 167 | (SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_92) | 167 | (SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_92) |
| 168 | << 2) + | 168 | << 2) + |
| 169 | adev->asic_funcs->encode_ext_smn_addressing(i); | 169 | amdgpu_reg_get_smn_base64(adev, MP0_HWIP, i); |
| 170 | at += snprintf(bl_status_msg + at, | 170 | at += snprintf(bl_status_msg + at, |
| 171 | PSP13_BL_STATUS_SIZE - at, | 171 | PSP13_BL_STATUS_SIZE - at, |
| 172 | " status(%02i): 0x%08x", i, | 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 | 0x80000000, 0x80000000, false); | 69 | 0x80000000, 0x80000000, false); |
| 70 | } else { | 70 | } else { |
| 71 | /* Write the ring destroy command*/ | 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 | GFX_CTRL_CMD_ID_DESTROY_RINGS); | 73 | GFX_CTRL_CMD_ID_DESTROY_RINGS); |
| 74 | /* there might be handshake issue with hardware which needs delay */ | 74 | /* there might be handshake issue with hardware which needs delay */ |
| 75 | mdelay(20); | 75 | mdelay(20); |
| 76 | /* Wait for response flag (bit 31) */ | 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 | 0x80000000, 0x80000000, false); | 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 | } else { | 117 | } else { |
| 118 | /* Wait for sOS ready for ring creation */ | 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 | 0x80000000, 0x80000000, false); | 120 | 0x80000000, 0x80000000, false); |
| 121 | if (ret) { | 121 | if (ret) { |
| 122 | DRM_ERROR("Failed to wait for trust OS ready for ring creation\n"); | 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 | /* Write low address of the ring to C2PMSG_69 */ | 126 | /* Write low address of the ring to C2PMSG_69 */ |
| 127 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | 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 | /* Write high address of the ring to C2PMSG_70 */ | 129 | /* Write high address of the ring to C2PMSG_70 */ |
| 130 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | 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 | /* Write size of ring to C2PMSG_71 */ | 132 | /* Write size of ring to C2PMSG_71 */ |
| 133 | psp_ring_reg = ring->ring_size; | 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 | /* Write the ring initialization command to C2PMSG_64 */ | 135 | /* Write the ring initialization command to C2PMSG_64 */ |
| 136 | psp_ring_reg = ring_type; | 136 | psp_ring_reg = ring_type; |
| 137 | psp_ring_reg = psp_ring_reg << 16; | 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 | /* there might be handshake issue with hardware which needs delay */ | 140 | /* there might be handshake issue with hardware which needs delay */ |
| 141 | mdelay(20); | 141 | mdelay(20); |
| 142 | 142 | ||
| 143 | /* Wait for response flag (bit 31) in C2PMSG_64 */ | 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 | 0x80000000, 0x8000FFFF, false); | 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 | if (amdgpu_sriov_vf(adev)) | 174 | if (amdgpu_sriov_vf(adev)) |
| 175 | data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102); | 175 | data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102); |
| 176 | else | 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 | return data; | 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 | WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101, | 188 | WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101, |
| 189 | GFX_CTRL_CMD_ID_CONSUME_CMD); | 189 | GFX_CTRL_CMD_ID_CONSUME_CMD); |
| 190 | } else | 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 | static const struct psp_funcs psp_v15_0_0_funcs = { | 194 | static const struct psp_funcs psp_v15_0_0_funcs = { |
| @@ -51,7 +51,6 @@ · 50 unmodified lines | |||
| 51 | 51 | ||
| 52 | static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev); | 52 | static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev); |
| 53 | static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v2_4_set_irq_funcs(struct amdgpu_device *adev); | 54 | static void sdma_v2_4_set_irq_funcs(struct amdgpu_device *adev); |
| 56 | 55 | ||
| 57 | MODULE_FIRMWARE("amdgpu/topaz_sdma.bin"); | 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 | amdgpu_ring_write(ring, val); | 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 | static int sdma_v2_4_early_init(struct amdgpu_ip_block *ip_block) | 819 | static int sdma_v2_4_early_init(struct amdgpu_ip_block *ip_block) |
| 813 | { | 820 | { |
| 814 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v2_4_set_ring_funcs(adev); | 830 | sdma_v2_4_set_ring_funcs(adev); |
| 824 | sdma_v2_4_set_buffer_funcs(adev); | 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 | sdma_v2_4_set_irq_funcs(adev); | 833 | sdma_v2_4_set_irq_funcs(adev); |
| 827 | 834 | ||
| 828 | return 0; | 835 | return 0; |
| @@ -1232,26 +1239,6 @@ static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev) · 403 unmodified lines | |||
| 1232 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version sdma_v2_4_ip_block = { | 1242 | const struct amdgpu_ip_block_version sdma_v2_4_ip_block = { |
| 1256 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 1243 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1257 | .major = 2, | 1244 | .major = 2, |
| @@ -51,7 +51,6 @@ · 50 unmodified lines | |||
| 51 | 51 | ||
| 52 | static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev); | 52 | static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev); |
| 53 | static void sdma_v3_0_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v3_0_set_irq_funcs(struct amdgpu_device *adev); | 54 | static void sdma_v3_0_set_irq_funcs(struct amdgpu_device *adev); |
| 56 | 55 | ||
| 57 | MODULE_FIRMWARE("amdgpu/tonga_sdma.bin"); | 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 | amdgpu_ring_write(ring, val); | 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 | static int sdma_v3_0_early_init(struct amdgpu_ip_block *ip_block) | 1092 | static int sdma_v3_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1086 | { | 1093 | { |
| 1087 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v3_0_set_ring_funcs(adev); | 1110 | sdma_v3_0_set_ring_funcs(adev); |
| 1104 | sdma_v3_0_set_buffer_funcs(adev); | 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 | sdma_v3_0_set_irq_funcs(adev); | 1113 | sdma_v3_0_set_irq_funcs(adev); |
| 1107 | 1114 | ||
| 1108 | return 0; | 1115 | return 0; |
| @@ -1674,26 +1681,6 @@ static void sdma_v3_0_set_buffer_funcs(struct amdgpu_device *adev) · 565 unmodified lines | |||
| 1674 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version sdma_v3_0_ip_block = | 1684 | const struct amdgpu_ip_block_version sdma_v3_0_ip_block = |
| 1698 | { | 1685 | { |
| 1699 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 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 | static void sdma_v4_0_set_ring_funcs(struct amdgpu_device *adev); | 130 | static void sdma_v4_0_set_ring_funcs(struct amdgpu_device *adev); |
| 131 | static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev); | 132 | static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev); |
| 134 | static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev); | 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 | static int sdma_v4_0_early_init(struct amdgpu_ip_block *ip_block) | 1761 | static int sdma_v4_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1755 | { | 1762 | { |
| 1756 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v4_0_set_ring_funcs(adev); | 1777 | sdma_v4_0_set_ring_funcs(adev); |
| 1771 | sdma_v4_0_set_buffer_funcs(adev); | 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 | sdma_v4_0_set_irq_funcs(adev); | 1780 | sdma_v4_0_set_irq_funcs(adev); |
| 1774 | sdma_v4_0_set_ras_funcs(adev); | 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 | static const struct amdgpu_buffer_funcs sdma_v4_0_buffer_funcs = { | 2606 | static const struct amdgpu_buffer_funcs sdma_v4_0_buffer_funcs = { |
| 2600 | .copy_max_bytes = 0x400000, | 2607 | .copy_max_bytes = 1 << 22, |
| 2601 | .copy_num_dw = 7, | 2608 | .copy_num_dw = 7, |
| 2602 | .emit_copy_buffer = sdma_v4_0_emit_copy_buffer, | 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 | .fill_num_dw = 5, | 2622 | .fill_num_dw = 5, |
| 2606 | .emit_fill_buffer = sdma_v4_0_emit_fill_buffer, | 2623 | .emit_fill_buffer = sdma_v4_0_emit_fill_buffer, |
| 2607 | }; | 2624 | }; |
| 2608 | 2625 | ||
| 2609 | static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev) | 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 | if (adev->sdma.has_page_queue) | 2632 | if (adev->sdma.has_page_queue) |
| 2613 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].page; | 2633 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].page; |
| 2614 | else | 2634 | else |
| 2615 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | static void sdma_v4_0_get_ras_error_count(uint32_t value, | 2638 | static void sdma_v4_0_get_ras_error_count(uint32_t value, |
| 2643 | uint32_t instance, | 2639 | uint32_t instance, |
| 2644 | uint32_t *sec_count) | 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 | static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev); | 105 | static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev); |
| 106 | static void sdma_v4_4_2_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev); | 107 | static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev); |
| 109 | static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev); | 108 | static void sdma_v4_4_2_set_ras_funcs(struct amdgpu_device *adev); |
| 110 | static void sdma_v4_4_2_update_reset_mask(struct amdgpu_device *adev); | 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 | .soft_reset_kernel_queue = &sdma_v4_4_2_soft_reset_engine, | 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 | static int sdma_v4_4_2_early_init(struct amdgpu_ip_block *ip_block) | 1357 | static int sdma_v4_4_2_early_init(struct amdgpu_ip_block *ip_block) |
| 1351 | { | 1358 | { |
| 1352 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v4_4_2_set_ring_funcs(adev); | 1370 | sdma_v4_4_2_set_ring_funcs(adev); |
| 1364 | sdma_v4_4_2_set_buffer_funcs(adev); | 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 | sdma_v4_4_2_set_irq_funcs(adev); | 1373 | sdma_v4_4_2_set_irq_funcs(adev); |
| 1367 | sdma_v4_4_2_set_ras_funcs(adev); | 1374 | sdma_v4_4_2_set_ras_funcs(adev); |
| 1368 | return 0; | 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 | static const struct amdgpu_buffer_funcs sdma_v4_4_2_buffer_funcs = { | 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 | .copy_num_dw = 7, | 2309 | .copy_num_dw = 7, |
| 2303 | .emit_copy_buffer = sdma_v4_4_2_emit_copy_buffer, | 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 | .fill_num_dw = 5, | 2313 | .fill_num_dw = 5, |
| 2307 | .emit_fill_buffer = sdma_v4_4_2_emit_fill_buffer, | 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 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | * sdma_v4_4_2_update_reset_mask - update reset mask for SDMA | 2327 | * sdma_v4_4_2_update_reset_mask - update reset mask for SDMA |
| 2345 | * @adev: Pointer to the AMDGPU device structure | 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 | static void sdma_v5_0_set_ring_funcs(struct amdgpu_device *adev); | 111 | static void sdma_v5_0_set_ring_funcs(struct amdgpu_device *adev); |
| 112 | static void sdma_v5_0_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v5_0_set_irq_funcs(struct amdgpu_device *adev); | 113 | static void sdma_v5_0_set_irq_funcs(struct amdgpu_device *adev); |
| 115 | static int sdma_v5_0_stop_queue(struct amdgpu_ring *ring); | 114 | static int sdma_v5_0_stop_queue(struct amdgpu_ring *ring); |
| 116 | static int sdma_v5_0_restore_queue(struct amdgpu_ring *ring); | 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 | .soft_reset_kernel_queue = &sdma_v5_0_soft_reset_engine, | 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 | static int sdma_v5_0_early_init(struct amdgpu_ip_block *ip_block) | 1366 | static int sdma_v5_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1361 | { | 1367 | { |
| 1362 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v5_0_set_ring_funcs(adev); | 1375 | sdma_v5_0_set_ring_funcs(adev); |
| 1370 | sdma_v5_0_set_buffer_funcs(adev); | 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 | sdma_v5_0_set_irq_funcs(adev); | 1378 | sdma_v5_0_set_irq_funcs(adev); |
| 1373 | sdma_v5_0_set_mqd_funcs(adev); | 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 | const struct amdgpu_ip_block_version sdma_v5_0_ip_block = { | 2061 | const struct amdgpu_ip_block_version sdma_v5_0_ip_block = { |
| 2077 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 2062 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 2078 | .major = 5, | 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 | static void sdma_v5_2_set_ring_funcs(struct amdgpu_device *adev); | 112 | static void sdma_v5_2_set_ring_funcs(struct amdgpu_device *adev); |
| 113 | static void sdma_v5_2_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v5_2_set_irq_funcs(struct amdgpu_device *adev); | 114 | static void sdma_v5_2_set_irq_funcs(struct amdgpu_device *adev); |
| 116 | static int sdma_v5_2_stop_queue(struct amdgpu_ring *ring); | 115 | static int sdma_v5_2_stop_queue(struct amdgpu_ring *ring); |
| 117 | static int sdma_v5_2_restore_queue(struct amdgpu_ring *ring); | 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 | amdgpu_ring_emit_reg_wait(ring, reg1, mask, mask); | 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 | static int sdma_v5_2_early_init(struct amdgpu_ip_block *ip_block) | 1257 | static int sdma_v5_2_early_init(struct amdgpu_ip_block *ip_block) |
| 1252 | { | 1258 | { |
| 1253 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v5_2_set_ring_funcs(adev); | 1266 | sdma_v5_2_set_ring_funcs(adev); |
| 1261 | sdma_v5_2_set_buffer_funcs(adev); | 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 | sdma_v5_2_set_irq_funcs(adev); | 1269 | sdma_v5_2_set_irq_funcs(adev); |
| 1264 | sdma_v5_2_set_mqd_funcs(adev); | 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 | static const struct amdgpu_buffer_funcs sdma_v5_2_buffer_funcs = { | 2047 | static const struct amdgpu_buffer_funcs sdma_v5_2_buffer_funcs = { |
| 2042 | .copy_max_bytes = 0x400000, | 2048 | .copy_max_bytes = 1 << 30, |
| 2043 | .copy_num_dw = 7, | 2049 | .copy_num_dw = 7, |
| 2044 | .emit_copy_buffer = sdma_v5_2_emit_copy_buffer, | 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 | .fill_num_dw = 5, | 2053 | .fill_num_dw = 5, |
| 2048 | .emit_fill_buffer = sdma_v5_2_emit_fill_buffer, | 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 | const struct amdgpu_ip_block_version sdma_v5_2_ip_block = { | 2065 | const struct amdgpu_ip_block_version sdma_v5_2_ip_block = { |
| 2081 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 2066 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 2082 | .major = 5, | 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 | static void sdma_v6_0_set_ring_funcs(struct amdgpu_device *adev); | 121 | static void sdma_v6_0_set_ring_funcs(struct amdgpu_device *adev); |
| 122 | static void sdma_v6_0_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v6_0_set_irq_funcs(struct amdgpu_device *adev); | 123 | static void sdma_v6_0_set_irq_funcs(struct amdgpu_device *adev); |
| 125 | static int sdma_v6_0_start(struct amdgpu_device *adev); | 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 | csa_info->alignment = SDMA6_CSA_ALIGNMENT; | 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 | static int sdma_v6_0_early_init(struct amdgpu_ip_block *ip_block) | 1289 | static int sdma_v6_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1284 | { | 1290 | { |
| 1285 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v6_0_set_ring_funcs(adev); | 1315 | sdma_v6_0_set_ring_funcs(adev); |
| 1310 | sdma_v6_0_set_buffer_funcs(adev); | 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 | sdma_v6_0_set_irq_funcs(adev); | 1318 | sdma_v6_0_set_irq_funcs(adev); |
| 1313 | sdma_v6_0_set_mqd_funcs(adev); | 1319 | sdma_v6_0_set_mqd_funcs(adev); |
| 1314 | sdma_v6_0_set_ras_funcs(adev); | 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 | static const struct amdgpu_buffer_funcs sdma_v6_0_buffer_funcs = { | 1886 | static const struct amdgpu_buffer_funcs sdma_v6_0_buffer_funcs = { |
| 1881 | .copy_max_bytes = 0x400000, | 1887 | .copy_max_bytes = 1 << 30, |
| 1882 | .copy_num_dw = 7, | 1888 | .copy_num_dw = 7, |
| 1883 | .emit_copy_buffer = sdma_v6_0_emit_copy_buffer, | 1889 | .emit_copy_buffer = sdma_v6_0_emit_copy_buffer, |
| 1884 | 1890 | ||
| 1885 | .fill_max_bytes = 0x400000, | 1891 | .fill_max_bytes = 1 << 30, |
| 1886 | .fill_num_dw = 5, | 1892 | .fill_num_dw = 5, |
| 1887 | .emit_fill_buffer = sdma_v6_0_emit_fill_buffer, | 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 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version sdma_v6_0_ip_block = { | 1902 | const struct amdgpu_ip_block_version sdma_v6_0_ip_block = { |
| 1916 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 1903 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1917 | .major = 6, | 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 | static void sdma_v7_0_set_ring_funcs(struct amdgpu_device *adev); | 120 | static void sdma_v7_0_set_ring_funcs(struct amdgpu_device *adev); |
| 121 | static void sdma_v7_0_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v7_0_set_irq_funcs(struct amdgpu_device *adev); | 122 | static void sdma_v7_0_set_irq_funcs(struct amdgpu_device *adev); |
| 124 | static int sdma_v7_0_start(struct amdgpu_device *adev); | 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 | csa_info->alignment = SDMA7_CSA_ALIGNMENT; | 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 | static int sdma_v7_0_early_init(struct amdgpu_ip_block *ip_block) | 1273 | static int sdma_v7_0_early_init(struct amdgpu_ip_block *ip_block) |
| 1268 | { | 1274 | { |
| 1269 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v7_0_set_ring_funcs(adev); | 1301 | sdma_v7_0_set_ring_funcs(adev); |
| 1296 | sdma_v7_0_set_buffer_funcs(adev); | 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 | sdma_v7_0_set_irq_funcs(adev); | 1304 | sdma_v7_0_set_irq_funcs(adev); |
| 1299 | sdma_v7_0_set_mqd_funcs(adev); | 1305 | sdma_v7_0_set_mqd_funcs(adev); |
| 1300 | adev->sdma.get_csa_info = &sdma_v7_0_get_csa_info; | 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 | static const struct amdgpu_buffer_funcs sdma_v7_0_buffer_funcs = { | 1837 | static const struct amdgpu_buffer_funcs sdma_v7_0_buffer_funcs = { |
| 1832 | .copy_max_bytes = 0x400000, | 1838 | .copy_max_bytes = 1 << 30, |
| 1833 | .copy_num_dw = 8, | 1839 | .copy_num_dw = 8, |
| 1834 | .emit_copy_buffer = sdma_v7_0_emit_copy_buffer, | 1840 | .emit_copy_buffer = sdma_v7_0_emit_copy_buffer, |
| 1835 | .fill_max_bytes = 0x400000, | 1841 | .fill_max_bytes = 1 << 30, |
| 1836 | .fill_num_dw = 5, | 1842 | .fill_num_dw = 5, |
| 1837 | .emit_fill_buffer = sdma_v7_0_emit_fill_buffer, | 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 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version sdma_v7_0_ip_block = { | 1852 | const struct amdgpu_ip_block_version sdma_v7_0_ip_block = { |
| 1866 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 1853 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1867 | .major = 7, | 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 | static void sdma_v7_1_set_ring_funcs(struct amdgpu_device *adev); | 111 | static void sdma_v7_1_set_ring_funcs(struct amdgpu_device *adev); |
| 112 | static void sdma_v7_1_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void sdma_v7_1_set_irq_funcs(struct amdgpu_device *adev); | 113 | static void sdma_v7_1_set_irq_funcs(struct amdgpu_device *adev); |
| 115 | static int sdma_v7_1_inst_start(struct amdgpu_device *adev, | 114 | static int sdma_v7_1_inst_start(struct amdgpu_device *adev, |
| 116 | uint32_t inst_mask); | 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 | amdgpu_ring_emit_reg_wait(ring, reg1, mask, mask); | 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 | static int sdma_v7_1_early_init(struct amdgpu_ip_block *ip_block) | 1257 | static int sdma_v7_1_early_init(struct amdgpu_ip_block *ip_block) |
| 1252 | { | 1258 | { |
| 1253 | struct amdgpu_device *adev = ip_block->adev; | 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 | sdma_v7_1_set_ring_funcs(adev); | 1268 | sdma_v7_1_set_ring_funcs(adev); |
| 1263 | sdma_v7_1_set_buffer_funcs(adev); | 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 | sdma_v7_1_set_irq_funcs(adev); | 1271 | sdma_v7_1_set_irq_funcs(adev); |
| 1266 | sdma_v7_1_set_mqd_funcs(adev); | 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 | static const struct amdgpu_buffer_funcs sdma_v7_1_buffer_funcs = { | 1747 | static const struct amdgpu_buffer_funcs sdma_v7_1_buffer_funcs = { |
| 1742 | .copy_max_bytes = 0x400000, | 1748 | .copy_max_bytes = 1 << 30, |
| 1743 | .copy_num_dw = 8, | 1749 | .copy_num_dw = 8, |
| 1744 | .emit_copy_buffer = sdma_v7_1_emit_copy_buffer, | 1750 | .emit_copy_buffer = sdma_v7_1_emit_copy_buffer, |
| 1745 | .fill_max_bytes = 0x400000, | 1751 | .fill_max_bytes = 1 << 30, |
| 1746 | .fill_num_dw = 5, | 1752 | .fill_num_dw = 5, |
| 1747 | .emit_fill_buffer = sdma_v7_1_emit_fill_buffer, | 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 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version sdma_v7_1_ip_block = { | 1762 | const struct amdgpu_ip_block_version sdma_v7_1_ip_block = { |
| 1776 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 1763 | .type = AMD_IP_BLOCK_TYPE_SDMA, |
| 1777 | .major = 7, | 1764 | .major = 7, |
| @@ -1027,11 +1027,11 @@ static u32 si_pcie_rreg(struct amdgpu_device *adev, u32 reg) · 1026 unmodified lines | |||
| 1027 | unsigned long flags; | 1027 | unsigned long flags; |
| 1028 | u32 r; | 1028 | u32 r; |
| 1029 | 1029 | ||
| 1030 | spin_lock_irqsave(&adev->pcie_idx_lock, flags); | 1030 | spin_lock_irqsave(&adev->reg.pcie.lock, flags); |
| 1031 | WREG32(AMDGPU_PCIE_INDEX, reg); | 1031 | WREG32(AMDGPU_PCIE_INDEX, reg); |
| 1032 | (void)RREG32(AMDGPU_PCIE_INDEX); | 1032 | (void)RREG32(AMDGPU_PCIE_INDEX); |
| 1033 | r = RREG32(AMDGPU_PCIE_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(AMDGPU_PCIE_INDEX, reg); | 1043 | WREG32(AMDGPU_PCIE_INDEX, reg); |
| 1044 | (void)RREG32(AMDGPU_PCIE_INDEX); | 1044 | (void)RREG32(AMDGPU_PCIE_INDEX); |
| 1045 | WREG32(AMDGPU_PCIE_DATA, v); | 1045 | WREG32(AMDGPU_PCIE_DATA, v); |
| 1046 | (void)RREG32(AMDGPU_PCIE_DATA); | 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 | static u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 1052 | unsigned long flags; |
| 1053 | u32 r; | 1053 | u32 r; |
| 1054 | 1054 | ||
| 1055 | spin_lock_irqsave(&adev->pcie_idx_lock, flags); | 1055 | spin_lock_irqsave(&adev->reg.pcie.lock, flags); |
| 1056 | WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); | 1056 | WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); |
| 1057 | (void)RREG32(PCIE_PORT_INDEX); | 1057 | (void)RREG32(PCIE_PORT_INDEX); |
| 1058 | r = RREG32(PCIE_PORT_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); | 1068 | WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); |
| 1069 | (void)RREG32(PCIE_PORT_INDEX); | 1069 | (void)RREG32(PCIE_PORT_INDEX); |
| 1070 | WREG32(PCIE_PORT_DATA, (v)); | 1070 | WREG32(PCIE_PORT_DATA, (v)); |
| 1071 | (void)RREG32(PCIE_PORT_DATA); | 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 | static u32 si_smc_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 1077 | unsigned long flags; |
| 1078 | u32 r; | 1078 | u32 r; |
| 1079 | 1079 | ||
| 1080 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | 1080 | spin_lock_irqsave(&adev->reg.smc.lock, flags); |
| 1081 | WREG32(mmSMC_IND_INDEX_0, (reg)); | 1081 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 1082 | r = RREG32(mmSMC_IND_DATA_0); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmSMC_IND_INDEX_0, (reg)); | 1092 | WREG32(mmSMC_IND_INDEX_0, (reg)); |
| 1093 | WREG32(mmSMC_IND_DATA_0, (v)); | 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 | static u32 si_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 1099 | unsigned long flags; |
| 1100 | u32 r; | 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 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); | 1103 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 1104 | r = RREG32(mmUVD_CTX_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); | 1114 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 1115 | WREG32(mmUVD_CTX_DATA, (v)); | 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 | static struct amdgpu_allowed_register_entry si_allowed_read_registers[] = { | 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 | struct amdgpu_device *adev = ip_block->adev; | 2038 | struct amdgpu_device *adev = ip_block->adev; |
| 2039 | 2039 | ||
| 2040 | adev->smc_rreg = &si_smc_rreg; | 2040 | adev->reg.smc.rreg = si_smc_rreg; |
| 2041 | adev->smc_wreg = &si_smc_wreg; | 2041 | adev->reg.smc.wreg = si_smc_wreg; |
| 2042 | adev->pcie_rreg = &si_pcie_rreg; | 2042 | adev->reg.pcie.rreg = &si_pcie_rreg; |
| 2043 | adev->pcie_wreg = &si_pcie_wreg; | 2043 | adev->reg.pcie.wreg = &si_pcie_wreg; |
| 2044 | adev->pciep_rreg = &si_pciep_rreg; | 2044 | adev->reg.pcie.port_rreg = &si_pciep_rreg; |
| 2045 | adev->pciep_wreg = &si_pciep_wreg; | 2045 | adev->reg.pcie.port_wreg = &si_pciep_wreg; |
| 2046 | adev->uvd_ctx_rreg = si_uvd_ctx_rreg; | 2046 | adev->reg.uvd_ctx.rreg = &si_uvd_ctx_rreg; |
| 2047 | adev->uvd_ctx_wreg = si_uvd_ctx_wreg; | 2047 | adev->reg.uvd_ctx.wreg = &si_uvd_ctx_wreg; |
| 2048 | adev->didt_rreg = NULL; | ||
| 2049 | adev->didt_wreg = NULL; | ||
| 2050 | 2048 | ||
| 2051 | adev->asic_funcs = &si_asic_funcs; | 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 | unsigned long flags; | 2380 | unsigned long flags; |
| 2383 | u32 r; | 2381 | u32 r; |
| 2384 | 2382 | ||
| 2385 | spin_lock_irqsave(&adev->pcie_idx_lock, flags); | 2383 | spin_lock_irqsave(&adev->reg.pcie.lock, flags); |
| 2386 | WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); | 2384 | WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); |
| 2387 | r = RREG32(EVERGREEN_PIF_PHY0_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); | 2395 | WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); |
| 2398 | WREG32(EVERGREEN_PIF_PHY0_DATA, (v)); | 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 | static inline u32 si_pif_phy1_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 2402 | unsigned long flags; |
| 2405 | u32 r; | 2403 | u32 r; |
| 2406 | 2404 | ||
| 2407 | spin_lock_irqsave(&adev->pcie_idx_lock, flags); | 2405 | spin_lock_irqsave(&adev->reg.pcie.lock, flags); |
| 2408 | WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); | 2406 | WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); |
| 2409 | r = RREG32(EVERGREEN_PIF_PHY1_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); | 2417 | WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); |
| 2420 | WREG32(EVERGREEN_PIF_PHY1_DATA, (v)); | 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 | static void si_program_aspm(struct amdgpu_device *adev) | 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 | static void si_dma_set_ring_funcs(struct amdgpu_device *adev); | 38 | static void si_dma_set_ring_funcs(struct amdgpu_device *adev); |
| 39 | static void si_dma_set_buffer_funcs(struct amdgpu_device *adev); | 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 | static void si_dma_set_irq_funcs(struct amdgpu_device *adev); | 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 | amdgpu_ring_write(ring, val); | 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 | static int si_dma_early_init(struct amdgpu_ip_block *ip_block) | 483 | static int si_dma_early_init(struct amdgpu_ip_block *ip_block) |
| 477 | { | 484 | { |
| 478 | struct amdgpu_device *adev = ip_block->adev; | 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 | si_dma_set_ring_funcs(adev); | 489 | si_dma_set_ring_funcs(adev); |
| 483 | si_dma_set_buffer_funcs(adev); | 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 | si_dma_set_irq_funcs(adev); | 492 | si_dma_set_irq_funcs(adev); |
| 486 | 493 | ||
| 487 | return 0; | 494 | return 0; |
| @@ -830,26 +837,6 @@ static void si_dma_set_buffer_funcs(struct amdgpu_device *adev) · 342 unmodified lines | |||
| 830 | adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; | 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 | const struct amdgpu_ip_block_version si_dma_ip_block = | 840 | const struct amdgpu_ip_block_version si_dma_ip_block = |
| 854 | { | 841 | { |
| 855 | .type = AMD_IP_BLOCK_TYPE_SDMA, | 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 | address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); | 245 | address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); |
| 246 | data = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_DATA); | 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 | WREG32(address, ((reg) & 0x1ff)); | 249 | WREG32(address, ((reg) & 0x1ff)); |
| 250 | r = RREG32(data); | 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 | return r; | 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 | address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); | 259 | address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); |
| 260 | data = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_DATA); | 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 | WREG32(address, ((reg) & 0x1ff)); | 263 | WREG32(address, ((reg) & 0x1ff)); |
| 264 | WREG32(data, (v)); | 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 | static u32 soc15_didt_rreg(struct amdgpu_device *adev, u32 reg) | 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 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); | 273 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 274 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); | 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 | WREG32(address, (reg)); | 277 | WREG32(address, (reg)); |
| 278 | r = RREG32(data); | 278 | r = RREG32(data); |
| 279 | spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | 279 | spin_unlock_irqrestore(&adev->reg.didt.lock, flags); |
| 280 | return r; | 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 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); | 287 | address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); |
| 288 | data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); | 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 | WREG32(address, (reg)); | 291 | WREG32(address, (reg)); |
| 292 | WREG32(data, (v)); | 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 | static u32 soc15_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 298 | unsigned long flags; |
| 299 | u32 r; | 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 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); | 302 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); |
| 303 | r = RREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); | 313 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); |
| 314 | WREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA, (v)); | 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 | static u32 soc15_se_cac_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 320 | unsigned long flags; |
| 321 | u32 r; | 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 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); | 324 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); |
| 325 | r = RREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); | 335 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); |
| 336 | WREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA, (v)); | 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 | static u32 soc15_get_config_memsize(struct amdgpu_device *adev) | 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 | .get_pcie_replay_count = &amdgpu_nbio_get_pcie_replay_count, | 952 | .get_pcie_replay_count = &amdgpu_nbio_get_pcie_replay_count, |
| 953 | .supports_baco = &soc15_supports_baco, | 953 | .supports_baco = &soc15_supports_baco, |
| 954 | .query_video_codecs = &soc15_query_video_codecs, | 954 | .query_video_codecs = &soc15_query_video_codecs, |
| 955 | .encode_ext_smn_addressing = &aqua_vanjaram_encode_ext_smn_addressing, | ||
| 956 | .get_reg_state = &aqua_vanjaram_get_reg_state, | 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 | struct amdgpu_device *adev = ip_block->adev; | 960 | struct amdgpu_device *adev = ip_block->adev; |
| 962 | 961 | ||
| 963 | adev->nbio.funcs->set_reg_remap(adev); | 962 | adev->nbio.funcs->set_reg_remap(adev); |
| 964 | adev->smc_rreg = NULL; | 963 | adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; |
| 965 | adev->smc_wreg = NULL; | 964 | adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; |
| 966 | adev->pcie_rreg = &amdgpu_device_indirect_rreg; | 965 | adev->reg.pcie.rreg_ext = &amdgpu_device_indirect_rreg_ext; |
| 967 | adev->pcie_wreg = &amdgpu_device_indirect_wreg; | 966 | adev->reg.pcie.wreg_ext = &amdgpu_device_indirect_wreg_ext; |
| 968 | adev->pcie_rreg_ext = &amdgpu_device_indirect_rreg_ext; | 967 | adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; |
| 969 | adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext; | 968 | adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; |
| 970 | adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | 969 | adev->reg.pcie.rreg64_ext = &amdgpu_device_indirect_rreg64_ext; |
| 971 | adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | 970 | adev->reg.pcie.wreg64_ext = &amdgpu_device_indirect_wreg64_ext; |
| 972 | adev->pcie_rreg64_ext = &amdgpu_device_indirect_rreg64_ext; | 971 | adev->reg.uvd_ctx.rreg = &soc15_uvd_ctx_rreg; |
| 973 | adev->pcie_wreg64_ext = &amdgpu_device_indirect_wreg64_ext; | 972 | adev->reg.uvd_ctx.wreg = &soc15_uvd_ctx_wreg; |
| 974 | adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg; | 973 | adev->reg.didt.rreg = &soc15_didt_rreg; |
| 975 | adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg; | 974 | adev->reg.didt.wreg = &soc15_didt_wreg; |
| 976 | adev->didt_rreg = &soc15_didt_rreg; | 975 | adev->reg.gc_cac.rreg = &soc15_gc_cac_rreg; |
| 977 | adev->didt_wreg = &soc15_didt_wreg; | 976 | adev->reg.gc_cac.wreg = &soc15_gc_cac_wreg; |
| 978 | adev->gc_cac_rreg = &soc15_gc_cac_rreg; | 977 | adev->reg.se_cac.rreg = &soc15_se_cac_rreg; |
| 979 | adev->gc_cac_wreg = &soc15_gc_cac_wreg; | 978 | adev->reg.se_cac.wreg = &soc15_se_cac_wreg; |
| 980 | adev->se_cac_rreg = &soc15_se_cac_rreg; | ||
| 981 | adev->se_cac_wreg = &soc15_se_cac_wreg; | ||
| 982 | 979 | ||
| 983 | adev->rev_id = amdgpu_device_get_rev_id(adev); | 980 | adev->rev_id = amdgpu_device_get_rev_id(adev); |
| 984 | adev->external_rev_id = 0xFF; | 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 | case IP_VERSION(9, 4, 4): | 1197 | case IP_VERSION(9, 4, 4): |
| 1201 | case IP_VERSION(9, 5, 0): | 1198 | case IP_VERSION(9, 5, 0): |
| 1202 | adev->asic_funcs = &aqua_vanjaram_asic_funcs; | 1199 | adev->asic_funcs = &aqua_vanjaram_asic_funcs; |
| 1200 | adev->reg.smn.get_smn_base = &amdgpu_reg_smn_v1_0_get_base; | ||
| 1203 | adev->cg_flags = | 1201 | adev->cg_flags = |
| 1204 | AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGCG | | 1202 | AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGCG | |
| 1205 | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_SDMA_MGCG | | 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 | int vega20_reg_base_init(struct amdgpu_device *adev); | 118 | int vega20_reg_base_init(struct amdgpu_device *adev); |
| 119 | int arct_reg_base_init(struct amdgpu_device *adev); | 119 | int arct_reg_base_init(struct amdgpu_device *adev); |
| 120 | int aldebaran_reg_base_init(struct amdgpu_device *adev); | 120 | int aldebaran_reg_base_init(struct amdgpu_device *adev); |
| 121 | u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id); | ||
| 122 | int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev); | 121 | int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev); |
| 123 | ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, | 122 | ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, |
| 124 | enum amdgpu_reg_state reg_state, void *buf, | 123 | enum amdgpu_reg_state reg_state, void *buf, |
| @@ -195,19 +195,22 @@ · 194 unmodified lines | |||
| 195 | __RREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, AMDGPU_REGS_RLC, ip##_HWIP, inst) | 195 | __RREG32_SOC15_RLC__((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, AMDGPU_REGS_RLC, ip##_HWIP, inst) |
| 196 | 196 | ||
| 197 | /* inst equals to ext for some IPs */ | 197 | /* inst equals to ext for some IPs */ |
| 198 | #define RREG32_SOC15_EXT(ip, inst, reg, ext) \ | 198 | #define RREG32_SOC15_EXT(ip, inst, reg, ext) \ |
| 199 | RREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * 4 \ | 199 | RREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + \ |
| 200 | + adev->asic_funcs->encode_ext_smn_addressing(ext)) \ | 200 | reg) * 4 + \ |
| 201 | 201 | amdgpu_reg_get_smn_base64(adev, ip##_HWIP, inst)) | |
| 202 | #define WREG32_SOC15_EXT(ip, inst, reg, ext, value) \ | 202 | |
| 203 | WREG32_PCIE_EXT((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * 4 \ | 203 | #define WREG32_SOC15_EXT(ip, inst, reg, ext, value) \ |
| 204 | + adev->asic_funcs->encode_ext_smn_addressing(ext), \ | 204 | WREG32_PCIE_EXT( \ |
| 205 | value) \ | 205 | (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) * \ |
| 206 | 206 | 4 + \ | |
| 207 | #define RREG64_MCA(ext, mca_base, idx) \ | 207 | amdgpu_reg_get_smn_base64(adev, ip##_HWIP, inst), \ |
| 208 | RREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8)) | 208 | value) |
| 209 | 209 | ||
| 210 | #define WREG64_MCA(ext, mca_base, idx, val) \ | 210 | #define RREG64_MCA(smn_base, mca_base, idx) \ |
| 211 | WREG64_PCIE_EXT(adev->asic_funcs->encode_ext_smn_addressing(ext) + mca_base + (idx * 8), val) | 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 | #endif | 216 | #endif |
| @@ -229,10 +229,10 @@ static u32 soc21_didt_rreg(struct amdgpu_device *adev, u32 reg) · 228 unmodified lines | |||
| 229 | address = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_INDEX); | 229 | address = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_INDEX); |
| 230 | data = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_DATA); | 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 | WREG32(address, (reg)); | 233 | WREG32(address, (reg)); |
| 234 | r = RREG32(data); | 234 | r = RREG32(data); |
| 235 | spin_unlock_irqrestore(&adev->didt_idx_lock, flags); | 235 | spin_unlock_irqrestore(&adev->reg.didt.lock, flags); |
| 236 | return r; | 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 | address = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_INDEX); | 243 | address = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_INDEX); |
| 244 | data = SOC15_REG_OFFSET(GC, 0, regDIDT_IND_DATA); | 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 | WREG32(address, (reg)); | 247 | WREG32(address, (reg)); |
| 248 | WREG32(data, (v)); | 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 | static u32 soc21_get_config_memsize(struct amdgpu_device *adev) | 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 | struct amdgpu_device *adev = ip_block->adev; | 589 | struct amdgpu_device *adev = ip_block->adev; |
| 590 | 590 | ||
| 591 | adev->nbio.funcs->set_reg_remap(adev); | 591 | adev->nbio.funcs->set_reg_remap(adev); |
| 592 | adev->smc_rreg = NULL; | 592 | adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; |
| 593 | adev->smc_wreg = NULL; | 593 | adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; |
| 594 | adev->pcie_rreg = &amdgpu_device_indirect_rreg; | 594 | adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; |
| 595 | adev->pcie_wreg = &amdgpu_device_indirect_wreg; | 595 | adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; |
| 596 | adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | 596 | adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; |
| 597 | adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | 597 | adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; |
| 598 | adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | 598 | |
| 599 | adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | 599 | adev->reg.didt.rreg = &soc21_didt_rreg; |
| 600 | 600 | adev->reg.didt.wreg = &soc21_didt_wreg; | |
| 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; | ||
| 607 | 601 | ||
| 608 | adev->asic_funcs = &soc21_asic_funcs; | 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 | AMD_CG_SUPPORT_IH_CG | | 852 | AMD_CG_SUPPORT_IH_CG | |
| 859 | AMD_CG_SUPPORT_BIF_MGCG | | 853 | AMD_CG_SUPPORT_BIF_MGCG | |
| 860 | AMD_CG_SUPPORT_BIF_LS; | 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 | AMD_PG_SUPPORT_JPEG | | 858 | AMD_PG_SUPPORT_JPEG | |
| 863 | AMD_PG_SUPPORT_GFX_PG; | 859 | AMD_PG_SUPPORT_GFX_PG; |
| 864 | adev->external_rev_id = adev->rev_id + 0x1; | 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 | struct amdgpu_device *adev = ip_block->adev; | 362 | struct amdgpu_device *adev = ip_block->adev; |
| 363 | 363 | ||
| 364 | adev->nbio.funcs->set_reg_remap(adev); | 364 | adev->nbio.funcs->set_reg_remap(adev); |
| 365 | adev->smc_rreg = NULL; | 365 | adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; |
| 366 | adev->smc_wreg = NULL; | 366 | adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; |
| 367 | adev->pcie_rreg = &amdgpu_device_indirect_rreg; | 367 | adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; |
| 368 | adev->pcie_wreg = &amdgpu_device_indirect_wreg; | 368 | adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; |
| 369 | adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | 369 | adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; |
| 370 | adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | 370 | adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; |
| 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; | ||
| 377 | 371 | ||
| 378 | adev->asic_funcs = &soc24_asic_funcs; | 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 | struct amdgpu_device *adev = ip_block->adev; | 251 | struct amdgpu_device *adev = ip_block->adev; |
| 252 | 252 | ||
| 253 | adev->smc_rreg = NULL; | 253 | adev->reg.pcie.rreg = &amdgpu_device_indirect_rreg; |
| 254 | adev->smc_wreg = NULL; | 254 | adev->reg.pcie.wreg = &amdgpu_device_indirect_wreg; |
| 255 | adev->pcie_rreg = &amdgpu_device_indirect_rreg; | 255 | adev->reg.pcie.rreg_ext = &amdgpu_device_indirect_rreg_ext; |
| 256 | adev->pcie_wreg = &amdgpu_device_indirect_wreg; | 256 | adev->reg.pcie.wreg_ext = &amdgpu_device_indirect_wreg_ext; |
| 257 | adev->pcie_rreg_ext = &amdgpu_device_indirect_rreg_ext; | 257 | adev->reg.pcie.rreg64 = &amdgpu_device_indirect_rreg64; |
| 258 | adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext; | 258 | adev->reg.pcie.wreg64 = &amdgpu_device_indirect_wreg64; |
| 259 | adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64; | 259 | adev->reg.pcie.port_rreg = &amdgpu_device_pcie_port_rreg; |
| 260 | adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64; | 260 | adev->reg.pcie.port_wreg = &amdgpu_device_pcie_port_wreg; |
| 261 | adev->pciep_rreg = amdgpu_device_pcie_port_rreg; | 261 | adev->reg.pcie.rreg64_ext = &amdgpu_device_indirect_rreg64_ext; |
| 262 | adev->pciep_wreg = amdgpu_device_pcie_port_wreg; | 262 | adev->reg.pcie.wreg64_ext = &amdgpu_device_indirect_wreg64_ext; |
| 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; | ||
| 269 | 263 | ||
| 270 | adev->asic_funcs = &soc_v1_0_asic_funcs; | 264 | adev->asic_funcs = &soc_v1_0_asic_funcs; |
| 271 | 265 | ||
| @@ -47,11 +47,6 @@ · 46 unmodified lines | |||
| 47 | #define VCE_V1_0_DATA_SIZE (7808 * (AMDGPU_MAX_VCE_HANDLES + 1)) | 47 | #define VCE_V1_0_DATA_SIZE (7808 * (AMDGPU_MAX_VCE_HANDLES + 1)) |
| 48 | #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02 | 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 | static void vce_v1_0_set_ring_funcs(struct amdgpu_device *adev); | 50 | static void vce_v1_0_set_ring_funcs(struct amdgpu_device *adev); |
| 56 | static void vce_v1_0_set_irq_funcs(struct amdgpu_device *adev); | 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 | static int vce_v1_0_ensure_vcpu_bo_32bit_addr(struct amdgpu_device *adev) | 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 | u64 bo_size = amdgpu_bo_size(adev->vce.vcpu_bo); | 533 | u64 bo_size = amdgpu_bo_size(adev->vce.vcpu_bo); |
| 540 | u64 max_vcpu_bo_addr = 0xffffffff - bo_size; | 534 | u64 max_vcpu_bo_addr = 0xffffffff - bo_size; |
| 541 | u64 num_pages = ALIGN(bo_size, AMDGPU_GPU_PAGE_SIZE) / AMDGPU_GPU_PAGE_SIZE; | 535 | u64 num_pages = ALIGN(bo_size, AMDGPU_GPU_PAGE_SIZE) / AMDGPU_GPU_PAGE_SIZE; |
| 542 | u64 pa = amdgpu_gmc_vram_pa(adev, adev->vce.vcpu_bo); | 536 | u64 pa = amdgpu_gmc_vram_pa(adev, adev->vce.vcpu_bo); |
| 543 | u64 flags = AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | AMDGPU_PTE_VALID; | 537 | u64 flags = AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | AMDGPU_PTE_VALID; |
| 538 | u64 vce_gart_start_offs; | ||
| 539 | int r; | ||
| 544 | 540 | ||
| 545 | /* | 541 | r = amdgpu_gtt_mgr_alloc_entries(&adev->mman.gtt_mgr, |
| 546 | * Check if the VCPU BO already has a 32-bit address. | 542 | &adev->vce.gart_node, num_pages, |
| 547 | * Eg. if MC is configured to put VRAM in the low address range. | 543 | DRM_MM_INSERT_LOW); |
| 548 | */ | 544 | if (r) |
| 549 | if (gpu_addr <= max_vcpu_bo_addr) | 545 | return r; |
| 550 | return 0; | 546 | |
| 547 | vce_gart_start_offs = amdgpu_gtt_node_to_byte_offset(&adev->vce.gart_node); | ||
| 551 | 548 | ||
| 552 | /* Check if we can map the VCPU BO in GART to a 32-bit address. */ | 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 | return -EINVAL; | 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 | num_pages, flags, adev->gart.ptr); | 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 | if (adev->vce.gpu_addr > max_vcpu_bo_addr) | 556 | if (adev->vce.gpu_addr > max_vcpu_bo_addr) |
| 560 | return -EINVAL; | 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 | if (r) | 607 | if (r) |
| 611 | return r; | 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 | unsigned long flags; | 299 | unsigned long flags; |
| 300 | u32 r; | 300 | u32 r; |
| 301 | 301 | ||
| 302 | spin_lock_irqsave(&adev->pcie_idx_lock, flags); | 302 | spin_lock_irqsave(&adev->reg.pcie.lock, flags); |
| 303 | WREG32_NO_KIQ(mmPCIE_INDEX, reg); | 303 | WREG32_NO_KIQ(mmPCIE_INDEX, reg); |
| 304 | (void)RREG32_NO_KIQ(mmPCIE_INDEX); | 304 | (void)RREG32_NO_KIQ(mmPCIE_INDEX); |
| 305 | r = RREG32_NO_KIQ(mmPCIE_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32_NO_KIQ(mmPCIE_INDEX, reg); | 315 | WREG32_NO_KIQ(mmPCIE_INDEX, reg); |
| 316 | (void)RREG32_NO_KIQ(mmPCIE_INDEX); | 316 | (void)RREG32_NO_KIQ(mmPCIE_INDEX); |
| 317 | WREG32_NO_KIQ(mmPCIE_DATA, v); | 317 | WREG32_NO_KIQ(mmPCIE_DATA, v); |
| 318 | (void)RREG32_NO_KIQ(mmPCIE_DATA); | 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 | static u32 vi_smc_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 324 | unsigned long flags; |
| 325 | u32 r; | 325 | u32 r; |
| 326 | 326 | ||
| 327 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | 327 | spin_lock_irqsave(&adev->reg.smc.lock, flags); |
| 328 | WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg)); | 328 | WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg)); |
| 329 | r = RREG32_NO_KIQ(mmSMC_IND_DATA_11); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg)); | 339 | WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg)); |
| 340 | WREG32_NO_KIQ(mmSMC_IND_DATA_11, (v)); | 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 | /* smu_8_0_d.h */ | 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 | unsigned long flags; | 350 | unsigned long flags; |
| 351 | u32 r; | 351 | u32 r; |
| 352 | 352 | ||
| 353 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | 353 | spin_lock_irqsave(&adev->reg.smc.lock, flags); |
| 354 | WREG32(mmMP0PUB_IND_INDEX, (reg)); | 354 | WREG32(mmMP0PUB_IND_INDEX, (reg)); |
| 355 | r = RREG32(mmMP0PUB_IND_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmMP0PUB_IND_INDEX, (reg)); | 365 | WREG32(mmMP0PUB_IND_INDEX, (reg)); |
| 366 | WREG32(mmMP0PUB_IND_DATA, (v)); | 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 | static u32 vi_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 372 | unsigned long flags; |
| 373 | u32 r; | 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 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); | 376 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 377 | r = RREG32(mmUVD_CTX_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); | 387 | WREG32(mmUVD_CTX_INDEX, ((reg) & 0x1ff)); |
| 388 | WREG32(mmUVD_CTX_DATA, (v)); | 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 | static u32 vi_didt_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 394 | unsigned long flags; |
| 395 | u32 r; | 395 | u32 r; |
| 396 | 396 | ||
| 397 | spin_lock_irqsave(&adev->didt_idx_lock, flags); | 397 | spin_lock_irqsave(&adev->reg.didt.lock, flags); |
| 398 | WREG32(mmDIDT_IND_INDEX, (reg)); | 398 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 399 | r = RREG32(mmDIDT_IND_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmDIDT_IND_INDEX, (reg)); | 409 | WREG32(mmDIDT_IND_INDEX, (reg)); |
| 410 | WREG32(mmDIDT_IND_DATA, (v)); | 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 | static u32 vi_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) | 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 | unsigned long flags; | 416 | unsigned long flags; |
| 417 | u32 r; | 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 | WREG32(mmGC_CAC_IND_INDEX, (reg)); | 420 | WREG32(mmGC_CAC_IND_INDEX, (reg)); |
| 421 | r = RREG32(mmGC_CAC_IND_DATA); | 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 | return r; | 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 | unsigned long flags; | 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 | WREG32(mmGC_CAC_IND_INDEX, (reg)); | 431 | WREG32(mmGC_CAC_IND_INDEX, (reg)); |
| 432 | WREG32(mmGC_CAC_IND_DATA, (v)); | 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 | dw_ptr = (u32 *)bios; | 649 | dw_ptr = (u32 *)bios; |
| 650 | length_dw = ALIGN(length_bytes, 4) / 4; | 650 | length_dw = ALIGN(length_bytes, 4) / 4; |
| 651 | /* take the smc lock since we are using the smc index */ | 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 | /* set rom index to 0 */ | 653 | /* set rom index to 0 */ |
| 654 | WREG32(mmSMC_IND_INDEX_11, ixROM_INDEX); | 654 | WREG32(mmSMC_IND_INDEX_11, ixROM_INDEX); |
| 655 | WREG32(mmSMC_IND_DATA_11, 0); | 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 | WREG32(mmSMC_IND_INDEX_11, ixROM_DATA); | 657 | WREG32(mmSMC_IND_INDEX_11, ixROM_DATA); |
| 658 | for (i = 0; i < length_dw; i++) | 658 | for (i = 0; i < length_dw; i++) |
| 659 | dw_ptr[i] = RREG32(mmSMC_IND_DATA_11); | 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 | return true; | 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 | struct amdgpu_device *adev = ip_block->adev; | 1454 | struct amdgpu_device *adev = ip_block->adev; |
| 1455 | 1455 | ||
| 1456 | if (adev->flags & AMD_IS_APU) { | 1456 | if (adev->flags & AMD_IS_APU) { |
| 1457 | adev->smc_rreg = &cz_smc_rreg; | 1457 | adev->reg.smc.rreg = cz_smc_rreg; |
| 1458 | adev->smc_wreg = &cz_smc_wreg; | 1458 | adev->reg.smc.wreg = cz_smc_wreg; |
| 1459 | } else { | 1459 | } else { |
| 1460 | adev->smc_rreg = &vi_smc_rreg; | 1460 | adev->reg.smc.rreg = vi_smc_rreg; |
| 1461 | adev->smc_wreg = &vi_smc_wreg; | 1461 | adev->reg.smc.wreg = vi_smc_wreg; |
| 1462 | } | 1462 | } |
| 1463 | adev->pcie_rreg = &vi_pcie_rreg; | 1463 | adev->reg.pcie.rreg = &vi_pcie_rreg; |
| 1464 | adev->pcie_wreg = &vi_pcie_wreg; | 1464 | adev->reg.pcie.wreg = &vi_pcie_wreg; |
| 1465 | adev->uvd_ctx_rreg = &vi_uvd_ctx_rreg; | 1465 | adev->reg.uvd_ctx.rreg = &vi_uvd_ctx_rreg; |
| 1466 | adev->uvd_ctx_wreg = &vi_uvd_ctx_wreg; | 1466 | adev->reg.uvd_ctx.wreg = &vi_uvd_ctx_wreg; |
| 1467 | adev->didt_rreg = &vi_didt_rreg; | 1467 | adev->reg.didt.rreg = &vi_didt_rreg; |
| 1468 | adev->didt_wreg = &vi_didt_wreg; | 1468 | adev->reg.didt.wreg = &vi_didt_wreg; |
| 1469 | adev->gc_cac_rreg = &vi_gc_cac_rreg; | 1469 | adev->reg.gc_cac.rreg = &vi_gc_cac_rreg; |
| 1470 | adev->gc_cac_wreg = &vi_gc_cac_wreg; | 1470 | adev->reg.gc_cac.wreg = &vi_gc_cac_wreg; |
| 1471 | 1471 | ||
| 1472 | adev->asic_funcs = &vi_asic_funcs; | 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 | var SQ_WAVE_MODE_DST_SRC0_SRC1_VGPR_MSB_SIZE = 6 | 134 | var SQ_WAVE_MODE_DST_SRC0_SRC1_VGPR_MSB_SIZE = 6 |
| 135 | #endif | 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 | var TTMP11_DEBUG_TRAP_ENABLED_SHIFT = 23 | 137 | var TTMP11_DEBUG_TRAP_ENABLED_SHIFT = 23 |
| 141 | var TTMP11_DEBUG_TRAP_ENABLED_MASK = 0x800000 | 138 | var TTMP11_DEBUG_TRAP_ENABLED_MASK = 0x800000 |
| 142 | var TTMP11_FIRST_REPLAY_SHIFT = 22 | 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 | static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id) | 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)) | 345 | pdd->lds_base = MAKE_LDS_APP_BASE_V9(); |
| 346 | pdd->lds_base = pdd->dev->adev->gmc.shared_aperture_start; | ||
| 347 | else | ||
| 348 | pdd->lds_base = MAKE_LDS_APP_BASE_V9(); | ||
| 349 | pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base); | 346 | pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base); |
| 350 | 347 | ||
| 351 | pdd->gpuvm_base = AMDGPU_VA_RESERVED_BOTTOM; | 348 | pdd->gpuvm_base = AMDGPU_VA_RESERVED_BOTTOM; |
| 352 | pdd->gpuvm_limit = | 349 | pdd->gpuvm_limit = |
| 353 | pdd->dev->kfd->shared_resources.gpuvm_size - 1; | 350 | pdd->dev->kfd->shared_resources.gpuvm_size - 1; |
| 354 | 351 | ||
| 355 | if (KFD_GC_VERSION(pdd->dev) >= IP_VERSION(12, 1, 0)) | 352 | pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9(); |
| 356 | pdd->scratch_base = pdd->dev->adev->gmc.private_aperture_start; | ||
| 357 | else | ||
| 358 | pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9(); | ||
| 359 | pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base); | 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 | pdd->qpd.cwsr_base = AMDGPU_VA_RESERVED_TRAP_START(pdd->dev->adev); | 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 | int kfd_init_apertures(struct kfd_process *process) | 381 | int kfd_init_apertures(struct kfd_process *process) |
| 369 | { | 382 | { |
| 370 | uint8_t id = 0; | 383 | uint8_t id = 0; |
| @@ -412,9 +425,11 @@ int kfd_init_apertures(struct kfd_process *process) · 41 unmodified lines | |||
| 412 | kfd_init_apertures_vi(pdd, id); | 425 | kfd_init_apertures_vi(pdd, id); |
| 413 | break; | 426 | break; |
| 414 | default: | 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 | kfd_init_apertures_v9(pdd, id); | 431 | kfd_init_apertures_v9(pdd, id); |
| 417 | else { | 432 | } else { |
| 418 | WARN(1, "Unexpected ASIC family %u", | 433 | WARN(1, "Unexpected ASIC family %u", |
| 419 | dev->adev->asic_type); | 434 | dev->adev->asic_type); |
| 420 | return -EINVAL; | 435 | return -EINVAL; |
| @@ -59,8 +59,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, · 58 unmodified lines | |||
| 59 | void *cpu_addr; | 59 | void *cpu_addr; |
| 60 | int r; | 60 | int r; |
| 61 | 61 | ||
| 62 | /* use gart window 0 */ | 62 | *gart_addr = amdgpu_compute_gart_address(&adev->gmc, entity, 0); |
| 63 | *gart_addr = adev->gmc.gart_start; | ||
| 64 | 63 | ||
| 65 | num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); | 64 | num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); |
| 66 | num_bytes = npages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE; | 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 | src_addr += job->ibs[0].gpu_addr; | 77 | src_addr += job->ibs[0].gpu_addr; |
| 79 | 78 | ||
| 80 | dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); | 79 | dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); |
| 80 | dst_addr += (entity->gart_window_offs[0] >> AMDGPU_GPU_PAGE_SHIFT) * 8; | ||
| 81 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, | 81 | amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, |
| 82 | dst_addr, num_bytes, 0); | 82 | dst_addr, num_bytes, 0); |
| 83 | 83 | ||
| @@ -116,7 +116,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, · 32 unmodified lines | |||
| 116 | * multiple GTT_MAX_PAGES transfer, all sdma operations are serialized, wait for | 116 | * multiple GTT_MAX_PAGES transfer, all sdma operations are serialized, wait for |
| 117 | * the last sdma finish fence which is returned to check copy memory is done. | 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 | * Return: | 121 | * Return: |
| 122 | * 0 - OK, otherwise error code | 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 | u64 size; | 136 | u64 size; |
| 137 | int r; | 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 | while (npages) { | 143 | while (npages) { |
| 144 | size = min(GTT_MAX_PAGES, npages); | 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 | out_unlock: | 177 | out_unlock: |
| 178 | mutex_unlock(&adev->mman.gtt_window_lock); | 178 | mutex_unlock(&entity->lock); |
| 179 | 179 | ||
| 180 | return r; | 180 | return r; |
| 181 | } | 181 | } |
| @@ -70,7 +70,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd, · 69 unmodified lines | |||
| 70 | static void set_priority(struct cik_mqd *m, struct queue_properties *q) | 70 | static void set_priority(struct cik_mqd *m, struct queue_properties *q) |
| 71 | { | 71 | { |
| 72 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 72 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 73 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, | 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 | static void set_priority(struct v10_compute_mqd *m, struct queue_properties *q) | 70 | static void set_priority(struct v10_compute_mqd *m, struct queue_properties *q) |
| 71 | { | 71 | { |
| 72 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 72 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 73 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, | 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 | static void set_priority(struct v11_compute_mqd *m, struct queue_properties *q) | 96 | static void set_priority(struct v11_compute_mqd *m, struct queue_properties *q) |
| 97 | { | 97 | { |
| 98 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 98 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 99 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 100 | } | 99 | } |
| 101 | 100 | ||
| 102 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, | 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 | static void set_priority(struct v12_compute_mqd *m, struct queue_properties *q) | 77 | static void set_priority(struct v12_compute_mqd *m, struct queue_properties *q) |
| 78 | { | 78 | { |
| 79 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 79 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 80 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, | 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 | static void set_priority(struct v12_1_compute_mqd *m, struct queue_properties *q) | 131 | static void set_priority(struct v12_1_compute_mqd *m, struct queue_properties *q) |
| 132 | { | 132 | { |
| 133 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 133 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 134 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, | 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 | static void set_priority(struct v9_mqd *m, struct queue_properties *q) | 106 | static void set_priority(struct v9_mqd *m, struct queue_properties *q) |
| 107 | { | 107 | { |
| 108 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 108 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 109 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 110 | } | 109 | } |
| 111 | 110 | ||
| 112 | static bool mqd_on_vram(struct amdgpu_device *adev) | 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 | static void set_priority(struct vi_mqd *m, struct queue_properties *q) | 73 | static void set_priority(struct vi_mqd *m, struct queue_properties *q) |
| 74 | { | 74 | { |
| 75 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; | 75 | m->cp_hqd_pipe_priority = pipe_priority_map[q->priority]; |
| 76 | /* m->cp_hqd_queue_priority = q->priority; */ | ||
| 77 | } | 76 | } |
| 78 | 77 | ||
| 79 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, | 78 | static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm, |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: MIT | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | * copy of this software and associated documentation files (the "Software"), | 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 | #define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin" | 153 | #define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin" |
| 154 | MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB); | 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 | * DOC: overview | 160 | * DOC: overview |
| 158 | * | 161 | * |
| @@ -1369,6 +1372,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) · 1210 unmodified lines | |||
| 1369 | case IP_VERSION(3, 5, 0): | 1372 | case IP_VERSION(3, 5, 0): |
| 1370 | case IP_VERSION(3, 5, 1): | 1373 | case IP_VERSION(3, 5, 1): |
| 1371 | case IP_VERSION(3, 6, 0): | 1374 | case IP_VERSION(3, 6, 0): |
| 1375 | case IP_VERSION(4, 2, 0): | ||
| 1372 | hw_params.ips_sequential_ono = adev->external_rev_id > 0x10; | 1376 | hw_params.ips_sequential_ono = adev->external_rev_id > 0x10; |
| 1373 | hw_params.lower_hbr3_phy_ssc = true; | 1377 | hw_params.lower_hbr3_phy_ssc = true; |
| 1374 | break; | 1378 | break; |
| @@ -1816,6 +1820,9 @@ static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev) · 441 unmodified lines | |||
| 1816 | case IP_VERSION(4, 0, 1): | 1820 | case IP_VERSION(4, 0, 1): |
| 1817 | bb_size = sizeof(struct dml2_soc_bb); | 1821 | bb_size = sizeof(struct dml2_soc_bb); |
| 1818 | break; | 1822 | break; |
| 1823 | case IP_VERSION(4, 2, 0): | ||
| 1824 | bb_size = sizeof(struct dml2_soc_bb); | ||
| 1825 | break; | ||
| 1819 | default: | 1826 | default: |
| 1820 | return NULL; | 1827 | return NULL; |
| 1821 | } | 1828 | } |
| @@ -1860,6 +1867,9 @@ static enum dmub_ips_disable_type dm_get_default_ips_mode( · 38 unmodified lines | |||
| 1860 | case IP_VERSION(3, 5, 1): | 1867 | case IP_VERSION(3, 5, 1): |
| 1861 | ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; | 1868 | ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; |
| 1862 | break; | 1869 | break; |
| 1870 | case IP_VERSION(4, 2, 0): | ||
| 1871 | ret = DMUB_IPS_DISABLE_ALL; | ||
| 1872 | break; | ||
| 1863 | default: | 1873 | default: |
| 1864 | /* ASICs older than DCN35 do not have IPSs */ | 1874 | /* ASICs older than DCN35 do not have IPSs */ |
| 1865 | if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0)) | 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 | if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) | 2013 | if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) |
| 2004 | init_data.num_virtual_links = 1; | 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 | retrieve_dmi_info(&adev->dm); | 2023 | retrieve_dmi_info(&adev->dm); |
| 2007 | if (adev->dm.edp0_on_dp1_quirk) | 2024 | if (adev->dm.edp0_on_dp1_quirk) |
| 2008 | init_data.flags.support_edp0_on_dp1 = true; | 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 | case IP_VERSION(3, 5, 1): | 2387 | case IP_VERSION(3, 5, 1): |
| 2371 | case IP_VERSION(3, 6, 0): | 2388 | case IP_VERSION(3, 6, 0): |
| 2372 | case IP_VERSION(4, 0, 1): | 2389 | case IP_VERSION(4, 0, 1): |
| 2390 | case IP_VERSION(4, 2, 0): | ||
| 2373 | return 0; | 2391 | return 0; |
| 2374 | default: | 2392 | default: |
| 2375 | break; | 2393 | break; |
| @@ -2503,7 +2521,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) · 127 unmodified lines | |||
| 2503 | case IP_VERSION(4, 0, 1): | 2521 | case IP_VERSION(4, 0, 1): |
| 2504 | dmub_asic = DMUB_ASIC_DCN401; | 2522 | dmub_asic = DMUB_ASIC_DCN401; |
| 2505 | break; | 2523 | break; |
| 2506 | 2524 | case IP_VERSION(4, 2, 0): | |
| 2525 | dmub_asic = DMUB_ASIC_DCN42; | ||
| 2526 | break; | ||
| 2507 | default: | 2527 | default: |
| 2508 | /* ASIC doesn't support DMUB. */ | 2528 | /* ASIC doesn't support DMUB. */ |
| 2509 | return 0; | 2529 | return 0; |
| @@ -4390,105 +4410,6 @@ static int register_hpd_handlers(struct amdgpu_device *adev) · 1880 unmodified lines | |||
| 4390 | return 0; | 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 | /* Register IRQ sources and initialize IRQ callbacks */ | 4413 | /* Register IRQ sources and initialize IRQ callbacks */ |
| 4493 | static int dce110_register_irq_handlers(struct amdgpu_device *adev) | 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 | struct dc_interrupt_params int_params = {0}; | 4418 | struct dc_interrupt_params int_params = {0}; |
| 4498 | int r; | 4419 | int r; |
| 4499 | int i; | 4420 | int i; |
| 4421 | unsigned int src_id; | ||
| 4500 | unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY; | 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 | if (adev->family >= AMDGPU_FAMILY_AI) | 4428 | if (adev->family >= AMDGPU_FAMILY_AI) |
| 4503 | client_id = SOC15_IH_CLIENTID_DCE; | 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 | /* Use VBLANK interrupt */ | 4446 | /* Use VBLANK interrupt */ |
| 4521 | for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) { | 4447 | for (i = 0; i < adev->mode_info.num_crtc; i++) { |
| 4522 | r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); | 4448 | src_id = vblank_d1 + i; |
| 4449 | r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->crtc_irq); | ||
| 4523 | if (r) { | 4450 | if (r) { |
| 4524 | drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n"); | 4451 | drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n"); |
| 4525 | return r; | 4452 | return r; |
| @@ -4527,7 +4454,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) · 1 unmodified line | |||
| 4527 | 4454 | ||
| 4528 | int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; | 4455 | int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; |
| 4529 | int_params.irq_source = | 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 | if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || | 4459 | if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || |
| 4533 | int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 || | 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 | return -ENOMEM; | 4473 | return -ENOMEM; |
| 4547 | } | 4474 | } |
| 4548 | 4475 | ||
| 4549 | /* Use VUPDATE interrupt */ | 4476 | if (dc_supports_vrr(adev->dm.dc->ctx->dce_version)) { |
| 4550 | for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { | 4477 | /* Use VUPDATE interrupt */ |
| 4551 | r = amdgpu_irq_add_id(adev, client_id, i, &adev->vupdate_irq); | 4478 | for (i = 0; i < adev->mode_info.num_crtc; i++) { |
| 4552 | if (r) { | 4479 | src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + i * 2; |
| 4553 | drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n"); | 4480 | r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->vupdate_irq); |
| 4554 | return r; | 4481 | if (r) { |
| 4555 | } | 4482 | drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n"); |
| 4556 | 4483 | return r; | |
| 4557 | int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; | 4484 | } |
| 4558 | int_params.irq_source = | ||
| 4559 | dc_interrupt_to_irq_source(dc, i, 0); | ||
| 4560 | 4485 | ||
| 4561 | if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || | 4486 | int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; |
| 4562 | int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 || | 4487 | int_params.irq_source = |
| 4563 | int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) { | 4488 | dc_interrupt_to_irq_source(dc, src_id, 0); |
| 4564 | drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n"); | ||
| 4565 | return -EINVAL; | ||
| 4566 | } | ||
| 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; | 4497 | c_irq_params = &adev->dm.vupdate_params[ |
| 4571 | c_irq_params->irq_src = int_params.irq_source; | 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, | 4502 | if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, |
| 4574 | dm_vupdate_high_irq, c_irq_params)) | 4503 | dm_vupdate_high_irq, c_irq_params)) |
| 4575 | return -ENOMEM; | 4504 | return -ENOMEM; |
| 4505 | } | ||
| 4576 | } | 4506 | } |
| 4577 | 4507 | ||
| 4578 | /* Use GRPH_PFLIP interrupt */ | 4508 | /* Use GRPH_PFLIP interrupt */ |
| @@ -5544,6 +5474,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 965 unmodified lines | |||
| 5544 | case IP_VERSION(3, 5, 1): | 5474 | case IP_VERSION(3, 5, 1): |
| 5545 | case IP_VERSION(3, 6, 0): | 5475 | case IP_VERSION(3, 6, 0): |
| 5546 | case IP_VERSION(4, 0, 1): | 5476 | case IP_VERSION(4, 0, 1): |
| 5477 | case IP_VERSION(4, 2, 0): | ||
| 5547 | if (register_outbox_irq_handlers(dm->adev)) { | 5478 | if (register_outbox_irq_handlers(dm->adev)) { |
| 5548 | drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); | 5479 | drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); |
| 5549 | goto fail; | 5480 | goto fail; |
| @@ -5568,6 +5499,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 18 unmodified lines | |||
| 5568 | case IP_VERSION(3, 5, 1): | 5499 | case IP_VERSION(3, 5, 1): |
| 5569 | case IP_VERSION(3, 6, 0): | 5500 | case IP_VERSION(3, 6, 0): |
| 5570 | case IP_VERSION(4, 0, 1): | 5501 | case IP_VERSION(4, 0, 1): |
| 5502 | case IP_VERSION(4, 2, 0): | ||
| 5571 | psr_feature_enabled = true; | 5503 | psr_feature_enabled = true; |
| 5572 | break; | 5504 | break; |
| 5573 | default: | 5505 | default: |
| @@ -5700,11 +5632,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 126 unmodified lines | |||
| 5700 | case CHIP_PITCAIRN: | 5632 | case CHIP_PITCAIRN: |
| 5701 | case CHIP_VERDE: | 5633 | case CHIP_VERDE: |
| 5702 | case CHIP_OLAND: | 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 | #endif | 5635 | #endif |
| 5709 | case CHIP_BONAIRE: | 5636 | case CHIP_BONAIRE: |
| 5710 | case CHIP_HAWAII: | 5637 | case CHIP_HAWAII: |
| @@ -5750,6 +5677,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) · 39 unmodified lines | |||
| 5750 | case IP_VERSION(3, 5, 1): | 5677 | case IP_VERSION(3, 5, 1): |
| 5751 | case IP_VERSION(3, 6, 0): | 5678 | case IP_VERSION(3, 6, 0): |
| 5752 | case IP_VERSION(4, 0, 1): | 5679 | case IP_VERSION(4, 0, 1): |
| 5680 | case IP_VERSION(4, 2, 0): | ||
| 5753 | if (dcn10_register_irq_handlers(dm->adev)) { | 5681 | if (dcn10_register_irq_handlers(dm->adev)) { |
| 5754 | drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); | 5682 | drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); |
| 5755 | goto fail; | 5683 | goto fail; |
| @@ -5898,6 +5826,9 @@ static int dm_init_microcode(struct amdgpu_device *adev) · 142 unmodified lines | |||
| 5898 | case IP_VERSION(4, 0, 1): | 5826 | case IP_VERSION(4, 0, 1): |
| 5899 | fw_name_dmub = FIRMWARE_DCN_401_DMUB; | 5827 | fw_name_dmub = FIRMWARE_DCN_401_DMUB; |
| 5900 | break; | 5828 | break; |
| 5829 | case IP_VERSION(4, 2, 0): | ||
| 5830 | fw_name_dmub = FIRMWARE_DCN_42_DMUB; | ||
| 5831 | break; | ||
| 5901 | default: | 5832 | default: |
| 5902 | /* ASIC doesn't support DMUB. */ | 5833 | /* ASIC doesn't support DMUB. */ |
| 5903 | return 0; | 5834 | return 0; |
| @@ -6025,6 +5956,7 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block) · 121 unmodified lines | |||
| 6025 | case IP_VERSION(3, 5, 1): | 5956 | case IP_VERSION(3, 5, 1): |
| 6026 | case IP_VERSION(3, 6, 0): | 5957 | case IP_VERSION(3, 6, 0): |
| 6027 | case IP_VERSION(4, 0, 1): | 5958 | case IP_VERSION(4, 0, 1): |
| 5959 | case IP_VERSION(4, 2, 0): | ||
| 6028 | adev->mode_info.num_crtc = 4; | 5960 | adev->mode_info.num_crtc = 4; |
| 6029 | adev->mode_info.num_hpd = 4; | 5961 | adev->mode_info.num_hpd = 4; |
| 6030 | adev->mode_info.num_dig = 4; | 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 | adev->mode_info.funcs = &dm_display_funcs; | 5973 | adev->mode_info.funcs = &dm_display_funcs; |
| 6042 | 5974 | ||
| 6043 | /* | 5975 | /* |
| 6044 | * Note: Do NOT change adev->audio_endpt_rreg and | 5976 | * Note: Do NOT change adev->reg.audio_endpt.rreg and |
| 6045 | * adev->audio_endpt_wreg because they are initialised in | 5977 | * adev->reg.audio_endpt.wreg because they are initialised in |
| 6046 | * amdgpu_device_init() | 5978 | * amdgpu_device_init() |
| 6047 | */ | 5979 | */ |
| 6048 | #if defined(CONFIG_DEBUG_KERNEL_DC) | 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 | return DRM_MODE_CONNECTOR_VGA; | 8515 | return DRM_MODE_CONNECTOR_VGA; |
| 8584 | case SIGNAL_TYPE_DISPLAY_PORT: | 8516 | case SIGNAL_TYPE_DISPLAY_PORT: |
| 8585 | case SIGNAL_TYPE_DISPLAY_PORT_MST: | 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 | return DRM_MODE_CONNECTOR_DisplayPort; | 8524 | return DRM_MODE_CONNECTOR_DisplayPort; |
| 8587 | case SIGNAL_TYPE_DVI_DUAL_LINK: | 8525 | case SIGNAL_TYPE_DVI_DUAL_LINK: |
| 8588 | case SIGNAL_TYPE_DVI_SINGLE_LINK: | 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 | connector_type == DRM_MODE_CONNECTOR_HDMIB) | 9195 | connector_type == DRM_MODE_CONNECTOR_HDMIB) |
| 9258 | amdgpu_dm_initialize_hdmi_connector(aconnector); | 9196 | amdgpu_dm_initialize_hdmi_connector(aconnector); |
| 9259 | 9197 | ||
| 9260 | if (connector_type == DRM_MODE_CONNECTOR_DisplayPort | 9198 | if (dc_is_dp_signal(link->connector_signal)) |
| 9261 | || connector_type == DRM_MODE_CONNECTOR_eDP) | ||
| 9262 | amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index); | 9199 | amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index); |
| 9263 | 9200 | ||
| 9264 | out_free: | 9201 | out_free: |
| @@ -12320,10 +12257,11 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev, · 3055 unmodified lines | |||
| 12320 | int i; | 12257 | int i; |
| 12321 | 12258 | ||
| 12322 | /* Overlay cursor not supported on HW before DCN | 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 | 12260 | * DCN401/420 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 | 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 | *cursor_mode = DM_CURSOR_NATIVE_MODE; | 12265 | *cursor_mode = DM_CURSOR_NATIVE_MODE; |
| 12328 | return 0; | 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 | /* Check if rotation or scaling is enabled on DCN401 */ | 12682 | /* Check if rotation or scaling is enabled on DCN401 */ |
| 12745 | if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) && | 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 | new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor); | 12686 | new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor); |
| 12748 | 12687 | ||
| 12749 | is_rotated = new_cursor_state && | 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 | struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func; | 1706 | struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func; |
| 1707 | struct drm_atomic_state *state = plane_state->state; | 1707 | struct drm_atomic_state *state = plane_state->state; |
| 1708 | const struct amdgpu_device *adev = drm_to_adev(colorop->dev); | 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 | const struct drm_device *dev = colorop->dev; | 1710 | const struct drm_device *dev = colorop->dev; |
| 1710 | const struct drm_color_lut32 *lut3d; | 1711 | const struct drm_color_lut32 *lut3d; |
| 1711 | uint32_t lut3d_size; | 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 | if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) { | 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 | drm_dbg(dev, "3D LUT is not supported by hardware\n"); | 1727 | drm_dbg(dev, "3D LUT is not supported by hardware\n"); |
| 1727 | return -EINVAL; | 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 | struct drm_colorop *colorop = plane_state->color_pipeline; | 1876 | struct drm_colorop *colorop = plane_state->color_pipeline; |
| 1876 | struct drm_device *dev = plane_state->plane->dev; | 1877 | struct drm_device *dev = plane_state->plane->dev; |
| 1877 | struct amdgpu_device *adev = drm_to_adev(dev); | 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 | int ret; | 1880 | int ret; |
| 1879 | 1881 | ||
| 1880 | /* 1D Curve - DEGAM TF */ | 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 | if (ret) | 1909 | if (ret) |
| 1908 | return ret; | 1910 | return ret; |
| 1909 | 1911 | ||
| 1910 | if (adev->dm.dc->caps.color.dpp.hw_3d_lut) { | 1912 | if (has_3dlut) { |
| 1911 | /* 1D Curve & LUT - SHAPER TF & LUT */ | 1913 | /* 1D Curve & LUT - SHAPER TF & LUT */ |
| 1912 | colorop = colorop->next; | 1914 | colorop = colorop->next; |
| 1913 | if (!colorop) { | 1915 | if (!colorop) { |
| @@ -64,6 +64,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr · 63 unmodified lines | |||
| 64 | struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS]; | 64 | struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS]; |
| 65 | struct drm_device *dev = plane->dev; | 65 | struct drm_device *dev = plane->dev; |
| 66 | struct amdgpu_device *adev = drm_to_adev(dev); | 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 | int ret; | 68 | int ret; |
| 68 | int i = 0; | 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 | i++; | 121 | i++; |
| 121 | 122 | ||
| 122 | if (adev->dm.dc->caps.color.dpp.hw_3d_lut) { | 123 | if (has_3dlut) { |
| 123 | /* 1D curve - SHAPER TF */ | 124 | /* 1D curve - SHAPER TF */ |
| 124 | ops[i] = kzalloc_obj(*ops[0]); | 125 | ops[i] = kzalloc_obj(*ops[0]); |
| 125 | if (!ops[i]) { | 126 | if (!ops[i]) { |
| @@ -765,15 +765,15 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, · 764 unmodified lines | |||
| 765 | dm->adev->mode_info.crtcs[crtc_index] = acrtc; | 765 | dm->adev->mode_info.crtcs[crtc_index] = acrtc; |
| 766 | 766 | ||
| 767 | /* Don't enable DRM CRTC degamma property for | 767 | /* Don't enable DRM CRTC degamma property for |
| 768 | * 1. Degamma is replaced by color pipeline. | 768 | * 1. DCE since it doesn't support programmable degamma anywhere. |
| 769 | * 2. DCE since it doesn't support programmable degamma anywhere. | 769 | * 2. DCN401 since pre-blending degamma LUT doesn't apply to cursor. |
| 770 | * 3. 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) | 775 | has_degamma = dm->adev->dm.dc->caps.color.dpp.dcn_arch && |
| 773 | has_degamma = false; | 776 | dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01; |
| 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; | ||
| 777 | 777 | ||
| 778 | drm_crtc_enable_color_mgmt(&acrtc->base, has_degamma ? MAX_COLOR_LUT_ENTRIES : 0, | 778 | drm_crtc_enable_color_mgmt(&acrtc->base, has_degamma ? MAX_COLOR_LUT_ENTRIES : 0, |
| 779 | true, MAX_COLOR_LUT_ENTRIES); | 779 | true, MAX_COLOR_LUT_ENTRIES); |
| @@ -1016,6 +1016,9 @@ enum dc_edid_status dm_helpers_read_local_edid( · 1015 unmodified lines | |||
| 1016 | else | 1016 | else |
| 1017 | ddc = &aconnector->i2c->base; | 1017 | ddc = &aconnector->i2c->base; |
| 1018 | 1018 | ||
| 1019 | if (link->dc->hwss.prepare_ddc) | ||
| 1020 | link->dc->hwss.prepare_ddc(link); | ||
| 1021 | |||
| 1019 | /* some dongles read edid incorrectly the first time, | 1022 | /* some dongles read edid incorrectly the first time, |
| 1020 | * do check sum and retry to make sure read correct edid. | 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 | link->panel_config.dsc.disable_dsc_edp = true; | 1165 | link->panel_config.dsc.disable_dsc_edp = true; |
| 1163 | 1166 | ||
| 1164 | if (dc_get_edp_link_panel_inst(ctx->dc, link, &panel_inst) && panel_inst == 1) { | 1167 | if (dc_get_edp_link_panel_inst(ctx->dc, link, &panel_inst) && panel_inst == 1) { |
| 1165 | link->panel_config.psr.disable_psr = true; | 1168 | link->panel_config.psr.disable_psr = true; |
| 1166 | link->panel_config.psr.disallow_psrsu = true;; | 1169 | link->panel_config.psr.disallow_psrsu = true; |
| 1167 | link->panel_config.psr.disallow_replay = true; | 1170 | link->panel_config.psr.disallow_replay = true; |
| 1168 | } | 1171 | } |
| 1169 | } | 1172 | } |
| 1170 | 1173 | ||
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: MIT | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | * copy of this software and associated documentation files (the "Software"), | 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 | case AMDGPU_FAMILY_GC_11_0_0: | 759 | case AMDGPU_FAMILY_GC_11_0_0: |
| 760 | case AMDGPU_FAMILY_GC_11_0_1: | 760 | case AMDGPU_FAMILY_GC_11_0_1: |
| 761 | case AMDGPU_FAMILY_GC_11_5_0: | 761 | case AMDGPU_FAMILY_GC_11_5_0: |
| 762 | case AMDGPU_FAMILY_GC_11_5_4: | ||
| 762 | amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity); | 763 | amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity); |
| 763 | break; | 764 | break; |
| 764 | case AMDGPU_FAMILY_GC_12_0_0: | 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 | if (ret) | 1257 | if (ret) |
| 1257 | return ret; | 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 | ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info); | 1268 | ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info); |
| 1260 | if (ret) | 1269 | if (ret) |
| 1261 | return ret; | 1270 | return ret; |
| @@ -780,28 +780,33 @@ static enum bp_result bios_parser_encoder_control( · 779 unmodified lines | |||
| 780 | return bp->cmd_tbl.dig_encoder_control(bp, cntl); | 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 | static enum bp_result bios_parser_dac_load_detection( | 795 | static enum bp_result bios_parser_dac_load_detection( |
| 784 | struct dc_bios *dcb, | 796 | struct dc_bios *dcb, |
| 785 | enum engine_id engine_id, | 797 | enum engine_id engine_id, |
| 786 | enum dal_device_type device_type, | 798 | struct graphics_object_id ext_enc_id) |
| 787 | uint32_t enum_id) | ||
| 788 | { | 799 | { |
| 789 | struct bios_parser *bp = BP_FROM_DCB(dcb); | 800 | struct bios_parser *bp = BP_FROM_DCB(dcb); |
| 790 | struct dc_context *ctx = dcb->ctx; | 801 | struct dc_context *ctx = dcb->ctx; |
| 791 | struct bp_load_detection_parameters bp_params = {0}; | 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 | uint32_t bios_0_scratch; | 805 | uint32_t bios_0_scratch; |
| 794 | uint32_t device_id_mask = 0; | 806 | uint32_t device_id_mask = 0; |
| 795 | 807 | ||
| 796 | bp_params.engine_id = engine_id; | 808 | bp_params.device_id = get_support_mask_for_device_id( |
| 797 | bp_params.device_id = get_support_mask_for_device_id(device_type, enum_id); | 809 | DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1); |
| 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; | ||
| 805 | 810 | ||
| 806 | if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) | 811 | if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) |
| 807 | device_id_mask = ATOM_S0_CRT1_MASK; | 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 | bios_0_scratch &= ~device_id_mask; | 820 | bios_0_scratch &= ~device_id_mask; |
| 816 | dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); | 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 | if (bp_result != BP_RESULT_OK) | 838 | if (bp_result != BP_RESULT_OK) |
| 821 | return bp_result; | 839 | return bp_result; |
| @@ -2912,6 +2930,8 @@ static const struct dc_vbios_funcs vbios_funcs = { · 2090 unmodified lines | |||
| 2912 | 2930 | ||
| 2913 | .encoder_control = bios_parser_encoder_control, | 2931 | .encoder_control = bios_parser_encoder_control, |
| 2914 | 2932 | ||
| 2933 | .external_encoder_control = bios_parser_external_encoder_control, | ||
| 2934 | |||
| 2915 | .dac_load_detection = bios_parser_dac_load_detection, | 2935 | .dac_load_detection = bios_parser_dac_load_detection, |
| 2916 | 2936 | ||
| 2917 | .transmitter_control = bios_parser_transmitter_control, | 2937 | .transmitter_control = bios_parser_transmitter_control, |
| @@ -226,6 +226,28 @@ static enum bp_result encoder_control_dig2_v1( · 225 unmodified lines | |||
| 226 | return result; | 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 | static enum bp_result encoder_control_digx_v3( | 251 | static enum bp_result encoder_control_digx_v3( |
| 230 | struct bios_parser *bp, | 252 | struct bios_parser *bp, |
| 231 | struct bp_encoder_control *cntl) | 253 | struct bp_encoder_control *cntl) |
| @@ -248,23 +270,7 @@ static enum bp_result encoder_control_digx_v3( · 16 unmodified lines | |||
| 248 | cntl->signal, | 270 | cntl->signal, |
| 249 | cntl->enable_dp_audio); | 271 | cntl->enable_dp_audio); |
| 250 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); | 272 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 251 | 273 | params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 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 | } | ||
| 268 | 274 | ||
| 269 | if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) | 275 | if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) |
| 270 | result = BP_RESULT_OK; | 276 | result = BP_RESULT_OK; |
| @@ -294,23 +300,7 @@ static enum bp_result encoder_control_digx_v4( · 23 unmodified lines | |||
| 294 | cntl->signal, | 300 | cntl->signal, |
| 295 | cntl->enable_dp_audio)); | 301 | cntl->enable_dp_audio)); |
| 296 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); | 302 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 297 | 303 | params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 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 | } | ||
| 314 | 304 | ||
| 315 | if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) | 305 | if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) |
| 316 | result = BP_RESULT_OK; | 306 | result = BP_RESULT_OK; |
| @@ -334,23 +324,7 @@ static enum bp_result encoder_control_digx_v5( · 17 unmodified lines | |||
| 334 | cntl->signal, | 324 | cntl->signal, |
| 335 | cntl->enable_dp_audio)); | 325 | cntl->enable_dp_audio)); |
| 336 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); | 326 | params.ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 337 | 327 | params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); | |
| 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 | } | ||
| 354 | 328 | ||
| 355 | if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) | 329 | if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) |
| 356 | switch (cntl->color_depth) { | 330 | switch (cntl->color_depth) { |
| @@ -1797,30 +1771,7 @@ static enum bp_result select_crtc_source_v3( · 1440 unmodified lines | |||
| 1797 | ¶ms.ucEncodeMode)) | 1771 | ¶ms.ucEncodeMode)) |
| 1798 | return BP_RESULT_BADINPUT; | 1772 | return BP_RESULT_BADINPUT; |
| 1799 | 1773 | ||
| 1800 | switch (bp_params->color_depth) { | 1774 | params.ucDstBpc = dc_color_depth_to_atom(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 | } | ||
| 1824 | 1775 | ||
| 1825 | if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) | 1776 | if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) |
| 1826 | result = BP_RESULT_OK; | 1777 | result = BP_RESULT_OK; |
| @@ -2569,6 +2520,7 @@ static enum bp_result external_encoder_control_v3( · 742 unmodified lines | |||
| 2569 | cpu_to_le16((uint16_t)cntl->connector_obj_id.id); | 2520 | cpu_to_le16((uint16_t)cntl->connector_obj_id.id); |
| 2570 | break; | 2521 | break; |
| 2571 | case EXTERNAL_ENCODER_CONTROL_SETUP: | 2522 | case EXTERNAL_ENCODER_CONTROL_SETUP: |
| 2523 | case EXTERNAL_ENCODER_CONTROL_ENABLE: | ||
| 2572 | /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in | 2524 | /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in |
| 2573 | * 10KHz | 2525 | * 10KHz |
| 2574 | * output display device pixel clock frequency in unit of 10KHz. | 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 | if (is_input_signal_dp) { | 2537 | if (is_input_signal_dp) { |
| 2586 | /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, | 2538 | /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, |
| 2587 | * only valid in encoder setup with DP mode. */ | 2539 | * only valid in encoder setup with DP mode. */ |
| 2588 | if (LINK_RATE_HIGH == cntl->link_rate) | 2540 | if (cntl->link_rate == LINK_RATE_LOW) |
| 2589 | cntl_params->ucConfig |= 1; | 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 | /* output color depth Indicate encoder data bpc format | 2549 | /* output color depth Indicate encoder data bpc format |
| 2591 | * in DP mode, only valid in encoder setup in DP mode. | 2550 | * in DP mode, only valid in encoder setup in DP mode. |
| 2592 | */ | 2551 | */ |
| 2593 | cntl_params->ucBitPerColor = | 2552 | cntl_params->ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); |
| 2594 | (uint8_t)(cntl->color_depth); | ||
| 2595 | } | 2553 | } |
| 2596 | /* Indicate how many lanes used by external encoder, only valid | 2554 | /* Indicate how many lanes used by external encoder, only valid |
| 2597 | * in encoder setup and enableoutput. */ | 2555 | * in encoder setup and enableoutput. */ |
| 2598 | cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); | 2556 | cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); |
| 2599 | break; | 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 | default: | 2558 | default: |
| 2609 | break; | 2559 | break; |
| 2610 | } | 2560 | } |
| @@ -84,6 +84,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( · 83 unmodified lines | |||
| 84 | case DCN_VERSION_3_51: | 84 | case DCN_VERSION_3_51: |
| 85 | case DCN_VERSION_3_6: | 85 | case DCN_VERSION_3_6: |
| 86 | case DCN_VERSION_4_01: | 86 | case DCN_VERSION_4_01: |
| 87 | case DCN_VERSION_4_2: | ||
| 87 | *h = dal_cmd_tbl_helper_dce112_get_table2(); | 88 | *h = dal_cmd_tbl_helper_dce112_get_table2(); |
| 88 | return true; | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR) | 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 | # DCE 100 and DCE8x | 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 | AMD_DAL_CLK_MGR_DCN401 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn401/,$(CLK_MGR_DCN401)) | 176 | AMD_DAL_CLK_MGR_DCN401 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn401/,$(CLK_MGR_DCN401)) |
| 189 | 177 | ||
| 190 | AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN401) | 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 | endif | 188 | endif |
| @@ -34,7 +34,6 @@ · 33 unmodified lines | |||
| 34 | #include "dce110/dce110_clk_mgr.h" | 34 | #include "dce110/dce110_clk_mgr.h" |
| 35 | #include "dce112/dce112_clk_mgr.h" | 35 | #include "dce112/dce112_clk_mgr.h" |
| 36 | #include "dce120/dce120_clk_mgr.h" | 36 | #include "dce120/dce120_clk_mgr.h" |
| 37 | #include "dce60/dce60_clk_mgr.h" | ||
| 38 | #include "dcn10/rv1_clk_mgr.h" | 37 | #include "dcn10/rv1_clk_mgr.h" |
| 39 | #include "dcn10/rv2_clk_mgr.h" | 38 | #include "dcn10/rv2_clk_mgr.h" |
| 40 | #include "dcn20/dcn20_clk_mgr.h" | 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 | struct hw_asic_id asic_id = ctx->asic_id; | 148 | struct hw_asic_id asic_id = ctx->asic_id; |
| 150 | 149 | ||
| 151 | switch (asic_id.chip_family) { | 150 | switch (asic_id.chip_family) { |
| 152 | #if defined(CONFIG_DRM_AMD_DC_SI) | 151 | case FAMILY_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 | ||
| 164 | case FAMILY_CI: | 152 | case FAMILY_CI: |
| 165 | case FAMILY_KV: { | 153 | case FAMILY_KV: { |
| 166 | struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr); | 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 | CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) | 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 | /* Max clock values for each state indexed by "enum clocks_state": */ | 78 | /* Max clock values for each state indexed by "enum clocks_state": */ |
| 67 | static const struct state_dependent_clocks dce80_max_clks_by_state[] = { | 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 | return dp_ref_clk_khz; | 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 | int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) | 155 | int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) |
| 130 | { | 156 | { |
| 131 | struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); | 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 | int dp_ref_clk_khz; | 160 | int dp_ref_clk_khz; |
| 135 | int target_div; | 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 | /* ASSERT DP Reference Clock source is from DFS*/ | 166 | /* ASSERT DP Reference Clock source is from DFS*/ |
| 138 | REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); | 167 | REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); |
| 139 | ASSERT(dprefclk_src_sel == 0); | 168 | ASSERT(dprefclk_src_sel == 0); |
| @@ -441,27 +470,37 @@ void dce_clk_mgr_construct( · 301 unmodified lines | |||
| 441 | struct clk_mgr *base = &clk_mgr->base; | 470 | struct clk_mgr *base = &clk_mgr->base; |
| 442 | struct dm_pp_static_clock_info static_clk_info = {0}; | 471 | struct dm_pp_static_clock_info static_clk_info = {0}; |
| 443 | 472 | ||
| 444 | memcpy(clk_mgr->max_clks_by_state, | 473 | if (ctx->dce_version <= DCE_VERSION_6_4) |
| 445 | dce80_max_clks_by_state, | 474 | memcpy(clk_mgr->max_clks_by_state, |
| 446 | sizeof(dce80_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 | base->ctx = ctx; | 483 | base->ctx = ctx; |
| 449 | base->funcs = &dce_funcs; | 484 | base->funcs = &dce_funcs; |
| 450 | 485 | ||
| 451 | clk_mgr->regs = &disp_clk_regs; | 486 | if (ctx->dce_version >= DCE_VERSION_8_0) { |
| 452 | clk_mgr->clk_mgr_shift = &disp_clk_shift; | 487 | clk_mgr->regs = &disp_clk_regs; |
| 453 | clk_mgr->clk_mgr_mask = &disp_clk_mask; | 488 | clk_mgr->clk_mgr_shift = &disp_clk_shift; |
| 454 | clk_mgr->dfs_bypass_disp_clk = 0; | 489 | clk_mgr->clk_mgr_mask = &disp_clk_mask; |
| 490 | } | ||
| 455 | 491 | ||
| 492 | clk_mgr->dfs_bypass_disp_clk = 0; | ||
| 456 | clk_mgr->dprefclk_ss_percentage = 0; | 493 | clk_mgr->dprefclk_ss_percentage = 0; |
| 457 | clk_mgr->dprefclk_ss_divider = 1000; | 494 | clk_mgr->dprefclk_ss_divider = 1000; |
| 458 | clk_mgr->ss_on_dprefclk = false; | 495 | clk_mgr->ss_on_dprefclk = false; |
| 459 | 496 | ||
| 460 | if (dm_pp_get_static_clocks(ctx, &static_clk_info)) | 497 | if (ctx->dce_version >= DCE_VERSION_8_0) { |
| 461 | clk_mgr->max_clks_state = static_clk_info.max_clocks_state; | 498 | if (dm_pp_get_static_clocks(ctx, &static_clk_info)) |
| 462 | else | 499 | clk_mgr->max_clks_state = static_clk_info.max_clocks_state; |
| 463 | clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; | 500 | else |
| 464 | clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; | 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 | base->clks.max_supported_dispclk_khz = | 505 | base->clks.max_supported_dispclk_khz = |
| 467 | clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; | 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 | dce_clock_read_integrated_info(clk_mgr); | 508 | dce_clock_read_integrated_info(clk_mgr); |
| 470 | dce_clock_read_ss_info(clk_mgr); | 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 | khz_to_mhz_ceil(requested_dispclk_khz)); | 204 | khz_to_mhz_ceil(requested_dispclk_khz)); |
| 205 | 205 | ||
| 206 | smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", requested_dispclk_khz, actual_dispclk_set_mhz); | 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 | int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) | 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 | /* TODO: add code for programing DP DTO, currently this is down by command table */ | 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 | int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz) | 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 | smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", requested_dcfclk_khz, actual_dcfclk_set_mhz); | 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 | int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz) | 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 | 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); | 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 | int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) | 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 | smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", requested_dpp_khz, actual_dppclk_set_mhz); | 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 | void dcn35_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info) | 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 | 0); | 424 | 0); |
| 425 | 425 | ||
| 426 | smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk); | 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 | int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) | 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 | 0); | 439 | 0); |
| 440 | 440 | ||
| 441 | smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk); | 441 | smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk); |
| 442 | return dtbclk * 1000; | 442 | return (int)((long long)dtbclk * 1000); |
| 443 | } | 443 | } |
| 444 | /* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */ | 444 | /* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */ |
| 445 | void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable) | 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 | return false; | 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 | * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of | 446 | * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of |
| 516 | * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate) | 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 | get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); | 1205 | get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); |
| 1275 | else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC) | 1206 | else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC) |
| 1276 | get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); | 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 | static void disable_dangling_plane(struct dc *dc, struct dc_state *context) | 1336 | static void disable_dangling_plane(struct dc *dc, struct dc_state *context) |
| 1327 | { | 1337 | { |
| 1328 | int i, j; | 1338 | int i, j; |
| @@ -3064,7 +3074,7 @@ struct surface_update_descriptor dc_check_update_surfaces_for_stream( · 1735 unmodified lines | |||
| 3064 | { | 3074 | { |
| 3065 | if (stream_update) | 3075 | if (stream_update) |
| 3066 | stream_update->stream->update_flags.raw = 0; | 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 | updates[i].surface->update_flags.raw = 0; | 3078 | updates[i].surface->update_flags.raw = 0; |
| 3069 | 3079 | ||
| 3070 | return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update); | 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 | if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW && | 5551 | if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW && |
| 5542 | dc->hwss.power_down_on_boot) { | 5552 | dc->hwss.power_down_on_boot) { |
| 5553 | if (dc->current_state->stream_count > 0) | ||
| 5554 | return; | ||
| 5555 | |||
| 5543 | if (dc->caps.ips_support) | 5556 | if (dc->caps.ips_support) |
| 5544 | dc_exit_ips_for_hw_access(dc); | 5557 | dc_exit_ips_for_hw_access(dc); |
| 5545 | dc->hwss.power_down_on_boot(dc); | 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 | if (!dc->current_state) | 5564 | if (!dc->current_state) |
| 5552 | return; | 5565 | return; |
| 5553 | 5566 | ||
| 5567 | dc_exit_ips_for_hw_access(dc); | ||
| 5568 | |||
| 5554 | switch (power_state) { | 5569 | switch (power_state) { |
| 5555 | case DC_ACPI_CM_POWER_STATE_D0: | 5570 | case DC_ACPI_CM_POWER_STATE_D0: |
| 5556 | dc_state_construct(dc, dc->current_state); | 5571 | dc_state_construct(dc, dc->current_state); |
| 5557 | 5572 | ||
| 5558 | dc_exit_ips_for_hw_access(dc); | ||
| 5559 | |||
| 5560 | dc_z10_restore(dc); | 5573 | dc_z10_restore(dc); |
| 5561 | 5574 | ||
| 5562 | dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state); | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 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 | block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE; | 846 | block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE; |
| 847 | (*num_steps)++; | 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 | if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) { | 860 | if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) { |
| 851 | block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc; | 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 | case HUBP_PROGRAM_MCACHE_ID: | 1039 | case HUBP_PROGRAM_MCACHE_ID: |
| 1030 | hwss_program_mcache_id_and_split_coordinate(params); | 1040 | hwss_program_mcache_id_and_split_coordinate(params); |
| 1031 | break; | 1041 | break; |
| 1042 | case DPP_PROGRAM_CM_HIST: | ||
| 1043 | hwss_program_cm_hist(params); | ||
| 1044 | break; | ||
| 1032 | case PROGRAM_CURSOR_UPDATE_NOW: | 1045 | case PROGRAM_CURSOR_UPDATE_NOW: |
| 1033 | dc->hwss.program_cursor_offload_now( | 1046 | dc->hwss.program_cursor_offload_now( |
| 1034 | params->program_cursor_update_now_params.dc, | 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 | void get_surface_tile_visual_confirm_color( | 2080 | void get_surface_tile_visual_confirm_color( |
| 2058 | struct pipe_ctx *pipe_ctx, | 2081 | struct pipe_ctx *pipe_ctx, |
| 2059 | struct tg_color *color) | 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 | void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state, | 3410 | void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state, |
| 3374 | struct dc *dc, | 3411 | struct dc *dc, |
| 3375 | bool enable) | 3412 | bool enable) |
| @@ -4071,3 +4108,24 @@ void hwss_add_tg_get_frame_count(struct block_sequence_state *seq_state, · 695 unmodified lines | |||
| 4071 | (*seq_state->num_steps)++; | 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 | #include "dcn351/dcn351_resource.h" | 78 | #include "dcn351/dcn351_resource.h" |
| 79 | #include "dcn36/dcn36_resource.h" | 79 | #include "dcn36/dcn36_resource.h" |
| 80 | #include "dcn401/dcn401_resource.h" | 80 | #include "dcn401/dcn401_resource.h" |
| 81 | #include "dcn42/dcn42_resource.h" | ||
| 81 | #if defined(CONFIG_DRM_AMD_DC_FP) | 82 | #if defined(CONFIG_DRM_AMD_DC_FP) |
| 82 | #include "dc_spl_translate.h" | 83 | #include "dc_spl_translate.h" |
| 83 | #endif | 84 | #endif |
| @@ -252,6 +253,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) · 168 unmodified lines | |||
| 252 | ASICREV_IS_GC_12_0_0_A0(asic_id.hw_internal_rev)) | 253 | ASICREV_IS_GC_12_0_0_A0(asic_id.hw_internal_rev)) |
| 253 | dc_version = DCN_VERSION_4_01; | 254 | dc_version = DCN_VERSION_4_01; |
| 254 | break; | 255 | break; |
| 256 | case AMDGPU_FAMILY_GC_11_5_4: | ||
| 257 | dc_version = DCN_VERSION_4_2; | ||
| 258 | break; | ||
| 255 | default: | 259 | default: |
| 256 | dc_version = DCE_VERSION_UNKNOWN; | 260 | dc_version = DCE_VERSION_UNKNOWN; |
| 257 | break; | 261 | break; |
| @@ -368,6 +372,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, · 110 unmodified lines | |||
| 368 | case DCN_VERSION_4_01: | 372 | case DCN_VERSION_4_01: |
| 369 | res_pool = dcn401_create_resource_pool(init_data, dc); | 373 | res_pool = dcn401_create_resource_pool(init_data, dc); |
| 370 | break; | 374 | break; |
| 375 | case DCN_VERSION_4_2: | ||
| 376 | res_pool = dcn42_create_resource_pool(init_data, dc); | ||
| 377 | break; | ||
| 371 | #endif /* CONFIG_DRM_AMD_DC_FP */ | 378 | #endif /* CONFIG_DRM_AMD_DC_FP */ |
| 372 | default: | 379 | default: |
| 373 | break; | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -63,7 +63,7 @@ struct dcn_dsc_reg_state; · 57 unmodified lines | |||
| 63 | struct dcn_optc_reg_state; | 63 | struct dcn_optc_reg_state; |
| 64 | struct dcn_dccg_reg_state; | 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 | * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC | 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 | VISUAL_CONFIRM_HW_CURSOR = 20, | 581 | VISUAL_CONFIRM_HW_CURSOR = 20, |
| 582 | VISUAL_CONFIRM_VABC = 21, | 582 | VISUAL_CONFIRM_VABC = 21, |
| 583 | VISUAL_CONFIRM_DCC = 22, | 583 | VISUAL_CONFIRM_DCC = 22, |
| 584 | VISUAL_CONFIRM_BOOSTED_REFRESH_RATE = 23, | ||
| 584 | VISUAL_CONFIRM_EXPLICIT = 0x80000000, | 585 | VISUAL_CONFIRM_EXPLICIT = 0x80000000, |
| 585 | }; | 586 | }; |
| 586 | 587 | ||
| @@ -733,6 +734,8 @@ struct dc_clocks { · 146 unmodified lines | |||
| 733 | struct { | 734 | struct { |
| 734 | uint8_t base_efficiency; //LP1 | 735 | uint8_t base_efficiency; //LP1 |
| 735 | uint8_t low_power_efficiency; //LP2 | 736 | uint8_t low_power_efficiency; //LP2 |
| 737 | uint8_t z8_stutter_efficiency; | ||
| 738 | int z8_stutter_period; | ||
| 736 | } stutter_efficiency; | 739 | } stutter_efficiency; |
| 737 | }; | 740 | }; |
| 738 | 741 | ||
| @@ -1211,6 +1214,7 @@ struct dc_debug_options { · 472 unmodified lines | |||
| 1211 | unsigned int num_fast_flips_to_steady_state_override; | 1214 | unsigned int num_fast_flips_to_steady_state_override; |
| 1212 | bool enable_dmu_recovery; | 1215 | bool enable_dmu_recovery; |
| 1213 | unsigned int force_vmin_threshold; | 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 | struct dc_plane_address current_address; | 1423 | struct dc_plane_address current_address; |
| 1420 | bool is_flip_pending; | 1424 | bool is_flip_pending; |
| 1421 | bool is_right_eye; | 1425 | bool is_right_eye; |
| 1426 | struct cm_hist cm_hist; | ||
| 1422 | }; | 1427 | }; |
| 1423 | 1428 | ||
| 1424 | union surface_update_flags { | 1429 | union surface_update_flags { |
| @@ -1455,6 +1460,7 @@ union surface_update_flags { · 30 unmodified lines | |||
| 1455 | uint32_t mcm_transfer_function_enable_change:1; /* disable or enable MCM transfer func */ | 1460 | uint32_t mcm_transfer_function_enable_change:1; /* disable or enable MCM transfer func */ |
| 1456 | uint32_t full_update:1; | 1461 | uint32_t full_update:1; |
| 1457 | uint32_t sdr_white_level_nits:1; | 1462 | uint32_t sdr_white_level_nits:1; |
| 1463 | uint32_t cm_hist_change:1; | ||
| 1458 | } bits; | 1464 | } bits; |
| 1459 | 1465 | ||
| 1460 | uint32_t raw; | 1466 | uint32_t raw; |
| @@ -1539,6 +1545,7 @@ struct dc_plane_state { · 78 unmodified lines | |||
| 1539 | int sharpness_level; | 1545 | int sharpness_level; |
| 1540 | enum linear_light_scaling linear_light_scaling; | 1546 | enum linear_light_scaling linear_light_scaling; |
| 1541 | unsigned int sdr_white_level_nits; | 1547 | unsigned int sdr_white_level_nits; |
| 1548 | struct cm_hist_control cm_hist_control; | ||
| 1542 | struct spl_sharpness_range sharpness_range; | 1549 | struct spl_sharpness_range sharpness_range; |
| 1543 | enum sharpness_range_source sharpness_source; | 1550 | enum sharpness_range_source sharpness_source; |
| 1544 | }; | 1551 | }; |
| @@ -1682,6 +1689,10 @@ struct dc_scratch_space { · 137 unmodified lines | |||
| 1682 | struct panel_cntl *panel_cntl; | 1689 | struct panel_cntl *panel_cntl; |
| 1683 | struct link_encoder *link_enc; | 1690 | struct link_encoder *link_enc; |
| 1684 | struct graphics_object_id link_id; | 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 | /* Endpoint type distinguishes display endpoints which do not have entries | 1696 | /* Endpoint type distinguishes display endpoints which do not have entries |
| 1686 | * in the BIOS connector table from those that do. Helps when tracking link | 1697 | * in the BIOS connector table from those that do. Helps when tracking link |
| 1687 | * encoder to display endpoint assignments. | 1698 | * encoder to display endpoint assignments. |
| @@ -1843,6 +1854,7 @@ struct dc_fast_update { · 155 unmodified lines | |||
| 1843 | struct dc_transfer_func *out_transfer_func; | 1854 | struct dc_transfer_func *out_transfer_func; |
| 1844 | struct dc_csc_transform *output_csc_transform; | 1855 | struct dc_csc_transform *output_csc_transform; |
| 1845 | const struct dc_csc_transform *cursor_csc_color_matrix; | 1856 | const struct dc_csc_transform *cursor_csc_color_matrix; |
| 1857 | struct cm_hist_control *cm_hist_control; | ||
| 1846 | }; | 1858 | }; |
| 1847 | 1859 | ||
| 1848 | struct dc_surface_update { | 1860 | struct dc_surface_update { |
| @@ -1875,6 +1887,7 @@ struct dc_surface_update { · 26 unmodified lines | |||
| 1875 | const struct dc_csc_transform *cursor_csc_color_matrix; | 1887 | const struct dc_csc_transform *cursor_csc_color_matrix; |
| 1876 | unsigned int sdr_white_level_nits; | 1888 | unsigned int sdr_white_level_nits; |
| 1877 | struct dc_bias_and_scale bias_and_scale; | 1889 | struct dc_bias_and_scale bias_and_scale; |
| 1890 | struct cm_hist_control *cm_hist_control; | ||
| 1878 | }; | 1891 | }; |
| 1879 | 1892 | ||
| 1880 | struct dc_underflow_debug_data { | 1893 | struct dc_underflow_debug_data { |
| @@ -97,11 +97,13 @@ struct dc_vbios_funcs { · 96 unmodified lines | |||
| 97 | enum bp_result (*encoder_control)( | 97 | enum bp_result (*encoder_control)( |
| 98 | struct dc_bios *bios, | 98 | struct dc_bios *bios, |
| 99 | struct bp_encoder_control *cntl); | 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 | enum bp_result (*dac_load_detection)( | 103 | enum bp_result (*dac_load_detection)( |
| 101 | struct dc_bios *bios, | 104 | struct dc_bios *bios, |
| 102 | enum engine_id engine_id, | 105 | enum engine_id engine_id, |
| 103 | enum dal_device_type device_type, | 106 | struct graphics_object_id ext_enc_id); |
| 104 | uint32_t enum_id); | ||
| 105 | enum bp_result (*transmitter_control)( | 107 | enum bp_result (*transmitter_control)( |
| 106 | struct dc_bios *bios, | 108 | struct dc_bios *bios, |
| 107 | struct bp_transmitter_control *cntl); | 109 | struct bp_transmitter_control *cntl); |
| @@ -947,8 +947,8 @@ union dp_tun_cap_support { · 946 unmodified lines | |||
| 947 | /* DPCD[0xE000E] DP_IN_ADAPTER_INFO register. */ | 947 | /* DPCD[0xE000E] DP_IN_ADAPTER_INFO register. */ |
| 948 | union dpia_info { | 948 | union dpia_info { |
| 949 | struct { | 949 | struct { |
| 950 | uint8_t dpia_num :5; | 950 | uint8_t dpia_num :6; |
| 951 | uint8_t rsvd :3; | 951 | uint8_t rsvd :2; |
| 952 | } bits; | 952 | } bits; |
| 953 | uint8_t raw; | 953 | uint8_t raw; |
| 954 | }; | 954 | }; |
| @@ -751,6 +751,8 @@ char *dce_version_to_string(const int version) · 750 unmodified lines | |||
| 751 | return "DCN 3.6"; | 751 | return "DCN 3.6"; |
| 752 | case DCN_VERSION_4_01: | 752 | case DCN_VERSION_4_01: |
| 753 | return "DCN 4.0.1"; | 753 | return "DCN 4.0.1"; |
| 754 | case DCN_VERSION_4_2: | ||
| 755 | return "DCN 4.2"; | ||
| 754 | default: | 756 | default: |
| 755 | return "Unknown"; | 757 | return "Unknown"; |
| 756 | } | 758 | } |
| @@ -271,6 +271,15 @@ enum tile_split_values_new { · 270 unmodified lines | |||
| 271 | DC_SURF_TILE_SPLIT_1KB = 0x4, | 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 | /* TODO: These values come from hardware spec. We need to readdress this | 283 | /* TODO: These values come from hardware spec. We need to readdress this |
| 275 | * if they ever change. | 284 | * if they ever change. |
| 276 | */ | 285 | */ |
| @@ -1137,6 +1146,7 @@ struct mcif_buf_params { · 860 unmodified lines | |||
| 1137 | unsigned int warmup_pitch; | 1146 | unsigned int warmup_pitch; |
| 1138 | unsigned int swlock; | 1147 | unsigned int swlock; |
| 1139 | unsigned int p_vmid; | 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 | enum symclk_state symclk_state; | 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 | #endif /* DC_HW_TYPES_H */ | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 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 | enum dc_cm2_gpu_mem_pixel_component_order { | 1347 | enum dc_cm2_gpu_mem_pixel_component_order { |
| 1348 | DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA, | 1348 | DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA, |
| 1349 | DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA | ||
| 1349 | }; | 1350 | }; |
| 1350 | 1351 | ||
| 1351 | enum dc_cm2_gpu_mem_format { | 1352 | enum dc_cm2_gpu_mem_format { |
| @@ -1367,6 +1368,9 @@ struct dc_cm2_gpu_mem_format_parameters { · 15 unmodified lines | |||
| 1367 | 1368 | ||
| 1368 | enum dc_cm2_gpu_mem_size { | 1369 | enum dc_cm2_gpu_mem_size { |
| 1369 | DC_CM2_GPU_MEM_SIZE_171717, | 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 | DC_CM2_GPU_MEM_SIZE_TRANSFORMED, | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 5 | # copy of this software and associated documentation files (the "Software"), |
| @@ -100,4 +100,13 @@ DCCG_DCN401 = dcn401_dccg.o · 94 unmodified lines | |||
| 100 | AMD_DAL_DCCG_DCN401 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn401/,$(DCCG_DCN401)) | 100 | AMD_DAL_DCCG_DCN401 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn401/,$(DCCG_DCN401)) |
| 101 | 101 | ||
| 102 | AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN401) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -362,6 +362,16 @@ · 356 unmodified lines | |||
| 362 | type SYMCLK32_LE3_EN;\ | 362 | type SYMCLK32_LE3_EN;\ |
| 363 | type DP_DTO_ENABLE[MAX_PIPES]; | 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 | struct dccg_shift { | 375 | struct dccg_shift { |
| 366 | DCCG_REG_FIELD_LIST(uint8_t) | 376 | DCCG_REG_FIELD_LIST(uint8_t) |
| 367 | DCCG3_REG_FIELD_LIST(uint8_t) | 377 | DCCG3_REG_FIELD_LIST(uint8_t) |
| @@ -370,6 +380,7 @@ struct dccg_shift { · 2 unmodified lines | |||
| 370 | DCCG32_REG_FIELD_LIST(uint8_t) | 380 | DCCG32_REG_FIELD_LIST(uint8_t) |
| 371 | DCCG35_REG_FIELD_LIST(uint8_t) | 381 | DCCG35_REG_FIELD_LIST(uint8_t) |
| 372 | DCCG401_REG_FIELD_LIST(uint8_t) | 382 | DCCG401_REG_FIELD_LIST(uint8_t) |
| 383 | DCCG42_REG_FIELD_LIST(uint8_t) | ||
| 373 | }; | 384 | }; |
| 374 | 385 | ||
| 375 | struct dccg_mask { | 386 | struct dccg_mask { |
| @@ -380,6 +391,7 @@ struct dccg_mask { · 4 unmodified lines | |||
| 380 | DCCG32_REG_FIELD_LIST(uint32_t) | 391 | DCCG32_REG_FIELD_LIST(uint32_t) |
| 381 | DCCG35_REG_FIELD_LIST(uint32_t) | 392 | DCCG35_REG_FIELD_LIST(uint32_t) |
| 382 | DCCG401_REG_FIELD_LIST(uint32_t) | 393 | DCCG401_REG_FIELD_LIST(uint32_t) |
| 394 | DCCG42_REG_FIELD_LIST(uint32_t) | ||
| 383 | }; | 395 | }; |
| 384 | 396 | ||
| 385 | #define DCCG_REG_VARIABLE_LIST \ | 397 | #define DCCG_REG_VARIABLE_LIST \ |
| @@ -493,6 +505,7 @@ struct dccg_mask { · 107 unmodified lines | |||
| 493 | 505 | ||
| 494 | struct dccg_registers { | 506 | struct dccg_registers { |
| 495 | DCCG_REG_VARIABLE_LIST; | 507 | DCCG_REG_VARIABLE_LIST; |
| 508 | uint32_t OTG_ADD_DROP_PIXEL_CNTL; | ||
| 496 | }; | 509 | }; |
| 497 | 510 | ||
| 498 | struct dcn_dccg { | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -300,6 +300,64 @@ · 294 unmodified lines | |||
| 300 | ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \ | 300 | ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \ |
| 301 | ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh) | 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 | #define ABM_REG_FIELD_LIST(type) \ | 361 | #define ABM_REG_FIELD_LIST(type) \ |
| 304 | type ABM1_HG_NUM_OF_BINS_SEL; \ | 362 | type ABM1_HG_NUM_OF_BINS_SEL; \ |
| 305 | type ABM1_HG_VMAX_SEL; \ | 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 | static bool dce_aud_endpoint_valid(struct audio *audio) | 1153 | static bool dce_aud_endpoint_valid(struct audio *audio) |
| 1246 | { | 1154 | { |
| 1247 | uint32_t value; | 1155 | uint32_t value; |
| @@ -1303,18 +1211,6 @@ static const struct audio_funcs funcs = { · 55 unmodified lines | |||
| 1303 | .destroy = dce_aud_destroy, | 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 | void dce_aud_destroy(struct audio **audio) | 1214 | void dce_aud_destroy(struct audio **audio) |
| 1319 | { | 1215 | { |
| 1320 | struct dce_audio *aud = DCE_AUD(*audio); | 1216 | struct dce_audio *aud = DCE_AUD(*audio); |
| @@ -1347,30 +1243,3 @@ struct audio *dce_audio_create( · 26 unmodified lines | |||
| 1347 | audio->masks = masks; | 1243 | audio->masks = masks; |
| 1348 | return &audio->base; | 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 | const struct dce_audio_shift *shifts, | 151 | const struct dce_audio_shift *shifts, |
| 152 | const struct dce_audio_mask *masks); | 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 | void dce_aud_destroy(struct audio **audio); | 154 | void dce_aud_destroy(struct audio **audio); |
| 164 | 155 | ||
| 165 | void dce_aud_hw_init(struct audio *audio); | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DAL_DIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/dio/dcn401/,$(DIO_DCN401)) | 123 | AMD_DAL_DIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/dio/dcn401/,$(DIO_DCN401)) |
| 124 | 124 | ||
| 125 | AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN401) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -190,6 +190,7 @@ struct dcn10_stream_enc_registers { · 184 unmodified lines | |||
| 190 | uint32_t DIG_FE_CLK_CNTL; | 190 | uint32_t DIG_FE_CLK_CNTL; |
| 191 | uint32_t DIG_FE_EN_CNTL; | 191 | uint32_t DIG_FE_EN_CNTL; |
| 192 | uint32_t STREAM_MAPPER_CONTROL; | 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 | type DP_VID_N_INTERVAL;\ | 599 | type DP_VID_N_INTERVAL;\ |
| 599 | type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ | 600 | type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ |
| 600 | type DP_STEER_FIFO_ENABLE | 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 | struct dcn10_stream_encoder_shift { | 607 | struct dcn10_stream_encoder_shift { |
| 602 | SE_REG_FIELD_LIST_DCN1_0(uint8_t); | 608 | SE_REG_FIELD_LIST_DCN1_0(uint8_t); |
| 603 | uint8_t HDMI_ACP_SEND; | 609 | uint8_t HDMI_ACP_SEND; |
| @@ -606,6 +612,7 @@ struct dcn10_stream_encoder_shift { · 2 unmodified lines | |||
| 606 | SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); | 612 | SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); |
| 607 | SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); | 613 | SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); |
| 608 | SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); | 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 | struct dcn10_stream_encoder_mask { | 618 | struct dcn10_stream_encoder_mask { |
| @@ -616,6 +623,7 @@ struct dcn10_stream_encoder_mask { · 4 unmodified lines | |||
| 616 | SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); | 623 | SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); |
| 617 | SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); | 624 | SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); |
| 618 | SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); | 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 | struct dcn10_stream_encoder { | 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 | memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); | 734 | memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); |
| 735 | 735 | ||
| 736 | dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable; | 736 | dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable; |
| 737 | dml_dispcfg->gpuvm_max_page_table_levels = 4; | 737 | if (dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels) |
| 738 | dml_dispcfg->hostvm_enable = false; | 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 | dml_dispcfg->minimize_det_reallocation = true; | 743 | dml_dispcfg->minimize_det_reallocation = true; |
| 740 | dml_dispcfg->overrides.enable_subvp_implicit_pmo = true; | 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 | dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state); | 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 | struct dc_state *context, | 378 | struct dc_state *context, |
| 379 | struct dml2_context *dml_ctx) | 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 | unsigned int num_fams2_streams = 0; | 382 | unsigned int num_fams2_streams = 0; |
| 383 | 383 | ||
| 384 | /* reset fams2 data */ | 384 | for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) { |
| 385 | memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | 385 | int dml_stream_idx; |
| 386 | memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | 386 | struct dc_stream_state *phantom_stream; |
| 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); | 387 | struct dc_stream_status *phantom_status; |
| 388 | memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); | 388 | enum fams2_stream_type type = 0; |
| 389 | 389 | ||
| 390 | if ((dml_ctx->v21.mode_programming.programming->fams2_required) || | 390 | union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; |
| 391 | (dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu)) { | 391 | union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams]; |
| 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; | ||
| 397 | 392 | ||
| 398 | union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; | 393 | struct dc_stream_state *stream = context->streams[dc_stream_idx]; |
| 399 | union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams]; | ||
| 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 || | 401 | dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); |
| 404 | dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) { | 402 | if (dml_stream_idx < 0) { |
| 405 | /* can ignore blanked or phantom streams */ | 403 | ASSERT(dml_stream_idx >= 0); |
| 406 | continue; | 404 | continue; |
| 407 | } | 405 | } |
| 408 | 406 | ||
| 409 | dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); | 407 | /* copy static state from PMO */ |
| 410 | if (dml_stream_idx < 0) { | 408 | memcpy(static_base_state, |
| 411 | ASSERT(dml_stream_idx >= 0); | 409 | &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, |
| 412 | continue; | 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 */ | 438 | |
| 416 | memcpy(static_base_state, | 439 | /* get per method programming */ |
| 417 | &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, | 440 | switch (type) { |
| 418 | sizeof(union dmub_cmd_fams2_config)); | 441 | case FAMS2_STREAM_TYPE_VBLANK: |
| 419 | 442 | case FAMS2_STREAM_TYPE_VACTIVE: | |
| 420 | if (dc->debug.fams_version.major == 3) { | 443 | case FAMS2_STREAM_TYPE_DRR: |
| 421 | memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams], | 444 | break; |
| 422 | &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2, | 445 | case FAMS2_STREAM_TYPE_SUBVP: |
| 423 | sizeof(union dmub_fams2_stream_static_sub_state_v2)); | 446 | phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); |
| 424 | } else { | 447 | if (!phantom_stream) |
| 425 | memcpy(static_sub_state, | 448 | break; |
| 426 | &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, | 449 | |
| 427 | sizeof(union dmub_cmd_fams2_config)); | 450 | phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); |
| 428 | } | 451 | |
| 452 | /* phantom status should always be present */ | ||
| 453 | ASSERT(phantom_status); | ||
| 454 | if (!phantom_status) | ||
| 455 | break; | ||
| 429 | 456 | ||
| 430 | switch (dc->debug.fams_version.minor) { | 457 | switch (dc->debug.fams_version.minor) { |
| 431 | case 1: | 458 | case 1: |
| 432 | default: | 459 | default: |
| 433 | type = static_base_state->stream_v1.base.type; | 460 | static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst; |
| 434 | 461 | ||
| 435 | /* get information from context */ | 462 | /* populate pipe masks for phantom planes */ |
| 436 | static_base_state->stream_v1.base.num_planes = context->stream_status[i].plane_count; | 463 | for (dc_plane_idx = 0; dc_plane_idx < phantom_status->plane_count; dc_plane_idx++) { |
| 437 | static_base_state->stream_v1.base.otg_inst = context->stream_status[i].primary_otg_inst; | 464 | for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { |
| 438 | 465 | if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream && | |
| 439 | /* populate pipe masks for planes */ | 466 | context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == phantom_stream->stream_id && |
| 440 | for (j = 0; j < context->stream_status[i].plane_count; j++) { | 467 | context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == phantom_status->plane_states[dc_plane_idx]) { |
| 441 | for (k = 0; k < dc->res_pool->pipe_count; k++) { | 468 | switch (dc->debug.fams_version.minor) { |
| 442 | if (context->res_ctx.pipe_ctx[k].stream && | 469 | case 1: |
| 443 | context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id && | 470 | default: |
| 444 | context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) { | 471 | static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << dc_pipe_idx); |
| 445 | static_base_state->stream_v1.base.pipe_mask |= (1 << k); | 472 | static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx); |
| 446 | static_base_state->stream_v1.base.plane_pipe_masks[j] |= (1 << k); | 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 */ | 487 | return num_fams2_streams; |
| 454 | switch (type) { | 488 | } |
| 455 | case FAMS2_STREAM_TYPE_VBLANK: | 489 | |
| 456 | case FAMS2_STREAM_TYPE_VACTIVE: | 490 | void dml21_build_fams2_programming(const struct dc *dc, |
| 457 | case FAMS2_STREAM_TYPE_DRR: | 491 | struct dc_state *context, |
| 458 | break; | 492 | struct dml2_context *dml_ctx) |
| 459 | case FAMS2_STREAM_TYPE_SUBVP: | 493 | { |
| 460 | phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); | 494 | unsigned int num_fams2_streams = 0; |
| 461 | if (!phantom_stream) | 495 | |
| 462 | break; | 496 | /* reset fams2 data */ |
| 463 | 497 | memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); | |
| 464 | phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); | 498 | memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); |
| 465 | 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); | |
| 466 | /* phantom status should always be present */ | 500 | memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); |
| 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 | } | ||
| 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 | struct dc_state; | 9 | struct dc_state; |
| 10 | struct dc_plane_state; | 10 | struct dc_plane_state; |
| 11 | struct pipe_ctx; | 11 | struct pipe_ctx; |
| 12 | struct dc_dmub_srv; | ||
| 12 | 13 | ||
| 13 | struct dml2_context; | 14 | struct dml2_context; |
| 14 | struct dml2_display_rq_regs; | 15 | struct dml2_display_rq_regs; |
| @@ -160,6 +160,8 @@ struct dml2_soc_bb { · 159 unmodified lines | |||
| 160 | unsigned long return_bus_width_bytes; | 160 | unsigned long return_bus_width_bytes; |
| 161 | unsigned long hostvm_min_page_size_kbytes; | 161 | unsigned long hostvm_min_page_size_kbytes; |
| 162 | unsigned long gpuvm_min_page_size_kbytes; | 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 | double phy_downspread_percent; | 165 | double phy_downspread_percent; |
| 164 | double dcn_downspread_percent; | 166 | double dcn_downspread_percent; |
| 165 | double dispclk_dppclk_vco_speed_mhz; | 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 | const struct dc_plane_state *plane) | 909 | const struct dc_plane_state *plane) |
| 910 | { | 910 | { |
| 911 | struct pipe_ctx *dpp_pipes[MAX_PIPES] = {0}; | 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 | return ctx->config.callbacks.get_mpc_slice_count(dpp_pipes[0]); | 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 | bool use_clock_dc_limits; | 240 | bool use_clock_dc_limits; |
| 241 | bool gpuvm_enable; | 241 | bool gpuvm_enable; |
| 242 | bool hostvm_enable; | ||
| 242 | bool force_tdlut_enable; | 243 | bool force_tdlut_enable; |
| 243 | void *bb_from_dmub; | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN401) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 4 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -653,6 +654,8 @@ · 648 unmodified lines | |||
| 653 | 654 | ||
| 654 | struct dcn401_dpp_registers { | 655 | struct dcn401_dpp_registers { |
| 655 | DPP_REG_VARIABLE_LIST_DCN401; | 656 | DPP_REG_VARIABLE_LIST_DCN401; |
| 657 | uint32_t ALPHA_2BIT_LUT01; | ||
| 658 | uint32_t ALPHA_2BIT_LUT23; | ||
| 656 | }; | 659 | }; |
| 657 | 660 | ||
| 658 | struct dcn401_dpp_shift { | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN401) | 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 | #include "dcn315/hw_factory_dcn315.h" | 53 | #include "dcn315/hw_factory_dcn315.h" |
| 54 | #include "dcn32/hw_factory_dcn32.h" | 54 | #include "dcn32/hw_factory_dcn32.h" |
| 55 | #include "dcn401/hw_factory_dcn401.h" | 55 | #include "dcn401/hw_factory_dcn401.h" |
| 56 | #include "dcn42/hw_factory_dcn42.h" | ||
| 56 | 57 | ||
| 57 | bool dal_hw_factory_init( | 58 | bool dal_hw_factory_init( |
| 58 | struct hw_factory *factory, | 59 | struct hw_factory *factory, |
| @@ -118,6 +119,9 @@ bool dal_hw_factory_init( · 59 unmodified lines | |||
| 118 | case DCN_VERSION_4_01: | 119 | case DCN_VERSION_4_01: |
| 119 | dal_hw_factory_dcn401_init(factory); | 120 | dal_hw_factory_dcn401_init(factory); |
| 120 | return true; | 121 | return true; |
| 122 | case DCN_VERSION_4_2: | ||
| 123 | dal_hw_factory_dcn42_init(factory); | ||
| 124 | return true; | ||
| 121 | default: | 125 | default: |
| 122 | ASSERT_CRITICAL(false); | 126 | ASSERT_CRITICAL(false); |
| 123 | return false; | 127 | return false; |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | |||
| 53 | #include "dcn315/hw_translate_dcn315.h" | 53 | #include "dcn315/hw_translate_dcn315.h" |
| 54 | #include "dcn32/hw_translate_dcn32.h" | 54 | #include "dcn32/hw_translate_dcn32.h" |
| 55 | #include "dcn401/hw_translate_dcn401.h" | 55 | #include "dcn401/hw_translate_dcn401.h" |
| 56 | #include "dcn42/hw_translate_dcn42.h" | ||
| 56 | 57 | ||
| 57 | /* | 58 | /* |
| 58 | * This unit | 59 | * This unit |
| @@ -119,6 +120,9 @@ bool dal_hw_translate_init( · 60 unmodified lines | |||
| 119 | case DCN_VERSION_4_01: | 120 | case DCN_VERSION_4_01: |
| 120 | dal_hw_translate_dcn401_init(translate); | 121 | dal_hw_translate_dcn401_init(translate); |
| 121 | return true; | 122 | return true; |
| 123 | case DCN_VERSION_4_2: | ||
| 124 | dal_hw_translate_dcn42_init(translate); | ||
| 125 | return true; | ||
| 122 | default: | 126 | default: |
| 123 | BREAK_TO_DEBUGGER(); | 127 | BREAK_TO_DEBUGGER(); |
| 124 | return false; | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32)) | 47 | AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32)) |
| 48 | 48 | ||
| 49 | AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN32) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -208,17 +208,24 @@ · 202 unmodified lines | |||
| 208 | type CRC_CONT_MODE_ENABLE;\ | 208 | type CRC_CONT_MODE_ENABLE;\ |
| 209 | type HBLANK_MINIMUM_SYMBOL_WIDTH | 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 | struct dcn31_hpo_dp_stream_encoder_registers { | 217 | struct dcn31_hpo_dp_stream_encoder_registers { |
| 213 | DCN3_1_HPO_DP_STREAM_ENC_REGS; | 218 | DCN3_1_HPO_DP_STREAM_ENC_REGS; |
| 214 | }; | 219 | }; |
| 215 | 220 | ||
| 216 | struct dcn31_hpo_dp_stream_encoder_shift { | 221 | struct dcn31_hpo_dp_stream_encoder_shift { |
| 217 | DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t); | 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 | struct dcn31_hpo_dp_stream_encoder_mask { | 226 | struct dcn31_hpo_dp_stream_encoder_mask { |
| 221 | DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t); | 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 | struct dcn31_hpo_dp_stream_encoder { | 231 | struct dcn31_hpo_dp_stream_encoder { |
| @@ -241,5 +248,4 @@ void dcn31_hpo_dp_stream_encoder_construct( · 16 unmodified lines | |||
| 241 | const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, | 248 | const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, |
| 242 | const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask); | 249 | const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask); |
| 243 | 250 | ||
| 244 | |||
| 245 | #endif // __DAL_DCN31_HPO_STREAM_ENCODER_H__ | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN401) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -441,6 +441,8 @@ struct dcn_hubbub_registers { · 435 unmodified lines | |||
| 441 | type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE;\ | 441 | type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE;\ |
| 442 | type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE | 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 | struct dcn_hubbub_shift { | 446 | struct dcn_hubbub_shift { |
| 445 | DCN_HUBBUB_REG_FIELD_LIST(uint8_t); | 447 | DCN_HUBBUB_REG_FIELD_LIST(uint8_t); |
| 446 | HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t); | 448 | HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t); |
| @@ -449,6 +451,7 @@ struct dcn_hubbub_shift { · 2 unmodified lines | |||
| 449 | HUBBUB_REG_FIELD_LIST_DCN32(uint8_t); | 451 | HUBBUB_REG_FIELD_LIST_DCN32(uint8_t); |
| 450 | HUBBUB_REG_FIELD_LIST_DCN35(uint8_t); | 452 | HUBBUB_REG_FIELD_LIST_DCN35(uint8_t); |
| 451 | HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t); | 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 | HUBBUB_REG_FIELD_LIST_DCN32(uint32_t); | 463 | HUBBUB_REG_FIELD_LIST_DCN32(uint32_t); |
| 461 | HUBBUB_REG_FIELD_LIST_DCN35(uint32_t); | 464 | HUBBUB_REG_FIELD_LIST_DCN35(uint32_t); |
| 462 | HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t); | 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 | # Permission is hereby granted, free of charge, to any person obtaining a | 4 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN401) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -288,16 +288,22 @@ · 282 unmodified lines | |||
| 288 | type MCACHEID_MALL_PREF_2H_P1;\ | 288 | type MCACHEID_MALL_PREF_2H_P1;\ |
| 289 | type HUBP_FGCG_REP_DIS | 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 | struct dcn_hubp2_registers { | 295 | struct dcn_hubp2_registers { |
| 292 | DCN401_HUBP_REG_COMMON_VARIABLE_LIST; | 296 | DCN401_HUBP_REG_COMMON_VARIABLE_LIST; |
| 293 | }; | 297 | }; |
| 294 | 298 | ||
| 295 | struct dcn_hubp2_shift { | 299 | struct dcn_hubp2_shift { |
| 296 | DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); | 300 | DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); |
| 301 | DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); | ||
| 297 | }; | 302 | }; |
| 298 | 303 | ||
| 299 | struct dcn_hubp2_mask { | 304 | struct dcn_hubp2_mask { |
| 300 | DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); | 305 | DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); |
| 306 | DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); | ||
| 301 | }; | 307 | }; |
| 302 | 308 | ||
| 303 | struct dcn20_hubp { | 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 | 1 | # Copyright 2022-2026 Advanced Micro Devices, Inc. | |
| 2 | # Copyright 2022 Advanced Micro Devices, Inc. | ||
| 3 | # | 2 | # |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | 3 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | # copy of this software and associated documentation files (the "Software"), | 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 | AMD_DAL_HWSS_DCN401 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn401/,$(HWSS_DCN401)) | 198 | AMD_DAL_HWSS_DCN401 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn401/,$(HWSS_DCN401)) |
| 200 | 199 | ||
| 201 | AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN401) | 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 | endif | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -700,6 +700,8 @@ struct dce_hwseq_registers { · 694 unmodified lines | |||
| 700 | uint32_t DOMAIN23_PG_STATUS; | 700 | uint32_t DOMAIN23_PG_STATUS; |
| 701 | uint32_t DOMAIN24_PG_STATUS; | 701 | uint32_t DOMAIN24_PG_STATUS; |
| 702 | uint32_t DOMAIN25_PG_STATUS; | 702 | uint32_t DOMAIN25_PG_STATUS; |
| 703 | uint32_t DOMAIN26_PG_CONFIG; | ||
| 704 | uint32_t DOMAIN26_PG_STATUS; | ||
| 703 | }; | 705 | }; |
| 704 | /* set field name */ | 706 | /* set field name */ |
| 705 | #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ | 707 | #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ |
| @@ -1245,6 +1247,13 @@ struct dce_hwseq_registers { · 539 unmodified lines | |||
| 1245 | type DOMAIN25_PGFSM_PWR_STATUS; \ | 1247 | type DOMAIN25_PGFSM_PWR_STATUS; \ |
| 1246 | type DOMAIN_DESIRED_PWR_STATE; | 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 | struct dce_hwseq_shift { | 1257 | struct dce_hwseq_shift { |
| 1249 | HWSEQ_REG_FIELD_LIST(uint8_t) | 1258 | HWSEQ_REG_FIELD_LIST(uint8_t) |
| 1250 | HWSEQ_DCN_REG_FIELD_LIST(uint8_t) | 1259 | HWSEQ_DCN_REG_FIELD_LIST(uint8_t) |
| @@ -1253,6 +1262,7 @@ struct dce_hwseq_shift { · 2 unmodified lines | |||
| 1253 | HWSEQ_DCN31_REG_FIELD_LIST(uint8_t) | 1262 | HWSEQ_DCN31_REG_FIELD_LIST(uint8_t) |
| 1254 | HWSEQ_DCN35_REG_FIELD_LIST(uint8_t) | 1263 | HWSEQ_DCN35_REG_FIELD_LIST(uint8_t) |
| 1255 | HWSEQ_DCN401_REG_FIELD_LIST(uint8_t) | 1264 | HWSEQ_DCN401_REG_FIELD_LIST(uint8_t) |
| 1265 | HWSEQ_DCN42_REG_FIELD_LIST(uint8_t) | ||
| 1256 | }; | 1266 | }; |
| 1257 | 1267 | ||
| 1258 | struct dce_hwseq_mask { | 1268 | struct dce_hwseq_mask { |
| @@ -1263,6 +1273,7 @@ struct dce_hwseq_mask { · 4 unmodified lines | |||
| 1263 | HWSEQ_DCN31_REG_FIELD_LIST(uint32_t) | 1273 | HWSEQ_DCN31_REG_FIELD_LIST(uint32_t) |
| 1264 | HWSEQ_DCN35_REG_FIELD_LIST(uint32_t) | 1274 | HWSEQ_DCN35_REG_FIELD_LIST(uint32_t) |
| 1265 | HWSEQ_DCN401_REG_FIELD_LIST(uint32_t) | 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 | void dce110_enable_stream(struct pipe_ctx *pipe_ctx) | 717 | void dce110_enable_stream(struct pipe_ctx *pipe_ctx) |
| 664 | { | 718 | { |
| 665 | enum dc_lane_count lane_count = | 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 | tg->funcs->set_early_control(tg, early_control); | 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 | static enum bp_result link_transmitter_control( | 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 | dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, | 1239 | dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| 1184 | link_enc->transmitter - TRANSMITTER_UNIPHY_A); | 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 | void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, | 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 | if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { | 3384 | if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { |
| 3321 | if (dc->clk_mgr->funcs->notify_link_rate_change) | 3385 | if (dc->clk_mgr->funcs->notify_link_rate_change) |
| 3322 | dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); | 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 | .enable_dp_link_output = dce110_enable_dp_link_output, | 3473 | .enable_dp_link_output = dce110_enable_dp_link_output, |
| 3410 | .enable_analog_link_output = dce110_enable_analog_link_output, | 3474 | .enable_analog_link_output = dce110_enable_analog_link_output, |
| 3411 | .disable_link_output = dce110_disable_link_output, | 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 | static const struct hwseq_private_funcs dce110_private_funcs = { | 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 | * audio corruption. Read current DISPCLK from DENTIST and request the same | 72 | * audio corruption. Read current DISPCLK from DENTIST and request the same |
| 73 | * freq to ensure that the timing is valid and unchanged. | 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 | clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; | 81 | clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; |
| 78 | clocks->fclk_p_state_change_support = true; | 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 | x_pos = pos_cpy.x - param.recout.x; | 1206 | x_pos = pos_cpy.x - param.recout.x; |
| 1203 | y_pos = pos_cpy.y - param.recout.y; | 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 | recout_x_pos = x_pos - pos_cpy.x_hotspot; | 1228 | recout_x_pos = x_pos - pos_cpy.x_hotspot; |
| 1206 | recout_y_pos = y_pos - pos_cpy.y_hotspot; | 1229 | recout_y_pos = y_pos - pos_cpy.y_hotspot; |
| 1207 | 1230 | ||
| @@ -1464,7 +1487,7 @@ void dcn401_optimize_bandwidth( · 256 unmodified lines | |||
| 1464 | dc->clk_mgr, | 1487 | dc->clk_mgr, |
| 1465 | context, | 1488 | context, |
| 1466 | true); | 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 | for (i = 0; i < dc->res_pool->pipe_count; ++i) { | 1491 | for (i = 0; i < dc->res_pool->pipe_count; ++i) { |
| 1469 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | 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 | && pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max | 1495 | && pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max |
| 1473 | && pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total) | 1496 | && pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total) |
| 1474 | pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp, | 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.