From 42df5c86e282c0b23ad85a84ea2341a27b2d1bf8 Mon Sep 17 00:00:00 2001 From: Joshua Elmasri Date: Fri, 8 May 2026 11:33:10 -0500 Subject: [PATCH] CHANGES --- flake.lock | 482 +- flake.nix | 9 +- hosts/desktop/configuration.nix | 18 +- hosts/desktop/home.nix | 1 - modules/default.nix | 1 + modules/helium/default.nix | 9 + ...DR Calibrated Profile 2-16-2026 165126.icc | Bin 0 -> 844 bytes ...DR Calibrated Profile 2-26-2026 153723.icc | Bin 0 -> 844 bytes modules/hypr/default.nix | 30 +- modules/stylix/default.nix | 16 +- modules/zen/default.nix | 1 - patches/0001-amdgpu-frl.patch | 14973 +++++++++++----- 12 files changed, 10391 insertions(+), 5149 deletions(-) create mode 100644 modules/helium/default.nix create mode 100755 modules/hypr/HDR Calibrated Profile 2-16-2026 165126.icc create mode 100755 modules/hypr/HDR Calibrated Profile 2-26-2026 153723.icc diff --git a/flake.lock b/flake.lock index 3754b8d..01a9799 100644 --- a/flake.lock +++ b/flake.lock @@ -37,11 +37,11 @@ ] }, "locked": { - "lastModified": 1771610171, - "narHash": "sha256-+DeInuhbm6a6PpHDNUS7pozDouq2+8xSDefoNaZLW0E=", + "lastModified": 1777499565, + "narHash": "sha256-nU55VWk99Pn1QzQDDjFISocC4SgDZ3Xp+zb6ji3JclM=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "7f9eb087703ec4acc6b288d02fa9ea3db803cd3d", + "rev": "813c1e8981893c11e118b19c125d6bc282f51765", "type": "github" }, "original": { @@ -74,11 +74,11 @@ ] }, "locked": { - "lastModified": 1769774308, - "narHash": "sha256-8Ve6VdUpcYbl8bS5oyDwVnnNobyPxdPmUHGgSDyOazQ=", + "lastModified": 1777578913, + "narHash": "sha256-2Hzr8T4oUtw2q0ZYxrgDB8kvy85QawlhpiQDk4eGOHQ=", "owner": "aylur", "repo": "astal", - "rev": "eb235f8813bdea2a4a38ac228f2efc4e2a8a90af", + "rev": "67ddc83e0bdbda6de7f6f15e4fbc5d6b9d2d1b18", "type": "github" }, "original": { @@ -125,11 +125,11 @@ "base16-helix": { "flake": false, "locked": { - "lastModified": 1760703920, - "narHash": "sha256-m82fGUYns4uHd+ZTdoLX2vlHikzwzdu2s2rYM2bNwzw=", + "lastModified": 1776754714, + "narHash": "sha256-E3OAK27smtATTmX45uoTSRsVD+Y+ZiVVfgM/tjpbtYg=", "owner": "tinted-theming", "repo": "base16-helix", - "rev": "d646af9b7d14bff08824538164af99d0c521b185", + "rev": "4d508123037e7851ad36ebf7d9c48b0e9e1eb581", "type": "github" }, "original": { @@ -158,11 +158,11 @@ "cachyos-kernel": { "flake": false, "locked": { - "lastModified": 1771517207, - "narHash": "sha256-+zDtnmXNyMd3hMepErdPDZzqYS0PiZA0Anbbx9Pvs4g=", + "lastModified": 1778178024, + "narHash": "sha256-RpzKUH+IaU1kwP9TyzYDcr3kx4ntATWz5FSm0YUVEFw=", "owner": "CachyOS", "repo": "linux-cachyos", - "rev": "39737576a25091a3c4ca00729b769a1f92ec98d5", + "rev": "633675209cb11d50c5bb05283dbbdd9aa1872aec", "type": "github" }, "original": { @@ -174,11 +174,11 @@ "cachyos-kernel-patches": { "flake": false, "locked": { - "lastModified": 1771516433, - "narHash": "sha256-SuockPZgd2bfjWGmdT8AUBTnBZWvxdA+b8Ss98lNC6c=", + "lastModified": 1777876120, + "narHash": "sha256-fdFgVCoua3rsQyyHkgxcnwi0hUktR8UtcI/suS8jcbg=", "owner": "CachyOS", "repo": "kernel-patches", - "rev": "505aef2086e584ba683a5ac1cb8ed8252fea2cfd", + "rev": "e80ce8172953b8c199daf6a2850974bb12731ae9", "type": "github" }, "original": { @@ -207,11 +207,11 @@ "firefox-gnome-theme": { "flake": false, "locked": { - "lastModified": 1764873433, - "narHash": "sha256-1XPewtGMi+9wN9Ispoluxunw/RwozuTRVuuQOmxzt+A=", + "lastModified": 1776136500, + "narHash": "sha256-r0gN2brVWA351zwMV0Flmlcd6SGMvYqFbvC3DfKFM8Y=", "owner": "rafaelmardojai", "repo": "firefox-gnome-theme", - "rev": "f7ffd917ac0d253dbd6a3bf3da06888f57c69f92", + "rev": "0f8ba203d475587f477e7ae12661bd8459e225b7", "type": "github" }, "original": { @@ -223,15 +223,15 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1767039857, - "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", - "owner": "NixOS", + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", "repo": "flake-compat", - "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "type": "github" }, "original": { - "owner": "NixOS", + "owner": "edolstra", "repo": "flake-compat", "type": "github" } @@ -253,6 +253,22 @@ } }, "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { "locked": { "lastModified": 1761640442, "narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=", @@ -272,11 +288,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1769996383, - "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", + "lastModified": 1777988971, + "narHash": "sha256-qIoWPDs+0/8JecyYgE3gpKQxW/4bLW/gp45vow9ioCQ=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", + "rev": "0678d8986be1661af6bb555f3489f2fdfc31f6ff", "type": "github" }, "original": { @@ -293,11 +309,11 @@ ] }, "locked": { - "lastModified": 1769996383, - "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", + "lastModified": 1777932387, + "narHash": "sha256-nUYVPiqrzr36ThiQOAr5MKeGHDBSDM3OFWkz0uDjOvc=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", + "rev": "71a3a77326609675e9f8b51084cf23d5d1945899", "type": "github" }, "original": { @@ -314,11 +330,11 @@ ] }, "locked": { - "lastModified": 1767609335, - "narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=", + "lastModified": 1775087534, + "narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "250481aafeb741edfe23d29195671c19b36b6dca", + "rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b", "type": "github" }, "original": { @@ -329,7 +345,25 @@ }, "flake-utils": { "inputs": { - "systems": "systems_2" + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" }, "locked": { "lastModified": 1731533236, @@ -403,20 +437,40 @@ "gnome-shell": { "flake": false, "locked": { - "host": "gitlab.gnome.org", "lastModified": 1767737596, "narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=", "owner": "GNOME", "repo": "gnome-shell", "rev": "ef02db02bf0ff342734d525b5767814770d85b49", - "type": "gitlab" + "type": "github" }, "original": { - "host": "gitlab.gnome.org", "owner": "GNOME", - "ref": "gnome-49", "repo": "gnome-shell", - "type": "gitlab" + "rev": "ef02db02bf0ff342734d525b5767814770d85b49", + "type": "github" + } + }, + "helium": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1778059517, + "narHash": "sha256-EaficK/DCUgnUQAqTvvRLZqVjFf+nOwSFnilYa0Axdc=", + "owner": "AlvaroParker", + "repo": "helium-nix", + "rev": "1f78b1a3b123e8f98296abcb3772dbc5b2eb574d", + "type": "github" + }, + "original": { + "owner": "AlvaroParker", + "repo": "helium-nix", + "type": "github" } }, "home-manager": { @@ -426,11 +480,11 @@ ] }, "locked": { - "lastModified": 1771851181, - "narHash": "sha256-gFgE6mGUftwseV3DUENMb0k0EiHd739lZexPo5O/sdQ=", + "lastModified": 1778248595, + "narHash": "sha256-dhFgEjoeJMYN/7OY6xfxS799YB4IjbbYXTjyGIJyLpc=", "owner": "nix-community", "repo": "home-manager", - "rev": "9a4b494b1aa1b93d8edf167f46dc8e0c0011280c", + "rev": "fdb2ccba9d5e1238d32e0c4a3ec1a277efa80c1d", "type": "github" }, "original": { @@ -455,11 +509,11 @@ ] }, "locked": { - "lastModified": 1753964049, - "narHash": "sha256-lIqabfBY7z/OANxHoPeIrDJrFyYy9jAM4GQLzZ2feCM=", + "lastModified": 1776511930, + "narHash": "sha256-fCpwFiTW0rT7oKJqr3cqHMnkwypSwQKpbtUEtxdkgrM=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "44e91d467bdad8dcf8bbd2ac7cf49972540980a5", + "rev": "39435900785d0c560c6ae8777d29f28617d031ef", "type": "github" }, "original": { @@ -484,11 +538,11 @@ ] }, "locked": { - "lastModified": 1770511807, - "narHash": "sha256-suKmSbSk34uPOJDTg/GbPrKEJutzK08vj0VoTvAFBCA=", + "lastModified": 1776426399, + "narHash": "sha256-RUESLKNikIeEq9ymGJ6nmcDXiSFQpUW1IhJ245nL3xM=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "7c75487edd43a71b61adb01cae8326d277aab683", + "rev": "68d064434787cf1ed4a2fe257c03c5f52f33cf84", "type": "github" }, "original": { @@ -510,15 +564,15 @@ "hyprwire": "hyprwire", "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems", + "systems": "systems_2", "xdph": "xdph" }, "locked": { - "lastModified": 1772022552, - "narHash": "sha256-L3zktLSXcvsqczTz7YL5PXYgn4a08tRfl9t6YYLESM8=", + "lastModified": 1778250672, + "narHash": "sha256-1ZiBsqEpVSNjG3HqpmXxGXr/GrSqt9+XNh4YRgYjGFU=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "457617b5a31f70ea63e1fcc0729f29e4a9e6b486", + "rev": "ac75bcab713490eb000e4fa48f7e7316c3535854", "type": "github" }, "original": { @@ -560,11 +614,11 @@ ] }, "locked": { - "lastModified": 1767023960, - "narHash": "sha256-R2HgtVS1G3KSIKAQ77aOZ+Q0HituOmPgXW9nBNkpp3Q=", + "lastModified": 1776426575, + "narHash": "sha256-KI6nIfVihn/DPaeB5Et46Xg3dkNHrrEtUd5LBBVomB0=", "owner": "hyprwm", "repo": "hyprland-guiutils", - "rev": "c2e906261142f5dd1ee0bfc44abba23e2754c660", + "rev": "a968d211048e3ed538e47b84cb3649299578f19d", "type": "github" }, "original": { @@ -590,11 +644,11 @@ ] }, "locked": { - "lastModified": 1771865848, - "narHash": "sha256-xwNa+1D8WPsDnJtUofDrtyDCZKZotbUymzV/R5s+M0I=", + "lastModified": 1777937752, + "narHash": "sha256-QDc78DC6xhWKpPJzsPEJBBFYpTb+g4kO6+ydRYLU4f4=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "b85a56b9531013c79f2f3846fd6ee2ff014b8960", + "rev": "b6e080577daf6575b95e6733dd2e2aef714bcf10", "type": "github" }, "original": { @@ -615,11 +669,11 @@ ] }, "locked": { - "lastModified": 1765214753, - "narHash": "sha256-P9zdGXOzToJJgu5sVjv7oeOGPIIwrd9hAUAP3PsmBBs=", + "lastModified": 1772460177, + "narHash": "sha256-/6G/MsPvtn7bc4Y32pserBT/Z4SUUdBd4XYJpOEKVR4=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "3f3860b869014c00e8b9e0528c7b4ddc335c21ab", + "rev": "1cb6db5fd6bb8aee419f4457402fa18293ace917", "type": "github" }, "original": { @@ -644,11 +698,11 @@ ] }, "locked": { - "lastModified": 1771866172, - "narHash": "sha256-fYFoXhQLrm1rD8vSFKQBOEX4OGCuJdLt1amKfHd5GAw=", + "lastModified": 1777320127, + "narHash": "sha256-Qu+Wf2Bp5qUjyn2YpZNq8a7JyzTGowhT1knrwE38a9U=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "0b219224910e7642eb0ed49f0db5ec3d008e3e41", + "rev": "090117506ddc3d7f26e650ff344d378c2ec329cc", "type": "github" }, "original": { @@ -696,11 +750,11 @@ ] }, "locked": { - "lastModified": 1764592794, - "narHash": "sha256-7CcO+wbTJ1L1NBQHierHzheQGPWwkIQug/w+fhTAVuU=", + "lastModified": 1772462885, + "narHash": "sha256-5pHXrQK9zasMnIo6yME6EOXmWGFMSnCITcfKshhKJ9I=", "owner": "hyprwm", "repo": "hyprtoolkit", - "rev": "5cfe0743f0e608e1462972303778d8a0859ee63e", + "rev": "9af245a69fa6b286b88ddfc340afd288e00a6998", "type": "github" }, "original": { @@ -721,11 +775,11 @@ ] }, "locked": { - "lastModified": 1771271487, - "narHash": "sha256-41gEiUS0Pyw3L/ge1l8MXn61cK14VAhgWB/JV8s/oNI=", + "lastModified": 1778179779, + "narHash": "sha256-Ri6rVf54CRD3aISHLhSY6H4tBScVjm9ebkv7rF2lcZM=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "340a792e3b3d482c4ae5f66d27a9096bdee6d76d", + "rev": "3e170e5ad010602671f5f25b327e8bdb8fdd532c", "type": "github" }, "original": { @@ -746,11 +800,11 @@ ] }, "locked": { - "lastModified": 1770501770, - "narHash": "sha256-NWRM6+YxTRv+bT9yvlhhJ2iLae1B1pNH3mAL5wi2rlQ=", + "lastModified": 1777159683, + "narHash": "sha256-Jxixw6wZphUp+nHYxOKUYSckL17QMBx2d5Zp0rJHr1g=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "0bd8b6cde9ec27d48aad9e5b4deefb3746909d40", + "rev": "b8632713a6beaf28b56f2a7b0ab2fb7088dbb404", "type": "github" }, "original": { @@ -775,11 +829,11 @@ ] }, "locked": { - "lastModified": 1771606233, - "narHash": "sha256-F3PLUqQ/TwgR70U+UeOqJnihJZ2EuunzojYC4g5xHr0=", + "lastModified": 1777388329, + "narHash": "sha256-40YxVGF2rA9iH3D7am5fy4EOSBbMgpJtJ9yhl0Cx+qI=", "owner": "hyprwm", "repo": "hyprwire", - "rev": "06c7f1f8c4194786c8400653c4efc49dc14c0f3a", + "rev": "04be2897e05f9b271d532b5ae56ca088d2eeac02", "type": "github" }, "original": { @@ -875,11 +929,11 @@ }, "master": { "locked": { - "lastModified": 1772051972, - "narHash": "sha256-qUGo6noKFC17GJlPumIJcJnAIu5oouJA6fBtFuLgJz0=", + "lastModified": 1778253243, + "narHash": "sha256-KkH2QvU6iRLDTGGEwH5jnMqHWj4zMTuHxi1S1zdr01w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4f63959d174c1e233df4b8a0a0d7482e670949eb", + "rev": "4fcda7103530b23c5ca44286344912082aad4220", "type": "github" }, "original": { @@ -911,11 +965,11 @@ }, "locked": { "dir": "packages/nix", - "lastModified": 1771985657, - "narHash": "sha256-wAnrrFZxuHrITZAfyUyuIItYW/2gjO+gm3TCupExdt4=", + "lastModified": 1778009348, + "narHash": "sha256-hIjlaMu6ildZqBMpxRVieHAGUjxsFSgWi24QMmpqM+Y=", "owner": "SteamClientHomebrew", "repo": "Millennium", - "rev": "dbbb365d32725022041caa2d2211f7934ca8ef58", + "rev": "e2c66a276e579ee73c5151b01897bf63503aa12c", "type": "github" }, "original": { @@ -928,17 +982,17 @@ "millennium-src": { "flake": false, "locked": { - "lastModified": 1770463863, - "narHash": "sha256-MceGTpXobCAh5Ll/1iTWcEf6/nHY3Ll1t06JxbYc+Co=", + "lastModified": 1777483535, + "narHash": "sha256-eqbNqc+5PibHLI8xgOrizXOVLcpE52MhmUR4o40S3PY=", "owner": "SteamClientHomebrew", "repo": "Millennium", - "rev": "1bc62c94a06f25f7e8d7e269f11cd968cf576bff", + "rev": "defffd7b6f0cf4d5e53f5a892819966801475704", "type": "github" }, "original": { "owner": "SteamClientHomebrew", "repo": "Millennium", - "rev": "1bc62c94a06f25f7e8d7e269f11cd968cf576bff", + "rev": "defffd7b6f0cf4d5e53f5a892819966801475704", "type": "github" } }, @@ -995,17 +1049,17 @@ }, "naviterm": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1770485744, - "narHash": "sha256-ZJGHKtEWhpXyONjy6/popJz0uL2MXmknGr9Vr1B6BAk=", + "lastModified": 1773476909, + "narHash": "sha256-hSg/7xFO+3G3wWFq1480OecREqTY+fu06L06rM2UBmQ=", "owner": "detoxify92", "repo": "naviterm", - "rev": "b311af7ae0ab095657264b5fe4a43b9118207584", + "rev": "f89dbde00222fb1e4f611419d05583d8edee4c25", "type": "gitlab" }, "original": { @@ -1018,16 +1072,16 @@ "inputs": { "cachyos-kernel": "cachyos-kernel", "cachyos-kernel-patches": "cachyos-kernel-patches", - "flake-compat": "flake-compat_2", + "flake-compat": "flake-compat_3", "flake-parts": "flake-parts", "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1771525883, - "narHash": "sha256-XqDuaRbxLGno5HcWRE5lQrgMBeXXs6ncGq+R6eCvsq8=", + "lastModified": 1778181525, + "narHash": "sha256-U+P5tE3OwxR0j41HABzpi2po3LAiJJ9kBv7jOjoGdhg=", "owner": "xddxdd", "repo": "nix-cachyos-kernel", - "rev": "15fb6039dd248d478a8f3f7f6c067b206da2bf54", + "rev": "0bbe21311da577d356ee096a03e379d17cf07279", "type": "github" }, "original": { @@ -1039,15 +1093,15 @@ }, "nixos-apple-silicon": { "inputs": { - "flake-compat": "flake-compat_3", + "flake-compat": "flake-compat_4", "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1771511514, - "narHash": "sha256-qhtonMK07BCVC/wZ+pZ9/MKhcTric7YUaCpW6pOg8IM=", + "lastModified": 1778234684, + "narHash": "sha256-usIHfvSt7aXvMvRGtcbsue3rA13Z+9TW/7I3WBzLqFY=", "owner": "tpwrules", "repo": "nixos-apple-silicon", - "rev": "2b92d495204be0b10845c66361444dbc8441c68d", + "rev": "3d7fe422ef6162154830209b9e50bf69e150cff7", "type": "github" }, "original": { @@ -1058,11 +1112,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1771848320, - "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", + "lastModified": 1777954456, + "narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2fc6539b481e1d2569f25f8799236694180c0993", + "rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1", "type": "github" }, "original": { @@ -1074,11 +1128,11 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1769909678, - "narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=", + "lastModified": 1777168982, + "narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "72716169fe93074c333e8d0173151350670b824c", + "rev": "f5901329dade4a6ea039af1433fb087bd9c1fe14", "type": "github" }, "original": { @@ -1105,11 +1159,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1771482645, - "narHash": "sha256-MpAKyXfJRDTgRU33Hja+G+3h9ywLAJJNRq4Pjbb4dQs=", + "lastModified": 1778157832, + "narHash": "sha256-KDidG68ivbHpI9mwl9NK4gARAROxEy3bZPe2BBo5ZyM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "724cf38d99ba81fbb4a347081db93e2e3a9bc2ae", + "rev": "ec299c6a33eee9baf5b4d72881ca2f15c06b4f01", "type": "github" }, "original": { @@ -1121,11 +1175,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1768305791, - "narHash": "sha256-AIdl6WAn9aymeaH/NvBj0H9qM+XuAuYbGMZaP0zcXAQ=", + "lastModified": 1777578337, + "narHash": "sha256-Ad49moKWeXtKBJNy2ebiTQUEgdLyvGmTeykAQ9xM+Z4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1412caf7bf9e660f2f962917c14b1ea1c3bc695e", + "rev": "15f4ee454b1dce334612fa6843b3e05cf546efab", "type": "github" }, "original": { @@ -1137,11 +1191,11 @@ }, "nixpkgs_5": { "locked": { - "lastModified": 1771848320, - "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", + "lastModified": 1777954456, + "narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2fc6539b481e1d2569f25f8799236694180c0993", + "rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1", "type": "github" }, "original": { @@ -1152,11 +1206,11 @@ }, "nixpkgs_6": { "locked": { - "lastModified": 1770380644, - "narHash": "sha256-P7dWMHRUWG5m4G+06jDyThXO7kwSk46C1kgjEWcybkE=", + "lastModified": 1777918403, + "narHash": "sha256-7QiZv0LcW1yIOLo2LNuCQjWon1Z1r99FwK24hbtBOF4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ae67888ff7ef9dff69b3cf0cc0fbfbcd3a722abe", + "rev": "afc5551119aae6eab73a95c1960891cfe63204f6", "type": "github" }, "original": { @@ -1166,18 +1220,34 @@ "type": "github" } }, + "nixpkgs_7": { + "locked": { + "lastModified": 1768564909, + "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nixvim": { "inputs": { "flake-parts": "flake-parts_2", "nixpkgs": "nixpkgs_6", - "systems": "systems_3" + "systems": "systems_4" }, "locked": { - "lastModified": 1771135771, - "narHash": "sha256-wyvBIhDuyCRyjB3yPg77qoyxrlgQtBR1rVW3c9knV3E=", + "lastModified": 1777991353, + "narHash": "sha256-DFwjggMV+nzCZpwK6Obxj9F+P59rbLVowGqHETfctBk=", "owner": "nix-community", "repo": "nixvim", - "rev": "ed0424f0b08d303a7348f52f7850ad1b2704f9ba", + "rev": "7986a276960b4dfaed9bb2c3c438b5ba71ae08f1", "type": "github" }, "original": { @@ -1194,11 +1264,11 @@ "noctalia-qs": "noctalia-qs" }, "locked": { - "lastModified": 1772037803, - "narHash": "sha256-307PELik0fSETKF0xwM2uAeIsFZTkOApEMnZ2wcTpA4=", + "lastModified": 1778104114, + "narHash": "sha256-+tbqLv7IW5Aem8kGF6cp4n3MtNBcwqmuGlMt6S1kQjs=", "owner": "noctalia-dev", "repo": "noctalia-shell", - "rev": "2e43e5348e290220d65b024aa543fc672b05a3cc", + "rev": "eb2b53ddaa7564f5c93031cbe65cd5b6ef3c12a9", "type": "github" }, "original": { @@ -1212,14 +1282,16 @@ "nixpkgs": [ "noctalia", "nixpkgs" - ] + ], + "systems": "systems_5", + "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1771796397, - "narHash": "sha256-lbZkAMNQl5Ymqhdvp46K8hubZ7n7KQRPnTP5bNJzMSk=", + "lastModified": 1777773024, + "narHash": "sha256-pLU+KB84A0Jei/vTD6pOS4Ovkmq3QDfPQHg1MlKsRqM=", "owner": "noctalia-dev", "repo": "noctalia-qs", - "rev": "1711c5a20b74a31b703394164c5d2d9561f13ee9", + "rev": "d3e26ccd9eecde9139be00caf5dc2d4260fb31ee", "type": "github" }, "original": { @@ -1240,11 +1312,11 @@ ] }, "locked": { - "lastModified": 1767810917, - "narHash": "sha256-ZKqhk772+v/bujjhla9VABwcvz+hB2IaRyeLT6CFnT0=", + "lastModified": 1777598946, + "narHash": "sha256-X239dAGaU1+gfDj8jKH8GzlqKMcxaVfXOio+uzBOkeE=", "owner": "nix-community", "repo": "NUR", - "rev": "dead29c804adc928d3a69dfe7f9f12d0eec1f1a4", + "rev": "5d55af01c0f86be583931fe99207fc56c14134b3", "type": "github" }, "original": { @@ -1255,7 +1327,7 @@ }, "pre-commit-hooks": { "inputs": { - "flake-compat": "flake-compat", + "flake-compat": "flake-compat_2", "gitignore": "gitignore", "nixpkgs": [ "hyprland", @@ -1263,11 +1335,11 @@ ] }, "locked": { - "lastModified": 1771858127, - "narHash": "sha256-Gtre9YoYl3n25tJH2AoSdjuwcqij5CPxL3U3xysYD08=", + "lastModified": 1776796298, + "narHash": "sha256-PcRvlWayisPSjd0UcRQbhG8Oqw78AcPE6x872cPRHN8=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "49bbbfc218bf3856dfa631cead3b052d78248b83", + "rev": "3cfd774b0a530725a077e17354fbdb87ea1c4aad", "type": "github" }, "original": { @@ -1296,6 +1368,7 @@ "root": { "inputs": { "astal": "astal", + "helium": "helium", "home-manager": "home-manager", "hyprland": "hyprland", "hyprland-plugins": "hyprland-plugins", @@ -1308,6 +1381,7 @@ "nixvim": "nixvim", "noctalia": "noctalia", "stylix": "stylix", + "subtui": "subtui", "zen-browser": "zen-browser" } }, @@ -1324,19 +1398,18 @@ "nixpkgs" ], "nur": "nur", - "systems": "systems_4", - "tinted-foot": "tinted-foot", + "systems": "systems_6", "tinted-kitty": "tinted-kitty", "tinted-schemes": "tinted-schemes", "tinted-tmux": "tinted-tmux", "tinted-zed": "tinted-zed" }, "locked": { - "lastModified": 1771787992, - "narHash": "sha256-Vg4bGwwenNYI8p3nJTl9FRyeIyrjATeZrZr+GyUSDrw=", + "lastModified": 1778104276, + "narHash": "sha256-/DSSnU0LLmOTG/OCgGwYpxP6+5YvxRx2g/GhI4x6aCU=", "owner": "nix-community", "repo": "stylix", - "rev": "30054cca073b49b42a71289edec858f535b27fe9", + "rev": "18ed8d270231e067fe2739998479ed5d7c659c2c", "type": "github" }, "original": { @@ -1345,22 +1418,25 @@ "type": "github" } }, + "subtui": { + "inputs": { + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1777120747, + "narHash": "sha256-r6uHOz3ffeVtizN+NeFqKTjcvCguuR0LwoUrCEwFziQ=", + "owner": "MattiaPun", + "repo": "SubTUI", + "rev": "cc4149f59c8d0e727207230e36410fcab9e257a8", + "type": "github" + }, + "original": { + "owner": "MattiaPun", + "repo": "SubTUI", + "type": "github" + } + }, "systems": { - "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", - "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default-linux", - "type": "github" - } - }, - "systems_2": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -1375,6 +1451,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, "systems_3": { "locked": { "lastModified": 1681028828, @@ -1405,20 +1496,33 @@ "type": "github" } }, - "tinted-foot": { - "flake": false, + "systems_5": { "locked": { - "lastModified": 1726913040, - "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=", - "owner": "tinted-theming", - "repo": "tinted-foot", - "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", "type": "github" }, "original": { - "owner": "tinted-theming", - "repo": "tinted-foot", - "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", "type": "github" } }, @@ -1441,11 +1545,11 @@ "tinted-schemes": { "flake": false, "locked": { - "lastModified": 1767710407, - "narHash": "sha256-+W1EB79Jl0/gm4JqmO0Nuc5C7hRdp4vfsV/VdzI+des=", + "lastModified": 1777041405, + "narHash": "sha256-BAGZ7ObFV/9Z61OJZun7ifPyhkuHqNuW1QIhQ8LuzCo=", "owner": "tinted-theming", "repo": "schemes", - "rev": "2800e2b8ac90f678d7e4acebe4fa253f602e05b2", + "rev": "5f868b3a338b6904c47f3833b9c411be641983a8", "type": "github" }, "original": { @@ -1457,11 +1561,11 @@ "tinted-tmux": { "flake": false, "locked": { - "lastModified": 1767489635, - "narHash": "sha256-e6nnFnWXKBCJjCv4QG4bbcouJ6y3yeT70V9MofL32lU=", + "lastModified": 1777169200, + "narHash": "sha256-h7dDbIzP5hDr9v97w9PL6jdAgXawmj6krcH+959rqpU=", "owner": "tinted-theming", "repo": "tinted-tmux", - "rev": "3c32729ccae99be44fe8a125d20be06f8d7d8184", + "rev": "f798c2dce44ef815bb6b8f05a82135c7942d35ac", "type": "github" }, "original": { @@ -1473,11 +1577,11 @@ "tinted-zed": { "flake": false, "locked": { - "lastModified": 1767488740, - "narHash": "sha256-wVOj0qyil8m+ouSsVZcNjl5ZR+1GdOOAooAatQXHbuU=", + "lastModified": 1777463218, + "narHash": "sha256-Bhkozqtq3BKLqWTlmKm8uAptfX4aRGI8QX3eEL54Vpc=", "owner": "tinted-theming", "repo": "base16-zed", - "rev": "11abb0b282ad3786a2aae088d3a01c60916f2e40", + "rev": "5768d08ed2e7944a26a958868cdb073cb8856dae", "type": "github" }, "original": { @@ -1486,6 +1590,28 @@ "type": "github" } }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "noctalia", + "noctalia-qs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1775636079, + "narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, "websocketpp-src": { "flake": false, "locked": { @@ -1531,11 +1657,11 @@ ] }, "locked": { - "lastModified": 1761431178, - "narHash": "sha256-xzjC1CV3+wpUQKNF+GnadnkeGUCJX+vgaWIZsnz9tzI=", + "lastModified": 1777585783, + "narHash": "sha256-JTeWRy42VElroJ0rVdZuVXSoTLsx+NzQfGPKMbtn3SU=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "4b8801228ff958d028f588f0c2b911dbf32297f9", + "rev": "fa50d6fbaff8f42c61071b87b034a90d82a33558", "type": "github" }, "original": { @@ -1554,11 +1680,11 @@ ] }, "locked": { - "lastModified": 1772005916, - "narHash": "sha256-aFYnT0gStcu1PVTh2Xzd0n8PIEKmqvTgrVkpv49qc6M=", + "lastModified": 1778218381, + "narHash": "sha256-mhxT7KkmM0h/vgr84o2p6gkzm21b5/dCnIMVKaoXU+I=", "owner": "0xc000022070", "repo": "zen-browser-flake", - "rev": "044299e83752f78f9fc5d6a648f7f3dd84bb3b18", + "rev": "ea79f20a194de74504821ab53e93c0cf92690f00", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 53cdbed..77d4cfb 100644 --- a/flake.nix +++ b/flake.nix @@ -17,6 +17,10 @@ url = "github:hyprwm/hyprland-plugins"; inputs.hyprland.follows = "hyprland"; }; + helium = { + url = "github:AlvaroParker/helium-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; naviterm = { url = "gitlab:detoxify92/naviterm"; inputs.nixpkgs.follows = "nixpkgs"; @@ -33,6 +37,9 @@ url = "github:nix-community/nixvim"; #inputs.nixpkgs.follows = "nixpkgs"; }; + subtui = { + url = "github:MattiaPun/SubTUI"; + }; nixos-apple-silicon = { url = "github:tpwrules/nixos-apple-silicon"; }; @@ -44,7 +51,7 @@ }; - outputs = { self, stylix, astal, nixpkgs, home-manager, zen-browser, master, nixos-apple-silicon, nix-cachyos-kernel, nixvim, noctalia,... }@inputs: + outputs = { self, stylix, astal, nixpkgs, home-manager, zen-browser, master, nixos-apple-silicon, subtui, nix-cachyos-kernel, nixvim, noctalia,... }@inputs: let system = "x86_64-linux"; lib = nixpkgs.lib; diff --git a/hosts/desktop/configuration.nix b/hosts/desktop/configuration.nix index 7d65200..cbd6d63 100644 --- a/hosts/desktop/configuration.nix +++ b/hosts/desktop/configuration.nix @@ -25,6 +25,11 @@ }; hardware.graphics.enable = true; +hardware.graphics.package = pkgs-master.mesa; + + +nix.settings.substituters = [ "https://attic.xuyh0120.win/lantian" ]; +nix.settings.trusted-public-keys = [ "lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc=" ]; boot = { @@ -43,13 +48,13 @@ boot = { # Enable "Silent Boot" consoleLogLevel = 0; initrd.verbose = false; - kernelPackages = pkgs.cachyosKernels.linuxPackages-cachyos-latest; + kernelPackages = pkgs.linuxPackages_latest; kernelModules = [ "amdgpu" ]; kernelPatches = [ /*{ name = "frl"; patch = ../../patches/0001-amdgpu-frl.patch; - }*/ + }/* /*{ name = "dsc"; patch = ../../patches/bigscreen_1.patch; @@ -313,6 +318,7 @@ services.pulseaudio.extraConfig = '' usbutils mangohud ffmpeg + linux-wallpaperengine oversteer # cemu broken with latest update wget @@ -322,9 +328,12 @@ services.pulseaudio.extraConfig = '' cowsay pfetch ryubing + inputs.subtui.packages.${pkgs.system}.default + mpv + pkgs-master.gelly + android-tools gomatrix python3 - #inputs.naviterm.packages.${pkgs.system}.default pavucontrol sbctl boxflat @@ -356,7 +365,7 @@ services.pulseaudio.extraConfig = '' services.xserver.enableTCP = true; services.sunshine = { - enable = false; + enable = true; autoStart = false; capSysAdmin = true; openFirewall = true; @@ -382,7 +391,6 @@ services.pulseaudio.extraConfig = '' }; services.wivrn.enable = true; services.wivrn.package = pkgs.wivrn; - services.wivrn.defaultRuntime = true; systemd.user.services.monado.environment = { STEAMVR_LH_ENABLE = "1"; XRT_COMPOSITOR_COMPUTE = "1"; diff --git a/hosts/desktop/home.nix b/hosts/desktop/home.nix index fc5d0a8..47259e2 100644 --- a/hosts/desktop/home.nix +++ b/hosts/desktop/home.nix @@ -11,7 +11,6 @@ home.packages = [ pkgs.element-desktop - pkgs.signal-desktop-bin pkgs.swaybg pkgs.gpu-screen-recorder pkgs.gpu-screen-recorder-gtk diff --git a/modules/default.nix b/modules/default.nix index 7fbd759..2f88c69 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -13,5 +13,6 @@ ./starship ./yazi ./zen + ./helium ]; } diff --git a/modules/helium/default.nix b/modules/helium/default.nix new file mode 100644 index 0000000..c1ef0b1 --- /dev/null +++ b/modules/helium/default.nix @@ -0,0 +1,9 @@ +{pkgs, inputs, lib, ...}: + +{ + programs.chromium = { + enable = true; + package = inputs.helium.packages.${pkgs.system}.default; + + }; +} diff --git a/modules/hypr/HDR Calibrated Profile 2-16-2026 165126.icc b/modules/hypr/HDR Calibrated Profile 2-16-2026 165126.icc new file mode 100755 index 0000000000000000000000000000000000000000..dd91322ed292c01022f32f2f33105e0ce5fd37dd GIT binary patch literal 844 zcmah`&ubG=5dM-jdTDD#@zlZ|3R|&mlP$@i2Ql5ERg6j!!HSn;_a%+y$MSYlTcik* zix&?ng14UR)w6>35Ade;?5Rk_lj6nV^Lv|WLQou-dEfWFnc259z|f__1;-ga3pARc z%%5K{t}ov(4(}n3qX29iE4hK6E1WBm4O)x>{rirNz`N5rFZuAq{fnT*1i#@p0mGz1^r0FGc#2V-w#b?sy__i9ZtGYSi1rk?B7i5zT7_p1NiN4qEWB z4v8A7SV0H_(^OCL%u#cB(?US6M0Yx0vO>oal^RhKmfM!A(HHp0_#6;a=J*zx{$juV zh3j2)Q+6kT)=%KjT2H&Z4D4?7dF7Vu-Nr>$=T8?1e~6^b>^3b<=#eScNR zpw?=d^JdCQTB)>cCCwRgF_X@EB|j9NIbW1*!T!MSUWwO0Vw27@7tNHH9HtJ5O$K0! zUZit}oI%X`s?^S&Qu}YnX(Nw;Z_kuc_qu#&L8&hf5F0zC`JdTn!g>6U|6_lbSv|om sE+WreIow8_+bAFGMeuC~u14FdP_ILf+n7ZP8AcmPdWM?jX-3WP3+Z2xZvX%Q literal 0 HcmV?d00001 diff --git a/modules/hypr/HDR Calibrated Profile 2-26-2026 153723.icc b/modules/hypr/HDR Calibrated Profile 2-26-2026 153723.icc new file mode 100755 index 0000000000000000000000000000000000000000..32f6c3a10534b011b34891b60de59b2012e764de GIT binary patch literal 844 zcmaiyO=uHA7>3`Z0YO?RA_{E}D=Mp4xA`G$X)mT*v|=NYMEpUJWOtLMZZ?0afUOas#Qe3QM&QE<)wlZM{{Dl@-*(RmWa)r-rG^(~JW$s;pIUj$BIj_|6@hCZPujJT0VCyls1tWS@oGj`GS9b2C$h`_n6`ZxB9ahHwEhIguF`7beI zFV%>{%mR}h@(v=#4=GpHq-?!r&FFmy{Cq5>ywk3GrlkCS7m+>3RsHX7RKfe$souuF yb6h<{7pIY%4(T&nyUmTuI!}-v?GW8l9)=7*oN5e55l7eOm{0-;*x@ literal 0 HcmV?d00001 diff --git a/modules/hypr/default.nix b/modules/hypr/default.nix index 7abc8c9..4b9fd60 100644 --- a/modules/hypr/default.nix +++ b/modules/hypr/default.nix @@ -17,11 +17,28 @@ "$mainMod" = "SUPER"; # Monitors - monitor = [ - "HDMI-A-1, 3840x2160@120, 0x0, auto, bitdepth, 10" + /*monitor = [ + "HDMI-A-1, 3840x2160@120, 0x0, auto, bitdepth, 10, cm, hdr, sdrsaturation, 1, sdrbrightness, 1.2, min_luminance = 0, max_luminance, 1200, max_avg_luminance, 200" "eDP-1, 2560x1600@60, 0x0, 1.6" "DP-1, highres@highrr, 0x0, 1" - ]; + ];*/ + + monitorv2 = [ + { + output = "HDMI-A-1"; + mode = "3840x2160@144"; + position = "0x0"; + scale = 1; + bitdepth = 10; + cm = "hdr"; + sdrbrightness = 1; + sdrsaturation = 1; + sdr_min_luminance = 0.005; + sdr_max_luminance = 200; + supports_hdr = 1; + supports_wide_color = 1; + } + ]; # Startup applications exec-once = [ @@ -71,7 +88,7 @@ gaps_out = 5; border_size = 2; layout = "dwindle"; - allow_tearing = false; + allow_tearing = true; }; decoration = { @@ -114,14 +131,11 @@ preserve_split = true; }; - gestures = [ - "3, horizontal, workspace" - ]; misc = { force_default_wallpaper = 0; enable_anr_dialog = 0; - vrr = 1; + vrr = 2; }; bind = [ diff --git a/modules/stylix/default.nix b/modules/stylix/default.nix index a8ebb18..61647b0 100644 --- a/modules/stylix/default.nix +++ b/modules/stylix/default.nix @@ -8,10 +8,20 @@ stylix.targets.zen-browser.profileNames = [ "default" ]; stylix.targets.zen-browser.enable = true; # blue aura house - stylix.image = pkgs.fetchurl { + /*stylix.image = pkgs.fetchurl { url = "https://w.wallhaven.cc/full/1p/wallhaven-1py8lw.jpg"; hash = "sha256-smJTuprm8PVKWv56hfv9UMzDXkHm3R7O1ALaNpNYy3E="; - }; + };*/ + # Tree succumbed to Purple flames + /*stylix.image = pkgs.fetchurl { + url = "https://gitea.base.jeditemple.com/joshuaelm/Wallpapers/raw/branch/main/generic/Purple%20Flames%20Burning%20Tree.png"; + hash = "sha256-g1LsfCpXEVpBcVsknCHOxYCXQaXrNokmR5fI6CGJHK0="; + };*/ + #shipwreck + stylix.image = pkgs.fetchurl { + url = "https://gitea.base.jeditemple.com/joshuaelm/Wallpapers/raw/branch/main/schemes/catppuccin/wallhaven-je8p85_3840x2160.png"; + hash = "sha256-2tWF3wyppfLOnBmI7+Nc5JcWcON6jMHdyqAmUoDRFzo="; + }; # coastal town /*stylix.image = pkgs.fetchurl { url = "https://w.wallhaven.cc/full/ex/wallhaven-ex8vml.jpg"; @@ -47,6 +57,6 @@ url = "https://gitea.base.jeditemple.com/joshuaelm/Wallpapers/raw/branch/main/generic/88677104_p0.png"; hash = "sha256-IIKzA4DgWg9P48A+x/vBKjaD7seNBtkh/0wSXY2O3x8="; };*/ - stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/atelier-sulphurpool.yaml"; + stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml"; } diff --git a/modules/zen/default.nix b/modules/zen/default.nix index b480a1d..34aee20 100644 --- a/modules/zen/default.nix +++ b/modules/zen/default.nix @@ -5,7 +5,6 @@ ]; programs.zen-browser = { enable = true; - suppressXdgMigrationWarning = true; profiles = { default = { # bookmarks, extensions, search engines... diff --git a/patches/0001-amdgpu-frl.patch b/patches/0001-amdgpu-frl.patch index 0f80614..df77a5c 100644 --- a/patches/0001-amdgpu-frl.patch +++ b/patches/0001-amdgpu-frl.patch @@ -1,75 +1,76 @@ -diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md -new file mode 100644 -index 000000000000..1cd10a4f2deb ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/issue.md -@@ -0,0 +1,10 @@ -+--- -+name: Issue -+about: Bug report -+title: '' -+labels: '' -+assignees: '' -+ -+--- -+ -+ -diff --git a/.github/workflows/genpatch.yml b/.github/workflows/genpatch.yml -new file mode 100644 -index 000000000000..a0dcad457f93 ---- /dev/null -+++ b/.github/workflows/genpatch.yml -@@ -0,0 +1,22 @@ -+name: Generate patch - Master branch -+on: -+ push: -+ branches: hdmi_frl -+ -+jobs: -+ generate_patch: -+ runs-on: ubuntu-24.04 -+ steps: -+ - name: Checkout repository -+ uses: actions/checkout@v4 -+ with: -+ ref: hdmi_frl -+ fetch-depth: 0 -+ - name: Generate patch -+ run: git diff origin/master > 0001-amdgpu-frl.patch -+ - name: Save artifacts -+ uses: actions/upload-artifact@v4 -+ with: -+ name: "Patch" -+ path: 0001-amdgpu-frl.patch -+ retention-days: 30 -diff --git a/.gitignore b/.gitignore -index 3a7241c941f5..d5dbc2628e85 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -10,7 +10,7 @@ - # - # Normal rules (sorted alphabetically) - # --.* -+. - *.a - *.asn1.[ch] - *.bin +From aa8d1c74d3be6b7cca94ccc7f7935a1321efbff9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 24 Jan 2026 20:42:10 +0100 +Subject: [PATCH 001/103] HDMI FRL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +- + .../drm/amd/display/dc/bios/command_table2.c | 3 + + .../display/dc/bios/command_table_helper2.c | 2 + + .../dce112/command_table_helper2_dce112.c | 3 + + .../bios/dce112/command_table_helper_dce112.c | 3 + + drivers/gpu/drm/amd/display/dc/core/dc.c | 3 + + .../gpu/drm/amd/display/dc/core/dc_resource.c | 32 +- + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 1 + + .../gpu/drm/amd/display/dc/dc_hdmi_types.h | 3 +- + .../amd/display/dc/dccg/dcn401/dcn401_dccg.c | 58 ++ + .../amd/display/dc/dccg/dcn401/dcn401_dccg.h | 5 + + .../dml2_0/dml21/dml21_translation_helper.c | 4 + + .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c | 2 + + drivers/gpu/drm/amd/display/dc/hpo/Makefile | 1 + + .../hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c | 179 ++++ + .../hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h | 130 +++ + .../hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 481 +++++++++++ + .../hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h | 772 ++++++++++++++++++ + .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 9 + + .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 13 +- + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 9 +- + .../drm/amd/display/dc/hwss/hw_sequencer.h | 4 + + .../gpu/drm/amd/display/dc/inc/core_types.h | 8 + + drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 6 + + .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 2 + + .../drm/amd/display/dc/inc/hw/link_encoder.h | 45 + + .../amd/display/dc/inc/hw/stream_encoder.h | 53 ++ + .../gpu/drm/amd/display/dc/inc/link_hwss.h | 4 + + drivers/gpu/drm/amd/display/dc/inc/resource.h | 9 + + drivers/gpu/drm/amd/display/dc/link/Makefile | 6 +- + .../display/dc/link/hwss/link_hwss_hpo_frl.c | 131 +++ + .../display/dc/link/hwss/link_hwss_hpo_frl.h | 29 + + .../drm/amd/display/dc/link/link_detection.c | 6 +- + .../gpu/drm/amd/display/dc/link/link_dpms.c | 75 +- + .../amd/display/dc/link/link_hwss_hpo_frl.c | 62 -- + .../drm/amd/display/dc/link/link_validation.c | 31 +- + .../amd/display/dc/link/protocols/link_ddc.c | 2 +- + .../dc/link/protocols/link_frl_training.c | 227 +++++ + .../dc/link/protocols/link_frl_training.h | 38 + + .../amd/display/dc/link/protocols/link_hpd.c | 1 + + .../dc/resource/dcn401/dcn401_resource.c | 104 ++- + .../dc/resource/dcn401/dcn401_resource.h | 1 + + .../drm/amd/display/include/logger_types.h | 4 +- + .../drm/amd/display/include/signal_types.h | 11 +- + .../gpu/drm/amd/display/modules/hdcp/hdcp.c | 1 + + drivers/gpu/drm/amd/include/atombios.h | 1 + + drivers/gpu/drm/amd/include/atomfirmware.h | 1 + + 47 files changed, 2494 insertions(+), 92 deletions(-) + create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c + create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h + create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c + create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h + create mode 100644 drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c + create mode 100644 drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.h + delete mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c + create mode 100644 drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c + create mode 100644 drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h + diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -index 0b4fc654e76f..02d8e52c03bd 100644 +index a8a59126b2d2b0..da075e431180df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -2062,6 +2062,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) - if (amdgpu_dc_debug_mask & DC_SKIP_DETECTION_LT) - adev->dm.dc->debug.skip_detection_link_training = true; - -+ if (amdgpu_dc_debug_mask & DC_OVERRIDE_PCON_VRR_ID_CHECK) -+ adev->dm.dc->debug.override_pcon_vrr_id_check = true; -+ - adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; - - /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ -@@ -3289,6 +3292,12 @@ static void emulated_link_detect(struct dc_link *link) +@@ -3276,6 +3276,12 @@ static void emulated_link_detect(struct dc_link *link) break; } @@ -82,49 +83,16 @@ index 0b4fc654e76f..02d8e52c03bd 100644 case SIGNAL_TYPE_DVI_SINGLE_LINK: { sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -@@ -6779,12 +6788,19 @@ static void fill_stream_properties_from_drm_display_mode( - - stream->out_transfer_func.type = TF_TYPE_PREDEFINED; - stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB; -+ -+ /* If pixel clock exceeds max HDMI TMDS clock, and FRL is not possible, try -+ * to fall back to 4:2:0 encoding for TMDS -+ */ - if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) { - if (!adjust_colour_depth_from_display_info(timing_out, info) && - drm_mode_is_420_also(info, mode_in) && - timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) { -- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; -- adjust_colour_depth_from_display_info(timing_out, info); -+ if (!stream->link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE || -+ stream->sink->edid_caps.frl_caps.max_rate == 0) { -+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; -+ adjust_colour_depth_from_display_info(timing_out, info); -+ } - } - } - -@@ -7383,8 +7399,8 @@ create_stream_for_sink(struct drm_connector *connector, +@@ -7369,7 +7375,7 @@ create_stream_for_sink(struct drm_connector *connector, update_stream_signal(stream, sink); - if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) -- mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); + if (dc_is_hdmi_signal(stream->signal)) -+ mod_build_hf_vsif_infopacket(stream, &stream->hfvsif_infopacket); + mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || - stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || -@@ -7843,6 +7859,8 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) - __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); - - new_state->freesync_capable = state->freesync_capable; -+ new_state->freesync_on_desktop_capable = -+ state->freesync_on_desktop_capable; - new_state->abm_level = state->abm_level; - new_state->scaling = state->scaling; - new_state->underscan_enable = state->underscan_enable; -@@ -8555,6 +8573,7 @@ static int to_drm_connector_type(enum signal_type st, uint32_t connector_id) +@@ -8541,6 +8547,7 @@ static int to_drm_connector_type(enum signal_type st, uint32_t connector_id) { switch (st) { case SIGNAL_TYPE_HDMI_TYPE_A: @@ -132,579 +100,31 @@ index 0b4fc654e76f..02d8e52c03bd 100644 return DRM_MODE_CONNECTOR_HDMIA; case SIGNAL_TYPE_EDP: return DRM_MODE_CONNECTOR_eDP; -@@ -8959,6 +8978,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, - aconnector->audio_inst = -1; - aconnector->pack_sdp_v1_3 = false; - aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE; -+ aconnector->hdmi_allm_capable = false; - memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info)); - mutex_init(&aconnector->hpd_lock); - mutex_init(&aconnector->handle_mst_msg_ready); -@@ -9049,8 +9069,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, - connector_type == DRM_MODE_CONNECTOR_eDP) { - drm_connector_attach_hdr_output_metadata_property(&aconnector->base); - -- if (!aconnector->mst_root) -+ if (!aconnector->mst_root) { - drm_connector_attach_vrr_capable_property(&aconnector->base); -+ drm_connector_attach_passive_vrr_capable_property(&aconnector->base); -+ } - - if (adev->dm.hdcp_workqueue) - drm_connector_attach_content_protection_property(&aconnector->base, true); -@@ -9154,6 +9176,10 @@ int amdgpu_dm_initialize_hdmi_connector(struct amdgpu_dm_connector *aconnector) - struct drm_device *ddev = aconnector->base.dev; - struct device *hdmi_dev = ddev->dev; - -+ /* ALLM */ -+ drm_connector_attach_allm_capable_property(&aconnector->base); -+ drm_connector_attach_allm_mode_property(&aconnector->base); -+ - if (amdgpu_dc_debug_mask & DC_DISABLE_HDMI_CEC) { - drm_info(ddev, "HDMI-CEC feature masked\n"); - return -EINVAL; -@@ -9621,7 +9647,11 @@ static void update_freesync_state_on_stream( - - aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context; - -- if (aconn && (aconn->as_type == FREESYNC_TYPE_PCON_IN_WHITELIST || aconn->vsdb_info.replay_mode)) { -+ if (aconn && aconn->as_type == ADAPTIVE_SYNC_TYPE_HDMI) -+ packet_type = PACKET_TYPE_VTEM; -+ -+ else if (aconn && (aconn->as_type == ADAPTIVE_SYNC_TYPE_PCON_ALLOWED || -+ aconn->vsdb_info.replay_mode)) { - pack_sdp_v1_3 = aconn->pack_sdp_v1_3; - - if (aconn->vsdb_info.amd_vsdb_version == 1) -@@ -10840,6 +10870,31 @@ static int amdgpu_dm_atomic_setup_commit(struct drm_atomic_state *state) - return 0; - } - -+static void update_allm_state_on_crtc_stream(struct dm_crtc_state *new_crtc_state, -+ const struct drm_connector_state *new_conn) -+{ -+ struct mod_freesync_config *config = &new_crtc_state->freesync_config; -+ struct dc_stream_state *new_stream = new_crtc_state->stream; -+ bool allm_active = false; -+ -+ switch (new_conn->allm_mode) { -+ case DRM_ALLM_MODE_ENABLED_DYNAMIC: -+ allm_active = config->state == VRR_STATE_ACTIVE_VARIABLE || -+ new_stream->content_type == DISPLAY_CONTENT_TYPE_GAME; -+ break; -+ -+ case DRM_ALLM_MODE_ENABLED_FORCED: -+ allm_active = true; -+ break; -+ -+ case DRM_ALLM_MODE_DISABLED: -+ default: -+ allm_active = false; -+ } -+ -+ new_stream->hdmi_allm_active = allm_active; -+} -+ - /** - * amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. - * @state: The atomic state to commit -@@ -10882,12 +10937,14 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) - for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { - struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); - struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); -+ struct amdgpu_dm_connector *dm_conn = to_amdgpu_dm_connector(connector); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); - struct dc_surface_update *dummy_updates; - struct dc_stream_update stream_update; - struct dc_info_packet hdr_packet; - struct dc_stream_status *status = NULL; - bool abm_changed, hdr_changed, scaling_changed, output_color_space_changed = false; -+ bool allm_changed = false; - - memset(&stream_update, 0, sizeof(stream_update)); - -@@ -10917,7 +10974,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) - hdr_changed = - !drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state); - -- if (!scaling_changed && !abm_changed && !hdr_changed && !output_color_space_changed) -+ allm_changed = dm_conn->hdmi_allm_capable && -+ (new_con_state->allm_mode != old_con_state->allm_mode); -+ -+ if (!scaling_changed && !abm_changed && !hdr_changed && -+ !output_color_space_changed && !allm_changed) - continue; - - stream_update.stream = dm_new_crtc_state->stream; -@@ -10947,6 +11008,17 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) - stream_update.hdr_static_metadata = &hdr_packet; - } - -+ if (allm_changed) { -+ update_allm_state_on_crtc_stream(dm_new_crtc_state, new_con_state); -+ mod_build_hf_vsif_infopacket(dm_new_crtc_state->stream, -+ &dm_new_crtc_state->stream->hfvsif_infopacket); -+ -+ stream_update.hdmi_allm_active = -+ &dm_new_crtc_state->stream->hdmi_allm_active; -+ stream_update.hfvsif_infopacket = -+ &dm_new_crtc_state->stream->hfvsif_infopacket; -+ } -+ - status = dc_stream_get_status(dm_new_crtc_state->stream); - - if (WARN_ON(!status)) -@@ -11326,6 +11398,12 @@ static void get_freesync_config_for_crtc( - config.vsif_supported = true; - config.btr = true; - -+ if (new_con_state->freesync_on_desktop_capable) -+ new_crtc_state->stream->freesync_on_desktop = -+ !new_crtc_state->base.passive_vrr_disabled; -+ else -+ new_crtc_state->stream->freesync_on_desktop = false; -+ - if (fs_vid_mode) { - config.state = VRR_STATE_ACTIVE_FIXED; - config.fixed_refresh_in_uhz = new_crtc_state->freesync_config.fixed_refresh_in_uhz; -@@ -11337,6 +11415,7 @@ static void get_freesync_config_for_crtc( - } - } else { - config.state = VRR_STATE_UNSUPPORTED; -+ new_crtc_state->stream->freesync_on_desktop = false; - } - out: - new_crtc_state->freesync_config = config; -@@ -13123,8 +13202,8 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector, - } - } - --static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, -- const struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) -+static int parse_amd_vsdb_did(struct amdgpu_dm_connector *aconnector, -+ const struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) - { - u8 *edid_ext = NULL; - int i; -@@ -13173,13 +13252,13 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, - return false; - } - --static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, -+static bool parse_amd_vsdb_cea(struct amdgpu_dm_connector *aconnector, - const struct edid *edid, - struct amdgpu_hdmi_vsdb_info *vsdb_info) - { -+ struct amdgpu_hdmi_vsdb_info vsdb_local = {0}; - u8 *edid_ext = NULL; - int i; -- bool valid_vsdb_found = false; - - /*----- drm_find_cea_extension() -----*/ - /* No EDID or EDID extensions */ -@@ -13200,9 +13279,99 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, - if (edid_ext[0] != CEA_EXT) - return -ENODEV; - -- valid_vsdb_found = parse_edid_cea(aconnector, edid_ext, EDID_LENGTH, vsdb_info); -+ if (!parse_edid_cea(aconnector, edid_ext, EDID_LENGTH, &vsdb_local)) -+ return -ENODEV; -+ -+ *vsdb_info = vsdb_local; -+ return false; -+} -+ -+static bool is_monitor_range_invalid(const struct drm_connector *conn) -+{ -+ return conn->display_info.monitor_range.min_vfreq == 0 || -+ conn->display_info.monitor_range.max_vfreq == 0; -+} -+ -+/* -+ * Returns true if (max_vfreq - min_vfreq) > 10 -+ */ -+static bool is_freesync_capable(const struct drm_monitor_range_info *range) -+{ -+ return (range->max_vfreq - range->min_vfreq) > 10; -+} -+ -+static void monitor_range_from_vsdb(struct drm_display_info *display, -+ const struct amdgpu_hdmi_vsdb_info *vsdb) -+{ -+ display->monitor_range.min_vfreq = vsdb->min_refresh_rate_hz; -+ display->monitor_range.max_vfreq = vsdb->max_refresh_rate_hz; -+} -+ -+/** -+ * Get VRR range from HDMI VRR info in EDID. If VRRmax == 0, -+ * try getting upper bound from AMD vsdb. -+ * -+ * @conn: drm_connector with HDMI VRR info -+ * @vsdb: AMD vsdb from CAE -+ */ -+static void monitor_range_from_hdmi(struct drm_display_info *display, -+ const struct amdgpu_hdmi_vsdb_info *vsdb) -+{ -+ u16 vrr_max = display->hdmi.vrr_cap.vrr_max; -+ -+ /* Try getting upper vrr bound from AMD vsdb */ -+ if (vrr_max == 0) -+ vrr_max = vsdb->max_refresh_rate_hz; -+ -+ /* Use max possible BRR value as a last resort */ -+ if (vrr_max == 0) -+ vrr_max = VTEM_BRR_MAX; -+ -+ display->monitor_range.min_vfreq = display->hdmi.vrr_cap.vrr_min; -+ display->monitor_range.max_vfreq = vrr_max; -+} -+ -+/* -+ * Returns true if connector is capable of freesync -+ * Optionally, can fetch the range from AMD vsdb -+ */ -+static bool copy_range_to_amdgpu_connector(struct drm_connector *conn) -+{ -+ struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); -+ struct drm_monitor_range_info *range = &conn->display_info.monitor_range; -+ -+ aconn->min_vfreq = range->min_vfreq; -+ aconn->max_vfreq = range->max_vfreq; - -- return valid_vsdb_found ? i : -ENODEV; -+ return is_freesync_capable(range); -+} -+ -+static void extend_range_from_vsdb(struct drm_display_info *display, -+ const struct amdgpu_hdmi_vsdb_info *vsdb) -+{ -+ u16 vrr_min = display->monitor_range.min_vfreq; -+ u16 vrr_max = display->monitor_range.max_vfreq; -+ -+ /* Always extend upper limit */ -+ if (vsdb->max_refresh_rate_hz > vrr_max) -+ vrr_max = vsdb->max_refresh_rate_hz; -+ -+ /* -+ * Only extend lower limit if current one disables LFC. -+ -+ * During widespread testing, we found that some manufacturers probably -+ * had issues with their monitors' lower VRR boundaries and adjusted -+ * them up (Gigabyte X34GS with official range 48 - 180, AMD vsdb 48 - -+ * 180 yet Monitor Ranges 55 - 180). After setting the lower boundary -+ * from AMD vsdb, such monitors start having blanking issues. -+ * -+ * Work around that by not touching VRR min if it still supports LFC. -+ */ -+ if (vsdb->min_refresh_rate_hz < vrr_min && (vrr_min * 2 >= vrr_max)) -+ vrr_min = vsdb->min_refresh_rate_hz; -+ -+ display->monitor_range.min_vfreq = vrr_min; -+ display->monitor_range.max_vfreq = vrr_max; - } - - /** -@@ -13219,16 +13388,20 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, - void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, - const struct drm_edid *drm_edid) - { -- int i = 0; - struct amdgpu_dm_connector *amdgpu_dm_connector = - to_amdgpu_dm_connector(connector); - struct dm_connector_state *dm_con_state = NULL; - struct dc_sink *sink; - struct amdgpu_device *adev = drm_to_adev(connector->dev); - struct amdgpu_hdmi_vsdb_info vsdb_info = {0}; -+ struct amdgpu_hdmi_vsdb_info vsdb_did = {0}; -+ struct drm_hdmi_vrr_cap hdmi_vrr = {0}; -+ struct dpcd_caps dpcd_caps = {0}; - const struct edid *edid; -+ bool freesync_on_desktop = false; - bool freesync_capable = false; -- enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; -+ bool pcon_allowed = false; -+ bool is_pcon = false; - - if (!connector->state) { - drm_err(adev_to_drm(adev), "%s - Connector has no state", __func__); -@@ -13256,68 +13429,77 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, - if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version)) - goto update; - -+ /* Gather all data */ - edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() -+ parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); -+ hdmi_vrr = connector->display_info.hdmi.vrr_cap; -+ -+ if (amdgpu_dm_connector->dc_link) { -+ dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; -+ is_pcon = dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER; -+ pcon_allowed = dm_helpers_is_vrr_pcon_allowed( -+ amdgpu_dm_connector->dc_link, connector->dev); -+ } -+ -+ /* DP & eDP excluding PCONs */ -+ if ((sink->sink_signal == SIGNAL_TYPE_EDP || -+ sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) && !is_pcon) { -+ /* Some eDP panels only have the refresh rate range info in DisplayID */ -+ if (is_monitor_range_invalid(connector)) -+ parse_edid_displayid_vrr(connector, edid); -+ /* -+ * Many monitors expose AMD vsdb in CAE even for DP and their -+ * monitor ranges do not contain Range Limits Only flag -+ */ -+ if (is_monitor_range_invalid(connector)) -+ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); - -- /* Some eDP panels only have the refresh rate range info in DisplayID */ -- if ((connector->display_info.monitor_range.min_vfreq == 0 || -- connector->display_info.monitor_range.max_vfreq == 0)) -- parse_edid_displayid_vrr(connector, edid); -- -- if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || -- sink->sink_signal == SIGNAL_TYPE_EDP)) { -- if (amdgpu_dm_connector->dc_link && -- amdgpu_dm_connector->dc_link->dpcd_caps.allow_invalid_MSA_timing_param) { -- amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq; -- amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq; -- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) -- freesync_capable = true; -- } -+ /* Try extending range if found in AMD vsdb */ -+ extend_range_from_vsdb(&connector->display_info, &vsdb_info); - -- parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); -+ if (dpcd_caps.allow_invalid_MSA_timing_param) -+ freesync_capable = copy_range_to_amdgpu_connector(connector); - -- if (vsdb_info.replay_mode) { -- amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_info.replay_mode; -- amdgpu_dm_connector->vsdb_info.amd_vsdb_version = vsdb_info.amd_vsdb_version; -+ /* eDP */ -+ parse_amd_vsdb_did(amdgpu_dm_connector, edid, &vsdb_did); -+ if (vsdb_did.replay_mode) { -+ amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_did.replay_mode; -+ amdgpu_dm_connector->vsdb_info.amd_vsdb_version = vsdb_did.amd_vsdb_version; +@@ -13252,7 +13259,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP; } - } else if (drm_edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { -- i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); -- if (i >= 0 && vsdb_info.freesync_supported) { -- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz; -- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz; -- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) -- freesync_capable = true; -- -- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz; -- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz; -- } -- } -- -- if (amdgpu_dm_connector->dc_link) -- as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); -- -- if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) { -- i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); -- if (i >= 0 && vsdb_info.freesync_supported && vsdb_info.amd_vsdb_version > 0) { -- -- amdgpu_dm_connector->pack_sdp_v1_3 = true; -- amdgpu_dm_connector->as_type = as_type; -+ /* HDMI */ -+ } else if (dc_is_hdmi_signal(sink->sink_signal)) { -+ /* Prefer HDMI VRR */ -+ if (hdmi_vrr.supported) { -+ amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_HDMI; -+ monitor_range_from_hdmi(&connector->display_info, &vsdb_info); -+ } else if (vsdb_info.freesync_supported) -+ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); -+ -+ freesync_capable = copy_range_to_amdgpu_connector(connector); -+ freesync_on_desktop = freesync_capable; -+ -+ /* DP -> HDMI PCON */ -+ } else if (pcon_allowed) { -+ /* Prefer HDMI VRR */ -+ if (hdmi_vrr.supported) -+ monitor_range_from_hdmi(&connector->display_info, &vsdb_info); -+ else if (vsdb_info.freesync_supported) { - amdgpu_dm_connector->vsdb_info = vsdb_info; -- -- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz; -- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz; -- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) -- freesync_capable = true; -- -- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz; -- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz; -+ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); - } -+ -+ amdgpu_dm_connector->pack_sdp_v1_3 = true; -+ amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_PCON_ALLOWED; -+ freesync_capable = copy_range_to_amdgpu_connector(connector); ++ } else if (drm_edid && dc_is_hdmi_frl_signal(sink->sink_signal)) { + i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); + if (i >= 0 && vsdb_info.freesync_supported) { + amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz; +diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +index f2b1720a6a6600..257358b95372c1 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +@@ -374,6 +374,9 @@ static enum bp_result transmitter_control_v1_7( + DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_10khz = %d\n", + __func__, dig_v1_7.symclk_units.symclk_10khz); } ++ DC_LOG_ERROR("phyid %d action %d laneset 0x%x lanenum %d hpdsel %d digfe_sel %d connobj_id %d HPO_instance %d symclk_10khz %d\n", ++ dig_v1_7.phyid, dig_v1_7.action, dig_v1_7.mode_laneset, dig_v1_7.lanenum, ++ dig_v1_7.hpdsel, dig_v1_7.digfe_sel, dig_v1_7.connobj_id, dig_v1_7.HPO_instance, dig_v1_7.symclk_units.symclk_10khz); - update: -- if (dm_con_state) -+ if (dm_con_state) { - dm_con_state->freesync_capable = freesync_capable; -+ dm_con_state->freesync_on_desktop_capable = freesync_on_desktop; -+ } - - if (connector->state && amdgpu_dm_connector->dc_link && !freesync_capable && - amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) { -@@ -13326,8 +13508,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, - } - - if (connector->vrr_capable_property) -- drm_connector_set_vrr_capable_property(connector, -- freesync_capable); -+ drm_connector_set_vrr_capable_property(connector, freesync_capable); -+ -+ if (connector->passive_vrr_capable_property) -+ drm_connector_set_passive_vrr_capable_property(connector, freesync_on_desktop); -+ -+ amdgpu_dm_connector->hdmi_allm_capable = connector->display_info.hdmi.allm; -+ if (connector->allm_capable_property) -+ drm_connector_set_allm_capable_property( -+ connector, connector->display_info.hdmi.allm); - } - - void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h -index 800813671748..b9d27a483b1e 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h -@@ -847,6 +847,9 @@ struct amdgpu_dm_connector { - unsigned int hdmi_hpd_debounce_delay_ms; - struct delayed_work hdmi_hpd_debounce_work; - struct dc_sink *hdmi_prev_sink; -+ -+ /* HDMI ALLM */ -+ bool hdmi_allm_capable; - }; - - static inline void amdgpu_dm_set_mst_status(uint8_t *status, -@@ -1020,6 +1023,7 @@ struct dm_connector_state { - uint8_t underscan_hborder; - bool underscan_enable; - bool freesync_capable; -+ bool freesync_on_desktop_capable; - bool update_hdcp; - bool abm_sysfs_forbidden; - uint8_t abm_level; -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c -index 1f41d6540b83..63d654c9128a 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c -@@ -137,7 +137,12 @@ enum dc_edid_status dm_helpers_parse_edid_caps( - edid_caps->display_name, - AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); - -- edid_caps->edid_hdmi = connector->display_info.is_hdmi; -+ if (connector->display_info.is_hdmi) { -+ edid_caps->edid_hdmi = true; -+ edid_caps->allm = connector->display_info.hdmi.allm; -+ edid_caps->fva = connector->display_info.hdmi.vrr_cap.fva; -+ edid_caps->hdmi_vrr = connector->display_info.hdmi.vrr_cap.supported; -+ } - - if (edid_caps->edid_hdmi) - populate_hdmi_info_from_connector(&connector->display_info.hdmi, edid_caps); -@@ -995,7 +1000,32 @@ dm_helpers_read_acpi_edid(struct amdgpu_dm_connector *aconnector) - - void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edid_caps *edid_caps) - { -+ struct dc_hdmi_dsc_caps *dsc = &edid_caps->dsc_caps; -+ - edid_caps->scdc_present = hdmi->scdc.supported; -+ -+ /* FRL */ -+ if (hdmi->frl_cap.max_rate == 0) -+ return; -+ -+ edid_caps->frl_caps.max_rate = hdmi->frl_cap.max_rate; -+ edid_caps->frl_caps.max_lanes = hdmi->frl_cap.max_lanes; -+ edid_caps->frl_caps.max_rate_per_lane = hdmi->frl_cap.max_rate_per_lane; -+ -+ /* DSC */ -+ if (hdmi->dsc_cap.v_1p2 != true) -+ return; -+ -+ dsc->v1p2 = hdmi->dsc_cap.v_1p2; -+ dsc->all_bpp = hdmi->dsc_cap.all_bpp; -+ dsc->native_420 = hdmi->dsc_cap.native_420; -+ dsc->max_bpc = hdmi->dsc_cap.bpc_supported; -+ dsc->max_slices = hdmi->dsc_cap.max_slices; -+ dsc->total_chunk_kbytes = hdmi->dsc_cap.total_chunk_kbytes; -+ -+ dsc->frl.max_rate = hdmi->dsc_cap.frl_cap.max_rate; -+ dsc->frl.max_lanes = hdmi->dsc_cap.frl_cap.max_lanes; -+ dsc->frl.max_rate_per_lane = hdmi->dsc_cap.frl_cap.max_rate_per_lane; - } - - enum dc_edid_status dm_helpers_read_local_edid( -@@ -1381,40 +1411,32 @@ void dm_helpers_dp_mst_update_branch_bandwidth( - // TODO - } - --static bool dm_is_freesync_pcon_whitelist(const uint32_t branch_dev_id) -+bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link, const struct drm_device *dev) - { -- bool ret_val = false; -+ if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER) -+ return false; -+ -+ if (!link->dpcd_caps.allow_invalid_MSA_timing_param) -+ return false; -+ -+ if (!link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT) -+ return false; - -- switch (branch_dev_id) { -+ switch (link->dpcd_caps.branch_dev_id) { - case DP_BRANCH_DEVICE_ID_0060AD: - case DP_BRANCH_DEVICE_ID_00E04C: - case DP_BRANCH_DEVICE_ID_90CC24: -- ret_val = true; -- break; -- default: -- break; -+ case DP_BRANCH_DEVICE_ID_2B02F0: -+ return true; - } - -- return ret_val; --} -- --enum adaptive_sync_type dm_get_adaptive_sync_support_type(struct dc_link *link) --{ -- struct dpcd_caps *dpcd_caps = &link->dpcd_caps; -- enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; -- -- switch (dpcd_caps->dongle_type) { -- case DISPLAY_DONGLE_DP_HDMI_CONVERTER: -- if (dpcd_caps->adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT == true && -- dpcd_caps->allow_invalid_MSA_timing_param == true && -- dm_is_freesync_pcon_whitelist(dpcd_caps->branch_dev_id)) -- as_type = FREESYNC_TYPE_PCON_IN_WHITELIST; -- break; -- default: -- break; -+ if (link->dc->debug.override_pcon_vrr_id_check) { -+ drm_info(dev, "Overriding VRR PCON check for ID: 0x%06x\n", -+ link->dpcd_caps.branch_dev_id); -+ return true; - } - -- return as_type; -+ return false; - } - - bool dm_helpers_is_fullscreen(struct dc_context *ctx, struct dc_stream_state *stream) + if (bp->base.ctx->dc->ctx->dmub_srv && + bp->base.ctx->dc->debug.dmub_command_table) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c -index 268e2414b34f..42e3aa3a8709 100644 +index 268e2414b34f03..42e3aa3a87091b 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -177,6 +177,8 @@ uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2( @@ -717,7 +137,7 @@ index 268e2414b34f..42e3aa3a8709 100644 return ATOM_ENCODER_MODE_LVDS; case SIGNAL_TYPE_EDP: diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c -index 349f0e5d5856..b2d9ae570b18 100644 +index 349f0e5d5856cf..b2d9ae570b186e 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -49,6 +49,9 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) @@ -731,7 +151,7 @@ index 349f0e5d5856..b2d9ae570b18 100644 atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; break; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c -index 1a5fefcde8af..2357ed6b8752 100644 +index 1a5fefcde8af4f..2357ed6b875204 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -47,6 +47,9 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) @@ -744,31 +164,8 @@ index 1a5fefcde8af..2357ed6b8752 100644 case SIGNAL_TYPE_DISPLAY_PORT_MST: atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; break; -diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c -index 72558cc55a9a..afc4bc30d214 100644 ---- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c -+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c -@@ -231,13 +231,16 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state * - - if (old_pipe->stream && new_pipe->stream && old_pipe->stream == new_pipe->stream) { - has_active_hpo = dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(old_pipe) && -- dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(new_pipe); -+ dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(new_pipe); - -+ has_active_hpo |= dc_is_hdmi_frl_signal(old_pipe->stream->signal) && -+ dc_is_hdmi_frl_signal(new_pipe->stream->signal); - } - - if (!has_active_hpo && !stream_changed_otg_dig_on && pipe->stream && - (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) || !pipe_link_enc) && -- !dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe)) { -+ !dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe) && -+ !dc_is_hdmi_frl_signal(pipe->stream->signal)) { - /* This w/a should not trigger when we have a dig active */ - if (disable) { - if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c -index cb85b7ac2697..1cca1f0c1aa2 100644 +index 8be9cbd43e180e..ecb10cec539e69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1528,6 +1528,9 @@ struct dc *dc_create(const struct dc_init_data *init_params) @@ -781,49 +178,11 @@ index cb85b7ac2697..1cca1f0c1aa2 100644 dc->nbio_reg_offsets = init_params->nbio_reg_offsets; dc->clk_reg_offsets = init_params->clk_reg_offsets; -@@ -3292,6 +3295,9 @@ static void copy_stream_update_to_stream(struct dc *dc, - if (update->vrr_active_fixed) - stream->vrr_active_fixed = *update->vrr_active_fixed; - -+ if (update->hdmi_allm_active) -+ stream->hdmi_allm_active = *update->hdmi_allm_active; -+ - if (update->crtc_timing_adjust) { - if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || - stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || -diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c -index bbce751b485f..b08362afbd76 100644 ---- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c -+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c -@@ -270,6 +270,8 @@ char *dc_status_to_str(enum dc_status status) - return "HW Cursor not supported"; - case DC_FAIL_DP_TUNNEL_BW_VALIDATE: - return "Fail DP Tunnel BW validation"; -+ case DC_FAIL_FRL_LINK_BANDWIDTH: -+ return "Insufficient FRL link bandwidth"; - case DC_ERROR_UNEXPECTED: - return "Unexpected error"; - } -diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c -index 7bb4504889be..01233ccfd5ae 100644 ---- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c -+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c -@@ -345,6 +345,10 @@ enum dc_link_encoding_format dc_link_get_highest_encoding_format(const struct dc - DP_128b_132b_ENCODING) - return DC_LINK_ENCODING_DP_128b_132b; - } else if (dc_is_hdmi_signal(link->connector_signal)) { -+ if (link->local_sink->edid_caps.frl_caps.max_rate > 0) -+ return DC_LINK_ENCODING_HDMI_FRL; -+ else -+ return DC_LINK_ENCODING_HDMI_TMDS; - } - - return DC_LINK_ENCODING_UNSPECIFIED; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c -index 848c267ef11e..beeaeae4810e 100644 +index 848c267ef11e74..60f04c45b839a1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c -@@ -48,10 +48,13 @@ +@@ -48,6 +48,7 @@ #include "virtual/virtual_link_hwss.h" #include "link/hwss/link_hwss_dio.h" #include "link/hwss/link_hwss_dpia.h" @@ -831,13 +190,7 @@ index 848c267ef11e..beeaeae4810e 100644 #include "link/hwss/link_hwss_hpo_dp.h" #include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h" #include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h" - -+#include "link/protocols/link_frl_training.h" -+ - #if defined(CONFIG_DRM_AMD_DC_SI) - #include "dce60/dce60_resource.h" - #endif -@@ -511,6 +514,27 @@ bool resource_construct( +@@ -511,6 +512,27 @@ bool resource_construct( } } @@ -865,15 +218,11 @@ index 848c267ef11e..beeaeae4810e 100644 for (i = 0; i < caps->num_mpc_3dlut; i++) { pool->mpc_lut[i] = dc_create_3dlut_func(); if (pool->mpc_lut[i] == NULL) -@@ -4033,6 +4057,15 @@ enum dc_status resource_map_pool_resources( +@@ -4033,6 +4055,11 @@ enum dc_status resource_map_pool_resources( } } + if (dc_is_hdmi_frl_signal(stream->signal)) { -+ if (!hdmi_decide_link_settings(stream, pipe_ctx)) -+ return DC_FAIL_FRL_LINK_BANDWIDTH; -+ -+ /* Only one pair of encoders on all HW so far. */ + pipe_ctx->stream_res.hpo_hdmi_stream_enc = pool->hpo_hdmi_stream_enc[0]; + pipe_ctx->link_res.hpo_hdmi_link_enc = pool->hpo_hdmi_link_enc[0]; + } @@ -881,16 +230,15 @@ index 848c267ef11e..beeaeae4810e 100644 if (dc->config.unify_link_enc_assignment && is_dio_encoder) if (!add_dio_link_enc_to_ctx(dc, context, pool, pipe_ctx, stream)) return DC_NO_LINK_ENC_RESOURCE; -@@ -4659,7 +4692,7 @@ static void set_avi_info_frame( - vic = 0; - format = stream->timing.timing_3d_format; - /*todo, add 3DStereo support*/ -- if (format != TIMING_3D_FORMAT_NONE) { -+ if (format != TIMING_3D_FORMAT_NONE || stream->hdmi_allm_active) { - // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled - switch (pipe_ctx->stream->timing.hdmi_vic) { - case 1: -@@ -5484,6 +5517,8 @@ const struct link_hwss *get_link_hwss(const struct dc_link *link, +@@ -5175,6 +5202,7 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) + + if (res == DC_OK) { + if (link->ep_type == DISPLAY_ENDPOINT_PHY && ++ !dc_is_hdmi_frl_signal(stream->signal) && /* FIXME: Temporary w/a for link encoder bringup */ + !link->link_enc->funcs->validate_output_with_stream( + link->link_enc, stream)) + res = DC_FAIL_ENC_VALIDATE; +@@ -5484,6 +5512,8 @@ const struct link_hwss *get_link_hwss(const struct dc_link *link, */ return (requires_fixed_vs_pe_retimer_hpo_link_hwss(link) ? get_hpo_fixed_vs_pe_retimer_dp_link_hwss() : get_hpo_dp_link_hwss()); @@ -899,43 +247,15 @@ index 848c267ef11e..beeaeae4810e 100644 else if (can_use_dpia_link_hwss(link, link_res)) return get_dpia_link_hwss(); else if (can_use_dio_link_hwss(link, link_res)) -@@ -5711,5 +5746,5 @@ bool resource_is_hpo_acquired(struct dc_state *context) +@@ -5711,5 +5741,5 @@ bool resource_is_hpo_acquired(struct dc_state *context) } } - return false; + return true; } -diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c -index f59020f1a722..cd7d6f5c9c0f 100644 ---- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c -+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c -@@ -52,6 +52,11 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink) - else - stream->signal = sink->sink_signal; - -+ if (dc_is_hdmi_tmds_signal(stream->signal)) -+ if (stream->link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE && -+ sink->edid_caps.frl_caps.max_rate > 0) -+ stream->signal = SIGNAL_TYPE_HDMI_FRL; -+ - if (dc_is_dvi_signal(stream->signal)) { - if (stream->ctx->dc->caps.dual_link_dvi && - (stream->timing.pix_clk_100hz / 10) > TMDS_MAX_PIXEL_CLOCK && -diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h -index ab19b6230945..7b22575ff638 100644 ---- a/drivers/gpu/drm/amd/display/dc/dc.h -+++ b/drivers/gpu/drm/amd/display/dc/dc.h -@@ -1057,6 +1057,7 @@ struct dc_debug_options { - bool scl_reset_length10; - bool hdmi20_disable; - bool skip_detection_link_training; -+ bool override_pcon_vrr_id_check; - uint32_t edid_read_retry_times; - unsigned int force_odm_combine; //bit vector based on otg inst - unsigned int seamless_boot_odm_combine; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h -index 5e3646b7550c..f4f1e9f3e6d5 100644 +index 79e1696def6305..af519c24dacabb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -157,6 +157,7 @@ struct dc_link_settings { @@ -947,7 +267,7 @@ index 5e3646b7550c..f4f1e9f3e6d5 100644 struct dc_tunnel_settings { diff --git a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h -index fcd3ab4b0045..ef779ba1c14c 100644 +index fcd3ab4b004594..ef779ba1c14cb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h @@ -64,7 +64,8 @@ struct dp_hdmi_dongle_signature_data { @@ -960,419 +280,8 @@ index fcd3ab4b0045..ef779ba1c14c 100644 #define HDMI_SCDC_ERR_DETECT 0x50 #define HDMI_SCDC_TEST_CONFIG 0xC0 -diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h -index 719b98d8e8ca..dc181854386f 100644 ---- a/drivers/gpu/drm/amd/display/dc/dc_stream.h -+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h -@@ -242,6 +242,7 @@ struct dc_stream_state { - bool vrr_active_variable; - bool freesync_on_desktop; - bool vrr_active_fixed; -+ bool hdmi_allm_active; - - bool converter_disable_audio; - uint8_t qs_bit; -@@ -345,6 +346,7 @@ struct dc_stream_update { - bool *allow_freesync; - bool *vrr_active_variable; - bool *vrr_active_fixed; -+ bool *hdmi_allm_active; - - struct colorspace_transform *gamut_remap; - enum dc_color_space *output_color_space; -diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h -index 0e953059ff6d..2b90eb174d77 100644 ---- a/drivers/gpu/drm/amd/display/dc/dc_types.h -+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h -@@ -185,6 +185,41 @@ struct dc_panel_patch { - unsigned int wait_after_dpcd_poweroff_ms; - }; - -+/** -+ * struct dc_hdmi_frl_caps - HDMI FRL Capabilities read from EDID. -+ */ -+struct dc_hdmi_frl_caps { -+ /* raw max_rate field */ -+ uint8_t max_rate; -+ -+ /* max supported data rate per lane in Gbps */ -+ uint8_t max_rate_per_lane; -+ -+ /* max supported FRL lanes by sink */ -+ uint8_t max_lanes; -+}; -+ -+/** -+ * struct dc_hdmi_dsc_caps - HDMI DSC Capabilities read from EDID. -+ */ -+struct dc_hdmi_dsc_caps { -+ /* Support DSC v1.2 */ -+ bool v1p2; -+ -+ bool all_bpp; -+ bool native_420; -+ -+ uint8_t max_bpc; -+ uint8_t total_chunk_kbytes; -+ uint8_t max_slices; -+ -+ /* max supported pixel clock per slice in MHz */ -+ uint16_t max_clk; -+ -+ /* Alternative FRL caps to use with DSC */ -+ struct dc_hdmi_frl_caps frl; -+}; -+ - /** - * struct dc_edid_caps - Capabilities read from EDID. - * @analog: Whether the monitor is analog. Used by DVI-I handling. -@@ -210,9 +245,16 @@ struct dc_edid_caps { - - uint32_t max_tmds_clk_mhz; - -- /*HDMI 2.0 caps*/ -+ /* HDMI 2.0 caps */ - bool lte_340mcsc_scramble; - -+ /* HDMI 2.1 caps */ -+ struct dc_hdmi_frl_caps frl_caps; -+ struct dc_hdmi_dsc_caps dsc_caps; -+ bool allm; -+ bool fva; -+ bool hdmi_vrr; -+ - bool edid_hdmi; - bool hdr_supported; - bool rr_capable; -diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c -index 97df04b7e39d..13383f2b68ff 100644 ---- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c -+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c -@@ -170,6 +170,59 @@ void dccg31_set_dpstreamclk( - dccg31_enable_dpstreamclk(dccg, otg_inst); - } - -+static void dccg31_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, -+ HDMISTREAMCLK0_GATE_DISABLE, 1); -+ } -+ REG_UPDATE_2(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_SRC_SEL, otg_inst, -+ HDMISTREAMCLK0_EN, 1); -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg31_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ REG_UPDATE(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_EN, 0); -+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, -+ HDMISTREAMCLK0_GATE_DISABLE, 0); -+ } -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg31_set_hdmistreamclk( -+ struct dccg *dccg, -+ enum streamclk_source src, -+ int otg_inst, -+ int hdmi_hpo_inst) -+{ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ if (src == REFCLK) -+ dccg31_disable_hdmistreamclk(dccg, hdmi_hpo_inst); -+ else -+ dccg31_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); -+} -+ - void dccg31_enable_symclk32_se( - struct dccg *dccg, - int hpo_se_inst, -@@ -836,6 +889,7 @@ static const struct dccg_funcs dccg31_funcs = { - .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, - .dccg_init = dccg31_init, - .set_dpstreamclk = dccg31_set_dpstreamclk, -+ .set_hdmistreamclk = dccg31_set_hdmistreamclk, - .enable_symclk32_se = dccg31_enable_symclk32_se, - .disable_symclk32_se = dccg31_disable_symclk32_se, - .enable_symclk32_le = dccg31_enable_symclk32_le, -diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h -index bf659920d4cc..4d6753ade738 100644 ---- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h -+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h -@@ -147,6 +147,7 @@ - DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_GATE_DISABLE, mask_sh),\ -+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_ROOT_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ -diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c -index ef3db6beba25..a183950fbdd3 100644 ---- a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c -+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c -@@ -285,6 +285,59 @@ void dccg314_set_dpstreamclk( - } - } - -+static void dccg314_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, -+ HDMISTREAMCLK0_GATE_DISABLE, 1); -+ } -+ REG_UPDATE_2(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_SRC_SEL, otg_inst, -+ HDMISTREAMCLK0_EN, 1); -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg314_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ REG_UPDATE(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_EN, 0); -+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, -+ HDMISTREAMCLK0_GATE_DISABLE, 0); -+ } -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+void dccg314_set_hdmistreamclk( -+ struct dccg *dccg, -+ enum streamclk_source src, -+ int otg_inst, -+ int hdmi_hpo_inst) -+{ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ if (src == REFCLK) -+ dccg314_disable_hdmistreamclk(dccg, hdmi_hpo_inst); -+ else -+ dccg314_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); -+} -+ - static void dccg314_init(struct dccg *dccg) - { - int otg_inst; -@@ -359,6 +412,7 @@ static const struct dccg_funcs dccg314_funcs = { - .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, - .dccg_init = dccg314_init, - .set_dpstreamclk = dccg314_set_dpstreamclk, -+ .set_hdmistreamclk = dccg314_set_hdmistreamclk, - .enable_symclk32_se = dccg31_enable_symclk32_se, - .disable_symclk32_se = dccg31_disable_symclk32_se, - .enable_symclk32_le = dccg31_enable_symclk32_le, -diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h -index a609635f35db..b38dcdcd854c 100644 ---- a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h -+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h -@@ -151,6 +151,7 @@ - DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\ - DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\ - DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\ -+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\ - DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\ -@@ -208,4 +209,10 @@ void dccg314_set_dpstreamclk( - int otg_inst, - int dp_hpo_inst); - -+void dccg314_set_hdmistreamclk( -+ struct dccg *dccg, -+ enum streamclk_source src, -+ int otg_inst, -+ int hdmi_hpo_inst); -+ - #endif //__DCN314_DCCG_H__ -diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c -index 21a6ca5ca192..3db490280f09 100644 ---- a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c -+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c -@@ -309,6 +309,51 @@ static void dccg32_set_dpstreamclk( - } - } - -+static void dccg32_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ REG_UPDATE_2(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_SRC_SEL, otg_inst, -+ HDMISTREAMCLK0_EN, 1); -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg32_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ REG_UPDATE(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_EN, 0); -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg32_set_hdmistreamclk( -+ struct dccg *dccg, -+ enum streamclk_source src, -+ int otg_inst, -+ int hdmi_hpo_inst) -+{ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ if (src == REFCLK) -+ dccg32_disable_hdmistreamclk(dccg, hdmi_hpo_inst); -+ else -+ dccg32_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); -+} -+ - static void dccg32_otg_add_pixel(struct dccg *dccg, - uint32_t otg_inst) - { -@@ -332,6 +377,7 @@ static const struct dccg_funcs dccg32_funcs = { - .get_dccg_ref_freq = dccg32_get_dccg_ref_freq, - .dccg_init = dccg31_init, - .set_dpstreamclk = dccg32_set_dpstreamclk, -+ .set_hdmistreamclk = dccg32_set_hdmistreamclk, - .enable_symclk32_se = dccg31_enable_symclk32_se, - .disable_symclk32_se = dccg31_disable_symclk32_se, - .enable_symclk32_le = dccg31_enable_symclk32_le, -diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c -index bd2f528137b2..9224645eaf8d 100644 ---- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c -+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c -@@ -2155,6 +2155,63 @@ static void dccg35_set_dpstreamclk_root_clock_gating_cb( - dccg35_disable_dpstreamclk_new(dccg, dp_hpo_inst); - } - -+static void dccg35_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, -+ HDMISTREAMCLK0_ROOT_GATE_DISABLE, 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, -+ HDMISTREAMCLK0_GATE_DISABLE, 1); -+ } -+ REG_UPDATE_2(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_SRC_SEL, otg_inst, -+ HDMISTREAMCLK0_EN, 1); -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg35_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) -+{ -+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); -+ -+ switch (hdmi_hpo_inst) { -+ case 0: -+ REG_UPDATE(HDMISTREAMCLK_CNTL, -+ HDMISTREAMCLK0_EN, 0); -+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, -+ HDMISTREAMCLK0_ROOT_GATE_DISABLE, 0); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, -+ HDMISTREAMCLK0_GATE_DISABLE, 0); -+ } -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ return; -+ } -+} -+ -+static void dccg35_set_hdmistreamclk( -+ struct dccg *dccg, -+ enum streamclk_source src, -+ int otg_inst, -+ int hdmi_hpo_inst) -+{ -+ /* enabled to select one of the DTBCLKs for pipe */ -+ if (src == REFCLK) -+ dccg35_disable_hdmistreamclk(dccg, hdmi_hpo_inst); -+ else -+ dccg35_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); -+} -+ - static void dccg35_update_dpp_dto_cb(struct dccg *dccg, int dpp_inst, - int req_dppclk) - { -@@ -2398,6 +2455,7 @@ static const struct dccg_funcs dccg35_funcs_new = { - .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, - .dccg_init = dccg35_init_cb, - .set_dpstreamclk = dccg35_set_dpstreamclk_cb, -+ .set_hdmistreamclk = dccg35_set_hdmistreamclk, - .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating_cb, - .enable_symclk32_se = dccg35_enable_symclk32_se_cb, - .disable_symclk32_se = dccg35_disable_symclk32_se_cb, -@@ -2429,6 +2487,7 @@ static const struct dccg_funcs dccg35_funcs = { - .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, - .dccg_init = dccg35_init, - .set_dpstreamclk = dccg35_set_dpstreamclk, -+ .set_hdmistreamclk = dccg35_set_hdmistreamclk, - .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, - .enable_symclk32_se = dccg31_enable_symclk32_se, - .disable_symclk32_se = dccg35_disable_symclk32_se, diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c -index 663a18ee5162..f176100ea198 100644 +index 663a18ee51628a..f176100ea19878 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c @@ -587,6 +587,63 @@ void dccg401_set_dpstreamclk( @@ -1448,7 +357,7 @@ index 663a18ee5162..f176100ea198 100644 .disable_symclk32_se = dccg31_disable_symclk32_se, .enable_symclk32_le = dccg401_enable_symclk32_le, diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h -index 5947a35363aa..47c755351a30 100644 +index 5947a35363aace..47c755351a30a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h @@ -201,6 +201,11 @@ void dccg401_set_dpstreamclk( @@ -1463,133 +372,8 @@ index 5947a35363aa..47c755351a30 100644 void dccg401_enable_symclk32_le( struct dccg *dccg, int hpo_le_inst, -diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c -index 13e14aad3daa..32d125d7f1d7 100644 ---- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c -@@ -623,6 +623,10 @@ static bool dcn10_link_encoder_validate_hdmi_output( - enum dc_color_depth max_deep_color = - enc10->base.features.max_hdmi_deep_color; - -+ // FRL is always fine. TODO add validation -+ if (edid_caps->frl_caps.max_rate > 0) -+ return true; -+ - // check pixel clock against edid specified max TMDS clk - if (edid_caps->max_tmds_clk_mhz != 0 && - adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) -@@ -804,6 +808,7 @@ bool dcn10_link_encoder_validate_output_with_stream( - &stream->timing); - break; - case SIGNAL_TYPE_HDMI_TYPE_A: -+ case SIGNAL_TYPE_HDMI_FRL: - is_valid = dcn10_link_encoder_validate_hdmi_output( - enc10, - &stream->timing, -diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c -index 07d362ef0daf..a721fef7d484 100644 ---- a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c -@@ -387,6 +387,7 @@ void dcn31_link_encoder_construct( - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; -+ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, -diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c -index 65d28cb07b04..b55905cfeabd 100644 ---- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c -@@ -329,6 +329,7 @@ void dcn32_link_encoder_construct( - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; -+ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, -diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c -index 968f89295b64..8549359f55a8 100644 ---- a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c -@@ -183,6 +183,7 @@ void dcn321_link_encoder_construct( - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; -+ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, -diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c -index 20bf04dac609..6af1ca576d20 100644 ---- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c -@@ -260,6 +260,7 @@ void dcn35_link_encoder_construct( - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; -+ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; - - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", -diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c -index e1f0a1bf1075..b3612f7a890d 100644 ---- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c -@@ -314,6 +314,7 @@ void dcn401_link_encoder_construct( - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; -+ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, -diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h -index 7014b8c2c956..5e77deb09200 100644 ---- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h -+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h -@@ -220,10 +220,10 @@ int dm_helpers_dmub_set_config_sync(struct dc_context *ctx, - const struct dc_link *link, - struct set_config_cmd_payload *payload, - enum set_config_status *operation_result); --enum adaptive_sync_type dm_get_adaptive_sync_support_type(struct dc_link *link); - - enum dc_edid_status dm_helpers_get_sbios_edid(struct dc_link *link, struct dc_edid *edid); - -+bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link, const struct drm_device *dev); - bool dm_helpers_is_fullscreen(struct dc_context *ctx, struct dc_stream_state *stream); - bool dm_helpers_is_hdr_on(struct dc_context *ctx, struct dc_stream_state *stream); - -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c -index 7aaf13bbd4e4..867e5a198155 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c -@@ -1050,6 +1050,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) - continue; - if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) - return true; -+ if (dc_is_hdmi_frl_signal(context->res_ctx.pipe_ctx[i].stream->signal)) -+ return true; - } - return false; - } -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c -index 8a0f128722b0..29cbc6db6cd2 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c -@@ -1606,6 +1606,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) - continue; - if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) - return true; -+ if (dc_is_hdmi_frl_signal(context->res_ctx.pipe_ctx[i].stream->signal)) -+ return true; - } - return false; - } diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c -index bf5e7f4e0416..da55c52cd492 100644 +index bf5e7f4e04167f..da55c52cd4924a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c @@ -202,6 +202,9 @@ static void populate_dml21_output_config_from_stream_state(struct dml2_link_outp @@ -1611,7 +395,7 @@ index bf5e7f4e0416..da55c52cd492 100644 case SIGNAL_TYPE_RGB: case SIGNAL_TYPE_DISPLAY_PORT: diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c -index 73a1e6a03719..5aa1f15ee4cc 100644 +index 73a1e6a037192f..5aa1f15ee4cc70 100644 --- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c +++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c @@ -345,6 +345,7 @@ static const struct protection_properties *get_protection_properties_by_signal( @@ -1631,7 +415,7 @@ index 73a1e6a03719..5aa1f15ee4cc 100644 case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: diff --git a/drivers/gpu/drm/amd/display/dc/hpo/Makefile b/drivers/gpu/drm/amd/display/dc/hpo/Makefile -index 7f2c9ee0dff1..53bb6ab5616a 100644 +index 7f2c9ee0dff1d5..53bb6ab5616a60 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hpo/Makefile @@ -27,6 +27,7 @@ ifdef CONFIG_DRM_AMD_DC_FP @@ -1644,7 +428,7 @@ index 7f2c9ee0dff1..53bb6ab5616a 100644 diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c new file mode 100644 -index 000000000000..7373d8a135f8 +index 00000000000000..b13a818eef7277 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c @@ -0,0 +1,179 @@ @@ -1760,7 +544,7 @@ index 000000000000..7373d8a135f8 + cntl.engine_id = enc3->base.preferred_engine; + cntl.transmitter = enc3->base.transmitter; + cntl.signal = SIGNAL_TYPE_HDMI_FRL; -+ cntl.lanes_number = (frl_rate <= 2) ? 3 : 4; ++ cntl.lanes_number = (frl_rate <= 3) ? 3 : 4; + cntl.hpd_sel = enc3->base.hpd_source; + cntl.pixel_clock = hdmi_frl_rate_to_pixel_clock(frl_rate); + cntl.color_depth = COLOR_DEPTH_UNDEFINED; @@ -1829,10 +613,10 @@ index 000000000000..7373d8a135f8 +} diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h new file mode 100644 -index 000000000000..134d2ca1dc17 +index 00000000000000..2e32a0e09ad01f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h -@@ -0,0 +1,131 @@ +@@ -0,0 +1,130 @@ +/* + * HPO HDMI Link Encoder + * @@ -1867,7 +651,6 @@ index 000000000000..134d2ca1dc17 +}; + +#define DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(mask_sh) \ -+ SE_SF(HDMI_LINK_ENC_CONTROL, HDMI_LINK_ENC_ENABLE, mask_sh), \ + SE_SF(HDMI_LINK_ENC_CONTROL, HDMI_LINK_ENC_SOFT_RESET, mask_sh), \ + SE_SF(HDMI_LINK_ENC_CLK_CTRL, HDMI_LINK_ENC_CLOCK_EN, \ + mask_sh), \ @@ -1966,10 +749,10 @@ index 000000000000..134d2ca1dc17 +#endif /* __DAL_DCN401_HPO_HDMI_LINK_ENCODER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c new file mode 100644 -index 000000000000..3cc437683b2c +index 00000000000000..12b813c5e28945 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c -@@ -0,0 +1,523 @@ +@@ -0,0 +1,481 @@ +/* + * HPO HDMI Stream Encoder + * @@ -2270,10 +1053,9 @@ index 000000000000..3cc437683b2c + case PIXEL_ENCODING_YCBCR422: + pixel_encoding = 1; + break; -+ case PIXEL_ENCODING_YCBCR420: ++ case PIXEL_ENCODING_YCBCR444: + pixel_encoding = 2; + break; -+ case PIXEL_ENCODING_YCBCR444: + default: /* RGB */ + pixel_encoding = 0; + break; @@ -2356,60 +1138,13 @@ index 000000000000..3cc437683b2c + REG_UPDATE(HDMI_TB_ENC_GC_CONTROL, HDMI_GC_AVMUTE, 0); +} + -+struct frl_audio_clock_info { -+ uint32_t frl_lane_rate; -+ /* N - 32KHz audio */ -+ uint32_t n_32khz; -+ /* CTS - 32KHz audio*/ -+ uint32_t cts_32khz; -+ uint32_t n_44khz; -+ uint32_t cts_44khz; -+ uint32_t n_48khz; -+ uint32_t cts_48khz; -+}; -+ -+/* Values set by the Windows driver seem to depend only on FRL rate*/ -+static const struct frl_audio_clock_info frl_audio_clock_info_table[5] = { -+ {3, 4224, 171875, 5292, 156250, 5760, 156250}, -+ {6, 4032, 328125, 5292, 312500, 6048, 328125}, -+ {8, 4032, 437500, 3969, 312500, 6048, 437500}, -+ {10, 3456, 468750, 3969, 390625, 5184, 468750}, -+ {12, 3072, 500000, 3969, 468750, 4752, 515625}, -+}; -+ -+static void get_frl_audio_clock_info( -+ struct frl_audio_clock_info *audio_clock_info, -+ uint8_t frl_rate) -+{ -+ uint32_t index; -+ uint32_t frl_lane_rates[] = { 3, 6, 6, 8, 10, 12 }; -+ uint32_t frl_lane_rate; -+ -+ ASSERT(frl_rate >= 0 && frl_rate <= 6); -+ -+ frl_lane_rate = frl_lane_rates[frl_rate - 1]; -+ -+ /* search for FRL rate in table */ -+ for (index = 0; -+ index < sizeof(frl_audio_clock_info_table) / sizeof(struct frl_audio_clock_info); -+ index++) { -+ if (frl_audio_clock_info_table[index].frl_lane_rate == frl_lane_rate) { -+ *audio_clock_info = frl_audio_clock_info_table[index]; -+ return; -+ } -+ } -+ -+ /* Should never happen */ -+ *audio_clock_info = frl_audio_clock_info_table[0]; -+} -+ +static void setup_hdmi_audio(struct hpo_hdmi_stream_encoder *enc, -+ const struct audio_crtc_info *crtc_info, uint8_t frl_rate) ++ const struct audio_crtc_info *crtc_info) +{ + struct dcn30_hpo_hdmi_stream_encoder *enc3 = + DCN3_0_HPO_HDMI_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + -+ struct frl_audio_clock_info audio_clock_info = { 0 }; ++ struct audio_clock_info audio_clock_info = { 0 }; + + /* Setup audio in AFMT - program AFMT block associated with HPO */ + ASSERT(enc->afmt); @@ -2419,7 +1154,14 @@ index 000000000000..3cc437683b2c + HDMI_ACR_SOURCE, 0, HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ -+ get_frl_audio_clock_info(&audio_clock_info, frl_rate); ++ get_audio_clock_info(crtc_info->color_depth, ++ crtc_info->requested_pixel_clock_100Hz, ++ crtc_info->calculated_pixel_clock_100Hz, ++ &audio_clock_info); ++ DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d" ++ "calculated_pixel_clock_100Hz = %d \n", ++ __func__, crtc_info->requested_pixel_clock_100Hz, ++ crtc_info->calculated_pixel_clock_100Hz); + + REG_UPDATE(HDMI_TB_ENC_ACR_32_0, HDMI_ACR_CTS_32, + audio_clock_info.cts_32khz); @@ -2439,10 +1181,9 @@ index 000000000000..3cc437683b2c + +static void dcn30_hpo_hdmi_stream_enc_hdmi_audio_setup( + struct hpo_hdmi_stream_encoder *enc, unsigned int az_inst, -+ struct audio_info *info, struct audio_crtc_info *audio_crtc_info, -+ uint8_t frl_rate) ++ struct audio_info *info, struct audio_crtc_info *audio_crtc_info) +{ -+ setup_hdmi_audio(enc, audio_crtc_info, frl_rate); ++ setup_hdmi_audio(enc, audio_crtc_info); + ASSERT(enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} @@ -2495,10 +1236,10 @@ index 000000000000..3cc437683b2c +} diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h new file mode 100644 -index 000000000000..ba97e0c0e346 +index 00000000000000..0aa737efd3fa93 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h -@@ -0,0 +1,768 @@ +@@ -0,0 +1,772 @@ +/* + * HPO HDMI Stream Encoder + * @@ -2666,6 +1407,10 @@ index 000000000000..ba97e0c0e346 + SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ + FIFO_PIXEL_ENCODING_TYPE, mask_sh), \ + SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ ++ FIFO_UNCOMPRESSED_PIXEL_FORMAT, mask_sh), \ ++ SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ ++ FIFO_COMPRESSED_PIXEL_FORMAT, mask_sh), \ ++ SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ + FIFO_RESET_DONE, mask_sh), \ + SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ + FIFO_VIDEO_STREAM_ACTIVE, mask_sh), \ @@ -3269,10 +2014,10 @@ index 000000000000..ba97e0c0e346 +#endif /* __DAL_DCN401_HPO_HDMI_STREAM_ENCODER_H__ */ \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c -index 4659e1b489ba..2a4732dc7540 100644 +index ebd74b43e935ee..5c3270299cad85 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c -@@ -1159,6 +1159,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +@@ -1178,6 +1178,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) struct timing_generator *tg = pipe_ctx->stream_res.tg; struct dtbclk_dto_params dto_params = {0}; int dp_hpo_inst; @@ -3280,7 +2025,7 @@ index 4659e1b489ba..2a4732dc7540 100644 struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; -@@ -1170,6 +1171,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +@@ -1189,6 +1190,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc->funcs->hdmi_reset_stream_attribute( pipe_ctx->stream_res.stream_enc); @@ -3290,85 +2035,23 @@ index 4659e1b489ba..2a4732dc7540 100644 } if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { -@@ -1195,6 +1199,17 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +@@ -1214,6 +1218,11 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->set_dtbclk_dto(dccg, &dto_params); } } + } else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) && dccg) { -+ dto_params.otg_inst = tg->inst; -+ dto_params.timing = &pipe_ctx->stream->timing; + hdmi_hpo_inst = pipe_ctx->stream_res.hpo_hdmi_stream_enc->inst; + if (dccg) { + dccg->funcs->set_hdmistreamclk(dccg, REFCLK, tg->inst, hdmi_hpo_inst); -+ if (!(dc->ctx->dce_version >= DCN_VERSION_3_5)) { -+ if (dccg && dccg->funcs->set_dtbclk_dto) -+ dccg->funcs->set_dtbclk_dto(dccg, &dto_params); -+ } + } } else if (dccg && dccg->funcs->disable_symclk_se) { dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A); -@@ -1459,7 +1474,8 @@ void build_audio_output( - - if (state->clk_mgr && - (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || -- pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) { -+ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || -+ pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_FRL)) { - audio_output->pll_info.audio_dto_source_clock_in_khz = - state->clk_mgr->funcs->get_dp_ref_clk_frequency( - state->clk_mgr); -@@ -2427,7 +2443,7 @@ static void dce110_setup_audio_dto( - - if (pipe_ctx->top_pipe) - continue; -- if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) -+ if (!dc_is_hdmi_signal(pipe_ctx->stream->signal)) - continue; - if (pipe_ctx->stream_res.audio != NULL) { - struct audio_output audio_output; -diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c -index a76436dcbe40..39df7785355c 100644 ---- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c -+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c -@@ -893,7 +893,7 @@ enum dc_status dcn20_enable_stream_timing( - return DC_ERROR_UNEXPECTED; - } - -- if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { -+ if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { - struct dccg *dccg = dc->res_pool->dccg; - struct timing_generator *tg = pipe_ctx->stream_res.tg; - struct dtbclk_dto_params dto_params = {0}; -@@ -3035,6 +3035,7 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) - struct dccg *dccg = dc->res_pool->dccg; - enum phyd32clk_clock_source phyd32clk; - int dp_hpo_inst; -+ int hdmi_hpo_inst = 0; - - struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; - struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; -@@ -3058,6 +3059,15 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) - } else { - dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); - } -+ } else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { -+ dto_params.otg_inst = tg->inst; -+ dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; -+ dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); -+ dto_params.timing = &pipe_ctx->stream->timing; -+ dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); -+ dccg->funcs->set_dtbclk_dto(dccg, &dto_params); -+ hdmi_hpo_inst = pipe_ctx->stream_res.hpo_hdmi_stream_enc->inst; -+ dccg->funcs->set_hdmistreamclk(dccg, DTBCLK0, tg->inst, hdmi_hpo_inst); - } else { - if (dccg->funcs->enable_symclk_se && link_enc) { - if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c -index 2adbcc105aa6..4d0097b3b363 100644 +index d1ecdb92b072b1..3d69122446ae8e 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c -@@ -379,6 +379,7 @@ void dcn31_enable_power_gating_plane( +@@ -378,6 +378,7 @@ void dcn31_enable_power_gating_plane( void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx) { bool is_hdmi_tmds; @@ -3376,7 +2059,7 @@ index 2adbcc105aa6..4d0097b3b363 100644 bool is_dp; ASSERT(pipe_ctx->stream); -@@ -387,16 +388,22 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx) +@@ -386,16 +387,22 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx) return; /* this is not root pipe */ is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); @@ -3402,74 +2085,11 @@ index 2adbcc105aa6..4d0097b3b363 100644 if (pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->update_dp_info_packets_sdp_line_num) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->update_dp_info_packets_sdp_line_num( pipe_ctx->stream_res.hpo_dp_stream_enc, -diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c -index 3e239124c17d..83796ef35ade 100644 ---- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c -+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c -@@ -191,6 +191,11 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx - pipe_ctx->stream_res.tg->funcs->set_odm_bypass( - pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); - -+ /* no idea if this is the correct logic. but windows seems to pick manual mode */ -+ if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) -+ pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode( -+ pipe_ctx->stream_res.tg, true); -+ - if (mpc->funcs->set_out_rate_control) { - for (i = 0; i < opp_cnt; ++i) { - mpc->funcs->set_out_rate_control( -@@ -334,7 +339,7 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig - two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); - odm_combine_factor = get_odm_config(pipe_ctx, NULL); - -- if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { -+ if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(stream->signal)) { - *k1_div = PIXEL_RATE_DIV_BY_1; - *k2_div = PIXEL_RATE_DIV_BY_1; - } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) { -diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c -index 518794fad9e1..d6618275654f 100644 ---- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c -+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c -@@ -1154,6 +1154,11 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * - pipe_ctx->stream_res.tg->funcs->set_odm_bypass( - pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); - -+ /* no idea if this is the correct logic. but windows seems to pick manual mode */ -+ if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) -+ pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode( -+ pipe_ctx->stream_res.tg, true); -+ - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control( - odm_pipe->stream_res.opp, -@@ -1197,7 +1202,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign - two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); - odm_combine_factor = get_odm_config(pipe_ctx, NULL); - -- if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { -+ if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(stream->signal)) { - *k1_div = PIXEL_RATE_DIV_BY_1; - *k2_div = PIXEL_RATE_DIV_BY_1; - } else if (dc_is_hdmi_tmds_signal(stream->signal) || dc_is_dvi_signal(stream->signal)) { -diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c -index f7e16fee7594..10e0c0ac46c7 100644 ---- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c -+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c -@@ -919,7 +919,7 @@ void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx - void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, - struct pg_block_update *update_state) - { -- bool hpo_frl_stream_enc_acquired = false; -+ bool hpo_frl_stream_enc_acquired = true; // HACK - bool hpo_dp_stream_enc_acquired = false; - int i = 0, j = 0; - int edp_num = 0; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c -index 39b6f6d2d7c1..b9ac6f433d0a 100644 +index 5eda7648d0d2ba..40a6301f30371b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c -@@ -907,6 +907,7 @@ static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) +@@ -906,6 +906,7 @@ static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) static void dcn401_enable_stream_calc( struct pipe_ctx *pipe_ctx, int *dp_hpo_inst, @@ -3477,9 +2097,9 @@ index 39b6f6d2d7c1..b9ac6f433d0a 100644 enum phyd32clk_clock_source *phyd32clk, unsigned int *tmds_div, uint32_t *early_control) -@@ -923,6 +924,9 @@ static void dcn401_enable_stream_calc( - *phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link); - } +@@ -922,6 +923,9 @@ static void dcn401_enable_stream_calc( + + *phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link); + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) + *hdmi_hpo_inst = pipe_ctx->stream_res.hpo_hdmi_stream_enc->inst; @@ -3487,15 +2107,15 @@ index 39b6f6d2d7c1..b9ac6f433d0a 100644 if (dc_is_tmds_signal(pipe_ctx->stream->signal)) dcn401_calculate_dccg_tmds_div_value(pipe_ctx, tmds_div); else -@@ -952,6 +956,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) +@@ -951,6 +955,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) struct dccg *dccg = dc->res_pool->dccg; - enum phyd32clk_clock_source phyd32clk = PHYD32CLKA; + enum phyd32clk_clock_source phyd32clk; int dp_hpo_inst = 0; + int hdmi_hpo_inst = 0; unsigned int tmds_div = PIXEL_RATE_DIV_NA; unsigned int unused_div = PIXEL_RATE_DIV_NA; struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; -@@ -960,7 +965,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) +@@ -959,7 +964,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) if (!dc->config.unify_link_enc_assignment) link_enc = link_enc_cfg_get_link_enc(link); @@ -3504,7 +2124,7 @@ index 39b6f6d2d7c1..b9ac6f433d0a 100644 &tmds_div, &early_control); if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) { -@@ -975,6 +980,8 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) +@@ -974,6 +979,8 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A); } @@ -3514,7 +2134,7 @@ index 39b6f6d2d7c1..b9ac6f433d0a 100644 if (dc->res_pool->dccg->funcs->set_pixel_rate_div) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h -index 51b0f0fd8fcd..7b17c23521cc 100644 +index 8ed9eea40c5646..4dc441ab95fdcd 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -1184,6 +1184,10 @@ struct hw_sequencer_funcs { @@ -3528,20 +2148,8 @@ index 51b0f0fd8fcd..7b17c23521cc 100644 void (*disable_link_output)(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); -diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h -index 82085d9c3f40..b6e60b1e53d3 100644 ---- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h -+++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h -@@ -60,6 +60,7 @@ enum dc_status { - DC_FAIL_DP_LINK_BANDWIDTH = 28, - DC_FAIL_HW_CURSOR_SUPPORT = 29, - DC_FAIL_DP_TUNNEL_BW_VALIDATE = 30, -+ DC_FAIL_FRL_LINK_BANDWIDTH = 31, - DC_ERROR_UNEXPECTED = -1 - }; - diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h -index 61d8ef759aca..da8f2db12a72 100644 +index 5ed2cd3448040d..39ba4aafbe5f73 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -286,6 +286,12 @@ struct resource_pool { @@ -3574,7 +2182,7 @@ index 61d8ef759aca..da8f2db12a72 100644 struct link_config { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h -index 1e6ffd86a4c0..89592d6b58b5 100644 +index 500a601e99b502..d1868ac692a5c0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -235,6 +235,12 @@ struct dccg_funcs { @@ -3591,7 +2199,7 @@ index 1e6ffd86a4c0..89592d6b58b5 100644 struct dccg *dccg, int hpo_se_inst, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h -index a61d12ec61bc..e641ecdf9f87 100644 +index a61d12ec61bc4c..e641ecdf9f87f8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -78,6 +78,8 @@ @@ -3604,18 +2212,10 @@ index a61d12ec61bc..e641ecdf9f87 100644 /* Pipe topology snapshot structures */ #define MAX_TOPOLOGY_SNAPSHOTS 4 diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h -index d795fc43dc9d..aad69c708829 100644 +index df512920a9fabe..ee174926f6a90f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h -@@ -67,6 +67,7 @@ struct encoder_feature_support { - uint32_t IS_UHBR13_5_CAPABLE:1; - uint32_t IS_UHBR20_CAPABLE:1; - uint32_t DP_IS_USB_C:1; -+ uint32_t IS_HDMI_FRL_CAPABLE:1; - } bits; - uint32_t raw; - } flags; -@@ -239,6 +240,13 @@ struct hpo_dp_link_enc_state { +@@ -233,6 +233,13 @@ struct hpo_dp_link_enc_state { uint32_t vc_rate_y[4]; }; @@ -3629,7 +2229,7 @@ index d795fc43dc9d..aad69c708829 100644 struct hpo_dp_link_encoder { const struct hpo_dp_link_encoder_funcs *funcs; struct dc_context *ctx; -@@ -248,6 +256,15 @@ struct hpo_dp_link_encoder { +@@ -242,6 +249,15 @@ struct hpo_dp_link_encoder { enum hpd_source_id hpd_source; }; @@ -3645,7 +2245,7 @@ index d795fc43dc9d..aad69c708829 100644 struct hpo_dp_link_encoder_funcs { void (*enable_link_phy)(struct hpo_dp_link_encoder *enc, -@@ -291,4 +308,33 @@ struct hpo_dp_link_encoder_funcs { +@@ -285,4 +301,33 @@ struct hpo_dp_link_encoder_funcs { uint8_t ffe_preset); }; @@ -3680,7 +2280,7 @@ index d795fc43dc9d..aad69c708829 100644 + #endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h -index 27f950ae45ee..d45d7b024e75 100644 +index 27f950ae45ee51..be3a0c25e56cdf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -288,6 +288,12 @@ struct hpo_dp_stream_encoder_state { @@ -3714,11 +2314,13 @@ index 27f950ae45ee..d45d7b024e75 100644 struct hpo_dp_stream_encoder_funcs { void (*enable_stream)( struct hpo_dp_stream_encoder *enc); -@@ -362,4 +379,39 @@ struct hpo_dp_stream_encoder_funcs { +@@ -362,4 +379,40 @@ struct hpo_dp_stream_encoder_funcs { uint16_t width); }; +struct hpo_hdmi_stream_encoder_funcs { ++ ++ /* Core lifecycle */ + void (*enable)( + struct hpo_hdmi_stream_encoder *enc, + uint8_t source_select); @@ -3742,8 +2344,7 @@ index 27f950ae45ee..d45d7b024e75 100644 + struct hpo_hdmi_stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, -+ struct audio_crtc_info *audio_crtc_info, -+ uint8_t frl_rate); ++ struct audio_crtc_info *audio_crtc_info); + + void (*hdmi_audio_enable)( + struct hpo_hdmi_stream_encoder *enc); @@ -3754,20 +2355,8 @@ index 27f950ae45ee..d45d7b024e75 100644 + + #endif /* STREAM_ENCODER_H_ */ -diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h -index da7bf59c4b9d..9cf729d341f4 100644 ---- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h -+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h -@@ -106,6 +106,7 @@ enum crc_selection { - - enum otg_out_mux_dest { - OUT_MUX_DIO = 0, -+ OUT_MUX_HPO_HDMI = 1, - OUT_MUX_HPO_DP = 2, - }; - diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h -index 0f69946cce9f..f0224cd3bf44 100644 +index 0f69946cce9f64..f0224cd3bf44fa 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -56,6 +56,10 @@ struct link_hwss_ext { @@ -3782,7 +2371,7 @@ index 0f69946cce9f..f0224cd3bf44 100644 const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h -index 79746d931471..05d4450562d4 100644 +index 79746d931471a8..05d4450562d4eb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -59,6 +59,8 @@ struct resource_caps { @@ -3809,7 +2398,7 @@ index 79746d931471..05d4450562d4 100644 struct dc_context *ctx); }; diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile -index 84dace27daf7..b972cc3cadcd 100644 +index 84c7af5fa5891b..0b41feef37cd3a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/Makefile +++ b/drivers/gpu/drm/amd/display/dc/link/Makefile @@ -43,7 +43,8 @@ AMD_DISPLAY_FILES += $(AMD_DAL_LINK_ACCESSORIES) @@ -3822,23 +2411,22 @@ index 84dace27daf7..b972cc3cadcd 100644 AMD_DAL_LINK_HWSS = $(addprefix $(AMDDALPATH)/dc/link/hwss/, \ $(LINK_HWSS)) -@@ -56,7 +57,9 @@ LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \ +@@ -56,7 +57,8 @@ LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \ link_dp_training.o link_dp_training_8b_10b.o link_dp_training_128b_132b.o \ link_dp_training_dpia.o link_dp_training_auxless.o \ link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o link_dp_capability.o \ --link_edp_panel_control.o link_dp_panel_replay.o link_dp_irq_handler.o link_dp_dpia_bw.o -+link_edp_panel_control.o link_dp_panel_replay.o link_dp_irq_handler.o \ -+link_dp_dpia_bw.o link_frl_training.o -+ +-link_edp_panel_control.o link_dp_irq_handler.o link_dp_dpia_bw.o ++link_edp_panel_control.o link_dp_irq_handler.o link_dp_dpia_bw.o \ ++link_frl_training.o AMD_DAL_LINK_PROTOCOLS = $(addprefix $(AMDDALPATH)/dc/link/protocols/, \ $(LINK_PROTOCOLS)) diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c new file mode 100644 -index 000000000000..c3e66e66e43e +index 00000000000000..2059102c28b978 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c -@@ -0,0 +1,132 @@ +@@ -0,0 +1,131 @@ +/* + * HPO HDMI link sequencing + * @@ -3868,7 +2456,7 @@ index 000000000000..c3e66e66e43e + + enc = link_res->hpo_hdmi_link_enc; + frl_rate = link_settings->frl_rate; -+ lane_count = (frl_rate <= 2) ? 3 : 4; ++ lane_count = (frl_rate <= 3) ? 3 : 4; + + enc->funcs->configure_transmitter(enc, link, frl_rate, + link->link_enc->transmitter, @@ -3892,7 +2480,7 @@ index 000000000000..c3e66e66e43e + enc->funcs->link_disable(enc); +} + -+static void setup_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) ++void setup_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct hpo_hdmi_stream_encoder *stream_enc = + pipe_ctx->stream_res.hpo_hdmi_stream_enc; @@ -3901,7 +2489,7 @@ index 000000000000..c3e66e66e43e + stream_enc->funcs->enable(stream_enc, otg_inst); +} + -+static void reset_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) ++void reset_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct hpo_hdmi_stream_encoder *stream_enc = + pipe_ctx->stream_res.hpo_hdmi_stream_enc; @@ -3913,7 +2501,7 @@ index 000000000000..c3e66e66e43e + stream_enc->funcs->disable(stream_enc); +} + -+static void setup_hpo_hdmi_frl_stream_attribute(struct pipe_ctx *pipe_ctx) ++void setup_hpo_hdmi_frl_stream_attribute(struct pipe_ctx *pipe_ctx) +{ + struct hpo_hdmi_stream_encoder *stream_enc = + pipe_ctx->stream_res.hpo_hdmi_stream_enc; @@ -3928,23 +2516,22 @@ index 000000000000..c3e66e66e43e + output_color_space); +} + -+static void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, ++void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output, + uint32_t audio_inst) +{ + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.hpo_hdmi_stream_enc, audio_inst, -+ &pipe_ctx->stream->audio_info, &audio_output->crtc_info, -+ pipe_ctx->link_config.dp_link_settings.frl_rate); ++ &pipe_ctx->stream->audio_info, &audio_output->crtc_info); +} + -+static void enable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) ++void enable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) +{ + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs->hdmi_audio_enable( + pipe_ctx->stream_res.hpo_hdmi_stream_enc); +} + -+static void disable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) ++void disable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->stream_res.audio) + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs @@ -3973,7 +2560,7 @@ index 000000000000..c3e66e66e43e +} diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.h new file mode 100644 -index 000000000000..6e6291b1e3c7 +index 00000000000000..6e6291b1e3c7f3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.h @@ -0,0 +1,29 @@ @@ -4007,7 +2594,7 @@ index 000000000000..6e6291b1e3c7 + +#endif /* __LINK_HWSS_HPO_HDMI_FRL_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c -index 578509e8d0e2..4021f53984ac 100644 +index 7fa6bc97a91935..7db87e2125a16b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -78,6 +78,7 @@ static enum ddc_transaction_type get_ddc_transaction_type(enum signal_type sink_ @@ -4018,7 +2605,7 @@ index 578509e8d0e2..4021f53984ac 100644 case SIGNAL_TYPE_LVDS: case SIGNAL_TYPE_RGB: transaction_type = DDC_TRANSACTION_TYPE_I2C; -@@ -1019,10 +1020,11 @@ static bool detect_link_and_local_sink(struct dc_link *link, +@@ -1017,10 +1018,11 @@ static bool detect_link_and_local_sink(struct dc_link *link, /* From Disconnected-to-Connected. */ switch (link->connector_signal) { @@ -4031,7 +2618,7 @@ index 578509e8d0e2..4021f53984ac 100644 else sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; break; -@@ -1502,6 +1504,7 @@ bool link_is_hdcp14(struct dc_link *link, enum signal_type signal) +@@ -1507,6 +1509,7 @@ bool link_is_hdcp14(struct dc_link *link, enum signal_type signal) case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_HDMI_TYPE_A: @@ -4039,7 +2626,7 @@ index 578509e8d0e2..4021f53984ac 100644 /* HDMI doesn't tell us its HDCP(1.4) capability, so assume to always be capable, * we can poll for bksv but some displays have an issue with this. Since its so rare * for a display to not be 1.4 capable, this assumtion is ok -@@ -1528,6 +1531,7 @@ bool link_is_hdcp22(struct dc_link *link, enum signal_type signal) +@@ -1533,6 +1536,7 @@ bool link_is_hdcp22(struct dc_link *link, enum signal_type signal) case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_HDMI_TYPE_A: @@ -4048,18 +2635,18 @@ index 578509e8d0e2..4021f53984ac 100644 break; default: diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c -index 91742bde4dc2..d0adcbe5cee5 100644 +index 6ae13414761716..646c2170ed85a6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c -@@ -48,6 +48,7 @@ +@@ -47,6 +47,7 @@ + #include "protocols/link_dp_training.h" #include "protocols/link_edp_panel_control.h" - #include "protocols/link_dp_panel_replay.h" #include "protocols/link_dp_dpia_bw.h" +#include "protocols/link_frl_training.h" #include "dm_helpers.h" #include "link_enc_cfg.h" -@@ -687,6 +688,9 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) +@@ -686,6 +687,9 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) if (dp_is_128b_132b_signal(pipe_ctx)) config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; @@ -4069,7 +2656,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 /* dig back end */ config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst; -@@ -695,6 +699,8 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) +@@ -694,6 +698,8 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; if (dp_is_128b_132b_signal(pipe_ctx)) config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst; @@ -4078,7 +2665,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 /* dio output index is dpia index for DPIA endpoint & dcio index by default */ if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) -@@ -1904,7 +1910,7 @@ static void disable_link(struct dc_link *link, +@@ -1962,7 +1968,7 @@ static void disable_link(struct dc_link *link, } } @@ -4087,22 +2674,30 @@ index 91742bde4dc2..d0adcbe5cee5 100644 { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; -@@ -1915,15 +1921,39 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) +@@ -1973,15 +1979,54 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) bool is_vga_mode = (stream->timing.h_addressable == 640) && (stream->timing.v_addressable == 480); struct dc *dc = pipe_ctx->stream->ctx->dc; ++ uint8_t frl_rate, lane_count; + + DC_LOG_HW_LINK_TRAINING("enable_link_hdmi entered\n"); ++ ++ if (dc_is_hdmi_frl_signal(stream->signal)) { ++ link->cur_link_settings.frl_rate = 6; ++ link->cur_link_settings.lane_count = 4; ++ ++ DC_LOG_HW_LINK_TRAINING( ++ "FORCING FRL: rate=%d lanes=%d\n", ++ link->cur_link_settings.frl_rate, ++ link->cur_link_settings.lane_count); ++ } + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) && + link_hwss->ext.enable_hdmi_link_output) { + -+ link->cur_link_settings.frl_rate = -+ pipe_ctx->link_config.dp_link_settings.frl_rate; -+ link->cur_link_settings.lane_count = -+ pipe_ctx->link_config.dp_link_settings.lane_count; ++ DC_LOG_HW_LINK_TRAINING("HDMI FRL detected, using HPO path\n"); + + link_hwss->ext.enable_hdmi_link_output( + link, @@ -4110,7 +2705,14 @@ index 91742bde4dc2..d0adcbe5cee5 100644 + pipe_ctx->stream->signal, + &link->cur_link_settings); + -+ if (!dc_link_perform_frl_training(link, &pipe_ctx->link_res)) { ++ frl_rate = link->cur_link_settings.frl_rate; ++ lane_count = (frl_rate <= 3) ? 3 : 4; ++ ++ if (!dc_link_perform_frl_training( ++ link, ++ &pipe_ctx->link_res, ++ frl_rate, ++ lane_count)) { + DC_LOG_HW_LINK_TRAINING("HDMI FRL: training failed\n"); + return DC_ERROR_UNEXPECTED; + } @@ -4128,7 +2730,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 } if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { -@@ -1946,7 +1976,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) +@@ -2004,7 +2049,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) } } @@ -4137,7 +2739,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 write_scdc_data( stream->link->ddc, stream->phy_pix_clk, -@@ -1975,6 +2005,8 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) +@@ -2033,6 +2078,8 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) read_scdc_data(link->ddc); @@ -4146,7 +2748,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 } static enum dc_status enable_link_dp(struct dc_state *state, -@@ -2179,6 +2211,7 @@ static enum dc_status enable_link( +@@ -2232,6 +2279,7 @@ static enum dc_status enable_link( return DC_ERROR_UNEXPECTED; link = stream->link; @@ -4154,7 +2756,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 /* There's some scenarios where driver is unloaded with display * still enabled. When driver is reloaded, it may cause a display * to not light up if there is a mismatch between old and new -@@ -2187,6 +2220,7 @@ static enum dc_status enable_link( +@@ -2240,6 +2288,7 @@ static enum dc_status enable_link( */ if (link->link_status.link_active) disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal); @@ -4162,7 +2764,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: -@@ -2202,8 +2236,8 @@ static enum dc_status enable_link( +@@ -2255,8 +2304,8 @@ static enum dc_status enable_link( case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_HDMI_TYPE_A: @@ -4173,7 +2775,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 break; case SIGNAL_TYPE_LVDS: enable_link_lvds(pipe_ctx); -@@ -2308,6 +2342,8 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) +@@ -2361,6 +2410,8 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) if (dp_is_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; @@ -4182,7 +2784,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 if (dc_is_virtual_signal(pipe_ctx->stream->signal)) return; -@@ -2339,7 +2375,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) +@@ -2392,7 +2443,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) dp_is_128b_132b_signal(pipe_ctx)) update_sst_payload(pipe_ctx, false); @@ -4191,17 +2793,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 struct ext_hdmi_settings settings = {0}; enum engine_id eng_id = pipe_ctx->stream_res.stream_enc->id; -@@ -2364,6 +2400,9 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) - } - } - -+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) -+ dc_link_disable_frl(pipe_ctx->stream->link); -+ - if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && - !dp_is_128b_132b_signal(pipe_ctx)) { - -@@ -2386,7 +2425,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) +@@ -2439,7 +2490,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) if (dc_is_dp_signal(pipe_ctx->stream->signal)) link_set_dsc_enable(pipe_ctx, false); } @@ -4210,7 +2802,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 if (pipe_ctx->stream_res.tg->funcs->set_out_mux) pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); } -@@ -2424,6 +2463,8 @@ void link_set_dpms_on( +@@ -2477,6 +2528,8 @@ void link_set_dpms_on( if (dp_is_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; @@ -4219,7 +2811,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 if (dc_is_virtual_signal(pipe_ctx->stream->signal)) return; -@@ -2443,7 +2484,8 @@ void link_set_dpms_on( +@@ -2495,7 +2548,8 @@ void link_set_dpms_on( ASSERT(link_enc); if (!dc_is_virtual_signal(pipe_ctx->stream->signal) @@ -4229,18 +2821,16 @@ index 91742bde4dc2..d0adcbe5cee5 100644 if (link_enc) link_enc->funcs->setup( link_enc, -@@ -2455,6 +2497,10 @@ void link_set_dpms_on( +@@ -2505,7 +2559,7 @@ void link_set_dpms_on( + pipe_ctx->stream->link->link_state_valid = true; + if (pipe_ctx->stream_res.tg->funcs->set_out_mux) { - if (dp_is_128b_132b_signal(pipe_ctx)) +- if (dp_is_128b_132b_signal(pipe_ctx)) ++ if (dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) otg_out_dest = OUT_MUX_HPO_DP; -+ else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) -+ /* DCN401 unified the DP and HDMI output mux values */ -+ otg_out_dest = (dc->ctx->dce_version < DCN_VERSION_4_01) ? -+ OUT_MUX_HPO_HDMI : OUT_MUX_HPO_DP; else otg_out_dest = OUT_MUX_DIO; - pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest); -@@ -2566,7 +2612,8 @@ void link_set_dpms_on( +@@ -2615,7 +2669,8 @@ void link_set_dpms_on( * from transmitter control. */ if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) || @@ -4252,7 +2842,7 @@ index 91742bde4dc2..d0adcbe5cee5 100644 link_enc->funcs->setup( diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c deleted file mode 100644 -index 4b5eccd994c4..000000000000 +index 4b5eccd994c461..00000000000000 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c +++ /dev/null @@ -1,62 +0,0 @@ @@ -4318,8 +2908,57 @@ index 4b5eccd994c4..000000000000 -{ - return &hpo_frl_link_hwss; -} +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +index acdc162de5353b..b56a9c74c3e89d 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +@@ -329,6 +329,29 @@ static bool dp_validate_mode_timing( + return false; + } + ++static enum dc_status hdmi_validate_mode_timing( ++ struct dc_link *link, ++ const struct dc_crtc_timing *timing) ++{ ++ uint32_t pix_clk_100hz; ++ ++ memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings)); ++ ++ pix_clk_100hz = get_tmds_output_pixel_clock_100hz(timing); ++ ++ /* TMDS always allowed if it fits */ ++ if (pix_clk_100hz <= 340000) { ++ /* TMDS path: frl_rate stays 0 */ ++ return DC_OK; ++ } ++ ++ /* YEET FRL12 at the link, i'm too tired to do this properly */ ++ link->cur_link_settings.frl_rate = 6; ++ link->cur_link_settings.lane_count = 4; ++ return DC_OK; ++} ++ ++ + enum dc_status link_validate_mode_timing( + const struct dc_stream_state *stream, + struct dc_link *link, +@@ -359,7 +382,13 @@ enum dc_status link_validate_mode_timing( + timing)) + return DC_NO_DP_LINK_BANDWIDTH; + break; +- ++ case SIGNAL_TYPE_HDMI_TYPE_A: ++ case SIGNAL_TYPE_HDMI_FRL: ++ if (!hdmi_validate_mode_timing( ++ link, ++ timing)) ++ return DC_NO_DP_LINK_BANDWIDTH; ++ break; + default: + break; + } diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c -index 5d2bcce2f669..6c5ee009fa6d 100644 +index 5d2bcce2f669d1..6c5ee009fa6d79 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c @@ -596,7 +596,7 @@ void read_scdc_data(struct ddc_service *ddc_service) @@ -4333,10 +2972,10 @@ index 5d2bcce2f669..6c5ee009fa6d 100644 sizeof(status_data.byte)); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c new file mode 100644 -index 000000000000..5e83c2bb4256 +index 00000000000000..289aaeb9103fd3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c -@@ -0,0 +1,581 @@ +@@ -0,0 +1,227 @@ +/* + * HDMI 2.1 Fixed Rate Link (FRL) training + * @@ -4391,19 +3030,18 @@ index 000000000000..5e83c2bb4256 +} + +bool dc_link_perform_frl_training(struct dc_link *link, -+ const struct link_resource *link_res) ++ const struct link_resource *link_res, ++ uint8_t frl_rate, uint8_t lane_count) +{ + struct hpo_hdmi_link_encoder *enc = link_res->hpo_hdmi_link_enc; -+ uint8_t lane_count = link->cur_link_settings.lane_count; -+ uint8_t frl_rate = link->cur_link_settings.frl_rate; + uint8_t sink_version; + uint8_t update; + uint8_t status; ++ uint8_t flags; + uint16_t ltp_req; + uint8_t write_buffer[2]; + int poll; + int lane; -+ int post_training_timeout; + + if (!enc || lane_count == 0 || lane_count > FRL_MAX_LANES) + return false; @@ -4427,26 +3065,24 @@ index 000000000000..5e83c2bb4256 + + /* Write source version = 1 */ + write_buffer[0] = 0x01; -+ frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, write_buffer, 1); ++ frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, &write_buffer[0], 1); + -+retrain: + /* Reset FRL rate */ + write_buffer[0] = 0; + write_buffer[1] = 0; -+ frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2); ++ frl_write_scdc(link, 0x30, &write_buffer[0], 2); + + /* ------------------------------------------------------------------ */ + /* Step 2: Wait for FLT_READY */ + /* ------------------------------------------------------------------ */ + for (poll = 0; poll < FRL_MAX_POLLS; poll++) { -+ if (!frl_read_scdc(link, HDMI_SCDC_STATUS_FLAGS_0, &status, 1)) { -+ msleep(FRL_POLL_DELAY_MS); -+ continue; -+ } ++ if (!frl_read_scdc(link, HDMI_SCDC_STATUS_FLAGS_0, &status, 1)) ++ goto poll_delay; + + if (status & SCDC_FLT_READY_BIT) + break; + ++poll_delay: + msleep(FRL_POLL_DELAY_MS); + } + @@ -4479,6 +3115,14 @@ index 000000000000..5e83c2bb4256 + + pr_err("FRL DEBUG: UPDATE_0 = 0x%02x\n", update); + ++ if (update & SCDC_FRL_START_BIT) { ++ pr_err("FRL DEBUG: FRL_START asserted\n"); ++ DC_LOG_HW_LINK_TRAINING( ++ "HDMI FRL: Link already trained\n"); ++ enc->funcs->set_training_enable(enc, false); ++ return true; ++ } ++ + if (!(update & SCDC_FLT_UPDATE_BIT)) { + pr_err("FRL DEBUG: FLT_UPDATE not set\n"); + msleep(FRL_POLL_DELAY_MS); @@ -4514,33 +3158,10 @@ index 000000000000..5e83c2bb4256 + } + + if (lane == lane_count) { ++ DC_LOG_HW_LINK_TRAINING( ++ "HDMI FRL: training successful\n"); + enc->funcs->set_training_enable(enc, false); -+ for (post_training_timeout = 0; -+ post_training_timeout < FRL_MAX_POLLS; -+ post_training_timeout++) { -+ if (!frl_read_scdc(link, HDMI_SCDC_UPDATE_0, &update, 1)) { -+ msleep(FRL_POLL_DELAY_MS); -+ continue; -+ } -+ -+ if (update & (SCDC_FLT_UPDATE_BIT | SCDC_FRL_START_BIT)) -+ break; -+ -+ msleep(FRL_POLL_DELAY_MS); -+ } -+ -+ frl_write_scdc(link, HDMI_SCDC_UPDATE_0, &update, 1); -+ -+ if (update & SCDC_FRL_START_BIT) { -+ DC_LOG_HW_LINK_TRAINING("HDMI FRL: training successful\n"); -+ return true; -+ } else if (update & SCDC_FLT_UPDATE_BIT) { -+ DC_LOG_HW_LINK_TRAINING("HDMI FRL: retraining needed\n"); -+ goto retrain; -+ } else { -+ DC_LOG_HW_LINK_TRAINING("HDMI FRL: did not receive status update!\n"); -+ return false; -+ } ++ return true; + } + + /* Program requested training patterns */ @@ -4582,349 +3203,12 @@ index 000000000000..5e83c2bb4256 + + return false; +} -+ -+void dc_link_disable_frl(struct dc_link *link) -+{ -+ uint8_t write_buffer[2]; -+ -+ /* Inform the sink not to expect an FRL signal */ -+ write_buffer[0] = 0; -+ write_buffer[1] = 0; -+ frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2); -+} -+ -+/* DFM calc -+ * References: -+ * https://github.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_linux/drv/mpp/component/hdmi/src/mkp/drv_hdmi_dfm.c#L264 -+ * https://github.com/jelyoussefi/intel-gpu-i915/blob/e366083d562341ce15d5fe1a39bb6e07f18a4745/drivers/gpu/drm/i915/display/intel_hdmi.c#L4217 -+ * TODO Move to generic DRM */ -+ -+#define DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000 5 /* +0.50% -> 5/1000 */ -+#define DFM_TOLERANCE_AUDIO_CLOCK_PPM 1000 /* +/- 1000 ppm */ -+#define DFM_TOLERANCE_FRL_BIT_RATE_PPM 300 /* +/- 300 ppm */ -+#define DFM_TB_BORROWED_MAX 400 -+#define DFM_FRL_CFRL_CB 510 -+ -+struct dfm_config { -+ /* Video Timing */ -+ uint32_t pixel_clock_khz; /* Nominal */ -+ uint32_t hactive; -+ uint32_t hblank; -+ uint32_t bpc; /* Bits per component */ -+ enum dc_pixel_encoding encoding; -+ -+ /* FRL Configuration */ -+ uint32_t frl_bit_rate_gbps; /* 3, 6, 8, 10, 12 */ -+ uint8_t lanes; /* 3 or 4 */ -+ -+ /* Audio */ -+ bool audio_enable; -+ uint32_t audio_freq_hz; -+ uint8_t audio_channels; -+}; -+ -+struct dfm_results { -+ /* Calculated Parameters */ -+ uint64_t f_pixel_clock_max; -+ uint64_t r_frl_char_min; -+ uint32_t overhead_ppm; -+ -+ /* Audio */ -+ uint32_t audio_packets_line; -+ uint32_t hblank_audio_min; -+ -+ /* Tri-Bytes */ -+ uint32_t tb_active; -+ uint32_t tb_blank; -+ -+ /* Compression */ -+ uint32_t cfrl_rc_savings; -+ -+ /* Timing (ns) */ -+ uint64_t t_active_min; -+ uint64_t t_active_ref; -+ uint64_t t_blank_min; -+ uint64_t t_blank_ref; -+ -+ /* Borrowing */ -+ uint64_t tb_borrowed; -+ -+ /* Utilization */ -+ uint32_t cfrl_line; -+ uint32_t cfrl_actual_payload; -+ int32_t margin_ppm; /* Can be negative */ -+ -+ /* Pass/Fail Flags */ -+ bool audio_supported; -+ bool dfm_supported; -+ bool utilization_supported; -+ bool total_supported; -+}; -+ -+ -+#define CEILING(x, y) (((x) + (y) - 1) / (y)) -+ -+static uint32_t calc_overhead_ppm(uint8_t lanes) -+{ -+ uint32_t cfrl_sb = (4 * 510) + lanes; -+ -+ uint64_t oh_sb_num = (uint64_t)lanes * 1000000ULL; -+ uint32_t oh_sb = (uint32_t)((oh_sb_num + (cfrl_sb/2)) / cfrl_sb); /* Rounding */ -+ -+ uint64_t oh_rs_num = 32ULL * 1000000ULL; -+ uint32_t oh_rs = (uint32_t)((oh_rs_num + (cfrl_sb/2)) / cfrl_sb); -+ -+ uint64_t oh_map_num = 2500000ULL; /* 2.5 * 1M */ -+ uint32_t oh_map = (uint32_t)((oh_map_num + (cfrl_sb/2)) / cfrl_sb); -+ -+ uint32_t oh_m = 3000; -+ -+ return oh_sb + oh_rs + oh_map + oh_m; -+} -+ -+static void calc_audio(const struct dfm_config *cfg, -+ uint64_t t_line_ns, -+ struct dfm_results *res) -+{ -+ if (!cfg->audio_enable) { -+ res->audio_packets_line = 0; -+ res->hblank_audio_min = 64; -+ return; -+ } -+ -+ uint32_t ap = 1; -+ if (cfg->audio_channels > 22) { -+ ap = 4; /* ACAT 3 (up to 30.2ch) */ -+ } else if (cfg->audio_channels > 10) { -+ ap = 3; /* ACAT 2 (up to 22.2ch) */ -+ } else if (cfg->audio_channels > 8) { -+ ap = 2; /* ACAT 1 (up to 10.2ch) */ -+ } else { -+ ap = 1; /* Layout 0/1 */ -+ } -+ -+ uint64_t rap = (uint64_t)cfg->audio_freq_hz * (1000000 + DFM_TOLERANCE_AUDIO_CLOCK_PPM); -+ rap = (rap * ap) / 1000000; -+ -+ uint64_t avg_pkts_x1000 = (rap * t_line_ns) / 1000000; /* ns to ms scale */ -+ -+ res->audio_packets_line = (uint32_t)((avg_pkts_x1000 + 999) / 1000); -+ -+ res->hblank_audio_min = 64 + (32 * res->audio_packets_line); -+} -+ -+/* Table 6-44: RC Compression Savings */ -+static void calc_rc_compression(const struct dfm_config *cfg, struct dfm_results *res) -+{ -+ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; -+ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; -+ -+ uint64_t raw_num = (uint64_t)cfg->hblank * kcd * 8; -+ uint64_t raw_den = (uint64_t)k420 * 7; -+ uint32_t raw_capacity = (uint32_t)(raw_num / raw_den); /* FLOOR */ -+ -+ uint32_t deduct = 32 * (1 + res->audio_packets_line) + 7; -+ int32_t free_chars = (int32_t)raw_capacity - (int32_t)deduct; -+ -+ if (free_chars < 0) free_chars = 0; -+ -+ int32_t margin = 4; -+ -+ int32_t base = free_chars - margin; -+ if (base < 0) base = 0; -+ -+ res->cfrl_rc_savings = (uint32_t)((base * 7) / 8); -+} -+ -+/* Core DFM Check Function */ -+static void perform_dfm_check(const struct dfm_config *cfg, struct dfm_results *res) -+{ -+ memset(res, 0, sizeof(struct dfm_results)); -+ -+ uint32_t htotal = cfg->hactive + cfg->hblank; -+ -+ res->overhead_ppm = calc_overhead_ppm(cfg->lanes); -+ -+ res->f_pixel_clock_max = (uint64_t)cfg->pixel_clock_khz * 1000; -+ res->f_pixel_clock_max = res->f_pixel_clock_max * (1000 + DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000) / 1000; -+ -+ uint64_t t_line_ns = ((uint64_t)htotal * 1000000000ULL) / res->f_pixel_clock_max; -+ -+ uint64_t r_bit_nominal = (uint64_t)cfg->frl_bit_rate_gbps * 1000000000ULL; -+ uint64_t r_bit_min = r_bit_nominal * (1000000 - DFM_TOLERANCE_FRL_BIT_RATE_PPM) / 1000000; -+ -+ res->r_frl_char_min = r_bit_min / 18; -+ -+ uint64_t cap_calc = (t_line_ns * res->r_frl_char_min * cfg->lanes) / 1000000000ULL; -+ res->cfrl_line = (uint32_t)cap_calc; -+ -+ calc_audio(cfg, t_line_ns, res); -+ -+ calc_rc_compression(cfg, res); -+ -+ uint32_t bpp; -+ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; -+ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; -+ -+ bpp = (24 * kcd) / (k420 * 8); -+ -+ uint64_t bytes_line = ((uint64_t)bpp * cfg->hactive) / 8; -+ -+ res->tb_active = (uint32_t)CEILING(bytes_line, 3); -+ -+ uint64_t tb_blank_num = (uint64_t)cfg->hblank * kcd; -+ uint64_t tb_blank_den = (uint64_t)k420 * 8; -+ res->tb_blank = (uint32_t)CEILING(tb_blank_num, tb_blank_den); -+ -+ if (res->hblank_audio_min <= res->tb_blank) { -+ res->audio_supported = true; -+ } else { -+ res->audio_supported = false; -+ res->total_supported = false; -+ return; -+ } -+ -+ uint64_t tb_total = res->tb_active + res->tb_blank; -+ uint64_t f_tb_avg = (res->f_pixel_clock_max * tb_total) / htotal; -+ -+ res->t_active_ref = (t_line_ns * cfg->hactive) / htotal; -+ -+ res->t_blank_ref = (t_line_ns * cfg->hblank) / htotal; -+ -+ uint64_t r_frl_eff = res->r_frl_char_min * (1000000 - res->overhead_ppm) / 1000000; -+ -+ res->t_active_min = (3ULL * res->tb_active * 1000000000ULL) / (2ULL * cfg->lanes * r_frl_eff); -+ -+ res->t_blank_min = (res->tb_blank * 1000000000ULL) / (cfg->lanes * r_frl_eff); -+ -+ if (res->t_active_ref >= res->t_active_min && res->t_blank_ref >= res->t_blank_min) { -+ res->tb_borrowed = 0; -+ res->dfm_supported = true; -+ } else if (res->t_active_ref < res->t_active_min) { -+ uint64_t borrow_time_ns = res->t_active_min - res->t_active_ref; -+ -+ res->tb_borrowed = CEILING(borrow_time_ns * f_tb_avg, 1000000000ULL); -+ -+ if (res->tb_borrowed <= DFM_TB_BORROWED_MAX) { -+ res->dfm_supported = true; -+ } else { -+ res->dfm_supported = false; -+ } -+ } else { -+ /* Blanking needs more time than available */ -+ res->dfm_supported = false; -+ } -+ -+ if (!res->dfm_supported) { -+ res->total_supported = false; -+ return; -+ } -+ -+ uint64_t total_chars_req = (3 * tb_total) / 2; -+ if (total_chars_req > res->cfrl_rc_savings) { -+ res->cfrl_actual_payload = (uint32_t)CEILING((total_chars_req - res->cfrl_rc_savings), 1); -+ } else { -+ res->cfrl_actual_payload = 0; -+ } -+ -+ uint64_t util_ppm = ((uint64_t)res->cfrl_actual_payload * 1000000ULL) / res->cfrl_line; -+ -+ int32_t margin_ppm = 1000000 - (int32_t)util_ppm + (int32_t)res->overhead_ppm; -+ res->margin_ppm = margin_ppm; -+ -+ if (margin_ppm >= 0) { -+ res->utilization_supported = true; -+ res->total_supported = true; -+ } else { -+ res->utilization_supported = false; -+ res->total_supported = false; -+ } -+} -+ -+bool hdmi_decide_link_settings( -+ struct dc_stream_state *stream, -+ struct pipe_ctx *pipe_ctx) -+{ -+ struct dfm_config cfg; -+ struct dfm_results res; -+ uint8_t frl_rate; -+ static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; -+ uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; -+ uint8_t best_borrow_rate = 0; -+ uint8_t best_borrow_lanes = 0; -+ struct dfm_results best_borrow_res = {0}; -+ -+ if (max_rate == 0 || max_rate > 6) -+ return false; -+ -+ memset(&cfg, 0, sizeof(cfg)); -+ -+ cfg.pixel_clock_khz = stream->timing.pix_clk_100hz / 10; -+ cfg.hactive = stream->timing.h_addressable; -+ cfg.hblank = stream->timing.h_total - stream->timing.h_addressable; -+ cfg.encoding = stream->timing.pixel_encoding; -+ -+ switch (stream->timing.display_color_depth) { -+ case COLOR_DEPTH_888: cfg.bpc = 8; break; -+ case COLOR_DEPTH_101010: cfg.bpc = 10; break; -+ case COLOR_DEPTH_121212: cfg.bpc = 12; break; -+ case COLOR_DEPTH_161616: cfg.bpc = 16; break; -+ default: -+ cfg.bpc = 8; -+ break; -+ } -+ -+ if (stream->audio_info.mode_count) { -+ cfg.audio_enable = true; -+ /* If we assume the worst case (e.g. 192KHz 32 channel audio) we risk -+ * unfairly pruning low res modes with short Hblank periods. Instead, -+ * assume a standard surround sound mode that should allow all video -+ * modes to work. -+ */ -+ cfg.audio_freq_hz = 48000; -+ cfg.audio_channels = 8; -+ } -+ -+ for (frl_rate = 1; frl_rate <= max_rate; frl_rate++) { -+ cfg.frl_bit_rate_gbps = frl_rates_gbps[frl_rate - 1]; -+ cfg.lanes = (frl_rate <= 2) ? 3 : 4; -+ -+ perform_dfm_check(&cfg, &res); -+ -+ if (res.total_supported) { -+ if (res.tb_borrowed == 0) { -+ pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; -+ pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; -+ -+ pr_info("HDMI FRL: Rate %d Supported. Borrowed: 0, Margin: %d ppm\n", -+ frl_rate, res.margin_ppm); -+ return true; -+ } else if (best_borrow_rate == 0) { -+ best_borrow_rate = frl_rate; -+ best_borrow_lanes = cfg.lanes; -+ best_borrow_res = res; -+ } -+ } -+ } -+ -+ if (best_borrow_rate > 0) { -+ pipe_ctx->link_config.dp_link_settings.frl_rate = best_borrow_rate; -+ pipe_ctx->link_config.dp_link_settings.lane_count = best_borrow_lanes; -+ -+ pr_info("HDMI FRL: Rate %d Supported (with borrowing). Borrowed: %llu, Margin: %d ppm\n", -+ best_borrow_rate, best_borrow_res.tb_borrowed, best_borrow_res.margin_ppm); -+ return true; -+ } -+ -+ return false; -+} -\ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h new file mode 100644 -index 000000000000..b6f23e6d8394 +index 00000000000000..39c60d3d5accdb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h -@@ -0,0 +1,53 @@ +@@ -0,0 +1,38 @@ +/* + * HDMI 2.1 Fixed Rate Link (FRL) training + * @@ -4959,30 +3243,15 @@ index 000000000000..b6f23e6d8394 + * false - training failed, link is disabled + */ +bool dc_link_perform_frl_training(struct dc_link *link, -+ const struct link_resource *link_res); -+ -+/* -+ * Disable FRL mode in the sink. Allows fallback to TMDS. -+ */ -+void dc_link_disable_frl(struct dc_link *link); -+ -+/* -+ * Perform HDMI DFM calculation to determine the optimal link settings. -+ * -+ * Returns: -+ * true - Link verification succeeded, link can be configured -+ * false - Link verification failed, link cannot be configured -+ */ -+bool hdmi_decide_link_settings( -+ struct dc_stream_state *stream, -+ struct pipe_ctx *pipe_ctx); ++ const struct link_resource *link_res, ++ uint8_t frl_rate, uint8_t lane_count); + +#endif /* __LINK_HDMI_FRL_TRAINING_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c -index 29f3a03687b2..953a8b6171ad 100644 +index caa617883f62ef..30f0adb7b3465e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c -@@ -80,6 +80,7 @@ bool program_hpd_filter(const struct dc_link *link) +@@ -187,6 +187,7 @@ bool program_hpd_filter(const struct dc_link *link) case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_HDMI_TYPE_A: @@ -4990,1302 +3259,8 @@ index 29f3a03687b2..953a8b6171ad 100644 /* Program hpd filter */ delay_on_connect_in_ms = 500; delay_on_disconnect_in_ms = 100; -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c -index e853ea110310..b59be1ddd3c8 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c -@@ -56,6 +56,8 @@ - #include "dcn30/dcn30_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn31/dcn31_apg.h" - #include "dcn31/dcn31_dio_link_encoder.h" - #include "dcn31/dcn31_vpg.h" -@@ -450,6 +452,18 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define hpo_dp_link_encoder_reg_list(id)\ - [id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ -@@ -473,6 +487,18 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs(id)\ - [id] = {\ - DPP_REG_LIST_DCN30(id),\ -@@ -819,6 +845,8 @@ static const struct resource_caps res_cap_dcn31 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, -@@ -1304,6 +1332,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn31_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1322,6 +1388,24 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn31_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn31_hwseq_create( - struct dc_context *ctx) - { -@@ -1341,6 +1425,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn31_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn31_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn31_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn31_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c -index 3ccde75a4ecb..3076b1d17098 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c -@@ -59,6 +59,8 @@ - #include "dcn314/dcn314_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn31/dcn31_apg.h" - #include "dcn31/dcn31_vpg.h" - #include "dcn31/dcn31_afmt.h" -@@ -457,6 +459,17 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; - - #define hpo_dp_link_encoder_reg_list(id)\ - [id] = {\ -@@ -479,6 +492,18 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs(id)\ - [id] = {\ - DPP_REG_LIST_DCN30(id),\ -@@ -831,6 +856,8 @@ static const struct resource_caps res_cap_dcn314 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, -@@ -1363,6 +1390,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn314_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): -+ * VPG[9] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 9; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1381,6 +1446,24 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn314_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn314_hwseq_create( - struct dc_context *ctx) - { -@@ -1400,6 +1483,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn314_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn314_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn314_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn314_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c -index 4e962f522f1b..0f0e34189ccf 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c -@@ -55,6 +55,8 @@ - #include "dcn30/dcn30_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn31/dcn31_apg.h" - #include "dcn31/dcn31_dio_link_encoder.h" - #include "dcn31/dcn31_vpg.h" -@@ -452,6 +454,17 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; - - #define hpo_dp_link_encoder_reg_list(id)\ - [id] = {\ -@@ -476,6 +489,18 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs(id)\ - [id] = {\ - DPP_REG_LIST_DCN30(id),\ -@@ -818,6 +843,8 @@ static const struct resource_caps res_cap_dcn31 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, -@@ -1305,6 +1332,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn315_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1323,6 +1388,24 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn315_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn31_hwseq_create( - struct dc_context *ctx) - { -@@ -1342,6 +1425,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn315_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn315_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn315_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn31_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c -index 5a95dd54cb42..7a035748814b 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c -@@ -55,6 +55,8 @@ - #include "dcn30/dcn30_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn31/dcn31_apg.h" - #include "dcn31/dcn31_dio_link_encoder.h" - #include "dcn31/dcn31_vpg.h" -@@ -442,6 +444,17 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; - - #define hpo_dp_link_encoder_reg_list(id)\ - [id] = {\ -@@ -466,6 +479,17 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) - }; - -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; - - #define dpp_regs(id)\ - [id] = {\ -@@ -813,6 +837,8 @@ static const struct resource_caps res_cap_dcn31 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, -@@ -1299,6 +1325,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn316_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1317,6 +1381,23 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn316_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} - - static struct dce_hwseq *dcn31_hwseq_create( - struct dc_context *ctx) -@@ -1337,6 +1418,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn316_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn316_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn316_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn31_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c -index b276fec3e479..a53570beed60 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c -@@ -57,6 +57,8 @@ - #include "dcn32/dcn32_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn32/dcn32_hpo_dp_link_encoder.h" - #include "dcn31/dcn31_apg.h" - #include "dcn31/dcn31_dio_link_encoder.h" -@@ -345,6 +347,18 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_stream_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; - - #define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) -@@ -363,6 +377,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_link_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs_init(id)\ - DPP_REG_LIST_DCN30_COMMON_RI(id) - -@@ -651,6 +678,8 @@ static const struct resource_caps res_cap_dcn32 = { - .num_stream_encoder = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, -@@ -1301,6 +1330,48 @@ static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn32_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance: -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn32_vpg_create(ctx, vpg_inst); -+ afmt = dcn32_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_stream_enc_regs -+ hpo_hdmi_stream_encoder_reg_init(), -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1324,6 +1395,28 @@ static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn32_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_link_enc_regs -+ hpo_hdmi_link_encoder_reg_init(), -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn32_hwseq_create( - struct dc_context *ctx) - { -@@ -1347,6 +1440,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn32_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn32_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn32_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn32_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c -index 3466ca34c93f..a5feaf536bc0 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c -@@ -59,6 +59,8 @@ - #include "dcn32/dcn32_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn32/dcn32_hpo_dp_link_encoder.h" - #include "dcn31/dcn31_apg.h" - #include "dcn31/dcn31_dio_link_encoder.h" -@@ -344,6 +346,18 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_stream_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; - - #define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) -@@ -362,6 +376,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_link_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs_init(id)\ - DPP_REG_LIST_DCN30_COMMON_RI(id) - -@@ -647,6 +674,8 @@ static const struct resource_caps res_cap_dcn321 = { - .num_stream_encoder = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, -@@ -1282,6 +1311,48 @@ static struct hpo_dp_stream_encoder *dcn321_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn321_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance: -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn321_vpg_create(ctx, vpg_inst); -+ afmt = dcn321_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_stream_enc_regs -+ hpo_hdmi_stream_encoder_reg_init(), -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1305,6 +1376,28 @@ static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn321_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_link_enc_regs -+ hpo_hdmi_link_encoder_reg_init(), -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn321_hwseq_create( - struct dc_context *ctx) - { -@@ -1328,6 +1421,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn321_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn321_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn321_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn321_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn321_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn321_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c -index 45454a097264..8680acae8f1a 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c -@@ -60,6 +60,8 @@ - #include "dcn35/dcn35_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn32/dcn32_hpo_dp_link_encoder.h" - #include "link_service.h" - #include "dcn31/dcn31_apg.h" -@@ -365,6 +367,19 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_stream_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) - /*DCN3_1_RDPCSTX_REG_LIST(0),*/ -@@ -382,6 +397,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_link_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs_init(id)\ - DPP_REG_LIST_DCN35_RI(id) - -@@ -673,6 +701,8 @@ static const struct resource_caps res_cap_dcn35 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ - .num_dwb = 1, - .num_ddc = 5, -@@ -1364,6 +1394,48 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn35_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance: -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_stream_enc_regs -+ hpo_hdmi_stream_encoder_reg_init(), -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1387,6 +1459,28 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn35_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_link_enc_regs -+ hpo_hdmi_link_encoder_reg_init(), -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn35_hwseq_create( - struct dc_context *ctx) - { -@@ -1410,6 +1504,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn35_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn35_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn35_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn35_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c -index e3c587165807..c6d12eb99bc0 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c -@@ -39,6 +39,8 @@ - #include "dcn35/dcn35_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn32/dcn32_hpo_dp_link_encoder.h" - #include "link_service.h" - #include "dcn31/dcn31_apg.h" -@@ -345,6 +347,19 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_stream_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) - /*DCN3_1_RDPCSTX_REG_LIST(0),*/ -@@ -362,6 +377,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_link_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs_init(id)\ - DPP_REG_LIST_DCN35_RI(id) - -@@ -653,6 +681,8 @@ static const struct resource_caps res_cap_dcn351 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ - .num_dwb = 1, - .num_ddc = 5, -@@ -1344,6 +1374,48 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn35_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance: -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_stream_enc_regs -+ hpo_hdmi_stream_encoder_reg_init(), -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1367,6 +1439,28 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn35_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_link_enc_regs -+ hpo_hdmi_link_encoder_reg_init(), -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn351_hwseq_create( - struct dc_context *ctx) - { -@@ -1390,6 +1484,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn35_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn35_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn35_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn351_hwseq_create, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c -index 6469d5fe2e6d..74bf9e68830c 100644 ---- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c -@@ -39,6 +39,8 @@ - #include "dcn35/dcn35_dio_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_stream_encoder.h" - #include "dcn31/dcn31_hpo_dp_link_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" -+#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" - #include "dcn32/dcn32_hpo_dp_link_encoder.h" - #include "link_service.h" - #include "dcn31/dcn31_apg.h" -@@ -350,6 +352,19 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_stream_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { -+ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) - -@@ -363,6 +378,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) - }; - -+#define hpo_hdmi_link_encoder_reg_init()\ -+ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() -+ -+static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) -+}; -+ -+static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { -+ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) -+}; -+ - #define dpp_regs_init(id)\ - DPP_REG_LIST_DCN35_RI(id) - -@@ -654,6 +682,8 @@ static const struct resource_caps res_cap_dcn36 = { - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, -+ .num_hpo_hdmi_stream_encoder = 1, -+ .num_hpo_hdmi_link_encoder = 1, - .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ - .num_dwb = 1, - .num_ddc = 5, -@@ -1345,6 +1375,48 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_stream_encoder *dcn36_hpo_hdmi_stream_encoder_create( -+ enum engine_id eng_id, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; -+ struct vpg *vpg; -+ struct afmt *afmt; -+ uint32_t hpo_hdmi_inst; -+ uint32_t vpg_inst; -+ uint32_t afmt_inst; -+ -+ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; -+ -+ /* Mapping of VPG register blocks to HPO HDMI block instance: -+ * VPG[5] -> HPO_HDMI[0] -+ * AFMT[5] -> HPO_HDMI[0] -+ */ -+ vpg_inst = hpo_hdmi_inst + 5; -+ afmt_inst = hpo_hdmi_inst + 5; -+ -+ /* allocate HPO stream encoder and create VPG sub-block */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); -+ vpg = dcn31_vpg_create(ctx, vpg_inst); -+ afmt = dcn31_afmt_create(ctx, afmt_inst); -+ -+ if (!hpo_hdmi_enc30 || !vpg || !afmt) { -+ kfree(hpo_hdmi_enc30); -+ kfree(vpg); -+ return NULL; -+ } -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_stream_enc_regs -+ hpo_hdmi_stream_encoder_reg_init(), -+ -+ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, -+ vpg, afmt, &hpo_hdmi_stream_enc_regs, -+ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -@@ -1368,6 +1440,28 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - return &hpo_dp_enc31->base; - } - -+static struct hpo_hdmi_link_encoder *dcn36_hpo_hdmi_link_encoder_create( -+ uint8_t inst, -+ struct dc_context *ctx) -+{ -+ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; -+ -+ /* allocate HPO link encoder */ -+ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); -+ if (!hpo_hdmi_enc30) -+ return NULL; /* out of memory */ -+ -+#undef REG_STRUCT -+#define REG_STRUCT hpo_hdmi_link_enc_regs -+ hpo_hdmi_link_encoder_reg_init(), -+ -+ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, -+ &hpo_hdmi_link_enc_regs, -+ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); -+ -+ return &hpo_hdmi_enc30->base; -+} -+ - static struct dce_hwseq *dcn36_hwseq_create( - struct dc_context *ctx) - { -@@ -1391,6 +1485,8 @@ static const struct resource_create_funcs res_create_funcs = { - .create_stream_encoder = dcn35_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, -+ .create_hpo_hdmi_stream_encoder = dcn36_hpo_hdmi_stream_encoder_create, -+ .create_hpo_hdmi_link_encoder = dcn36_hpo_hdmi_link_encoder_create, - .create_hwseq = dcn36_hwseq_create, - }; - diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c -index 1cdbb65da4a3..ef2bd22ffa78 100644 +index 875ae97489d324..f50c588b270c73 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -36,6 +36,8 @@ @@ -6449,10 +3424,10 @@ index 1cdbb65da4a3..ef2bd22ffa78 100644 }; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h -index 08bec1755617..04860827d762 100644 +index e1fa2e80a15ac3..00f7a9f1f5b8a6 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h -@@ -627,6 +627,7 @@ unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx); +@@ -624,6 +624,7 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context); SR(DPPCLK_DTO_CTRL), DCCG_SRII(DTO_PARAM, DPPCLK, 0), \ DCCG_SRII(DTO_PARAM, DPPCLK, 1), DCCG_SRII(DTO_PARAM, DPPCLK, 2), \ DCCG_SRII(DTO_PARAM, DPPCLK, 3), DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \ @@ -6460,20 +3435,8 @@ index 08bec1755617..04860827d762 100644 SR(PHYASYMCLK_CLOCK_CNTL), SR(PHYBSYMCLK_CLOCK_CNTL), \ SR(PHYCSYMCLK_CLOCK_CNTL), SR(PHYDSYMCLK_CLOCK_CNTL), \ SR(DPSTREAMCLK_CNTL), SR(HDMISTREAMCLK_CNTL), \ -diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h -index 1c603b12957f..e838f7c1269c 100644 ---- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h -+++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h -@@ -36,6 +36,7 @@ - #define DP_BRANCH_DEVICE_ID_006037 0x006037 - #define DP_BRANCH_DEVICE_ID_001CF8 0x001CF8 - #define DP_BRANCH_DEVICE_ID_0060AD 0x0060AD -+#define DP_BRANCH_DEVICE_ID_2B02F0 0x2B02F0 /* Chrontel CH7218 */ - #define DP_BRANCH_HW_REV_10 0x10 - #define DP_BRANCH_HW_REV_20 0x20 - diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h -index 177acb0574f1..53df1349bea2 100644 +index 177acb0574f1cd..53df1349bea222 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -35,7 +35,7 @@ @@ -6495,7 +3458,7 @@ index 177acb0574f1..53df1349bea2 100644 #define DC_LOG_DML(...) pr_debug("[DML]:"__VA_ARGS__) #define DC_LOG_EVENT_MODE_SET(...) drm_dbg_kms((DC_LOGGER)->dev, __VA_ARGS__) diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h -index 3a2c2d2fb629..662e6c963256 100644 +index 3a2c2d2fb6291f..662e6c963256c0 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -42,6 +42,7 @@ enum signal_type { @@ -6532,30 +3495,8 @@ index 3a2c2d2fb629..662e6c963256 100644 } static inline bool dc_is_dp_sst_signal(enum signal_type signal) -diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c -index 1aae46d703ba..db197cf048e1 100644 ---- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c -+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c -@@ -27,6 +27,7 @@ - #include "dc.h" - #include "mod_freesync.h" - #include "core_types.h" -+#include "mod_info_packet.h" - - #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 - -@@ -955,6 +956,9 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, - return; - - switch (packet_type) { -+ case PACKET_TYPE_VTEM: -+ mod_build_vtem_infopacket(stream, vrr, infopacket); -+ break; - case PACKET_TYPE_FS_V3: - build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket, stream->freesync_on_desktop); - break; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c -index ca402ddcdacc..d6cba97f6375 100644 +index ca402ddcdacc82..d6cba97f637596 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -584,6 +584,7 @@ enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode( @@ -6566,1088 +3507,303 @@ index ca402ddcdacc..d6cba97f6375 100644 mode = MOD_HDCP_MODE_DEFAULT; break; case SIGNAL_TYPE_EDP: -diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h -index ddd64b7e4c04..9d767e6fc977 100644 ---- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h -+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h -@@ -33,11 +33,13 @@ struct dc_stream_state; - struct dc_info_packet; - struct mod_vrr_params; +diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h +index b344acefc60668..3969abd2fdb7ee 100644 +--- a/drivers/gpu/drm/amd/include/atombios.h ++++ b/drivers/gpu/drm/amd/include/atombios.h +@@ -1588,6 +1588,7 @@ typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 + #define ATOM_TRANSMITTER_DIGMODE_V6_DP 0 + #define ATOM_TRANSMITTER_DIGMODE_V6_DVI 2 + #define ATOM_TRANSMITTER_DIGMODE_V6_HDMI 3 ++#define ATOM_TRANSMITTER_DIGMODE_V6_HDMI_FRL 4 + #define ATOM_TRANSMITTER_DIGMODE_V6_DP_MST 5 -+#define VTEM_BRR_MAX 1023 -+ - void set_vsc_packet_colorimetry_data( - const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, - enum dc_color_space cs, -- enum color_transfer_func tf); -+ enum color_transfer_func tf);\ - - void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, -@@ -47,12 +49,17 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet); - -+void mod_build_vtem_infopacket(const struct dc_stream_state *stream, -+ const struct mod_vrr_params *vrr, -+ struct dc_info_packet *infopacket); -+ - enum adaptive_sync_type { -- ADAPTIVE_SYNC_TYPE_NONE = 0, -- ADAPTIVE_SYNC_TYPE_DP = 1, -- FREESYNC_TYPE_PCON_IN_WHITELIST = 2, -- FREESYNC_TYPE_PCON_NOT_IN_WHITELIST = 3, -- ADAPTIVE_SYNC_TYPE_EDP = 4, -+ ADAPTIVE_SYNC_TYPE_NONE = 0, -+ ADAPTIVE_SYNC_TYPE_DP = 1, -+ ADAPTIVE_SYNC_TYPE_PCON_ALLOWED = 2, -+ ADAPTIVE_SYNC_TYPE_PCON_NOT_ALLOWED = 3, -+ ADAPTIVE_SYNC_TYPE_EDP = 4, -+ ADAPTIVE_SYNC_TYPE_HDMI = 5, - }; - - enum adaptive_sync_sdp_version { -diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c -index 00473c6284d5..7dcea43ba2c4 100644 ---- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c -+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c -@@ -48,8 +48,12 @@ enum vsc_packet_revision { - vsc_packet_rev7 = 7, - }; - -+#define HDMI_INFOFRAME_TYPE_EMP 0x7F - #define HDMI_INFOFRAME_TYPE_VENDOR 0x81 --#define HF_VSIF_VERSION 1 -+#define HDMI_INFOFRAME_LENGTH_MASK 0x1F -+#define HF_VSIF_VERSION 1 -+#define HF_VSIF_3D_BIT 0 -+#define HF_VSIF_ALLM_BIT 1 - - // VTEM Byte Offset - #define VTEM_PB0 0 -@@ -60,64 +64,51 @@ enum vsc_packet_revision { - #define VTEM_PB5 5 - #define VTEM_PB6 6 - --#define VTEM_MD0 7 --#define VTEM_MD1 8 --#define VTEM_MD2 9 --#define VTEM_MD3 10 -- -- --// VTEM Byte Masks --//PB0 --#define MASK_VTEM_PB0__RESERVED0 0x01 --#define MASK_VTEM_PB0__SYNC 0x02 --#define MASK_VTEM_PB0__VFR 0x04 --#define MASK_VTEM_PB0__AFR 0x08 --#define MASK_VTEM_PB0__DS_TYPE 0x30 -- //0: Periodic pseudo-static EM Data Set -- //1: Periodic dynamic EM Data Set -- //2: Unique EM Data Set -- //3: Reserved --#define MASK_VTEM_PB0__END 0x40 --#define MASK_VTEM_PB0__NEW 0x80 -- --//PB1 --#define MASK_VTEM_PB1__RESERVED1 0xFF -- --//PB2 --#define MASK_VTEM_PB2__ORGANIZATION_ID 0xFF -- //0: This is a Vendor Specific EM Data Set -- //1: This EM Data Set is defined by This Specification (HDMI 2.1 r102.clean) -- //2: This EM Data Set is defined by CTA-861-G -- //3: This EM Data Set is defined by VESA --//PB3 --#define MASK_VTEM_PB3__DATA_SET_TAG_MSB 0xFF --//PB4 --#define MASK_VTEM_PB4__DATA_SET_TAG_LSB 0xFF --//PB5 --#define MASK_VTEM_PB5__DATA_SET_LENGTH_MSB 0xFF --//PB6 --#define MASK_VTEM_PB6__DATA_SET_LENGTH_LSB 0xFF -- -- -- --//PB7-27 (20 bytes): --//PB7 = MD0 --#define MASK_VTEM_MD0__VRR_EN 0x01 --#define MASK_VTEM_MD0__M_CONST 0x02 --#define MASK_VTEM_MD0__QMS_EN 0x04 --#define MASK_VTEM_MD0__RESERVED2 0x08 --#define MASK_VTEM_MD0__FVA_FACTOR_M1 0xF0 -- --//MD1 --#define MASK_VTEM_MD1__BASE_VFRONT 0xFF -- --//MD2 --#define MASK_VTEM_MD2__BASE_REFRESH_RATE_98 0x03 --#define MASK_VTEM_MD2__RB 0x04 --#define MASK_VTEM_MD2__NEXT_TFR 0xF8 -- --//MD3 --#define MASK_VTEM_MD3__BASE_REFRESH_RATE_07 0xFF -+#define VTEM_ORG_ID 1 -+#define VTEM_DATA_SET_TAG 1 -+#define VTEM_DATA_SET_LENGTH 4 -+ -+#define VTEM_M_CONST 0 -+#define VTEM_FVA_FACTOR 0 -+ -+#define VTEM_BRR_MASK_UPPER 0x03 -+#define VTEM_BRR_MASK_LOWER 0xFF -+ -+/* VTEM Byte Offset */ -+#define VTEM_PB0 0 -+#define VTEM_PB1 1 -+#define VTEM_PB2 2 -+#define VTEM_PB3 3 -+#define VTEM_PB4 4 -+#define VTEM_PB5 5 -+#define VTEM_PB6 6 -+ -+#define VTEM_MD0 7 -+#define VTEM_MD1 8 -+#define VTEM_MD2 9 -+#define VTEM_MD3 10 -+ -+/* Extended Metadata Packet */ -+/* Header */ -+#define EMP_LAST_BIT 6 -+#define EMP_FIRST_BIT 7 -+/* PB0 */ -+#define EMP_SNC_BIT 1 -+#define EMP_VFR_BIT 2 -+#define EMP_AFR_BIT 3 -+#define EMP_DST_BIT 4 -+#define EMP_END_BIT 6 -+#define EMP_NEW_BIT 7 -+/* PB7 = MD0 */ -+#define VTEM_VRR_BIT 0 -+#define VTEM_M_CONST_BIT 1 -+#define VTEM_FVA_BIT 4 -+/* MD1 Base_Vfront */ -+/* MD2 */ -+#define VTEM_BRR_UPPER_BIT 0 -+#define VTEM_RB_BIT 2 -+/* MD3 BRR Lower */ -+ - - enum ColorimetryRGBDP { - ColorimetryRGB_DP_sRGB = 0, -@@ -496,9 +487,29 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + //ucHPDSel +diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h +index 3d083010e734a3..6949baf76737aa 100644 +--- a/drivers/gpu/drm/amd/include/atomfirmware.h ++++ b/drivers/gpu/drm/amd/include/atomfirmware.h +@@ -97,6 +97,7 @@ enum atom_encode_mode_def + ATOM_ENCODER_MODE_LVDS =1, + ATOM_ENCODER_MODE_DVI =2, + ATOM_ENCODER_MODE_HDMI =3, ++ ATOM_ENCODER_MODE_HDMI_FRL =4, + ATOM_ENCODER_MODE_DP_AUDIO =5, + ATOM_ENCODER_MODE_DP_MST =5, + ATOM_ENCODER_MODE_CRT =15, + +From dfd8772501865cd2b031946e7199ba178fdbf9ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 21:05:17 +0100 +Subject: [PATCH 002/103] Restore HDMI FRL on DCN314 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit: +- Instantiates HPO HDMI encoders +- Restores HPO HDMI registers to the register list +- Implements set_hdmistreamclk + +Signed-off-by: Michał Kopeć +--- + .../amd/display/dc/dccg/dcn314/dcn314_dccg.c | 54 ++ + .../amd/display/dc/dccg/dcn314/dcn314_dccg.h | 6 + + .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 4 + + .../dc/resource/dcn314/dcn314_resource.c | 85 +++ + .../include/asic_reg/dcn/dcn_3_1_4_offset.h | 113 ++++ + .../include/asic_reg/dcn/dcn_3_1_4_sh_mask.h | 544 ++++++++++++++++++ + 6 files changed, 806 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c +index ef3db6beba25cd..a183950fbdd305 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.c +@@ -285,6 +285,59 @@ void dccg314_set_dpstreamclk( } } -+static bool is_hdmi_vic_mode(const struct dc_stream_state *stream) ++static void dccg314_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) +{ -+ if (stream->timing.hdmi_vic == 0) -+ return false; ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + -+ if (stream->timing.h_total < 3840 || -+ stream->timing.v_total < 2160) -+ return false; -+ -+ /* 3D/ALLM forces HDMI VIC -> CTA VIC translation */ -+ if (stream->view_format != VIEW_3D_FORMAT_NONE) -+ return false; -+ -+ if (stream->hdmi_allm_active) -+ return false; -+ -+ return true; ++ /* enabled to select one of the DTBCLKs for pipe */ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, ++ HDMISTREAMCLK0_GATE_DISABLE, 1); ++ } ++ REG_UPDATE_2(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_SRC_SEL, otg_inst, ++ HDMISTREAMCLK0_EN, 1); ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } +} + - /** - * mod_build_hf_vsif_infopacket - Prepare HDMI Vendor Specific info frame. - * Follows HDMI Spec to build up Vendor Specific info frame -+ * Conforms to h14b-vsif or hf-vsif based on the capabilities - * - * @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.) - * @info_packet: output structure where to store VSIF -@@ -506,63 +517,76 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet) ++static void dccg314_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ REG_UPDATE(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_EN, 0); ++ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, ++ HDMISTREAMCLK0_GATE_DISABLE, 0); ++ } ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++void dccg314_set_hdmistreamclk( ++ struct dccg *dccg, ++ enum streamclk_source src, ++ int otg_inst, ++ int hdmi_hpo_inst) ++{ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ if (src == REFCLK) ++ dccg314_disable_hdmistreamclk(dccg, hdmi_hpo_inst); ++ else ++ dccg314_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); ++} ++ + static void dccg314_init(struct dccg *dccg) { -- unsigned int length = 5; - bool hdmi_vic_mode = false; -+ bool allm = false; -+ bool stereo = false; - uint8_t checksum = 0; -- uint32_t i = 0; -+ uint8_t offset = 0; -+ uint8_t i = 0; -+ uint8_t length = 5; -+ uint32_t oui = HDMI_IEEE_OUI; - enum dc_timing_3d_format format; + int otg_inst; +@@ -359,6 +412,7 @@ static const struct dccg_funcs dccg314_funcs = { + .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, + .dccg_init = dccg314_init, + .set_dpstreamclk = dccg314_set_dpstreamclk, ++ .set_hdmistreamclk = dccg314_set_hdmistreamclk, + .enable_symclk32_se = dccg31_enable_symclk32_se, + .disable_symclk32_se = dccg31_disable_symclk32_se, + .enable_symclk32_le = dccg31_enable_symclk32_le, +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h +index a609635f35dbdd..1757db56d1399d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h +@@ -208,4 +208,10 @@ void dccg314_set_dpstreamclk( + int otg_inst, + int dp_hpo_inst); - info_packet->valid = false; -- format = stream->timing.timing_3d_format; -- if (stream->view_format == VIEW_3D_FORMAT_NONE) -- format = TIMING_3D_FORMAT_NONE; ++void dccg314_set_hdmistreamclk( ++ struct dccg *dccg, ++ enum streamclk_source src, ++ int otg_inst, ++ int hdmi_hpo_inst); ++ + #endif //__DCN314_DCCG_H__ +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index c8ff8ae85a0306..c3c0a59a00f2d2 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -3034,6 +3034,7 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) + struct dccg *dccg = dc->res_pool->dccg; + enum phyd32clk_clock_source phyd32clk; + int dp_hpo_inst; ++ int hdmi_hpo_inst = 0; -- if (stream->timing.hdmi_vic != 0 -- && stream->timing.h_total >= 3840 -- && stream->timing.v_total >= 2160 -- && format == TIMING_3D_FORMAT_NONE) -- hdmi_vic_mode = true; -+ allm = stream->hdmi_allm_active; -+ format = stream->view_format == VIEW_3D_FORMAT_NONE ? -+ TIMING_3D_FORMAT_NONE : -+ stream->timing.timing_3d_format; -+ stereo = format != TIMING_3D_FORMAT_NONE; -+ hdmi_vic_mode = is_hdmi_vic_mode(stream); - -- if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode) -+ if (!stereo && !hdmi_vic_mode && !allm) - return; - -- info_packet->sb[1] = 0x03; -- info_packet->sb[2] = 0x0C; -- info_packet->sb[3] = 0x00; -+ if (allm) -+ oui = HDMI_FORUM_IEEE_OUI; - -- if (format != TIMING_3D_FORMAT_NONE) -- info_packet->sb[4] = (2 << 5); -+ info_packet->sb[1] = oui & 0xFF; -+ info_packet->sb[2] = (oui >> 8) & 0xFF; -+ info_packet->sb[3] = (oui >> 16) & 0xFF; - -- else if (hdmi_vic_mode) -- info_packet->sb[4] = (1 << 5); -+ if (oui == HDMI_FORUM_IEEE_OUI) { -+ offset = 2; -+ length += 2; -+ info_packet->sb[4] = HF_VSIF_VERSION; -+ info_packet->sb[5] = stereo << HF_VSIF_3D_BIT; -+ info_packet->sb[5] |= allm << HF_VSIF_ALLM_BIT; -+ } - -- switch (format) { -- case TIMING_3D_FORMAT_HW_FRAME_PACKING: -- case TIMING_3D_FORMAT_SW_FRAME_PACKING: -- info_packet->sb[5] = (0x0 << 4); -- break; -+ if (stereo) { -+ info_packet->sb[4 + offset] = (2 << 5); - -- case TIMING_3D_FORMAT_SIDE_BY_SIDE: -- case TIMING_3D_FORMAT_SBS_SW_PACKED: -- info_packet->sb[5] = (0x8 << 4); -- length = 6; -- break; -+ switch (format) { -+ case TIMING_3D_FORMAT_HW_FRAME_PACKING: -+ case TIMING_3D_FORMAT_SW_FRAME_PACKING: -+ info_packet->sb[5 + offset] = (0x0 << 4); -+ break; - -- case TIMING_3D_FORMAT_TOP_AND_BOTTOM: -- case TIMING_3D_FORMAT_TB_SW_PACKED: -- info_packet->sb[5] = (0x6 << 4); -- break; -+ case TIMING_3D_FORMAT_SIDE_BY_SIDE: -+ case TIMING_3D_FORMAT_SBS_SW_PACKED: -+ info_packet->sb[5 + offset] = (0x8 << 4); -+ ++length; -+ break; - -- default: -- break; -- } -+ case TIMING_3D_FORMAT_TOP_AND_BOTTOM: -+ case TIMING_3D_FORMAT_TB_SW_PACKED: -+ info_packet->sb[5 + offset] = (0x6 << 4); -+ break; -+ -+ default: -+ break; -+ } - -- if (hdmi_vic_mode) -+ /* Doesn't need the offset as it can't be used with hf-vsif */ -+ } else if (hdmi_vic_mode) { -+ info_packet->sb[4] = (1 << 5); - info_packet->sb[5] = stream->timing.hdmi_vic; -+ } - - info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; - info_packet->hb1 = 0x01; -- info_packet->hb2 = (uint8_t) (length); -+ info_packet->hb2 = length & HDMI_INFOFRAME_LENGTH_MASK; - - checksum += info_packet->hb0; - checksum += info_packet->hb1; -@@ -576,6 +600,92 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - info_packet->valid = true; - } - -+static void build_vtem_infopacket_header(struct dc_info_packet *infopacket) -+{ -+ uint8_t pb0 = 0; -+ -+ /* might need logic in the future */ -+ pb0 |= 0 << EMP_SNC_BIT; -+ pb0 |= 1 << EMP_VFR_BIT; -+ pb0 |= 0 << EMP_AFR_BIT; -+ pb0 |= 0 << EMP_DST_BIT; -+ pb0 |= 0 << EMP_END_BIT; -+ pb0 |= 1 << EMP_NEW_BIT; -+ -+ infopacket->hb0 = HDMI_INFOFRAME_TYPE_EMP; -+ infopacket->hb1 = (1 << EMP_FIRST_BIT) | (1 << EMP_LAST_BIT); -+ infopacket->hb2 = 0; // sequence -+ -+ infopacket->sb[VTEM_PB0] = pb0; -+ infopacket->sb[VTEM_PB2] = VTEM_ORG_ID; -+ infopacket->sb[VTEM_PB4] = VTEM_DATA_SET_TAG; -+ infopacket->sb[VTEM_PB6] = VTEM_DATA_SET_LENGTH; -+} -+ -+static void build_vtem_infopacket_data(const struct dc_stream_state *stream, -+ const struct mod_vrr_params *vrr, -+ struct dc_info_packet *infopacket) -+{ -+ unsigned int hblank = 0; -+ unsigned int brr = 0; -+ bool vrr_active = false; -+ bool rb = false; -+ -+ /* -+ * Enables FreeSync-like behavior by keeping HDMI VRR signalling active -+ * in fixed refresh rate conditions like normal desktop work/web browsing. -+ * Functinally behaves like non-VRR mode by keeping the actual refresh -+ * rate fixed. -+ */ -+ if (stream->freesync_on_desktop) { -+ vrr_active = vrr->state != VRR_STATE_DISABLED && -+ vrr->state != VRR_STATE_UNSUPPORTED; -+ } else { -+ vrr_active = vrr->state == VRR_STATE_ACTIVE_VARIABLE || -+ vrr->state == VRR_STATE_ACTIVE_FIXED; -+ } -+ -+ infopacket->sb[VTEM_MD0] = VTEM_M_CONST << VTEM_M_CONST_BIT; -+ infopacket->sb[VTEM_MD0] |= VTEM_FVA_FACTOR << VTEM_FVA_BIT; -+ infopacket->sb[VTEM_MD0] |= vrr_active << VTEM_VRR_BIT; -+ -+ infopacket->sb[VTEM_MD1] = 0; -+ infopacket->sb[VTEM_MD2] = 0; -+ infopacket->sb[VTEM_MD3] = 0; -+ -+ if (!vrr_active || is_hdmi_vic_mode(stream)) -+ return; -+ /* -+ * In accordance with CVT 1.2 and CVT 2.1: -+ * Reduced Blanking standard defines a fixed value of -+ * 160 for hblank, further reduced to 80 in RB2. RB3 uses -+ * fixed hblank of 80 pixels + up to 120 additional pixels -+ * in 8-pixel steps. -+ */ -+ hblank = stream->timing.h_total - stream->timing.h_addressable; -+ rb = (hblank >= 80 && hblank <= 200 && hblank % 8 == 0); -+ brr = div_u64(mod_freesync_calc_nominal_field_rate(stream), 1000000); -+ -+ if (brr > VTEM_BRR_MAX) { -+ infopacket->valid = false; -+ return; -+ } -+ -+ infopacket->sb[VTEM_MD1] = (uint8_t) stream->timing.v_front_porch; -+ infopacket->sb[VTEM_MD2] = rb << VTEM_RB_BIT; -+ infopacket->sb[VTEM_MD2] |= (brr >> 8) & VTEM_BRR_MASK_UPPER; -+ infopacket->sb[VTEM_MD3] = brr & VTEM_BRR_MASK_LOWER; -+} -+ -+void mod_build_vtem_infopacket(const struct dc_stream_state *stream, -+ const struct mod_vrr_params *vrr, -+ struct dc_info_packet *infopacket) -+{ -+ infopacket->valid = true; -+ build_vtem_infopacket_header(infopacket); -+ build_vtem_infopacket_data(stream, vrr, infopacket); -+} -+ - void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, - enum adaptive_sync_type asType, - const struct AS_Df_params *param, -@@ -590,7 +700,7 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, - if (stream != NULL) - mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet); - break; -- case FREESYNC_TYPE_PCON_IN_WHITELIST: -+ case ADAPTIVE_SYNC_TYPE_PCON_ALLOWED: - case ADAPTIVE_SYNC_TYPE_EDP: - if (stream && stream->link->replay_settings.config.replay_supported && - stream->link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY) -@@ -599,7 +709,8 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, - mod_build_adaptive_sync_infopacket_v1(info_packet); - break; - case ADAPTIVE_SYNC_TYPE_NONE: -- case FREESYNC_TYPE_PCON_NOT_IN_WHITELIST: -+ case ADAPTIVE_SYNC_TYPE_PCON_NOT_ALLOWED: -+ case ADAPTIVE_SYNC_TYPE_HDMI: - default: - break; - } -diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h -index ac2d3701e2bd..894e1e738ce0 100644 ---- a/drivers/gpu/drm/amd/include/amd_shared.h -+++ b/drivers/gpu/drm/amd/include/amd_shared.h -@@ -412,6 +412,12 @@ enum DC_DEBUG_MASK { - * @DC_SKIP_DETECTION_LT: (0x200000) If set, skip detection link training - */ - DC_SKIP_DETECTION_LT = 0x200000, -+ -+ /** -+ * @DC_OVERRIDE_PCON_VRR_ID_CHECK: (0x400000) If set, always return true if checking for -+ * PCON VRR compatibility and print it's ID in kernel log. -+ */ -+ DC_OVERRIDE_PCON_VRR_ID_CHECK = 0x400000, + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; + struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; +@@ -3057,6 +3058,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) + } else { + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + } ++ } else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { ++ hdmi_hpo_inst = pipe_ctx->stream_res.hpo_hdmi_stream_enc->inst; ++ dccg->funcs->set_hdmistreamclk(dccg, DTBCLK0, tg->inst, hdmi_hpo_inst); + } else { + if (dccg->funcs->enable_symclk_se) + dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +index 3ccde75a4ecbf1..3076b1d1709830 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +@@ -59,6 +59,8 @@ + #include "dcn314/dcn314_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn31/dcn31_apg.h" + #include "dcn31/dcn31_vpg.h" + #include "dcn31/dcn31_afmt.h" +@@ -457,6 +459,17 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) }; - enum amd_dpm_forced_level; -diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h -index 7fd906f10803..7de1451745cd 100644 ---- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h -+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h -@@ -12908,6 +12908,120 @@ - #define regDC_PERFMON22_PERFMON_LOW_BASE_IDX 3 ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; + #define hpo_dp_link_encoder_reg_list(id)\ + [id] = {\ +@@ -479,6 +492,18 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) + }; -+// addressBlock: dce_dc_hpo_hdmi_link_enc0_dispdec -+// base address: 0x2656c -+#define regHDMI_LINK_ENC_CONTROL 0x095b -+#define regHDMI_LINK_ENC_CONTROL_BASE_IDX 3 -+#define regHDMI_LINK_ENC_CLK_CTRL 0x095c -+#define regHDMI_LINK_ENC_CLK_CTRL_BASE_IDX 3 ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++}; + ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; + -+// addressBlock: dce_dc_hpo_hdmi_frl_enc0_dispdec -+// base address: 0x26594 -+#define regHDMI_FRL_ENC_CONFIG 0x0965 -+#define regHDMI_FRL_ENC_CONFIG_BASE_IDX 3 -+#define regHDMI_FRL_ENC_CONFIG2 0x0966 -+#define regHDMI_FRL_ENC_CONFIG2_BASE_IDX 3 -+#define regHDMI_FRL_ENC_METER_BUFFER_STATUS 0x0967 -+#define regHDMI_FRL_ENC_METER_BUFFER_STATUS_BASE_IDX 3 -+#define regHDMI_FRL_ENC_MEM_CTRL 0x0968 -+#define regHDMI_FRL_ENC_MEM_CTRL_BASE_IDX 3 ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; + -+ -+// addressBlock: dce_dc_hpo_hdmi_stream_enc0_dispdec -+// base address: 0x2634c -+#define regHDMI_STREAM_ENC_CLOCK_CONTROL 0x08d3 -+#define regHDMI_STREAM_ENC_CLOCK_CONTROL_BASE_IDX 3 -+#define regHDMI_STREAM_ENC_INPUT_MUX_CONTROL 0x08d5 -+#define regHDMI_STREAM_ENC_INPUT_MUX_CONTROL_BASE_IDX 3 -+#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0 0x08d6 -+#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0_BASE_IDX 3 -+#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1 0x08d7 -+#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1_BASE_IDX 3 -+#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2 0x08d8 -+#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2_BASE_IDX 3 -+ -+ -+// addressBlock: dce_dc_hpo_hdmi_tb_enc0_dispdec -+// base address: 0x2637c -+#define regHDMI_TB_ENC_CONTROL 0x08df -+#define regHDMI_TB_ENC_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_PIXEL_FORMAT 0x08e0 -+#define regHDMI_TB_ENC_PIXEL_FORMAT_BASE_IDX 3 -+#define regHDMI_TB_ENC_PACKET_CONTROL 0x08e1 -+#define regHDMI_TB_ENC_PACKET_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_PACKET_CONTROL 0x08e2 -+#define regHDMI_TB_ENC_ACR_PACKET_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_VBI_PACKET_CONTROL1 0x08e3 -+#define regHDMI_TB_ENC_VBI_PACKET_CONTROL1_BASE_IDX 3 -+#define regHDMI_TB_ENC_VBI_PACKET_CONTROL2 0x08e4 -+#define regHDMI_TB_ENC_VBI_PACKET_CONTROL2_BASE_IDX 3 -+#define regHDMI_TB_ENC_GC_CONTROL 0x08e5 -+#define regHDMI_TB_ENC_GC_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL0 0x08e6 -+#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL0_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL1 0x08e7 -+#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL1_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL2 0x08e8 -+#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL2_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET0_1_LINE 0x08e9 -+#define regHDMI_TB_ENC_GENERIC_PACKET0_1_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET2_3_LINE 0x08ea -+#define regHDMI_TB_ENC_GENERIC_PACKET2_3_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET4_5_LINE 0x08eb -+#define regHDMI_TB_ENC_GENERIC_PACKET4_5_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET6_7_LINE 0x08ec -+#define regHDMI_TB_ENC_GENERIC_PACKET6_7_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET8_9_LINE 0x08ed -+#define regHDMI_TB_ENC_GENERIC_PACKET8_9_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET10_11_LINE 0x08ee -+#define regHDMI_TB_ENC_GENERIC_PACKET10_11_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET12_13_LINE 0x08ef -+#define regHDMI_TB_ENC_GENERIC_PACKET12_13_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_GENERIC_PACKET14_LINE 0x08f0 -+#define regHDMI_TB_ENC_GENERIC_PACKET14_LINE_BASE_IDX 3 -+#define regHDMI_TB_ENC_DB_CONTROL 0x08f1 -+#define regHDMI_TB_ENC_DB_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_32_0 0x08f2 -+#define regHDMI_TB_ENC_ACR_32_0_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_32_1 0x08f3 -+#define regHDMI_TB_ENC_ACR_32_1_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_44_0 0x08f4 -+#define regHDMI_TB_ENC_ACR_44_0_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_44_1 0x08f5 -+#define regHDMI_TB_ENC_ACR_44_1_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_48_0 0x08f6 -+#define regHDMI_TB_ENC_ACR_48_0_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_48_1 0x08f7 -+#define regHDMI_TB_ENC_ACR_48_1_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_STATUS_0 0x08f8 -+#define regHDMI_TB_ENC_ACR_STATUS_0_BASE_IDX 3 -+#define regHDMI_TB_ENC_ACR_STATUS_1 0x08f9 -+#define regHDMI_TB_ENC_ACR_STATUS_1_BASE_IDX 3 -+#define regHDMI_TB_ENC_BUFFER_CONTROL 0x08fb -+#define regHDMI_TB_ENC_BUFFER_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_MEM_CTRL 0x08fe -+#define regHDMI_TB_ENC_MEM_CTRL_BASE_IDX 3 -+#define regHDMI_TB_ENC_METADATA_PACKET_CONTROL 0x08ff -+#define regHDMI_TB_ENC_METADATA_PACKET_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_H_ACTIVE_BLANK 0x0900 -+#define regHDMI_TB_ENC_H_ACTIVE_BLANK_BASE_IDX 3 -+#define regHDMI_TB_ENC_HC_ACTIVE_BLANK 0x0901 -+#define regHDMI_TB_ENC_HC_ACTIVE_BLANK_BASE_IDX 3 -+#define regHDMI_TB_ENC_CRC_CNTL 0x0903 -+#define regHDMI_TB_ENC_CRC_CNTL_BASE_IDX 3 -+#define regHDMI_TB_ENC_CRC_RESULT_0 0x0904 -+#define regHDMI_TB_ENC_CRC_RESULT_0_BASE_IDX 3 -+#define regHDMI_TB_ENC_ENCRYPTION_CONTROL 0x0907 -+#define regHDMI_TB_ENC_ENCRYPTION_CONTROL_BASE_IDX 3 -+#define regHDMI_TB_ENC_MODE 0x0908 -+#define regHDMI_TB_ENC_MODE_BASE_IDX 3 -+#define regHDMI_TB_ENC_INPUT_FIFO_STATUS 0x0909 -+#define regHDMI_TB_ENC_INPUT_FIFO_STATUS_BASE_IDX 3 -+#define regHDMI_TB_ENC_CRC_RESULT_1 0x090a -+#define regHDMI_TB_ENC_CRC_RESULT_1_BASE_IDX 3 -+ -+ - // addressBlock: dce_dc_hpo_hdmi_stream_enc0_afmt_afmt_dispdec - // base address: 0x2646c - #define regAFMT5_AFMT_VBI_PACKET_CONTROL 0x091c -diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h -index 07fbfafe6056..21ae70bf0eee 100644 ---- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h -+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h -@@ -48392,6 +48392,507 @@ - #define DC_PERFMON22_PERFMON_LOW__PERFMON_LOW_MASK 0xFFFFFFFFL + #define dpp_regs(id)\ + [id] = {\ + DPP_REG_LIST_DCN30(id),\ +@@ -831,6 +856,8 @@ static const struct resource_caps res_cap_dcn314 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, +@@ -1363,6 +1390,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } ++static struct hpo_hdmi_stream_encoder *dcn314_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): ++ * VPG[9] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 9; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1381,6 +1446,24 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } -+#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_ENABLE__SHIFT 0x0 -+#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_SOFT_RESET__SHIFT 0x4 -+#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_ENABLE_MASK 0x00000001L -+#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_SOFT_RESET_MASK 0x00000010L -+#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_EN__SHIFT 0x0 -+#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_ON_HDMICHARCLK__SHIFT 0x1 -+#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_EN_MASK 0x00000001L -+#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_ON_HDMICHARCLK_MASK 0x00000002L ++static struct hpo_hdmi_link_encoder *dcn314_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; + ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ + -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE_COUNT__SHIFT 0x0 -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_TRAINING_ENABLE__SHIFT 0x1 -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_SCRAMBLER_DISABLE__SHIFT 0x2 -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE0_TRAINING_PATTERN__SHIFT 0x10 -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE1_TRAINING_PATTERN__SHIFT 0x14 -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE2_TRAINING_PATTERN__SHIFT 0x18 -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE3_TRAINING_PATTERN__SHIFT 0x1c -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE_COUNT_MASK 0x00000001L -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_TRAINING_ENABLE_MASK 0x00000002L -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_SCRAMBLER_DISABLE_MASK 0x00000004L -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE0_TRAINING_PATTERN_MASK 0x000F0000L -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE1_TRAINING_PATTERN_MASK 0x00F00000L -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE2_TRAINING_PATTERN_MASK 0x0F000000L -+#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE3_TRAINING_PATTERN_MASK 0xF0000000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE__SHIFT 0x0 -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_THRESHOLD__SHIFT 0xc -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_CAL_EN__SHIFT 0x18 -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_RC_COMPRESS_DISABLE__SHIFT 0x19 -+#define HDMI_FRL_ENC_CONFIG2__HDMI_FRL_HDMISTREAMCLK_DB_SEL__SHIFT 0x1a -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE_RESET__SHIFT 0x1c -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_EXCEED_STATUS__SHIFT 0x1d -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_METER_BUFFER_OVERFLOW_STATUS__SHIFT 0x1e -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE_MASK 0x000001FFL -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_THRESHOLD_MASK 0x001FF000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_CAL_EN_MASK 0x01000000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_RC_COMPRESS_DISABLE_MASK 0x02000000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_FRL_HDMISTREAMCLK_DB_SEL_MASK 0x0C000000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE_RESET_MASK 0x10000000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_EXCEED_STATUS_MASK 0x20000000L -+#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_METER_BUFFER_OVERFLOW_STATUS_MASK 0x40000000L -+#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_MAX_METER_BUFFER_LEVEL__SHIFT 0x0 -+#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_METER_BUFFER_MAX_LEVEL_RESET__SHIFT 0x1f -+#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_MAX_METER_BUFFER_LEVEL_MASK 0x0000007FL -+#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_METER_BUFFER_MAX_LEVEL_RESET_MASK 0x80000000L -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_DIS__SHIFT 0x0 -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_FORCE__SHIFT 0x1 -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_STATE__SHIFT 0x4 -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE__SHIFT 0x8 -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_DIS_MASK 0x00000001L -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_FORCE_MASK 0x00000006L -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_STATE_MASK 0x00000030L -+#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE_MASK 0x00000300L ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); + ++ return &hpo_hdmi_enc30->base; ++} + -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_EN__SHIFT 0x0 -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_DISPCLK__SHIFT 0x4 -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_SOCCLK__SHIFT 0x8 -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_HDMISTREAMCLK__SHIFT 0xc -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_EN_MASK 0x00000001L -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_DISPCLK_MASK 0x00000010L -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_SOCCLK_MASK 0x00000100L -+#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_HDMISTREAMCLK_MASK 0x00001000L -+#define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL__SHIFT 0x0 -+#define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL_MASK 0x00000007L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_VIDEO_STREAM_ACTIVE__SHIFT 0x18 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_VIDEO_STREAM_ACTIVE_MASK 0x01000000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR_MASK 0x30000000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x0 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x1 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x2 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_OVERWRITE_LEVEL__SHIFT 0x4 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MINIMUM_LEVEL__SHIFT 0xc -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MAXIMUM_LEVEL__SHIFT 0x10 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x18 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CALIBRATED__SHIFT 0x1f -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000001L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECAL_AVERAGE_MASK 0x00000002L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECOMP_MINMAX_MASK 0x00000004L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_OVERWRITE_LEVEL_MASK 0x000003F0L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MINIMUM_LEVEL_MASK 0x0000F000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MAXIMUM_LEVEL_MASK 0x001F0000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CAL_AVERAGE_LEVEL_MASK 0x3F000000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CALIBRATED_MASK 0x80000000L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_START_LEVEL__SHIFT 0x0 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_CLOCK_SRC__SHIFT 0x5 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_PENDING__SHIFT 0x8 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_DISABLE__SHIFT 0xc -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_START_LEVEL_MASK 0x0000001FL -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_CLOCK_SRC_MASK 0x00000020L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_PENDING_MASK 0x00000100L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_DISABLE_MASK 0x00001000L -+ -+ -+#define HDMI_TB_ENC_CONTROL__HDMI_TB_ENC_EN__SHIFT 0x0 -+#define HDMI_TB_ENC_CONTROL__HDMI_RESET__SHIFT 0x4 -+#define HDMI_TB_ENC_CONTROL__HDMI_RESET_DONE__SHIFT 0x8 -+#define HDMI_TB_ENC_CONTROL__HDMI_TB_ENC_EN_MASK 0x00000001L -+#define HDMI_TB_ENC_CONTROL__HDMI_RESET_MASK 0x00000010L -+#define HDMI_TB_ENC_CONTROL__HDMI_RESET_DONE_MASK 0x00000100L -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_ENABLE__SHIFT 0x0 -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_DEPTH__SHIFT 0x8 -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_PIXEL_ENCODING__SHIFT 0x10 -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DSC_MODE__SHIFT 0x18 -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_ENABLE_MASK 0x00000001L -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_DEPTH_MASK 0x00000300L -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_PIXEL_ENCODING_MASK 0x00030000L -+#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DSC_MODE_MASK 0x03000000L -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_PACKETS_PER_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_ISLANDS_PER_LINE__SHIFT 0x8 -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_OVERFLOW__SHIFT 0xc -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_TB_ENC_PACKET_ERROR_CLEAR__SHIFT 0x10 -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_PACKETS_PER_LINE_MASK 0x0000001FL -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_ISLANDS_PER_LINE_MASK 0x00000300L -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_OVERFLOW_MASK 0x00001000L -+#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_TB_ENC_PACKET_ERROR_CLEAR_MASK 0x00010000L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SEND__SHIFT 0x0 -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_CONT__SHIFT 0x1 -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SELECT__SHIFT 0x4 -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE__SHIFT 0x8 -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND__SHIFT 0xc -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE__SHIFT 0x10 -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY__SHIFT 0x1f -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SEND_MASK 0x00000001L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_CONT_MASK 0x00000002L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SELECT_MASK 0x00000030L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE_MASK 0x00000100L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK 0x00001000L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE_MASK 0x00070000L -+#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY_MASK 0x80000000L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_SEND__SHIFT 0x0 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_CONT__SHIFT 0x1 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_SEND__SHIFT 0x4 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_CONT__SHIFT 0x5 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_LINE_REFERENCE__SHIFT 0x6 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_SEND__SHIFT 0x8 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_LINE_REFERENCE__SHIFT 0x9 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_SEND__SHIFT 0xc -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_CONT__SHIFT 0xd -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE_REFERENCE__SHIFT 0xe -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_SEND_MASK 0x00000001L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_CONT_MASK 0x00000002L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_SEND_MASK 0x00000010L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_CONT_MASK 0x00000020L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_LINE_REFERENCE_MASK 0x00000040L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_SEND_MASK 0x00000100L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_LINE_REFERENCE_MASK 0x00000200L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_SEND_MASK 0x00001000L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_CONT_MASK 0x00002000L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE_REFERENCE_MASK 0x00004000L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ISRC_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ACP_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ISRC_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ACP_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE__SHIFT 0x0 -+#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE_CONT__SHIFT 0x2 -+#define HDMI_TB_ENC_GC_CONTROL__HDMI_DEFAULT_PHASE__SHIFT 0x4 -+#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE_MASK 0x00000001L -+#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE_CONT_MASK 0x00000004L -+#define HDMI_TB_ENC_GC_CONTROL__HDMI_DEFAULT_PHASE_MASK 0x00000010L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT__SHIFT 0x1 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LOCK_EN__SHIFT 0x2 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_REFERENCE__SHIFT 0x3 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND__SHIFT 0x4 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT__SHIFT 0x5 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LOCK_EN__SHIFT 0x6 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_REFERENCE__SHIFT 0x7 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_SEND__SHIFT 0x8 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_CONT__SHIFT 0x9 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LOCK_EN__SHIFT 0xa -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LINE_REFERENCE__SHIFT 0xb -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_SEND__SHIFT 0xc -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_CONT__SHIFT 0xd -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LOCK_EN__SHIFT 0xe -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LINE_REFERENCE__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_SEND__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_CONT__SHIFT 0x11 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LOCK_EN__SHIFT 0x12 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LINE_REFERENCE__SHIFT 0x13 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_SEND__SHIFT 0x14 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_CONT__SHIFT 0x15 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LOCK_EN__SHIFT 0x16 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LINE_REFERENCE__SHIFT 0x17 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_SEND__SHIFT 0x18 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_CONT__SHIFT 0x19 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LOCK_EN__SHIFT 0x1a -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LINE_REFERENCE__SHIFT 0x1b -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_SEND__SHIFT 0x1c -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_CONT__SHIFT 0x1d -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LOCK_EN__SHIFT 0x1e -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LINE_REFERENCE__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND_MASK 0x00000001L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT_MASK 0x00000002L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LOCK_EN_MASK 0x00000004L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_REFERENCE_MASK 0x00000008L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND_MASK 0x00000010L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT_MASK 0x00000020L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LOCK_EN_MASK 0x00000040L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_REFERENCE_MASK 0x00000080L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_SEND_MASK 0x00000100L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_CONT_MASK 0x00000200L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LOCK_EN_MASK 0x00000400L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LINE_REFERENCE_MASK 0x00000800L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_SEND_MASK 0x00001000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_CONT_MASK 0x00002000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LOCK_EN_MASK 0x00004000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LINE_REFERENCE_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_SEND_MASK 0x00010000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_CONT_MASK 0x00020000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LOCK_EN_MASK 0x00040000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LINE_REFERENCE_MASK 0x00080000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_SEND_MASK 0x00100000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_CONT_MASK 0x00200000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LOCK_EN_MASK 0x00400000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LINE_REFERENCE_MASK 0x00800000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_SEND_MASK 0x01000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_CONT_MASK 0x02000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LOCK_EN_MASK 0x04000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LINE_REFERENCE_MASK 0x08000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_SEND_MASK 0x10000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_CONT_MASK 0x20000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LOCK_EN_MASK 0x40000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LINE_REFERENCE_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_SEND__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_CONT__SHIFT 0x1 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LOCK_EN__SHIFT 0x2 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LINE_REFERENCE__SHIFT 0x3 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_SEND__SHIFT 0x4 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_CONT__SHIFT 0x5 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LOCK_EN__SHIFT 0x6 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LINE_REFERENCE__SHIFT 0x7 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_SEND__SHIFT 0x8 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_CONT__SHIFT 0x9 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LOCK_EN__SHIFT 0xa -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LINE_REFERENCE__SHIFT 0xb -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_SEND__SHIFT 0xc -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_CONT__SHIFT 0xd -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LOCK_EN__SHIFT 0xe -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LINE_REFERENCE__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_SEND__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_CONT__SHIFT 0x11 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LOCK_EN__SHIFT 0x12 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LINE_REFERENCE__SHIFT 0x13 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_SEND__SHIFT 0x14 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_CONT__SHIFT 0x15 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LOCK_EN__SHIFT 0x16 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LINE_REFERENCE__SHIFT 0x17 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_SEND__SHIFT 0x18 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_CONT__SHIFT 0x19 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LOCK_EN__SHIFT 0x1a -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LINE_REFERENCE__SHIFT 0x1b -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_SEND_MASK 0x00000001L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_CONT_MASK 0x00000002L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LOCK_EN_MASK 0x00000004L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LINE_REFERENCE_MASK 0x00000008L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_SEND_MASK 0x00000010L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_CONT_MASK 0x00000020L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LOCK_EN_MASK 0x00000040L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LINE_REFERENCE_MASK 0x00000080L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_SEND_MASK 0x00000100L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_CONT_MASK 0x00000200L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LOCK_EN_MASK 0x00000400L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LINE_REFERENCE_MASK 0x00000800L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_SEND_MASK 0x00001000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_CONT_MASK 0x00002000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LOCK_EN_MASK 0x00004000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LINE_REFERENCE_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_SEND_MASK 0x00010000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_CONT_MASK 0x00020000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LOCK_EN_MASK 0x00040000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LINE_REFERENCE_MASK 0x00080000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_SEND_MASK 0x00100000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_CONT_MASK 0x00200000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LOCK_EN_MASK 0x00400000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LINE_REFERENCE_MASK 0x00800000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_SEND_MASK 0x01000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_CONT_MASK 0x02000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LOCK_EN_MASK 0x04000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LINE_REFERENCE_MASK 0x08000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND_PENDING__SHIFT 0x1 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND__SHIFT 0x2 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND_PENDING__SHIFT 0x3 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND__SHIFT 0x4 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND_PENDING__SHIFT 0x5 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND__SHIFT 0x6 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND_PENDING__SHIFT 0x7 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND__SHIFT 0x8 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND_PENDING__SHIFT 0x9 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND__SHIFT 0xa -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND_PENDING__SHIFT 0xb -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND__SHIFT 0xc -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND_PENDING__SHIFT 0xd -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND__SHIFT 0xe -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND_PENDING__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND_PENDING__SHIFT 0x11 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND__SHIFT 0x12 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND_PENDING__SHIFT 0x13 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND__SHIFT 0x14 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND_PENDING__SHIFT 0x15 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND__SHIFT 0x16 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND_PENDING__SHIFT 0x17 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND__SHIFT 0x18 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND_PENDING__SHIFT 0x19 -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND__SHIFT 0x1a -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND_PENDING__SHIFT 0x1b -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND__SHIFT 0x1c -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND_PENDING__SHIFT 0x1d -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND_MASK 0x00000001L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND_PENDING_MASK 0x00000002L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND_MASK 0x00000004L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND_PENDING_MASK 0x00000008L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND_MASK 0x00000010L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND_PENDING_MASK 0x00000020L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND_MASK 0x00000040L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND_PENDING_MASK 0x00000080L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND_MASK 0x00000100L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND_PENDING_MASK 0x00000200L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND_MASK 0x00000400L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND_PENDING_MASK 0x00000800L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND_MASK 0x00001000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND_PENDING_MASK 0x00002000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND_MASK 0x00004000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND_PENDING_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND_MASK 0x00010000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND_PENDING_MASK 0x00020000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND_MASK 0x00040000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND_PENDING_MASK 0x00080000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND_MASK 0x00100000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND_PENDING_MASK 0x00200000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND_MASK 0x00400000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND_PENDING_MASK 0x00800000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND_MASK 0x01000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND_PENDING_MASK 0x02000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND_MASK 0x04000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND_PENDING_MASK 0x08000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND_MASK 0x10000000L -+#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND_PENDING_MASK 0x20000000L -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_EMP__SHIFT 0x1f -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_LINE_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_EMP_MASK 0x80000000L -+#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_LINE__SHIFT 0x0 -+#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_EMP__SHIFT 0xf -+#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_LINE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_EMP_MASK 0x00008000L -+#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_PENDING__SHIFT 0x0 -+#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_DISABLE__SHIFT 0xc -+#define HDMI_TB_ENC_DB_CONTROL__VUPDATE_DB_PENDING__SHIFT 0xf -+#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_PENDING_MASK 0x00000001L -+#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_DISABLE_MASK 0x00001000L -+#define HDMI_TB_ENC_DB_CONTROL__VUPDATE_DB_PENDING_MASK 0x00008000L -+#define HDMI_TB_ENC_ACR_32_0__HDMI_ACR_CTS_32__SHIFT 0xc -+#define HDMI_TB_ENC_ACR_32_0__HDMI_ACR_CTS_32_MASK 0xFFFFF000L -+#define HDMI_TB_ENC_ACR_32_1__HDMI_ACR_N_32__SHIFT 0x0 -+#define HDMI_TB_ENC_ACR_32_1__HDMI_ACR_N_32_MASK 0x000FFFFFL -+#define HDMI_TB_ENC_ACR_44_0__HDMI_ACR_CTS_44__SHIFT 0xc -+#define HDMI_TB_ENC_ACR_44_0__HDMI_ACR_CTS_44_MASK 0xFFFFF000L -+#define HDMI_TB_ENC_ACR_44_1__HDMI_ACR_N_44__SHIFT 0x0 -+#define HDMI_TB_ENC_ACR_44_1__HDMI_ACR_N_44_MASK 0x000FFFFFL -+#define HDMI_TB_ENC_ACR_48_0__HDMI_ACR_CTS_48__SHIFT 0xc -+#define HDMI_TB_ENC_ACR_48_0__HDMI_ACR_CTS_48_MASK 0xFFFFF000L -+#define HDMI_TB_ENC_ACR_48_1__HDMI_ACR_N_48__SHIFT 0x0 -+#define HDMI_TB_ENC_ACR_48_1__HDMI_ACR_N_48_MASK 0x000FFFFFL -+#define HDMI_TB_ENC_ACR_STATUS_0__HDMI_ACR_CTS__SHIFT 0xc -+#define HDMI_TB_ENC_ACR_STATUS_0__HDMI_ACR_CTS_MASK 0xFFFFF000L -+#define HDMI_TB_ENC_ACR_STATUS_1__HDMI_ACR_N__SHIFT 0x0 -+#define HDMI_TB_ENC_ACR_STATUS_1__HDMI_ACR_N_MASK 0x000FFFFFL -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_EN__SHIFT 0x0 -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_EN__SHIFT 0x1 -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_MAX_MIN_LEVEL_RESET__SHIFT 0x4 -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_LEVEL__SHIFT 0x8 -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_LEVEL__SHIFT 0x18 -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_EN_MASK 0x00000001L -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_EN_MASK 0x00000002L -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_MAX_MIN_LEVEL_RESET_MASK 0x00000010L -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_LEVEL_MASK 0x0000FF00L -+#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_LEVEL_MASK 0x1F000000L -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_DIS__SHIFT 0x0 -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_FORCE__SHIFT 0x1 -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_STATE__SHIFT 0x4 -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE__SHIFT 0x8 -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_DIS_MASK 0x00000001L -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_FORCE_MASK 0x00000006L -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_STATE_MASK 0x00000030L -+#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE_MASK 0x00000300L -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_ENABLE__SHIFT 0x0 -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE_REFERENCE__SHIFT 0x4 -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_MISSED__SHIFT 0x8 -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE__SHIFT 0x10 -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_ENABLE_MASK 0x00000001L -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE_REFERENCE_MASK 0x00000010L -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_MISSED_MASK 0x00000100L -+#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE_MASK 0xFFFF0000L -+#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_ACTIVE__SHIFT 0x0 -+#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_BLANK__SHIFT 0x10 -+#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_ACTIVE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_BLANK_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_ACTIVE__SHIFT 0x0 -+#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_BLANK__SHIFT 0x10 -+#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_ACTIVE_MASK 0x00007FFFL -+#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_BLANK_MASK 0x7FFF0000L -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_EN__SHIFT 0x0 -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_CONT_EN__SHIFT 0x1 -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_TYPE__SHIFT 0x8 -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_SRC_SEL__SHIFT 0xa -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_EN__SHIFT 0x10 -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_MODE__SHIFT 0x11 -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_EN_MASK 0x00000001L -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_CONT_EN_MASK 0x00000002L -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_TYPE_MASK 0x00000300L -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_SRC_SEL_MASK 0x00000C00L -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_EN_MASK 0x00010000L -+#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_MODE_MASK 0x00060000L -+#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE0__SHIFT 0x0 -+#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE1__SHIFT 0x10 -+#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE0_MASK 0x0000FFFFL -+#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE1_MASK 0xFFFF0000L -+#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_ENABLE__SHIFT 0x0 -+#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_WHEN_AVMUTE__SHIFT 0x4 -+#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_ENABLE_MASK 0x00000001L -+#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_WHEN_AVMUTE_MASK 0x00000010L -+#define HDMI_TB_ENC_MODE__HDMI_BORROW_MODE__SHIFT 0x0 -+#define HDMI_TB_ENC_MODE__HDMI_SKIP_FIRST_HBLANK__SHIFT 0x8 -+#define HDMI_TB_ENC_MODE__HDMI_BORROW_MODE_MASK 0x00000003L -+#define HDMI_TB_ENC_MODE__HDMI_SKIP_FIRST_HBLANK_MASK 0x00000100L -+#define HDMI_TB_ENC_INPUT_FIFO_STATUS__INPUT_FIFO_ERROR__SHIFT 0x0 -+#define HDMI_TB_ENC_INPUT_FIFO_STATUS__INPUT_FIFO_ERROR_MASK 0x00000001L -+#define HDMI_TB_ENC_CRC_RESULT_1__CRC_TRIBYTE2__SHIFT 0x0 -+#define HDMI_TB_ENC_CRC_RESULT_1__CRC_TRIBYTE2_MASK 0x0000FFFFL -+ -+ -+ - // addressBlock: dce_dc_hpo_hdmi_stream_enc0_afmt_afmt_dispdec - //AFMT5_AFMT_VBI_PACKET_CONTROL - #define AFMT5_AFMT_VBI_PACKET_CONTROL__AFMT_HDMI_AUDIO_PACKETS_PER_LINE__SHIFT 0x10 + static struct dce_hwseq *dcn314_hwseq_create( + struct dc_context *ctx) + { +@@ -1400,6 +1483,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn314_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn314_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn314_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn314_hwseq_create, + }; + diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_offset.h -index 20a6ee7adeef..3c601d1cd894 100644 +index 20a6ee7adeef4f..3c601d1cd89419 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_offset.h @@ -14561,6 +14561,40 @@ @@ -7778,7 +3934,7 @@ index 20a6ee7adeef..3c601d1cd894 100644 // addressBlock: dce_dc_hpo_hpo_top_dispdec // base address: 0x2790c diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_sh_mask.h -index d3d98d43287c..714d26c64427 100644 +index d3d98d43287ca6..714d26c64427ca 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_4_sh_mask.h @@ -59877,6 +59877,122 @@ @@ -8339,8 +4495,1392 @@ index d3d98d43287c..714d26c64427 100644 // addressBlock: dce_dc_hpo_hpo_top_dispdec //HPO_TOP_CLOCK_CONTROL #define HPO_TOP_CLOCK_CONTROL__HPO_DISPCLK_R_GATE_DIS__SHIFT 0x0 + +From aa82458a44d46442d27f0556581d899f9ae3ccb0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 23:10:43 +0100 +Subject: [PATCH 003/103] + drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c: implement + set_hdmistreamclk +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../amd/display/dc/dccg/dcn35/dcn35_dccg.c | 58 +++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c +index bd2f528137b206..14a54d013fe32f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c +@@ -2155,6 +2155,63 @@ static void dccg35_set_dpstreamclk_root_clock_gating_cb( + dccg35_disable_dpstreamclk_new(dccg, dp_hpo_inst); + } + ++static void dccg35_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, ++ HDMISTREAMCLK0_ROOT_GATE_DISABLE, 1); ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, ++ HDMISTREAMCLK0_GATE_DISABLE, 1); ++ } ++ REG_UPDATE_2(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_SRC_SEL, otg_inst, ++ HDMISTREAMCLK0_EN, 1); ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++static void dccg35_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ REG_UPDATE(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_EN, 0); ++ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, ++ HDMISTREAMCLK0_ROOT_GATE_DISABLE, 0); ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, ++ HDMISTREAMCLK0_GATE_DISABLE, 0); ++ } ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++static void dccg35_set_hdmistreamclk( ++ struct dccg *dccg, ++ enum streamclk_source src, ++ int otg_inst, ++ int hdmi_hpo_inst) ++{ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ if (src == REFCLK) ++ dccg35_disable_hdmistreamclk(dccg, hdmi_hpo_inst); ++ else ++ dccg35_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); ++} ++ + static void dccg35_update_dpp_dto_cb(struct dccg *dccg, int dpp_inst, + int req_dppclk) + { +@@ -2398,6 +2455,7 @@ static const struct dccg_funcs dccg35_funcs_new = { + .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, + .dccg_init = dccg35_init_cb, + .set_dpstreamclk = dccg35_set_dpstreamclk_cb, ++ .set_hdmistreamclk = dccg35_set_hdmistreamclk, + .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating_cb, + .enable_symclk32_se = dccg35_enable_symclk32_se_cb, + .disable_symclk32_se = dccg35_disable_symclk32_se_cb, + +From 936712411aa17643b27c3e11cfda1ba006135db2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 23:25:53 +0100 +Subject: [PATCH 004/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h: + drop unused registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These don't exist on earlier DCN. Drop to make the encoder compatible with all DCN gens. + +Signed-off-by: Michał Kopeć +--- + .../amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h +index 0aa737efd3fa93..ba97e0c0e34697 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.h +@@ -164,10 +164,6 @@ struct dcn30_hpo_hdmi_stream_encoder_registers { + FIFO_RESET, mask_sh), \ + SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ + FIFO_PIXEL_ENCODING_TYPE, mask_sh), \ +- SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ +- FIFO_UNCOMPRESSED_PIXEL_FORMAT, mask_sh), \ +- SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ +- FIFO_COMPRESSED_PIXEL_FORMAT, mask_sh), \ + SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ + FIFO_RESET_DONE, mask_sh), \ + SE_SF(HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, \ + +From 27155ee1d0aea5165476b173f3bb3ba5732e9aeb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 23:28:22 +0100 +Subject: [PATCH 005/103] + drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c: instantiate + HPO HDMI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../dc/resource/dcn35/dcn35_resource.c | 96 +++++++++++++++++++ + 1 file changed, 96 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +index d056e5fd545871..3143d504611d99 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +@@ -60,6 +60,8 @@ + #include "dcn35/dcn35_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn32/dcn32_hpo_dp_link_encoder.h" + #include "link_service.h" + #include "dcn31/dcn31_apg.h" +@@ -365,6 +367,19 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_stream_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ +@@ -382,6 +397,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_link_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs_init(id)\ + DPP_REG_LIST_DCN35_RI(id) + +@@ -673,6 +701,8 @@ static const struct resource_caps res_cap_dcn35 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ + .num_dwb = 1, + .num_ddc = 5, +@@ -1364,6 +1394,48 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn35_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance: ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_stream_enc_regs ++ hpo_hdmi_stream_encoder_reg_init(), ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1387,6 +1459,28 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn35_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_link_enc_regs ++ hpo_hdmi_link_encoder_reg_init(), ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn35_hwseq_create( + struct dc_context *ctx) + { +@@ -1410,6 +1504,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn35_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn35_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn35_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn35_hwseq_create, + }; + + +From 88a08e2c98a7cde21c4a53652c9a0bb34c6dc307 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 23:30:04 +0100 +Subject: [PATCH 006/103] + drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_{5,6}_{0,1}*: Rename HDMI + stream enc register +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rename + +HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING + +to + +HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE + +This makes the register name the same as on DCN401, ensuring we can use a common +HPO HDMI encoder implementation on all gens. + +Signed-off-by: Michał Kopeć +--- + drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h | 4 ++-- + drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h | 4 ++-- + drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h +index ff77b71167eb71..2e0a344931833e 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h +@@ -52413,7 +52413,7 @@ + #define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL_MASK 0x00000007L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 +-#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING__SHIFT 0x8 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 +@@ -52421,7 +52421,7 @@ + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L +-#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_MASK 0x00000300L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L +diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h +index d0e95d324053fb..8859272970b73f 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h +@@ -52392,7 +52392,7 @@ + #define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL_MASK 0x00000007L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 +-#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING__SHIFT 0x8 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 +@@ -52400,7 +52400,7 @@ + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L +-#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_MASK 0x00000300L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L +diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h +index 3ffb6ec8b40a56..2b461f3f2e5d09 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h +@@ -48669,7 +48669,7 @@ + //HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 +-#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING__SHIFT 0x8 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 +@@ -48677,7 +48677,7 @@ + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L +-#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_MASK 0x00000300L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L + #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L + +From 5b059b1875e33babc7334ba42ed48ef08c7558de Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 23:36:48 +0100 +Subject: [PATCH 007/103] + drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c: instantiate + HPO HDMI Encoders +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../dc/resource/dcn351/dcn351_resource.c | 96 +++++++++++++++++++ + 1 file changed, 96 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +index 9fab3169069c40..da459a40bc8c07 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +@@ -39,6 +39,8 @@ + #include "dcn35/dcn35_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn32/dcn32_hpo_dp_link_encoder.h" + #include "link_service.h" + #include "dcn31/dcn31_apg.h" +@@ -345,6 +347,19 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_stream_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ +@@ -362,6 +377,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_link_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs_init(id)\ + DPP_REG_LIST_DCN35_RI(id) + +@@ -653,6 +681,8 @@ static const struct resource_caps res_cap_dcn351 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ + .num_dwb = 1, + .num_ddc = 5, +@@ -1344,6 +1374,48 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn35_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance: ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_stream_enc_regs ++ hpo_hdmi_stream_encoder_reg_init(), ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1367,6 +1439,28 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn35_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_link_enc_regs ++ hpo_hdmi_link_encoder_reg_init(), ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn351_hwseq_create( + struct dc_context *ctx) + { +@@ -1390,6 +1484,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn35_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn35_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn35_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn351_hwseq_create, + }; + + +From 1665155933990ae61a6958aefd80c97db7350f26 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 14 Feb 2026 23:43:25 +0100 +Subject: [PATCH 008/103] + drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c: instantiate + HPO HDMI Encoders +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../dc/resource/dcn36/dcn36_resource.c | 96 +++++++++++++++++++ + 1 file changed, 96 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +index 6469d5fe2e6d46..74bf9e68830cf3 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +@@ -39,6 +39,8 @@ + #include "dcn35/dcn35_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn32/dcn32_hpo_dp_link_encoder.h" + #include "link_service.h" + #include "dcn31/dcn31_apg.h" +@@ -350,6 +352,19 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_stream_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + +@@ -363,6 +378,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_link_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs_init(id)\ + DPP_REG_LIST_DCN35_RI(id) + +@@ -654,6 +682,8 @@ static const struct resource_caps res_cap_dcn36 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ + .num_dwb = 1, + .num_ddc = 5, +@@ -1345,6 +1375,48 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn36_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance: ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_stream_enc_regs ++ hpo_hdmi_stream_encoder_reg_init(), ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1368,6 +1440,28 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn36_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_link_enc_regs ++ hpo_hdmi_link_encoder_reg_init(), ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn36_hwseq_create( + struct dc_context *ctx) + { +@@ -1391,6 +1485,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn35_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn36_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn36_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn36_hwseq_create, + }; + + +From bc90d6faa15253caae0298616e26919a5f9203a5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:08:46 +0100 +Subject: [PATCH 009/103] dcn_3_1_2_offset.h dcn_3_1_2_sh_mask.h: add HPO HDMI + registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../include/asic_reg/dcn/dcn_3_1_2_offset.h | 114 ++++ + .../include/asic_reg/dcn/dcn_3_1_2_sh_mask.h | 501 ++++++++++++++++++ + 2 files changed, 615 insertions(+) + +diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h +index 7fd906f1080391..7de1451745cda2 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h +@@ -12908,6 +12908,120 @@ + #define regDC_PERFMON22_PERFMON_LOW_BASE_IDX 3 + + ++// addressBlock: dce_dc_hpo_hdmi_link_enc0_dispdec ++// base address: 0x2656c ++#define regHDMI_LINK_ENC_CONTROL 0x095b ++#define regHDMI_LINK_ENC_CONTROL_BASE_IDX 3 ++#define regHDMI_LINK_ENC_CLK_CTRL 0x095c ++#define regHDMI_LINK_ENC_CLK_CTRL_BASE_IDX 3 ++ ++ ++// addressBlock: dce_dc_hpo_hdmi_frl_enc0_dispdec ++// base address: 0x26594 ++#define regHDMI_FRL_ENC_CONFIG 0x0965 ++#define regHDMI_FRL_ENC_CONFIG_BASE_IDX 3 ++#define regHDMI_FRL_ENC_CONFIG2 0x0966 ++#define regHDMI_FRL_ENC_CONFIG2_BASE_IDX 3 ++#define regHDMI_FRL_ENC_METER_BUFFER_STATUS 0x0967 ++#define regHDMI_FRL_ENC_METER_BUFFER_STATUS_BASE_IDX 3 ++#define regHDMI_FRL_ENC_MEM_CTRL 0x0968 ++#define regHDMI_FRL_ENC_MEM_CTRL_BASE_IDX 3 ++ ++ ++// addressBlock: dce_dc_hpo_hdmi_stream_enc0_dispdec ++// base address: 0x2634c ++#define regHDMI_STREAM_ENC_CLOCK_CONTROL 0x08d3 ++#define regHDMI_STREAM_ENC_CLOCK_CONTROL_BASE_IDX 3 ++#define regHDMI_STREAM_ENC_INPUT_MUX_CONTROL 0x08d5 ++#define regHDMI_STREAM_ENC_INPUT_MUX_CONTROL_BASE_IDX 3 ++#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0 0x08d6 ++#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0_BASE_IDX 3 ++#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1 0x08d7 ++#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1_BASE_IDX 3 ++#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2 0x08d8 ++#define regHDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2_BASE_IDX 3 ++ ++ ++// addressBlock: dce_dc_hpo_hdmi_tb_enc0_dispdec ++// base address: 0x2637c ++#define regHDMI_TB_ENC_CONTROL 0x08df ++#define regHDMI_TB_ENC_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_PIXEL_FORMAT 0x08e0 ++#define regHDMI_TB_ENC_PIXEL_FORMAT_BASE_IDX 3 ++#define regHDMI_TB_ENC_PACKET_CONTROL 0x08e1 ++#define regHDMI_TB_ENC_PACKET_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_PACKET_CONTROL 0x08e2 ++#define regHDMI_TB_ENC_ACR_PACKET_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_VBI_PACKET_CONTROL1 0x08e3 ++#define regHDMI_TB_ENC_VBI_PACKET_CONTROL1_BASE_IDX 3 ++#define regHDMI_TB_ENC_VBI_PACKET_CONTROL2 0x08e4 ++#define regHDMI_TB_ENC_VBI_PACKET_CONTROL2_BASE_IDX 3 ++#define regHDMI_TB_ENC_GC_CONTROL 0x08e5 ++#define regHDMI_TB_ENC_GC_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL0 0x08e6 ++#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL0_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL1 0x08e7 ++#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL1_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL2 0x08e8 ++#define regHDMI_TB_ENC_GENERIC_PACKET_CONTROL2_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET0_1_LINE 0x08e9 ++#define regHDMI_TB_ENC_GENERIC_PACKET0_1_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET2_3_LINE 0x08ea ++#define regHDMI_TB_ENC_GENERIC_PACKET2_3_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET4_5_LINE 0x08eb ++#define regHDMI_TB_ENC_GENERIC_PACKET4_5_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET6_7_LINE 0x08ec ++#define regHDMI_TB_ENC_GENERIC_PACKET6_7_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET8_9_LINE 0x08ed ++#define regHDMI_TB_ENC_GENERIC_PACKET8_9_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET10_11_LINE 0x08ee ++#define regHDMI_TB_ENC_GENERIC_PACKET10_11_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET12_13_LINE 0x08ef ++#define regHDMI_TB_ENC_GENERIC_PACKET12_13_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_GENERIC_PACKET14_LINE 0x08f0 ++#define regHDMI_TB_ENC_GENERIC_PACKET14_LINE_BASE_IDX 3 ++#define regHDMI_TB_ENC_DB_CONTROL 0x08f1 ++#define regHDMI_TB_ENC_DB_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_32_0 0x08f2 ++#define regHDMI_TB_ENC_ACR_32_0_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_32_1 0x08f3 ++#define regHDMI_TB_ENC_ACR_32_1_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_44_0 0x08f4 ++#define regHDMI_TB_ENC_ACR_44_0_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_44_1 0x08f5 ++#define regHDMI_TB_ENC_ACR_44_1_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_48_0 0x08f6 ++#define regHDMI_TB_ENC_ACR_48_0_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_48_1 0x08f7 ++#define regHDMI_TB_ENC_ACR_48_1_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_STATUS_0 0x08f8 ++#define regHDMI_TB_ENC_ACR_STATUS_0_BASE_IDX 3 ++#define regHDMI_TB_ENC_ACR_STATUS_1 0x08f9 ++#define regHDMI_TB_ENC_ACR_STATUS_1_BASE_IDX 3 ++#define regHDMI_TB_ENC_BUFFER_CONTROL 0x08fb ++#define regHDMI_TB_ENC_BUFFER_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_MEM_CTRL 0x08fe ++#define regHDMI_TB_ENC_MEM_CTRL_BASE_IDX 3 ++#define regHDMI_TB_ENC_METADATA_PACKET_CONTROL 0x08ff ++#define regHDMI_TB_ENC_METADATA_PACKET_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_H_ACTIVE_BLANK 0x0900 ++#define regHDMI_TB_ENC_H_ACTIVE_BLANK_BASE_IDX 3 ++#define regHDMI_TB_ENC_HC_ACTIVE_BLANK 0x0901 ++#define regHDMI_TB_ENC_HC_ACTIVE_BLANK_BASE_IDX 3 ++#define regHDMI_TB_ENC_CRC_CNTL 0x0903 ++#define regHDMI_TB_ENC_CRC_CNTL_BASE_IDX 3 ++#define regHDMI_TB_ENC_CRC_RESULT_0 0x0904 ++#define regHDMI_TB_ENC_CRC_RESULT_0_BASE_IDX 3 ++#define regHDMI_TB_ENC_ENCRYPTION_CONTROL 0x0907 ++#define regHDMI_TB_ENC_ENCRYPTION_CONTROL_BASE_IDX 3 ++#define regHDMI_TB_ENC_MODE 0x0908 ++#define regHDMI_TB_ENC_MODE_BASE_IDX 3 ++#define regHDMI_TB_ENC_INPUT_FIFO_STATUS 0x0909 ++#define regHDMI_TB_ENC_INPUT_FIFO_STATUS_BASE_IDX 3 ++#define regHDMI_TB_ENC_CRC_RESULT_1 0x090a ++#define regHDMI_TB_ENC_CRC_RESULT_1_BASE_IDX 3 ++ ++ + // addressBlock: dce_dc_hpo_hdmi_stream_enc0_afmt_afmt_dispdec + // base address: 0x2646c + #define regAFMT5_AFMT_VBI_PACKET_CONTROL 0x091c +diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h +index 07fbfafe6056db..21ae70bf0eee78 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h +@@ -48392,6 +48392,507 @@ + #define DC_PERFMON22_PERFMON_LOW__PERFMON_LOW_MASK 0xFFFFFFFFL + + ++#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_ENABLE__SHIFT 0x0 ++#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_SOFT_RESET__SHIFT 0x4 ++#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_ENABLE_MASK 0x00000001L ++#define HDMI_LINK_ENC_CONTROL__HDMI_LINK_ENC_SOFT_RESET_MASK 0x00000010L ++#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_EN__SHIFT 0x0 ++#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_ON_HDMICHARCLK__SHIFT 0x1 ++#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_EN_MASK 0x00000001L ++#define HDMI_LINK_ENC_CLK_CTRL__HDMI_LINK_ENC_CLOCK_ON_HDMICHARCLK_MASK 0x00000002L ++ ++ ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE_COUNT__SHIFT 0x0 ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_TRAINING_ENABLE__SHIFT 0x1 ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_SCRAMBLER_DISABLE__SHIFT 0x2 ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE0_TRAINING_PATTERN__SHIFT 0x10 ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE1_TRAINING_PATTERN__SHIFT 0x14 ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE2_TRAINING_PATTERN__SHIFT 0x18 ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE3_TRAINING_PATTERN__SHIFT 0x1c ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE_COUNT_MASK 0x00000001L ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_TRAINING_ENABLE_MASK 0x00000002L ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_SCRAMBLER_DISABLE_MASK 0x00000004L ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE0_TRAINING_PATTERN_MASK 0x000F0000L ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE1_TRAINING_PATTERN_MASK 0x00F00000L ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE2_TRAINING_PATTERN_MASK 0x0F000000L ++#define HDMI_FRL_ENC_CONFIG__HDMI_LINK_LANE3_TRAINING_PATTERN_MASK 0xF0000000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE__SHIFT 0x0 ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_THRESHOLD__SHIFT 0xc ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_CAL_EN__SHIFT 0x18 ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_RC_COMPRESS_DISABLE__SHIFT 0x19 ++#define HDMI_FRL_ENC_CONFIG2__HDMI_FRL_HDMISTREAMCLK_DB_SEL__SHIFT 0x1a ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE_RESET__SHIFT 0x1c ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_EXCEED_STATUS__SHIFT 0x1d ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_METER_BUFFER_OVERFLOW_STATUS__SHIFT 0x1e ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE_MASK 0x000001FFL ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_THRESHOLD_MASK 0x001FF000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_CAL_EN_MASK 0x01000000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_RC_COMPRESS_DISABLE_MASK 0x02000000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_FRL_HDMISTREAMCLK_DB_SEL_MASK 0x0C000000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_MAX_JITTER_VALUE_RESET_MASK 0x10000000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_JITTER_EXCEED_STATUS_MASK 0x20000000L ++#define HDMI_FRL_ENC_CONFIG2__HDMI_LINK_METER_BUFFER_OVERFLOW_STATUS_MASK 0x40000000L ++#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_MAX_METER_BUFFER_LEVEL__SHIFT 0x0 ++#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_METER_BUFFER_MAX_LEVEL_RESET__SHIFT 0x1f ++#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_MAX_METER_BUFFER_LEVEL_MASK 0x0000007FL ++#define HDMI_FRL_ENC_METER_BUFFER_STATUS__HDMI_LINK_METER_BUFFER_MAX_LEVEL_RESET_MASK 0x80000000L ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_DIS__SHIFT 0x0 ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_FORCE__SHIFT 0x1 ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_STATE__SHIFT 0x4 ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE__SHIFT 0x8 ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_DIS_MASK 0x00000001L ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_FORCE_MASK 0x00000006L ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_PWR_STATE_MASK 0x00000030L ++#define HDMI_FRL_ENC_MEM_CTRL__METERBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE_MASK 0x00000300L ++ ++ ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_EN__SHIFT 0x0 ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_DISPCLK__SHIFT 0x4 ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_SOCCLK__SHIFT 0x8 ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_HDMISTREAMCLK__SHIFT 0xc ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_EN_MASK 0x00000001L ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_DISPCLK_MASK 0x00000010L ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_SOCCLK_MASK 0x00000100L ++#define HDMI_STREAM_ENC_CLOCK_CONTROL__HDMI_STREAM_ENC_CLOCK_ON_HDMISTREAMCLK_MASK 0x00001000L ++#define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL__SHIFT 0x0 ++#define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL_MASK 0x00000007L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_VIDEO_STREAM_ACTIVE__SHIFT 0x18 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_VIDEO_STREAM_ACTIVE_MASK 0x01000000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR_MASK 0x30000000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x0 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x1 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x2 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_OVERWRITE_LEVEL__SHIFT 0x4 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MINIMUM_LEVEL__SHIFT 0xc ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MAXIMUM_LEVEL__SHIFT 0x10 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x18 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CALIBRATED__SHIFT 0x1f ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000001L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECAL_AVERAGE_MASK 0x00000002L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_FORCE_RECOMP_MINMAX_MASK 0x00000004L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_OVERWRITE_LEVEL_MASK 0x000003F0L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MINIMUM_LEVEL_MASK 0x0000F000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_MAXIMUM_LEVEL_MASK 0x001F0000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CAL_AVERAGE_LEVEL_MASK 0x3F000000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL1__FIFO_CALIBRATED_MASK 0x80000000L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_START_LEVEL__SHIFT 0x0 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_CLOCK_SRC__SHIFT 0x5 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_PENDING__SHIFT 0x8 ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_DISABLE__SHIFT 0xc ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_START_LEVEL_MASK 0x0000001FL ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_READ_CLOCK_SRC_MASK 0x00000020L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_PENDING_MASK 0x00000100L ++#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL2__FIFO_DB_DISABLE_MASK 0x00001000L ++ ++ ++#define HDMI_TB_ENC_CONTROL__HDMI_TB_ENC_EN__SHIFT 0x0 ++#define HDMI_TB_ENC_CONTROL__HDMI_RESET__SHIFT 0x4 ++#define HDMI_TB_ENC_CONTROL__HDMI_RESET_DONE__SHIFT 0x8 ++#define HDMI_TB_ENC_CONTROL__HDMI_TB_ENC_EN_MASK 0x00000001L ++#define HDMI_TB_ENC_CONTROL__HDMI_RESET_MASK 0x00000010L ++#define HDMI_TB_ENC_CONTROL__HDMI_RESET_DONE_MASK 0x00000100L ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_ENABLE__SHIFT 0x0 ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_DEPTH__SHIFT 0x8 ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_PIXEL_ENCODING__SHIFT 0x10 ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DSC_MODE__SHIFT 0x18 ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_ENABLE_MASK 0x00000001L ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DEEP_COLOR_DEPTH_MASK 0x00000300L ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_PIXEL_ENCODING_MASK 0x00030000L ++#define HDMI_TB_ENC_PIXEL_FORMAT__HDMI_DSC_MODE_MASK 0x03000000L ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_PACKETS_PER_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_ISLANDS_PER_LINE__SHIFT 0x8 ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_OVERFLOW__SHIFT 0xc ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_TB_ENC_PACKET_ERROR_CLEAR__SHIFT 0x10 ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_PACKETS_PER_LINE_MASK 0x0000001FL ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_MAX_ISLANDS_PER_LINE_MASK 0x00000300L ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_OVERFLOW_MASK 0x00001000L ++#define HDMI_TB_ENC_PACKET_CONTROL__HDMI_TB_ENC_PACKET_ERROR_CLEAR_MASK 0x00010000L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SEND__SHIFT 0x0 ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_CONT__SHIFT 0x1 ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SELECT__SHIFT 0x4 ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE__SHIFT 0x8 ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND__SHIFT 0xc ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE__SHIFT 0x10 ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY__SHIFT 0x1f ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SEND_MASK 0x00000001L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_CONT_MASK 0x00000002L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SELECT_MASK 0x00000030L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE_MASK 0x00000100L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK 0x00001000L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE_MASK 0x00070000L ++#define HDMI_TB_ENC_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY_MASK 0x80000000L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_SEND__SHIFT 0x0 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_CONT__SHIFT 0x1 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_SEND__SHIFT 0x4 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_CONT__SHIFT 0x5 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_LINE_REFERENCE__SHIFT 0x6 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_SEND__SHIFT 0x8 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_LINE_REFERENCE__SHIFT 0x9 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_SEND__SHIFT 0xc ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_CONT__SHIFT 0xd ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE_REFERENCE__SHIFT 0xe ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_SEND_MASK 0x00000001L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_GC_CONT_MASK 0x00000002L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_SEND_MASK 0x00000010L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_CONT_MASK 0x00000020L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ISRC_LINE_REFERENCE_MASK 0x00000040L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_SEND_MASK 0x00000100L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_ACP_LINE_REFERENCE_MASK 0x00000200L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_SEND_MASK 0x00001000L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_CONT_MASK 0x00002000L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE_REFERENCE_MASK 0x00004000L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL1__HDMI_AUDIO_INFO_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ISRC_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ACP_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ISRC_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_VBI_PACKET_CONTROL2__HDMI_ACP_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE__SHIFT 0x0 ++#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE_CONT__SHIFT 0x2 ++#define HDMI_TB_ENC_GC_CONTROL__HDMI_DEFAULT_PHASE__SHIFT 0x4 ++#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE_MASK 0x00000001L ++#define HDMI_TB_ENC_GC_CONTROL__HDMI_GC_AVMUTE_CONT_MASK 0x00000004L ++#define HDMI_TB_ENC_GC_CONTROL__HDMI_DEFAULT_PHASE_MASK 0x00000010L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT__SHIFT 0x1 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LOCK_EN__SHIFT 0x2 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_REFERENCE__SHIFT 0x3 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND__SHIFT 0x4 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT__SHIFT 0x5 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LOCK_EN__SHIFT 0x6 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_REFERENCE__SHIFT 0x7 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_SEND__SHIFT 0x8 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_CONT__SHIFT 0x9 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LOCK_EN__SHIFT 0xa ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LINE_REFERENCE__SHIFT 0xb ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_SEND__SHIFT 0xc ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_CONT__SHIFT 0xd ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LOCK_EN__SHIFT 0xe ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LINE_REFERENCE__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_SEND__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_CONT__SHIFT 0x11 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LOCK_EN__SHIFT 0x12 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LINE_REFERENCE__SHIFT 0x13 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_SEND__SHIFT 0x14 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_CONT__SHIFT 0x15 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LOCK_EN__SHIFT 0x16 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LINE_REFERENCE__SHIFT 0x17 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_SEND__SHIFT 0x18 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_CONT__SHIFT 0x19 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LOCK_EN__SHIFT 0x1a ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LINE_REFERENCE__SHIFT 0x1b ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_SEND__SHIFT 0x1c ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_CONT__SHIFT 0x1d ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LOCK_EN__SHIFT 0x1e ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LINE_REFERENCE__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND_MASK 0x00000001L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT_MASK 0x00000002L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LOCK_EN_MASK 0x00000004L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_REFERENCE_MASK 0x00000008L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND_MASK 0x00000010L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT_MASK 0x00000020L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LOCK_EN_MASK 0x00000040L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_REFERENCE_MASK 0x00000080L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_SEND_MASK 0x00000100L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_CONT_MASK 0x00000200L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LOCK_EN_MASK 0x00000400L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC2_LINE_REFERENCE_MASK 0x00000800L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_SEND_MASK 0x00001000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_CONT_MASK 0x00002000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LOCK_EN_MASK 0x00004000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC3_LINE_REFERENCE_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_SEND_MASK 0x00010000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_CONT_MASK 0x00020000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LOCK_EN_MASK 0x00040000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC4_LINE_REFERENCE_MASK 0x00080000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_SEND_MASK 0x00100000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_CONT_MASK 0x00200000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LOCK_EN_MASK 0x00400000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC5_LINE_REFERENCE_MASK 0x00800000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_SEND_MASK 0x01000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_CONT_MASK 0x02000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LOCK_EN_MASK 0x04000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC6_LINE_REFERENCE_MASK 0x08000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_SEND_MASK 0x10000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_CONT_MASK 0x20000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LOCK_EN_MASK 0x40000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL0__HDMI_GENERIC7_LINE_REFERENCE_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_SEND__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_CONT__SHIFT 0x1 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LOCK_EN__SHIFT 0x2 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LINE_REFERENCE__SHIFT 0x3 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_SEND__SHIFT 0x4 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_CONT__SHIFT 0x5 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LOCK_EN__SHIFT 0x6 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LINE_REFERENCE__SHIFT 0x7 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_SEND__SHIFT 0x8 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_CONT__SHIFT 0x9 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LOCK_EN__SHIFT 0xa ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LINE_REFERENCE__SHIFT 0xb ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_SEND__SHIFT 0xc ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_CONT__SHIFT 0xd ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LOCK_EN__SHIFT 0xe ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LINE_REFERENCE__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_SEND__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_CONT__SHIFT 0x11 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LOCK_EN__SHIFT 0x12 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LINE_REFERENCE__SHIFT 0x13 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_SEND__SHIFT 0x14 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_CONT__SHIFT 0x15 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LOCK_EN__SHIFT 0x16 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LINE_REFERENCE__SHIFT 0x17 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_SEND__SHIFT 0x18 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_CONT__SHIFT 0x19 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LOCK_EN__SHIFT 0x1a ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LINE_REFERENCE__SHIFT 0x1b ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_SEND_MASK 0x00000001L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_CONT_MASK 0x00000002L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LOCK_EN_MASK 0x00000004L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC8_LINE_REFERENCE_MASK 0x00000008L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_SEND_MASK 0x00000010L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_CONT_MASK 0x00000020L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LOCK_EN_MASK 0x00000040L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC9_LINE_REFERENCE_MASK 0x00000080L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_SEND_MASK 0x00000100L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_CONT_MASK 0x00000200L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LOCK_EN_MASK 0x00000400L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC10_LINE_REFERENCE_MASK 0x00000800L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_SEND_MASK 0x00001000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_CONT_MASK 0x00002000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LOCK_EN_MASK 0x00004000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC11_LINE_REFERENCE_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_SEND_MASK 0x00010000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_CONT_MASK 0x00020000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LOCK_EN_MASK 0x00040000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC12_LINE_REFERENCE_MASK 0x00080000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_SEND_MASK 0x00100000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_CONT_MASK 0x00200000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LOCK_EN_MASK 0x00400000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC13_LINE_REFERENCE_MASK 0x00800000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_SEND_MASK 0x01000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_CONT_MASK 0x02000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LOCK_EN_MASK 0x04000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL1__HDMI_GENERIC14_LINE_REFERENCE_MASK 0x08000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND_PENDING__SHIFT 0x1 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND__SHIFT 0x2 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND_PENDING__SHIFT 0x3 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND__SHIFT 0x4 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND_PENDING__SHIFT 0x5 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND__SHIFT 0x6 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND_PENDING__SHIFT 0x7 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND__SHIFT 0x8 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND_PENDING__SHIFT 0x9 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND__SHIFT 0xa ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND_PENDING__SHIFT 0xb ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND__SHIFT 0xc ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND_PENDING__SHIFT 0xd ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND__SHIFT 0xe ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND_PENDING__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND_PENDING__SHIFT 0x11 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND__SHIFT 0x12 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND_PENDING__SHIFT 0x13 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND__SHIFT 0x14 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND_PENDING__SHIFT 0x15 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND__SHIFT 0x16 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND_PENDING__SHIFT 0x17 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND__SHIFT 0x18 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND_PENDING__SHIFT 0x19 ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND__SHIFT 0x1a ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND_PENDING__SHIFT 0x1b ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND__SHIFT 0x1c ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND_PENDING__SHIFT 0x1d ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND_MASK 0x00000001L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC0_IMMEDIATE_SEND_PENDING_MASK 0x00000002L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND_MASK 0x00000004L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC1_IMMEDIATE_SEND_PENDING_MASK 0x00000008L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND_MASK 0x00000010L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC2_IMMEDIATE_SEND_PENDING_MASK 0x00000020L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND_MASK 0x00000040L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC3_IMMEDIATE_SEND_PENDING_MASK 0x00000080L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND_MASK 0x00000100L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC4_IMMEDIATE_SEND_PENDING_MASK 0x00000200L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND_MASK 0x00000400L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC5_IMMEDIATE_SEND_PENDING_MASK 0x00000800L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND_MASK 0x00001000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC6_IMMEDIATE_SEND_PENDING_MASK 0x00002000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND_MASK 0x00004000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC7_IMMEDIATE_SEND_PENDING_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND_MASK 0x00010000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC8_IMMEDIATE_SEND_PENDING_MASK 0x00020000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND_MASK 0x00040000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC9_IMMEDIATE_SEND_PENDING_MASK 0x00080000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND_MASK 0x00100000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC10_IMMEDIATE_SEND_PENDING_MASK 0x00200000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND_MASK 0x00400000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC11_IMMEDIATE_SEND_PENDING_MASK 0x00800000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND_MASK 0x01000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC12_IMMEDIATE_SEND_PENDING_MASK 0x02000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND_MASK 0x04000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC13_IMMEDIATE_SEND_PENDING_MASK 0x08000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND_MASK 0x10000000L ++#define HDMI_TB_ENC_GENERIC_PACKET_CONTROL2__HDMI_GENERIC14_IMMEDIATE_SEND_PENDING_MASK 0x20000000L ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC0_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET0_1_LINE__HDMI_GENERIC1_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC2_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET2_3_LINE__HDMI_GENERIC3_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC4_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET4_5_LINE__HDMI_GENERIC5_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC6_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET6_7_LINE__HDMI_GENERIC7_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC8_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET8_9_LINE__HDMI_GENERIC9_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC10_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET10_11_LINE__HDMI_GENERIC11_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_EMP__SHIFT 0x1f ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC12_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_LINE_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_GENERIC_PACKET12_13_LINE__HDMI_GENERIC13_EMP_MASK 0x80000000L ++#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_LINE__SHIFT 0x0 ++#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_EMP__SHIFT 0xf ++#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_LINE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_GENERIC_PACKET14_LINE__HDMI_GENERIC14_EMP_MASK 0x00008000L ++#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_PENDING__SHIFT 0x0 ++#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_DISABLE__SHIFT 0xc ++#define HDMI_TB_ENC_DB_CONTROL__VUPDATE_DB_PENDING__SHIFT 0xf ++#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_PENDING_MASK 0x00000001L ++#define HDMI_TB_ENC_DB_CONTROL__HDMI_DB_DISABLE_MASK 0x00001000L ++#define HDMI_TB_ENC_DB_CONTROL__VUPDATE_DB_PENDING_MASK 0x00008000L ++#define HDMI_TB_ENC_ACR_32_0__HDMI_ACR_CTS_32__SHIFT 0xc ++#define HDMI_TB_ENC_ACR_32_0__HDMI_ACR_CTS_32_MASK 0xFFFFF000L ++#define HDMI_TB_ENC_ACR_32_1__HDMI_ACR_N_32__SHIFT 0x0 ++#define HDMI_TB_ENC_ACR_32_1__HDMI_ACR_N_32_MASK 0x000FFFFFL ++#define HDMI_TB_ENC_ACR_44_0__HDMI_ACR_CTS_44__SHIFT 0xc ++#define HDMI_TB_ENC_ACR_44_0__HDMI_ACR_CTS_44_MASK 0xFFFFF000L ++#define HDMI_TB_ENC_ACR_44_1__HDMI_ACR_N_44__SHIFT 0x0 ++#define HDMI_TB_ENC_ACR_44_1__HDMI_ACR_N_44_MASK 0x000FFFFFL ++#define HDMI_TB_ENC_ACR_48_0__HDMI_ACR_CTS_48__SHIFT 0xc ++#define HDMI_TB_ENC_ACR_48_0__HDMI_ACR_CTS_48_MASK 0xFFFFF000L ++#define HDMI_TB_ENC_ACR_48_1__HDMI_ACR_N_48__SHIFT 0x0 ++#define HDMI_TB_ENC_ACR_48_1__HDMI_ACR_N_48_MASK 0x000FFFFFL ++#define HDMI_TB_ENC_ACR_STATUS_0__HDMI_ACR_CTS__SHIFT 0xc ++#define HDMI_TB_ENC_ACR_STATUS_0__HDMI_ACR_CTS_MASK 0xFFFFF000L ++#define HDMI_TB_ENC_ACR_STATUS_1__HDMI_ACR_N__SHIFT 0x0 ++#define HDMI_TB_ENC_ACR_STATUS_1__HDMI_ACR_N_MASK 0x000FFFFFL ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_EN__SHIFT 0x0 ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_EN__SHIFT 0x1 ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_MAX_MIN_LEVEL_RESET__SHIFT 0x4 ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_LEVEL__SHIFT 0x8 ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_LEVEL__SHIFT 0x18 ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_EN_MASK 0x00000001L ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_EN_MASK 0x00000002L ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_MAX_MIN_LEVEL_RESET_MASK 0x00000010L ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_BORROWBUFFER_PREFILL_OVERRIDE_LEVEL_MASK 0x0000FF00L ++#define HDMI_TB_ENC_BUFFER_CONTROL__HDMI_RATE_BUFFER_PREFILL_OVERRIDE_LEVEL_MASK 0x1F000000L ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_DIS__SHIFT 0x0 ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_FORCE__SHIFT 0x1 ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_STATE__SHIFT 0x4 ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE__SHIFT 0x8 ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_DIS_MASK 0x00000001L ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_FORCE_MASK 0x00000006L ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_PWR_STATE_MASK 0x00000030L ++#define HDMI_TB_ENC_MEM_CTRL__BORROWBUFFER_MEM_DEFAULT_MEM_LOW_POWER_STATE_MASK 0x00000300L ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_ENABLE__SHIFT 0x0 ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE_REFERENCE__SHIFT 0x4 ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_MISSED__SHIFT 0x8 ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE__SHIFT 0x10 ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_ENABLE_MASK 0x00000001L ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE_REFERENCE_MASK 0x00000010L ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_MISSED_MASK 0x00000100L ++#define HDMI_TB_ENC_METADATA_PACKET_CONTROL__HDMI_METADATA_PACKET_LINE_MASK 0xFFFF0000L ++#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_ACTIVE__SHIFT 0x0 ++#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_BLANK__SHIFT 0x10 ++#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_ACTIVE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_H_ACTIVE_BLANK__HDMI_H_BLANK_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_ACTIVE__SHIFT 0x0 ++#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_BLANK__SHIFT 0x10 ++#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_ACTIVE_MASK 0x00007FFFL ++#define HDMI_TB_ENC_HC_ACTIVE_BLANK__HDMI_HC_BLANK_MASK 0x7FFF0000L ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_EN__SHIFT 0x0 ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_CONT_EN__SHIFT 0x1 ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_TYPE__SHIFT 0x8 ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_SRC_SEL__SHIFT 0xa ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_EN__SHIFT 0x10 ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_MODE__SHIFT 0x11 ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_EN_MASK 0x00000001L ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_CONT_EN_MASK 0x00000002L ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_TYPE_MASK 0x00000300L ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_SRC_SEL_MASK 0x00000C00L ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_EN_MASK 0x00010000L ++#define HDMI_TB_ENC_CRC_CNTL__HDMI_CRC_INTERLACE_MODE_MASK 0x00060000L ++#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE0__SHIFT 0x0 ++#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE1__SHIFT 0x10 ++#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE0_MASK 0x0000FFFFL ++#define HDMI_TB_ENC_CRC_RESULT_0__CRC_TRIBYTE1_MASK 0xFFFF0000L ++#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_ENABLE__SHIFT 0x0 ++#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_WHEN_AVMUTE__SHIFT 0x4 ++#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_ENABLE_MASK 0x00000001L ++#define HDMI_TB_ENC_ENCRYPTION_CONTROL__HDMI_EESS_WHEN_AVMUTE_MASK 0x00000010L ++#define HDMI_TB_ENC_MODE__HDMI_BORROW_MODE__SHIFT 0x0 ++#define HDMI_TB_ENC_MODE__HDMI_SKIP_FIRST_HBLANK__SHIFT 0x8 ++#define HDMI_TB_ENC_MODE__HDMI_BORROW_MODE_MASK 0x00000003L ++#define HDMI_TB_ENC_MODE__HDMI_SKIP_FIRST_HBLANK_MASK 0x00000100L ++#define HDMI_TB_ENC_INPUT_FIFO_STATUS__INPUT_FIFO_ERROR__SHIFT 0x0 ++#define HDMI_TB_ENC_INPUT_FIFO_STATUS__INPUT_FIFO_ERROR_MASK 0x00000001L ++#define HDMI_TB_ENC_CRC_RESULT_1__CRC_TRIBYTE2__SHIFT 0x0 ++#define HDMI_TB_ENC_CRC_RESULT_1__CRC_TRIBYTE2_MASK 0x0000FFFFL ++ ++ ++ + // addressBlock: dce_dc_hpo_hdmi_stream_enc0_afmt_afmt_dispdec + //AFMT5_AFMT_VBI_PACKET_CONTROL + #define AFMT5_AFMT_VBI_PACKET_CONTROL__AFMT_HDMI_AUDIO_PACKETS_PER_LINE__SHIFT 0x10 + +From 9b80e340582d4196ce7ca223dfcba6b1e30aae61 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:09:04 +0100 +Subject: [PATCH 010/103] dcn_3_1_5_offset.h dcn_3_1_5_sh_mask.h: add HPO HDMI + registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../include/asic_reg/dcn/dcn_3_1_5_offset.h | 115 ++++ + .../include/asic_reg/dcn/dcn_3_1_5_sh_mask.h | 501 ++++++++++++++++++ + 2 files changed, 616 insertions(+) + diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h -index 16a69d17bb1e..4ada68f95b03 100644 +index 16a69d17bb1e10..4ada68f95b03c2 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h @@ -8059,6 +8059,121 @@ @@ -8466,7 +6006,7 @@ index 16a69d17bb1e..4ada68f95b03 100644 // base address: 0x0 #define regDPG0_DPG_CONTROL 0x1854 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h -index 6473362e39a8..a2ab5fa3c2ec 100644 +index 6473362e39a89f..a2ab5fa3c2ec7f 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h @@ -25949,6 +25949,507 @@ @@ -8977,8 +6517,24 @@ index 6473362e39a8..a2ab5fa3c2ec 100644 // addressBlock: dce_dc_opp_dpg0_dispdec //DPG0_DPG_CONTROL #define DPG0_DPG_CONTROL__DPG_EN__SHIFT 0x0 + +From 6fe600eef8cd5b0105d9222d6702d3cca36c5d85 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:09:16 +0100 +Subject: [PATCH 011/103] dcn_3_1_6_offset.h dcn_3_1_6_sh_mask.h: add HPO HDMI + registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../include/asic_reg/dcn/dcn_3_1_6_offset.h | 114 ++++ + .../include/asic_reg/dcn/dcn_3_1_6_sh_mask.h | 501 ++++++++++++++++++ + 2 files changed, 615 insertions(+) + diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_offset.h -index a05bf8e4f58d..3a636a276e44 100644 +index a05bf8e4f58d96..3a636a276e4465 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_offset.h @@ -8520,6 +8520,120 @@ @@ -9103,7 +6659,7 @@ index a05bf8e4f58d..3a636a276e44 100644 // base address: 0x0 #define regDPG0_DPG_CONTROL 0x1854 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_sh_mask.h -index df84941bbe5b..8c2346d661ad 100644 +index df84941bbe5be5..8c2346d661adc8 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_6_sh_mask.h @@ -28690,6 +28690,507 @@ @@ -9614,8 +7170,24 @@ index df84941bbe5b..8c2346d661ad 100644 // addressBlock: dce_dc_opp_dpg0_dispdec //DPG0_DPG_CONTROL #define DPG0_DPG_CONTROL__DPG_EN__SHIFT 0x0 + +From 7086d416feeb7006dd40a0a3a0395979a1dc9559 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:09:39 +0100 +Subject: [PATCH 012/103] dcn_3_2_0_offset.h dcn_3_2_0_sh_mask.h: add HPO HDMI + registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../include/asic_reg/dcn/dcn_3_2_0_offset.h | 114 ++++ + .../include/asic_reg/dcn/dcn_3_2_0_sh_mask.h | 501 ++++++++++++++++++ + 2 files changed, 615 insertions(+) + diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h -index 78cb61d5800a..8d04e861f16b 100644 +index 78cb61d5800ac1..8d04e861f16b28 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h @@ -7462,6 +7462,120 @@ @@ -9740,7 +7312,7 @@ index 78cb61d5800a..8d04e861f16b 100644 // base address: 0x0 #define regDPG0_DPG_CONTROL 0x1854 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h -index c20bf730dc55..18d577ff90f6 100644 +index c20bf730dc553e..18d577ff90f6d2 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h @@ -23157,6 +23157,507 @@ @@ -10251,8 +7823,24 @@ index c20bf730dc55..18d577ff90f6 100644 // addressBlock: dcn_dc_opp_dpg0_dispdec //DPG0_DPG_CONTROL #define DPG0_DPG_CONTROL__DPG_EN__SHIFT 0x0 + +From fe1421744d0855669dc23a31dc585f5cf5ce06ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:09:50 +0100 +Subject: [PATCH 013/103] dcn_3_2_1_offset.h dcn_3_2_1_sh_mask.h: add HPO HDMI + registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../include/asic_reg/dcn/dcn_3_2_1_offset.h | 114 ++++ + .../include/asic_reg/dcn/dcn_3_2_1_sh_mask.h | 501 ++++++++++++++++++ + 2 files changed, 615 insertions(+) + diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h -index a04b8c32c564..2a316fd2544e 100644 +index a04b8c32c56497..2a316fd2544e1f 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h @@ -7461,6 +7461,120 @@ @@ -10377,7 +7965,7 @@ index a04b8c32c564..2a316fd2544e 100644 // base address: 0x0 #define regDPG0_DPG_CONTROL 0x1854 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h -index ce773fca621f..b083d9b614b5 100644 +index ce773fca621f5c..b083d9b614b5de 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h @@ -23133,6 +23133,507 @@ @@ -10888,101 +8476,1388 @@ index ce773fca621f..b083d9b614b5 100644 // addressBlock: dce_dc_opp_dpg0_dispdec //DPG0_DPG_CONTROL #define DPG0_DPG_CONTROL__DPG_EN__SHIFT 0x0 -diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h -index ff77b71167eb..2e0a34493183 100644 ---- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h -+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h -@@ -52413,7 +52413,7 @@ - #define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL_MASK 0x00000007L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 --#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING__SHIFT 0x8 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 -@@ -52421,7 +52421,7 @@ - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L --#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_MASK 0x00000300L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L -diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h -index d0e95d324053..8859272970b7 100644 ---- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h -+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_1_sh_mask.h -@@ -52392,7 +52392,7 @@ - #define HDMI_STREAM_ENC_INPUT_MUX_CONTROL__HDMI_STREAM_ENC_INPUT_MUX_SOURCE_SEL_MASK 0x00000007L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 --#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING__SHIFT 0x8 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 -@@ -52400,7 +52400,7 @@ - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L --#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_MASK 0x00000300L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L -diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h -index 3ffb6ec8b40a..2b461f3f2e5d 100644 ---- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h -+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_6_0_sh_mask.h -@@ -48669,7 +48669,7 @@ - //HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE__SHIFT 0x0 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET__SHIFT 0x4 --#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING__SHIFT 0x8 -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE__SHIFT 0x8 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE__SHIFT 0xc - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE__SHIFT 0x10 - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE__SHIFT 0x14 -@@ -48677,7 +48677,7 @@ - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ERROR__SHIFT 0x1c - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ENABLE_MASK 0x00000001L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_MASK 0x00000010L --#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_MASK 0x00000300L -+#define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_PIXEL_ENCODING_TYPE_MASK 0x00000300L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_ODM_COMBINE_MODE_MASK 0x00003000L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_DSC_MODE_MASK 0x00030000L - #define HDMI_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0__FIFO_RESET_DONE_MASK 0x00100000L -diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h -index b344acefc606..3969abd2fdb7 100644 ---- a/drivers/gpu/drm/amd/include/atombios.h -+++ b/drivers/gpu/drm/amd/include/atombios.h -@@ -1588,6 +1588,7 @@ typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 - #define ATOM_TRANSMITTER_DIGMODE_V6_DP 0 - #define ATOM_TRANSMITTER_DIGMODE_V6_DVI 2 - #define ATOM_TRANSMITTER_DIGMODE_V6_HDMI 3 -+#define ATOM_TRANSMITTER_DIGMODE_V6_HDMI_FRL 4 - #define ATOM_TRANSMITTER_DIGMODE_V6_DP_MST 5 + +From a634a5aa6afb1f4d7a0ffe4b1774d18cdf42c7cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:30:08 +0100 +Subject: [PATCH 014/103] + drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c: implement + set_hdmistreamclk +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../amd/display/dc/dccg/dcn31/dcn31_dccg.c | 54 +++++++++++++++++++ + .../amd/display/dc/dccg/dcn31/dcn31_dccg.h | 1 + + 2 files changed, 55 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c +index 97df04b7e39d18..13383f2b68ff78 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c +@@ -170,6 +170,59 @@ void dccg31_set_dpstreamclk( + dccg31_enable_dpstreamclk(dccg, otg_inst); + } - //ucHPDSel -diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h -index 3d083010e734..6949baf76737 100644 ---- a/drivers/gpu/drm/amd/include/atomfirmware.h -+++ b/drivers/gpu/drm/amd/include/atomfirmware.h -@@ -97,6 +97,7 @@ enum atom_encode_mode_def - ATOM_ENCODER_MODE_LVDS =1, - ATOM_ENCODER_MODE_DVI =2, - ATOM_ENCODER_MODE_HDMI =3, -+ ATOM_ENCODER_MODE_HDMI_FRL =4, - ATOM_ENCODER_MODE_DP_AUDIO =5, - ATOM_ENCODER_MODE_DP_MST =5, - ATOM_ENCODER_MODE_CRT =15, ++static void dccg31_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, ++ HDMISTREAMCLK0_GATE_DISABLE, 1); ++ } ++ REG_UPDATE_2(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_SRC_SEL, otg_inst, ++ HDMISTREAMCLK0_EN, 1); ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++static void dccg31_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ REG_UPDATE(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_EN, 0); ++ if (dccg->ctx->dc->debug.root_clock_optimization.bits.hdmistream) { ++ REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, ++ HDMISTREAMCLK0_GATE_DISABLE, 0); ++ } ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++static void dccg31_set_hdmistreamclk( ++ struct dccg *dccg, ++ enum streamclk_source src, ++ int otg_inst, ++ int hdmi_hpo_inst) ++{ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ if (src == REFCLK) ++ dccg31_disable_hdmistreamclk(dccg, hdmi_hpo_inst); ++ else ++ dccg31_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); ++} ++ + void dccg31_enable_symclk32_se( + struct dccg *dccg, + int hpo_se_inst, +@@ -836,6 +889,7 @@ static const struct dccg_funcs dccg31_funcs = { + .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, + .dccg_init = dccg31_init, + .set_dpstreamclk = dccg31_set_dpstreamclk, ++ .set_hdmistreamclk = dccg31_set_hdmistreamclk, + .enable_symclk32_se = dccg31_enable_symclk32_se, + .disable_symclk32_se = dccg31_disable_symclk32_se, + .enable_symclk32_le = dccg31_enable_symclk32_le, +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h +index bf659920d4cc2e..4d6753ade73888 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.h +@@ -147,6 +147,7 @@ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_GATE_DISABLE, mask_sh),\ ++ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ + +From 3c9dfe163667290d27f2419c69f3e0b49779f04d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:30:30 +0100 +Subject: [PATCH 015/103] + drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h: add missing + HDMISTREAMCLK define +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h +index 1757db56d1399d..b38dcdcd854c85 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn314/dcn314_dccg.h +@@ -151,6 +151,7 @@ + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\ + DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\ ++ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\ + +From 96743b0e7825ff9306d01aa13112d434c4800b49 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:40:20 +0100 +Subject: [PATCH 016/103] + drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c: Instantiate + HPO HDMI encoders +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../dc/resource/dcn32/dcn32_resource.c | 95 +++++++++++++++++++ + 1 file changed, 95 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +index b276fec3e479a2..a53570beed6016 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +@@ -57,6 +57,8 @@ + #include "dcn32/dcn32_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn32/dcn32_hpo_dp_link_encoder.h" + #include "dcn31/dcn31_apg.h" + #include "dcn31/dcn31_dio_link_encoder.h" +@@ -345,6 +347,18 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_stream_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; + + #define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) +@@ -363,6 +377,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_link_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs_init(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) + +@@ -651,6 +678,8 @@ static const struct resource_caps res_cap_dcn32 = { + .num_stream_encoder = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, +@@ -1301,6 +1330,48 @@ static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn32_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance: ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn32_vpg_create(ctx, vpg_inst); ++ afmt = dcn32_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_stream_enc_regs ++ hpo_hdmi_stream_encoder_reg_init(), ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1324,6 +1395,28 @@ static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn32_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_link_enc_regs ++ hpo_hdmi_link_encoder_reg_init(), ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn32_hwseq_create( + struct dc_context *ctx) + { +@@ -1347,6 +1440,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn32_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn32_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn32_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn32_hwseq_create, + }; + + +From 54dece95dcdd0d43fc31a7bc73e32d7ea18b9b86 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 00:40:36 +0100 +Subject: [PATCH 017/103] + drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c: instantiate + HPO HDMI encoders +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Michał Kopeć +--- + .../dc/resource/dcn321/dcn321_resource.c | 95 +++++++++++++++++++ + 1 file changed, 95 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +index 3466ca34c93fed..a5feaf536bc041 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +@@ -59,6 +59,8 @@ + #include "dcn32/dcn32_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn32/dcn32_hpo_dp_link_encoder.h" + #include "dcn31/dcn31_apg.h" + #include "dcn31/dcn31_dio_link_encoder.h" +@@ -344,6 +346,18 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_stream_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; + + #define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) +@@ -362,6 +376,19 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) + }; + ++#define hpo_hdmi_link_encoder_reg_init()\ ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++ ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs_init(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) + +@@ -647,6 +674,8 @@ static const struct resource_caps res_cap_dcn321 = { + .num_stream_encoder = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, +@@ -1282,6 +1311,48 @@ static struct hpo_dp_stream_encoder *dcn321_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn321_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance: ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn321_vpg_create(ctx, vpg_inst); ++ afmt = dcn321_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_stream_enc_regs ++ hpo_hdmi_stream_encoder_reg_init(), ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1305,6 +1376,28 @@ static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn321_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++#undef REG_STRUCT ++#define REG_STRUCT hpo_hdmi_link_enc_regs ++ hpo_hdmi_link_encoder_reg_init(), ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn321_hwseq_create( + struct dc_context *ctx) + { +@@ -1328,6 +1421,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn321_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn321_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn321_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn321_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn321_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn321_hwseq_create, + }; + + +From 2913ae1ad55f76626c9a30397a2a1d8d3e56d4a1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 01:02:38 +0100 +Subject: [PATCH 018/103] dcn31/dcn31_resource.c: instantiate HPO HDMI encoders + +--- + .../dc/resource/dcn31/dcn31_resource.c | 86 +++++++++++++++++++ + 1 file changed, 86 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +index 0d667b54ccf812..6334baffe7d742 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +@@ -56,6 +56,8 @@ + #include "dcn30/dcn30_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn31/dcn31_apg.h" + #include "dcn31/dcn31_dio_link_encoder.h" + #include "dcn31/dcn31_vpg.h" +@@ -450,6 +452,18 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define hpo_dp_link_encoder_reg_list(id)\ + [id] = {\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ +@@ -473,6 +487,18 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) + }; + ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs(id)\ + [id] = {\ + DPP_REG_LIST_DCN30(id),\ +@@ -819,6 +845,8 @@ static const struct resource_caps res_cap_dcn31 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, +@@ -1304,6 +1332,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn31_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1322,6 +1388,24 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn31_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn31_hwseq_create( + struct dc_context *ctx) + { +@@ -1341,6 +1425,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn31_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn31_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn31_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn31_hwseq_create, + }; + + +From aa35eb010a353d04e0db847ac25b7f9d4dc1887c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 01:03:05 +0100 +Subject: [PATCH 019/103] dcn315/dcn315_resource.c: instantiate HPO HDMI + encoders + +--- + .../dc/resource/dcn315/dcn315_resource.c | 85 +++++++++++++++++++ + 1 file changed, 85 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +index 4e962f522f1bee..0f0e34189ccf29 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +@@ -55,6 +55,8 @@ + #include "dcn30/dcn30_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn31/dcn31_apg.h" + #include "dcn31/dcn31_dio_link_encoder.h" + #include "dcn31/dcn31_vpg.h" +@@ -452,6 +454,17 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; + + #define hpo_dp_link_encoder_reg_list(id)\ + [id] = {\ +@@ -476,6 +489,18 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) + }; + ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; ++ + #define dpp_regs(id)\ + [id] = {\ + DPP_REG_LIST_DCN30(id),\ +@@ -818,6 +843,8 @@ static const struct resource_caps res_cap_dcn31 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, +@@ -1305,6 +1332,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn315_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1323,6 +1388,24 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn315_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct dce_hwseq *dcn31_hwseq_create( + struct dc_context *ctx) + { +@@ -1342,6 +1425,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn315_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn315_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn315_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn31_hwseq_create, + }; + + +From 56160a169c81cdab34b752a4a97c361d87786b45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 01:03:21 +0100 +Subject: [PATCH 020/103] dcn316/dcn316_resource.c: instantiate HPO HDMI + encoders + +--- + .../dc/resource/dcn316/dcn316_resource.c | 83 +++++++++++++++++++ + 1 file changed, 83 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +index 5a95dd54cb4298..7a035748814b89 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +@@ -55,6 +55,8 @@ + #include "dcn30/dcn30_dio_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_stream_encoder.h" + #include "dcn31/dcn31_hpo_dp_link_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_stream_encoder.h" ++#include "dcn30/dcn30_hpo_hdmi_link_encoder.h" + #include "dcn31/dcn31_apg.h" + #include "dcn31/dcn31_dio_link_encoder.h" + #include "dcn31/dcn31_vpg.h" +@@ -442,6 +444,17 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) + }; + ++static struct dcn30_hpo_hdmi_stream_encoder_registers hpo_hdmi_stream_enc_regs = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_shift hpo_hdmi_se_shift = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_stream_encoder_mask hpo_hdmi_se_mask = { ++ DCN3_0_HPO_HDMI_STREAM_ENC_MASK_SH_LIST(_MASK) ++}; + + #define hpo_dp_link_encoder_reg_list(id)\ + [id] = {\ +@@ -466,6 +479,17 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) + }; + ++static struct dcn30_hpo_hdmi_link_encoder_registers hpo_hdmi_link_enc_regs = { ++ DCN3_0_HPO_HDMI_LINK_ENC_REG_LIST() ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_shift hpo_hdmi_le_shift = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(__SHIFT) ++}; ++ ++static const struct dcn30_hpo_hdmi_link_encoder_mask hpo_hdmi_le_mask = { ++ DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(_MASK) ++}; + + #define dpp_regs(id)\ + [id] = {\ +@@ -813,6 +837,8 @@ static const struct resource_caps res_cap_dcn31 = { + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, ++ .num_hpo_hdmi_stream_encoder = 1, ++ .num_hpo_hdmi_link_encoder = 1, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, +@@ -1299,6 +1325,44 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_stream_encoder *dcn316_hpo_hdmi_stream_encoder_create( ++ enum engine_id eng_id, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_stream_encoder *hpo_hdmi_enc30; ++ struct vpg *vpg; ++ struct afmt *afmt; ++ uint32_t hpo_hdmi_inst; ++ uint32_t vpg_inst; ++ uint32_t afmt_inst; ++ ++ hpo_hdmi_inst = eng_id - ENGINE_ID_HPO_0; ++ ++ /* Mapping of VPG register blocks to HPO HDMI block instance (guessed): ++ * VPG[5] -> HPO_HDMI[0] ++ * AFMT[5] -> HPO_HDMI[0] ++ */ ++ vpg_inst = hpo_hdmi_inst + 5; ++ afmt_inst = hpo_hdmi_inst + 5; ++ ++ /* allocate HPO stream encoder and create VPG sub-block */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_stream_encoder), GFP_KERNEL); ++ vpg = dcn31_vpg_create(ctx, vpg_inst); ++ afmt = dcn31_afmt_create(ctx, afmt_inst); ++ ++ if (!hpo_hdmi_enc30 || !vpg || !afmt) { ++ kfree(hpo_hdmi_enc30); ++ kfree(vpg); ++ return NULL; ++ } ++ ++ dcn30_hpo_hdmi_stream_encoder_construct(hpo_hdmi_enc30, ctx, hpo_hdmi_inst, ++ vpg, afmt, &hpo_hdmi_stream_enc_regs, ++ &hpo_hdmi_se_shift, &hpo_hdmi_se_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} ++ + static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +@@ -1317,6 +1381,23 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + return &hpo_dp_enc31->base; + } + ++static struct hpo_hdmi_link_encoder *dcn316_hpo_hdmi_link_encoder_create( ++ uint8_t inst, ++ struct dc_context *ctx) ++{ ++ struct dcn30_hpo_hdmi_link_encoder *hpo_hdmi_enc30; ++ ++ /* allocate HPO link encoder */ ++ hpo_hdmi_enc30 = kzalloc(sizeof(struct dcn30_hpo_hdmi_link_encoder), GFP_KERNEL); ++ if (!hpo_hdmi_enc30) ++ return NULL; /* out of memory */ ++ ++ hpo_hdmi_link_encoder31_construct(hpo_hdmi_enc30, ctx, inst, ++ &hpo_hdmi_link_enc_regs, ++ &hpo_hdmi_le_shift, &hpo_hdmi_le_mask); ++ ++ return &hpo_hdmi_enc30->base; ++} + + static struct dce_hwseq *dcn31_hwseq_create( + struct dc_context *ctx) +@@ -1337,6 +1418,8 @@ static const struct resource_create_funcs res_create_funcs = { + .create_stream_encoder = dcn316_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, ++ .create_hpo_hdmi_stream_encoder = dcn316_hpo_hdmi_stream_encoder_create, ++ .create_hpo_hdmi_link_encoder = dcn316_hpo_hdmi_link_encoder_create, + .create_hwseq = dcn31_hwseq_create, + }; + + +From 184ed121ef773b9f49978eeb413b9506bea3dd48 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sun, 15 Feb 2026 01:43:51 +0100 +Subject: [PATCH 021/103] drm/edid: Improve HDMI FRL caps saving/parsing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +With a real client for these caps, there was a need to slightly modify +how they are saved and what info they contain. + +[How] +Save FRL info in renamed parsing function + save raw max_rate value. +Eject FRL data into separate struct, reused in dsc_caps. + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/drm_edid.c | 42 ++++++++++++++++++++----------------- + include/drm/drm_connector.h | 34 ++++++++++++++++++++---------- + 2 files changed, 46 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 26bb7710a46204..e987028ac443ae 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -6108,38 +6108,44 @@ static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db) + } + + static +-void drm_get_max_frl_rate(int max_frl_rate, u8 *max_lanes, u8 *max_rate_per_lane) ++void drm_parse_max_frl_rate(int max_frl_rate, struct drm_hdmi_frl_cap *frl) + { ++ u8 max_lanes, max_rate_per_lane; ++ + switch (max_frl_rate) { + case 1: +- *max_lanes = 3; +- *max_rate_per_lane = 3; ++ max_lanes = 3; ++ max_rate_per_lane = 3; + break; + case 2: +- *max_lanes = 3; +- *max_rate_per_lane = 6; ++ max_lanes = 3; ++ max_rate_per_lane = 6; + break; + case 3: +- *max_lanes = 4; +- *max_rate_per_lane = 6; ++ max_lanes = 4; ++ max_rate_per_lane = 6; + break; + case 4: +- *max_lanes = 4; +- *max_rate_per_lane = 8; ++ max_lanes = 4; ++ max_rate_per_lane = 8; + break; + case 5: +- *max_lanes = 4; +- *max_rate_per_lane = 10; ++ max_lanes = 4; ++ max_rate_per_lane = 10; + break; + case 6: +- *max_lanes = 4; +- *max_rate_per_lane = 12; ++ max_lanes = 4; ++ max_rate_per_lane = 12; + break; + case 0: + default: +- *max_lanes = 0; +- *max_rate_per_lane = 0; ++ max_lanes = 0; ++ max_rate_per_lane = 0; + } ++ ++ frl->max_lanes = max_lanes; ++ frl->max_rate = max_frl_rate; ++ frl->max_rate_per_lane = max_rate_per_lane; + } + + static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, +@@ -6178,8 +6184,7 @@ static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc, + u8 dsc_max_frl_rate; + + dsc_max_frl_rate = (hf_scds[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4; +- drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes, +- &hdmi_dsc->max_frl_rate_per_lane); ++ drm_parse_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->frl_cap); + + dsc_max_slices = hf_scds[12] & DRM_EDID_DSC_MAX_SLICES; + +@@ -6272,8 +6277,7 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, + + if (hf_scds[7]) { + max_frl_rate = (hf_scds[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4; +- drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes, +- &hdmi->max_frl_rate_per_lane); ++ drm_parse_max_frl_rate(max_frl_rate, &hdmi->frl_cap); + } + + drm_parse_ycbcr420_deep_color_info(connector, hf_scds); +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index 8f34f4b8183d83..f880b3097b2c3a 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -254,6 +254,24 @@ struct drm_scdc { + struct drm_scrambling scrambling; + }; + ++/** ++ * struct drm_hdmi_frl_cap - FRL capabilities of HDMI sink ++ * ++ * Describes the FRL support provided by HDMI 2.1 sink. ++ * The information is fetched fom additional HFVSDB blocks defined ++ * for HDMI 2.1. ++ */ ++struct drm_hdmi_frl_cap { ++ /** @max_rate: raw max rate value without parsing */ ++ u8 max_rate; ++ ++ /** @max_frl_rate_per_lane: support fixed rate link */ ++ u8 max_rate_per_lane; ++ ++ /** @max_lanes: supported by sink */ ++ u8 max_lanes; ++}; ++ + /** + * struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink + * +@@ -285,14 +303,11 @@ struct drm_hdmi_dsc_cap { + /** @clk_per_slice : max pixel clock in MHz supported per slice */ + int clk_per_slice; + +- /** @max_lanes : dsc max lanes supported for Fixed rate Link training */ +- u8 max_lanes; +- +- /** @max_frl_rate_per_lane : maximum frl rate with DSC per lane */ +- u8 max_frl_rate_per_lane; +- + /** @total_chunk_kbytes: max size of chunks in KBs supported per line*/ + u8 total_chunk_kbytes; ++ ++ /** @frl_cap: FRL under DSC capabilities of the sink */ ++ struct drm_hdmi_frl_cap frl_cap; + }; + + /** +@@ -324,11 +339,8 @@ struct drm_hdmi_info { + /** @y420_dc_modes: bitmap of deep color support index */ + u8 y420_dc_modes; + +- /** @max_frl_rate_per_lane: support fixed rate link */ +- u8 max_frl_rate_per_lane; +- +- /** @max_lanes: supported by sink */ +- u8 max_lanes; ++ /** @frl_cap: FRL capabilities of the sink */ ++ struct drm_hdmi_frl_cap frl_cap; + + /** @dsc_cap: DSC capabilities of the sink */ + struct drm_hdmi_dsc_cap dsc_cap; + +From 1ad22346d02858981375b619c86c2344d9349603 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sun, 15 Feb 2026 01:09:12 +0100 +Subject: [PATCH 022/103] drm/amd/display: Save HDMI FRL info to edid_caps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Incoming HDMI FRL training will need this info to properly decide on +link training settings. + +[How] +Add HDMI FRL data to dc_edid_caps as a separate struct. Copy HDMI FRL +caps to amdgpu's own edid_caps. + +Signed-off-by: Tomasz Pakuła +--- + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 8 ++++++++ + drivers/gpu/drm/amd/display/dc/dc_types.h | 17 +++++++++++++++++ + 2 files changed, 25 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index e5e993d3ef74a2..a5c19353dd2352 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -996,6 +996,14 @@ dm_helpers_read_acpi_edid(struct amdgpu_dm_connector *aconnector) + void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edid_caps *edid_caps) + { + edid_caps->scdc_present = hdmi->scdc.supported; ++ ++ /* FRL */ ++ if (edid_caps->frl_caps.max_rate == 0) ++ return; ++ ++ edid_caps->frl_caps.max_rate = hdmi->frl_cap.max_rate; ++ edid_caps->frl_caps.max_lanes = hdmi->frl_cap.max_lanes; ++ edid_caps->frl_caps.max_rate_per_lane = hdmi->frl_cap.max_rate_per_lane; + } + + enum dc_edid_status dm_helpers_read_local_edid( +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index f46039f642034f..c08e1c0f985851 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -185,6 +185,20 @@ struct dc_panel_patch { + unsigned int wait_after_dpcd_poweroff_ms; + }; + ++/** ++ * struct dc_hdmi_frl_caps - HDMI FRL Capabilities read from EDID. ++ */ ++struct dc_hdmi_frl_caps { ++ /* raw max_rate field */ ++ uint8_t max_rate; ++ ++ /* max supported data rate per lane in Gbps */ ++ uint8_t max_rate_per_lane; ++ ++ /* max supported FRL lanes by sink */ ++ uint8_t max_lanes; ++}; ++ + /** + * struct dc_edid_caps - Capabilities read from EDID. + * @analog: Whether the monitor is analog. Used by DVI-I handling. +@@ -213,6 +227,9 @@ struct dc_edid_caps { + /*HDMI 2.0 caps*/ + bool lte_340mcsc_scramble; + ++ /* HDMI 2.1 caps */ ++ struct dc_hdmi_frl_caps frl_caps; ++ + bool edid_hdmi; + bool hdr_supported; + bool rr_capable; + +From e2a65c3619b60b987b277857350a9ded7324c667 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sun, 15 Feb 2026 01:53:11 +0100 +Subject: [PATCH 023/103] drm/amd/display: Save HDMI DSC info to edid_caps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Incoming HDMI DSC over FRL support will need this info to properly +decide on link training settings and further link/compression settings. +Info about DSC support will also be needed to decide which modes can be +supported by DSC. + +[How] +Add HDMI DSC data to dc_edid_caps as a separate struct. Use FRL struct +inside not to duplicate efforts. Copy HDMI DSC caps to amdgpu's +own edid_caps. + +Signed-off-by: Tomasz Pakuła +--- + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 17 ++++++++++++++ + drivers/gpu/drm/amd/display/dc/dc_types.h | 22 +++++++++++++++++++ + 2 files changed, 39 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index a5c19353dd2352..ca2825aa4b08e0 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -995,6 +995,8 @@ dm_helpers_read_acpi_edid(struct amdgpu_dm_connector *aconnector) + + void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edid_caps *edid_caps) + { ++ struct dc_hdmi_dsc_caps *dsc = &edid_caps->dsc_caps; ++ + edid_caps->scdc_present = hdmi->scdc.supported; + + /* FRL */ +@@ -1004,6 +1006,21 @@ void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edi + edid_caps->frl_caps.max_rate = hdmi->frl_cap.max_rate; + edid_caps->frl_caps.max_lanes = hdmi->frl_cap.max_lanes; + edid_caps->frl_caps.max_rate_per_lane = hdmi->frl_cap.max_rate_per_lane; ++ ++ /* DSC */ ++ if (hdmi->dsc_cap.v_1p2 != true) ++ return; ++ ++ dsc->v1p2 = hdmi->dsc_cap.v_1p2; ++ dsc->all_bpp = hdmi->dsc_cap.all_bpp; ++ dsc->native_420 = hdmi->dsc_cap.native_420; ++ dsc->max_bpc = hdmi->dsc_cap.bpc_supported; ++ dsc->max_slices = hdmi->dsc_cap.max_slices; ++ dsc->total_chunk_kbytes = hdmi->dsc_cap.total_chunk_kbytes; ++ ++ dsc->frl.max_rate = hdmi->dsc_cap.frl_cap.max_rate; ++ dsc->frl.max_lanes = hdmi->dsc_cap.frl_cap.max_lanes; ++ dsc->frl.max_rate_per_lane = hdmi->dsc_cap.frl_cap.max_rate_per_lane; + } + + enum dc_edid_status dm_helpers_read_local_edid( +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index c08e1c0f985851..ef7ee70b6180b4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -199,6 +199,27 @@ struct dc_hdmi_frl_caps { + uint8_t max_lanes; + }; + ++/** ++ * struct dc_hdmi_dsc_caps - HDMI DSC Capabilities read from EDID. ++ */ ++struct dc_hdmi_dsc_caps { ++ /* Support DSC v1.2 */ ++ bool v1p2; ++ ++ bool all_bpp; ++ bool native_420; ++ ++ uint8_t max_bpc; ++ uint8_t total_chunk_kbytes; ++ uint8_t max_slices; ++ ++ /* max supported pixel clock per slice in MHz */ ++ uint16_t max_clk; ++ ++ /* Alternative FRL caps to use with DSC */ ++ struct dc_hdmi_frl_caps frl; ++}; ++ + /** + * struct dc_edid_caps - Capabilities read from EDID. + * @analog: Whether the monitor is analog. Used by DVI-I handling. +@@ -229,6 +250,7 @@ struct dc_edid_caps { + + /* HDMI 2.1 caps */ + struct dc_hdmi_frl_caps frl_caps; ++ struct dc_hdmi_dsc_caps dsc_caps; + + bool edid_hdmi; + bool hdr_supported; + +From 886b481d911bf8dcdb7848c16e90b84e22ec8820 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sun, 15 Feb 2026 02:31:29 +0100 +Subject: [PATCH 024/103] drm/amd/display: Pass FRL data from edid to dc_link +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Enable FRL training that's based on dat areceived from sink +in it's edid. + +[How] +Pass the data from local_sink's edid_caps to dc_link current config and +use it, to perform FRL training. + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 16 +++++----------- + .../dc/link/protocols/link_frl_training.c | 5 +++-- + .../dc/link/protocols/link_frl_training.h | 3 +-- + 3 files changed, 9 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +index 646c2170ed85a6..85dbb75fe06b7d 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +@@ -1979,13 +1979,14 @@ static enum dc_status enable_link_hdmi(struct pipe_ctx *pipe_ctx) + bool is_vga_mode = (stream->timing.h_addressable == 640) + && (stream->timing.v_addressable == 480); + struct dc *dc = pipe_ctx->stream->ctx->dc; +- uint8_t frl_rate, lane_count; + + DC_LOG_HW_LINK_TRAINING("enable_link_hdmi entered\n"); + + if (dc_is_hdmi_frl_signal(stream->signal)) { +- link->cur_link_settings.frl_rate = 6; +- link->cur_link_settings.lane_count = 4; ++ link->cur_link_settings.frl_rate = ++ link->local_sink->edid_caps.frl_caps.max_rate; ++ link->cur_link_settings.lane_count = ++ link->local_sink->edid_caps.frl_caps.max_lanes; + + DC_LOG_HW_LINK_TRAINING( + "FORCING FRL: rate=%d lanes=%d\n", +@@ -2006,14 +2007,7 @@ static enum dc_status enable_link_hdmi(struct pipe_ctx *pipe_ctx) + pipe_ctx->stream->signal, + &link->cur_link_settings); + +- frl_rate = link->cur_link_settings.frl_rate; +- lane_count = (frl_rate <= 3) ? 3 : 4; +- +- if (!dc_link_perform_frl_training( +- link, +- &pipe_ctx->link_res, +- frl_rate, +- lane_count)) { ++ if (!dc_link_perform_frl_training(link, &pipe_ctx->link_res)) { + DC_LOG_HW_LINK_TRAINING("HDMI FRL: training failed\n"); + return DC_ERROR_UNEXPECTED; + } +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 289aaeb9103fd3..07cd6546049296 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -52,10 +52,11 @@ static bool frl_write_scdc(struct dc_link *link, uint8_t offset, + } + + bool dc_link_perform_frl_training(struct dc_link *link, +- const struct link_resource *link_res, +- uint8_t frl_rate, uint8_t lane_count) ++ const struct link_resource *link_res) + { + struct hpo_hdmi_link_encoder *enc = link_res->hpo_hdmi_link_enc; ++ uint8_t lane_count = link->cur_link_settings.lane_count; ++ uint8_t frl_rate = link->cur_link_settings.frl_rate; + uint8_t sink_version; + uint8_t update; + uint8_t status; +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +index 39c60d3d5accdb..91ec5049448cc2 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +@@ -32,7 +32,6 @@ struct link_resource; + * false - training failed, link is disabled + */ + bool dc_link_perform_frl_training(struct dc_link *link, +- const struct link_resource *link_res, +- uint8_t frl_rate, uint8_t lane_count); ++ const struct link_resource *link_res); + + #endif /* __LINK_HDMI_FRL_TRAINING_H__ */ + +From 88563d312f800ebbfc23615c435d5e94201ca15e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 10:26:41 +0100 +Subject: [PATCH 025/103] + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c: fix check for FRL + max rate + +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index ca2825aa4b08e0..3591e494114553 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -1000,7 +1000,7 @@ void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edi + edid_caps->scdc_present = hdmi->scdc.supported; + + /* FRL */ +- if (edid_caps->frl_caps.max_rate == 0) ++ if (hdmi->frl_cap.max_rate == 0) + return; + + edid_caps->frl_caps.max_rate = hdmi->frl_cap.max_rate; + +From aacf999df895a9ed9c7ad55371cc443836e7d5c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 07:00:40 +0100 +Subject: [PATCH 026/103] Fix compilation issue for frl_cap and dsc_cap + +--- + drivers/gpu/drm/display/drm_dp_helper.c | 2 +- + drivers/gpu/drm/i915/display/intel_dp.c | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c -index a697cc227e28..d0950a204b21 100644 +index f9fdf19de74a94..a0597abcb65432 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c -@@ -3904,7 +3904,7 @@ void drm_dp_pcon_hdmi_frl_link_error_count(struct drm_dp_aux *aux, +@@ -3875,7 +3875,7 @@ void drm_dp_pcon_hdmi_frl_link_error_count(struct drm_dp_aux *aux, int i, num_error; struct drm_hdmi_info *hdmi = &connector->display_info.hdmi; @@ -10991,8 +9866,2837 @@ index a697cc227e28..d0950a204b21 100644 if (drm_dp_dpcd_read_byte(aux, DP_PCON_HDMI_ERROR_STATUS_LN0 + i, &buf) < 0) return; +diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c +index 0ec82fcbcf48ef..67d14ce3d0af80 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp.c ++++ b/drivers/gpu/drm/i915/display/intel_dp.c +@@ -3904,13 +3904,13 @@ static int intel_dp_hdmi_sink_max_frl(struct intel_dp *intel_dp) + int max_lanes, rate_per_lane; + int max_dsc_lanes, dsc_rate_per_lane; + +- max_lanes = info->hdmi.max_lanes; +- rate_per_lane = info->hdmi.max_frl_rate_per_lane; ++ max_lanes = info->hdmi.frl_cap.max_lanes; ++ rate_per_lane = info->hdmi.frl_cap.max_rate_per_lane; + max_frl_rate = max_lanes * rate_per_lane; + + if (info->hdmi.dsc_cap.v_1p2) { +- max_dsc_lanes = info->hdmi.dsc_cap.max_lanes; +- dsc_rate_per_lane = info->hdmi.dsc_cap.max_frl_rate_per_lane; ++ max_dsc_lanes = info->hdmi.dsc_cap.frl_cap.max_lanes; ++ dsc_rate_per_lane = info->hdmi.dsc_cap.frl_cap.max_rate_per_lane; + if (max_dsc_lanes && dsc_rate_per_lane) + max_frl_rate = min(max_frl_rate, max_dsc_lanes * dsc_rate_per_lane); + } + +From 40ff9468ed420814584f61dd4407ded23b0eb95e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 07:01:16 +0100 +Subject: [PATCH 027/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c: fix + FRL lane count + +--- + .../drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c | 2 +- + drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c +index b13a818eef7277..7373d8a135f8bb 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.c +@@ -110,7 +110,7 @@ static void dcn30_hpo_hdmi_link_enc_configure_transmitter( + cntl.engine_id = enc3->base.preferred_engine; + cntl.transmitter = enc3->base.transmitter; + cntl.signal = SIGNAL_TYPE_HDMI_FRL; +- cntl.lanes_number = (frl_rate <= 3) ? 3 : 4; ++ cntl.lanes_number = (frl_rate <= 2) ? 3 : 4; + cntl.hpd_sel = enc3->base.hpd_source; + cntl.pixel_clock = hdmi_frl_rate_to_pixel_clock(frl_rate); + cntl.color_depth = COLOR_DEPTH_UNDEFINED; +diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +index 2059102c28b978..0122d0dfd19f90 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c ++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +@@ -27,7 +27,7 @@ static void enable_hpo_hdmi_frl_link_output( + + enc = link_res->hpo_hdmi_link_enc; + frl_rate = link_settings->frl_rate; +- lane_count = (frl_rate <= 3) ? 3 : 4; ++ lane_count = (frl_rate <= 2) ? 3 : 4; + + enc->funcs->configure_transmitter(enc, link, frl_rate, + link->link_enc->transmitter, + +From bdf51f52688e98f33abab43fd189097c498a2062 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 07:04:16 +0100 +Subject: [PATCH 028/103] + drivers/gpu/drm/amd/display/dc/link/link_validation.c: Add proper FRL link + validation + +--- + .../drm/amd/display/dc/link/link_validation.c | 44 ++++++++++++++----- + 1 file changed, 33 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +index b56a9c74c3e89d..4ea77329bb178a 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +@@ -329,28 +329,50 @@ static bool dp_validate_mode_timing( + return false; + } + +-static enum dc_status hdmi_validate_mode_timing( ++uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) ++{ ++ static const uint8_t frl_lane_rate_gbps[] = { ++ [1] = 3, [2] = 6, [3] = 6, [4] = 8, [5] = 10, [6] = 12, ++ }; ++ ++ uint32_t lane_rate_gbps; ++ uint32_t lane_count; ++ ++ if (frl_rate < 1 || frl_rate > 6) ++ return 0; ++ ++ lane_count = (frl_rate <= 2) ? 3 : 4; ++ lane_rate_gbps = frl_lane_rate_gbps[frl_rate]; ++ ++ return lane_count * lane_rate_gbps * 1000000; ++} ++ ++static bool hdmi_validate_mode_timing( + struct dc_link *link, + const struct dc_crtc_timing *timing) + { + uint32_t pix_clk_100hz; ++ uint32_t mode_bw_kbps; ++ uint32_t max_frl_bw_kbps; + + memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings)); + + pix_clk_100hz = get_tmds_output_pixel_clock_100hz(timing); ++ mode_bw_kbps = dc_bandwidth_in_kbps_from_timing(timing, ++ dc_link_get_highest_encoding_format(link)); + +- /* TMDS always allowed if it fits */ +- if (pix_clk_100hz <= 340000) { +- /* TMDS path: frl_rate stays 0 */ +- return DC_OK; +- } ++ max_frl_bw_kbps = hdmi_get_max_frl_bw_kbps( ++ link->local_sink->edid_caps.frl_caps.max_rate); + +- /* YEET FRL12 at the link, i'm too tired to do this properly */ +- link->cur_link_settings.frl_rate = 6; +- link->cur_link_settings.lane_count = 4; +- return DC_OK; +-} ++ /* TMDS is always allowed. */ ++ if (pix_clk_100hz <= 6000000) ++ return true; ++ /* FRL is allowed if the sink supports the required FRL rate. */ ++ else if (mode_bw_kbps <= max_frl_bw_kbps) ++ return true; + ++ return false; ++} + + enum dc_status link_validate_mode_timing( + const struct dc_stream_state *stream, + +From cdedf6383dd0bbad3877918f6092e03200f6694c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 07:22:27 +0100 +Subject: [PATCH 029/103] display/dc/core/dc_resource.c: Drop workaround for + FRL bringup + +--- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1 - + .../gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c | 5 +++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 60f04c45b839a1..15e4472fa8185b 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -5202,7 +5202,6 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) + + if (res == DC_OK) { + if (link->ep_type == DISPLAY_ENDPOINT_PHY && +- !dc_is_hdmi_frl_signal(stream->signal) && /* FIXME: Temporary w/a for link encoder bringup */ + !link->link_enc->funcs->validate_output_with_stream( + link->link_enc, stream)) + res = DC_FAIL_ENC_VALIDATE; +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c +index 1c12281164877d..10e05615c5d62a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c +@@ -620,6 +620,10 @@ static bool dcn10_link_encoder_validate_hdmi_output( + enum dc_color_depth max_deep_color = + enc10->base.features.max_hdmi_deep_color; + ++ // FRL is always fine. TODO add validation ++ if (edid_caps->frl_caps.max_rate > 0) ++ return true; ++ + // check pixel clock against edid specified max TMDS clk + if (edid_caps->max_tmds_clk_mhz != 0 && + adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) +@@ -800,6 +804,7 @@ bool dcn10_link_encoder_validate_output_with_stream( + &stream->timing); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: ++ case SIGNAL_TYPE_HDMI_FRL: + is_valid = dcn10_link_encoder_validate_hdmi_output( + enc10, + &stream->timing, + +From 69b458edb26c99b3f7ac68616f28afb028e3570b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 12:35:19 +0100 +Subject: [PATCH 030/103] Broken FRL link validation + +--- + .../drm/amd/display/dc/core/dc_link_exports.c | 4 ++ + .../gpu/drm/amd/display/dc/core/dc_resource.c | 51 ++++++++++++++++++- + .../drm/amd/display/dc/link/link_validation.c | 2 +- + 3 files changed, 54 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +index 9acd300197173f..7e7915e2f9670e 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +@@ -345,6 +345,10 @@ enum dc_link_encoding_format dc_link_get_highest_encoding_format(const struct dc + DP_128b_132b_ENCODING) + return DC_LINK_ENCODING_DP_128b_132b; + } else if (dc_is_hdmi_signal(link->connector_signal)) { ++ if (link->local_sink->edid_caps.frl_caps.max_rate > 0) ++ return DC_LINK_ENCODING_HDMI_FRL; ++ else ++ return DC_LINK_ENCODING_HDMI_TMDS; + } + + return DC_LINK_ENCODING_UNSPECIFIED; +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 15e4472fa8185b..db9cff9def39b0 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -3974,6 +3974,50 @@ static bool acquire_otg_master_pipe_for_stream( + return pipe_idx != FREE_PIPE_INDEX_NOT_FOUND; + } + ++static uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) ++{ ++ static const uint8_t frl_lane_rate_gbps[] = { ++ [1] = 3, [2] = 6, [3] = 6, [4] = 8, [5] = 10, [6] = 12, ++ }; ++ ++ uint32_t lane_rate_gbps; ++ uint32_t lane_count; ++ ++ if (frl_rate < 1 || frl_rate > 6) ++ return 0; ++ ++ lane_count = (frl_rate <= 2) ? 3 : 4; ++ lane_rate_gbps = frl_lane_rate_gbps[frl_rate]; ++ ++ return lane_count * lane_rate_gbps * 1000000 / 8; ++} ++ ++static bool hdmi_decide_link_settings( ++ struct dc_stream_state *stream, ++ struct pipe_ctx *pipe_ctx) ++{ ++ uint8_t frl_rate; ++ uint32_t rate_bw; ++ uint32_t req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing, ++ dc_link_get_highest_encoding_format(stream->link)); ++ ++ for (frl_rate = 1; ++ frl_rate < stream->link->local_sink->edid_caps.frl_caps.max_rate; ++ ++frl_rate) ++ { ++ rate_bw = hdmi_get_max_frl_bw_kbps(frl_rate); ++ pr_err("HDMI FRL: rate_bw %u, req_bw %u\n", rate_bw, req_bw); ++ if (rate_bw >= req_bw) { ++ pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = frl_rate <= 2 ? 3 : 4; ++ ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + enum dc_status resource_map_pool_resources( + const struct dc *dc, + struct dc_state *context, +@@ -4056,8 +4100,11 @@ enum dc_status resource_map_pool_resources( + } + + if (dc_is_hdmi_frl_signal(stream->signal)) { +- pipe_ctx->stream_res.hpo_hdmi_stream_enc = pool->hpo_hdmi_stream_enc[0]; +- pipe_ctx->link_res.hpo_hdmi_link_enc = pool->hpo_hdmi_link_enc[0]; ++ if (pipe_ctx->stream->link->local_sink->edid_caps.frl_caps.max_rate && ++ hdmi_decide_link_settings(stream, pipe_ctx)) { ++ pipe_ctx->stream_res.hpo_hdmi_stream_enc = pool->hpo_hdmi_stream_enc[0]; ++ pipe_ctx->link_res.hpo_hdmi_link_enc = pool->hpo_hdmi_link_enc[0]; ++ } + } + + if (dc->config.unify_link_enc_assignment && is_dio_encoder) +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +index 4ea77329bb178a..2a06dbccf0f531 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +@@ -329,7 +329,7 @@ static bool dp_validate_mode_timing( + return false; + } + +-uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) ++static uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) + { + static const uint8_t frl_lane_rate_gbps[] = { + [1] = 3, [2] = 6, [3] = 6, [4] = 8, [5] = 10, [6] = 12, + +From d6798d6dd41e3d59c29b33003acc647b827dc47c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 21:51:02 +0100 +Subject: [PATCH 031/103] drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c: + Upgrade signal to FRL if needed + +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index da075e431180df..e5bdb064aef487 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -6771,12 +6771,22 @@ static void fill_stream_properties_from_drm_display_mode( + + stream->out_transfer_func.type = TF_TYPE_PREDEFINED; + stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB; ++ ++ /* If pixel clock exceeds max HDMI TMDS clock, do one of two things: ++ * - If FRL is supported, upgrade the signal type to FRL ++ * - Else, try to fall back to 4:2:0 encoding for TMDS ++ */ + if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) { + if (!adjust_colour_depth_from_display_info(timing_out, info) && + drm_mode_is_420_also(info, mode_in) && + timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) { +- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; +- adjust_colour_depth_from_display_info(timing_out, info); ++ if (stream->link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE && ++ stream->sink->edid_caps.frl_caps.max_rate > 0) { ++ stream->signal = SIGNAL_TYPE_HDMI_FRL; ++ } else { ++ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; ++ adjust_colour_depth_from_display_info(timing_out, info); ++ } + } + } + +@@ -7373,7 +7383,9 @@ create_stream_for_sink(struct drm_connector *connector, + connector, + sink); + +- update_stream_signal(stream, sink); ++ /* Don't touch if already upgraded to FRL */ ++ if (stream->signal != SIGNAL_TYPE_HDMI_FRL) ++ update_stream_signal(stream, sink); + + if (dc_is_hdmi_signal(stream->signal)) + mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); + +From 85d6a0f21b9d3e63cddb7ec2fb1c8fe0a2f17f01 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 21:51:27 +0100 +Subject: [PATCH 032/103] drivers/gpu/drm/amd/display/dc/inc/core_status.h: Add + FRL bw error + +--- + drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 2 ++ + drivers/gpu/drm/amd/display/dc/inc/core_status.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +index bbce751b485fdc..b08362afbd764a 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +@@ -270,6 +270,8 @@ char *dc_status_to_str(enum dc_status status) + return "HW Cursor not supported"; + case DC_FAIL_DP_TUNNEL_BW_VALIDATE: + return "Fail DP Tunnel BW validation"; ++ case DC_FAIL_FRL_LINK_BANDWIDTH: ++ return "Insufficient FRL link bandwidth"; + case DC_ERROR_UNEXPECTED: + return "Unexpected error"; + } +diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h +index 82085d9c3f4078..b6e60b1e53d35f 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h +@@ -60,6 +60,7 @@ enum dc_status { + DC_FAIL_DP_LINK_BANDWIDTH = 28, + DC_FAIL_HW_CURSOR_SUPPORT = 29, + DC_FAIL_DP_TUNNEL_BW_VALIDATE = 30, ++ DC_FAIL_FRL_LINK_BANDWIDTH = 31, + DC_ERROR_UNEXPECTED = -1 + }; + + +From 788afca3f4407773d8d4ecb799735f7674e3ca76 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 21:51:51 +0100 +Subject: [PATCH 033/103] drivers/gpu/drm/amd/display/dc/core/dc_resource.c: + properly check FRL B/W + +--- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index db9cff9def39b0..b78b162cab5cf9 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -3989,7 +3989,7 @@ static uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) + lane_count = (frl_rate <= 2) ? 3 : 4; + lane_rate_gbps = frl_lane_rate_gbps[frl_rate]; + +- return lane_count * lane_rate_gbps * 1000000 / 8; ++ return lane_count * lane_rate_gbps * 1000000 * 16 / 18; + } + + static bool hdmi_decide_link_settings( +@@ -4002,7 +4002,7 @@ static bool hdmi_decide_link_settings( + dc_link_get_highest_encoding_format(stream->link)); + + for (frl_rate = 1; +- frl_rate < stream->link->local_sink->edid_caps.frl_caps.max_rate; ++ frl_rate <= stream->link->local_sink->edid_caps.frl_caps.max_rate; + ++frl_rate) + { + rate_bw = hdmi_get_max_frl_bw_kbps(frl_rate); +@@ -4100,11 +4100,12 @@ enum dc_status resource_map_pool_resources( + } + + if (dc_is_hdmi_frl_signal(stream->signal)) { +- if (pipe_ctx->stream->link->local_sink->edid_caps.frl_caps.max_rate && +- hdmi_decide_link_settings(stream, pipe_ctx)) { +- pipe_ctx->stream_res.hpo_hdmi_stream_enc = pool->hpo_hdmi_stream_enc[0]; +- pipe_ctx->link_res.hpo_hdmi_link_enc = pool->hpo_hdmi_link_enc[0]; +- } ++ if (!hdmi_decide_link_settings(stream, pipe_ctx)) ++ return DC_FAIL_FRL_LINK_BANDWIDTH; ++ ++ /* Only one pair of encoders on all HW so far. */ ++ pipe_ctx->stream_res.hpo_hdmi_stream_enc = pool->hpo_hdmi_stream_enc[0]; ++ pipe_ctx->link_res.hpo_hdmi_link_enc = pool->hpo_hdmi_link_enc[0]; + } + + if (dc->config.unify_link_enc_assignment && is_dio_encoder) + +From 1b46d66901e5c7de50f182761ae634152966f283 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 21:52:07 +0100 +Subject: [PATCH 034/103] drivers/gpu/drm/amd/display/dc/link/link_dpms.c: + don't force FRL rates + +--- + drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +index 85dbb75fe06b7d..066141cd069531 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +@@ -1982,24 +1982,15 @@ static enum dc_status enable_link_hdmi(struct pipe_ctx *pipe_ctx) + + DC_LOG_HW_LINK_TRAINING("enable_link_hdmi entered\n"); + +- if (dc_is_hdmi_frl_signal(stream->signal)) { +- link->cur_link_settings.frl_rate = +- link->local_sink->edid_caps.frl_caps.max_rate; +- link->cur_link_settings.lane_count = +- link->local_sink->edid_caps.frl_caps.max_lanes; +- +- DC_LOG_HW_LINK_TRAINING( +- "FORCING FRL: rate=%d lanes=%d\n", +- link->cur_link_settings.frl_rate, +- link->cur_link_settings.lane_count); +- } +- + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); + + if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) && + link_hwss->ext.enable_hdmi_link_output) { + +- DC_LOG_HW_LINK_TRAINING("HDMI FRL detected, using HPO path\n"); ++ link->cur_link_settings.frl_rate = ++ pipe_ctx->link_config.dp_link_settings.frl_rate; ++ link->cur_link_settings.lane_count = ++ pipe_ctx->link_config.dp_link_settings.lane_count; + + link_hwss->ext.enable_hdmi_link_output( + link, + +From 655d23b23ab029e65881a0a652c9e9b3e56747c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 21:52:48 +0100 +Subject: [PATCH 035/103] drivers/gpu/drm/amd/display/dc/dio/dcn*: add FRL cap + on supported DCN gens + +--- + .../gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c | 1 + + .../gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c | 1 + + .../gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c | 1 + + .../gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c | 1 + + .../gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c | 1 + + drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 1 + + 6 files changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c +index 84cc2ddc52fe89..7cc949075ec19a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c +@@ -384,6 +384,7 @@ void dcn31_link_encoder_construct( + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; ++ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c +index 06907e8a4eda12..cb5205d2d49f33 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c +@@ -317,6 +317,7 @@ void dcn32_link_encoder_construct( + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; ++ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c +index 2ed382a8e79c66..f092bde732818c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c +@@ -180,6 +180,7 @@ void dcn321_link_encoder_construct( + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; ++ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c +index 9972911330b653..ca5a5bcf22b3d6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c +@@ -258,6 +258,7 @@ void dcn35_link_encoder_construct( + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; ++ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; + + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c +index 7e558ca195ef0f..88389df2b25c33 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c +@@ -311,6 +311,7 @@ void dcn401_link_encoder_construct( + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; ++ enc10->base.features.flags.bits.IS_HDMI_FRL_CAPABLE = 1; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +index ee174926f6a90f..cba6661149a4b3 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +@@ -65,6 +65,7 @@ struct encoder_feature_support { + uint32_t IS_UHBR13_5_CAPABLE:1; + uint32_t IS_UHBR20_CAPABLE:1; + uint32_t DP_IS_USB_C:1; ++ uint32_t IS_HDMI_FRL_CAPABLE:1; + } bits; + uint32_t raw; + } flags; + +From 2b163d221eb5d4f88bddd5272ca3d4e04464cc31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 22:18:05 +0100 +Subject: [PATCH 036/103] drivers/gpu/drm/amd/display/dc/core/dc_stream.c: + properly upgrade signal to FRL + +--- + drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +index 129cd5f8498377..24d88998a3dc8a 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +@@ -52,6 +52,11 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink) + else + stream->signal = sink->sink_signal; + ++ if (dc_is_hdmi_tmds_signal(stream->signal)) ++ if (stream->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE && ++ sink->edid_caps.frl_caps.max_rate > 0) ++ stream->signal = SIGNAL_TYPE_HDMI_FRL; ++ + if (dc_is_dvi_signal(stream->signal)) { + if (stream->ctx->dc->caps.dual_link_dvi && + (stream->timing.pix_clk_100hz / 10) > TMDS_MAX_PIXEL_CLOCK && + +From c561df04981ccdfb4902fd466ecdbdfdd41320d9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 22:18:21 +0100 +Subject: [PATCH 037/103] drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c: + Remove fallback to TMDS + +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index e5bdb064aef487..6fc4a9672e4c76 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -6772,18 +6772,15 @@ static void fill_stream_properties_from_drm_display_mode( + stream->out_transfer_func.type = TF_TYPE_PREDEFINED; + stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB; + +- /* If pixel clock exceeds max HDMI TMDS clock, do one of two things: +- * - If FRL is supported, upgrade the signal type to FRL +- * - Else, try to fall back to 4:2:0 encoding for TMDS ++ /* If pixel clock exceeds max HDMI TMDS clock, and FRL is not possible, try ++ * to fall back to 4:2:0 encoding for TMDS + */ + if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) { + if (!adjust_colour_depth_from_display_info(timing_out, info) && + drm_mode_is_420_also(info, mode_in) && + timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) { +- if (stream->link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE && +- stream->sink->edid_caps.frl_caps.max_rate > 0) { +- stream->signal = SIGNAL_TYPE_HDMI_FRL; +- } else { ++ if (!stream->link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE || ++ stream->sink->edid_caps.frl_caps.max_rate == 0) { + timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; + adjust_colour_depth_from_display_info(timing_out, info); + } +@@ -7383,9 +7380,7 @@ create_stream_for_sink(struct drm_connector *connector, + connector, + sink); + +- /* Don't touch if already upgraded to FRL */ +- if (stream->signal != SIGNAL_TYPE_HDMI_FRL) +- update_stream_signal(stream, sink); ++ update_stream_signal(stream, sink); + + if (dc_is_hdmi_signal(stream->signal)) + mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); + +From 3514c61189950f58b2ebbc9c62febb3dff016b4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 22:28:06 +0100 +Subject: [PATCH 038/103] drivers/gpu/drm/amd/display/dc/core/dc_stream.c: fix + null pointer deref + +--- + drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +index 24d88998a3dc8a..746f20c305b3a2 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +@@ -53,7 +53,7 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink) + stream->signal = sink->sink_signal; + + if (dc_is_hdmi_tmds_signal(stream->signal)) +- if (stream->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE && ++ if (stream->link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE && + sink->edid_caps.frl_caps.max_rate > 0) + stream->signal = SIGNAL_TYPE_HDMI_FRL; + + +From b107d766ce864edaa3bb8c89e1efa83500b39c41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 22:36:40 +0100 +Subject: [PATCH 039/103] + drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c:dcn314_calculate_dccg_k1_k2_values: + handle frl case + +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +index 4ee6ed610de0b9..5350f480870aff 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +@@ -334,7 +334,7 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig + two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); + odm_combine_factor = get_odm_config(pipe_ctx, NULL); + +- if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { ++ if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(stream->signal)) { + *k1_div = PIXEL_RATE_DIV_BY_1; + *k2_div = PIXEL_RATE_DIV_BY_1; + } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) { + +From 744c6dae3a8490ef025581c77ea9eba27a94aa7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 15 Feb 2026 22:45:34 +0100 +Subject: [PATCH 040/103] + drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c:dcn32_calculate_dccg_k1_k2_values: + handle frl case + +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +index be1f3caf4096fe..27593e9988348f 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +@@ -1191,7 +1191,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign + two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); + odm_combine_factor = get_odm_config(pipe_ctx, NULL); + +- if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { ++ if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(stream->signal)) { + *k1_div = PIXEL_RATE_DIV_BY_1; + *k2_div = PIXEL_RATE_DIV_BY_1; + } else if (dc_is_hdmi_tmds_signal(stream->signal) || dc_is_dvi_signal(stream->signal)) { + +From 7752e9d8b0d06fbd208d7a1c65f7e975ff9805ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 18:53:46 +0100 +Subject: [PATCH 041/103] [HACK] + drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c: ungate HPO + permanently + +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +index 7aa0f452e8f7a3..325aa0882da6ba 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +@@ -918,7 +918,7 @@ void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx + void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state) + { +- bool hpo_frl_stream_enc_acquired = false; ++ bool hpo_frl_stream_enc_acquired = true; // HACK + bool hpo_dp_stream_enc_acquired = false; + int i = 0, j = 0; + int edp_num = 0; + +From 05024d613b83d2e9bea75a5acf49f82149976098 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:04 +0100 +Subject: [PATCH 042/103] drm/amd/display: Refactor + amdgpu_dm_update_freesync_caps() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +This function started to get very messy and hard to follow. + +[How] +Eject some functionality to separate functions and simplify greatly. + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 110 +++++++++++------- + 1 file changed, 69 insertions(+), 41 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 6fc4a9672e4c76..557a483a42918a 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13123,8 +13123,8 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector, + } + } + +-static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, +- const struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) ++static int parse_amd_vsdb_did(struct amdgpu_dm_connector *aconnector, ++ const struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) + { + u8 *edid_ext = NULL; + int i; +@@ -13158,13 +13158,13 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, + return false; + } + +-static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, ++static bool parse_amd_vsdb_cea(struct amdgpu_dm_connector *aconnector, + const struct edid *edid, + struct amdgpu_hdmi_vsdb_info *vsdb_info) + { ++ struct amdgpu_hdmi_vsdb_info vsdb_local = {0}; + u8 *edid_ext = NULL; + int i; +- bool valid_vsdb_found = false; + + /*----- drm_find_cea_extension() -----*/ + /* No EDID or EDID extensions */ +@@ -13185,9 +13185,47 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, + if (edid_ext[0] != CEA_EXT) + return -ENODEV; + +- valid_vsdb_found = parse_edid_cea(aconnector, edid_ext, EDID_LENGTH, vsdb_info); ++ if (!parse_edid_cea(aconnector, edid_ext, EDID_LENGTH, &vsdb_local)) ++ return -ENODEV; ++ ++ *vsdb_info = vsdb_local; ++ return false; ++} ++ ++static bool is_monitor_range_invalid(const struct drm_connector *conn) ++{ ++ return conn->display_info.monitor_range.min_vfreq == 0 || ++ conn->display_info.monitor_range.max_vfreq == 0; ++} ++ ++/* ++ * Returns true if (max_vfreq - min_vfreq) > 10 ++ */ ++static bool is_freesync_capable(const struct drm_monitor_range_info *range) ++{ ++ return (range->max_vfreq - range->min_vfreq) > 10; ++} ++ ++static void monitor_range_from_vsdb(struct drm_display_info *display, ++ const struct amdgpu_hdmi_vsdb_info *vsdb) ++{ ++ display->monitor_range.min_vfreq = vsdb->min_refresh_rate_hz; ++ display->monitor_range.max_vfreq = vsdb->max_refresh_rate_hz; ++} ++ ++/* ++ * Returns true if connector is capable of freesync ++ * Optionally, can fetch the range from AMD vsdb ++ */ ++static bool copy_range_to_amdgpu_connector(struct drm_connector *conn) ++{ ++ struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); ++ struct drm_monitor_range_info *range = &conn->display_info.monitor_range; ++ ++ aconn->min_vfreq = range->min_vfreq; ++ aconn->max_vfreq = range->max_vfreq; + +- return valid_vsdb_found ? i : -ENODEV; ++ return is_freesync_capable(range); + } + + /** +@@ -13204,13 +13242,14 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, + void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + const struct drm_edid *drm_edid) + { +- int i = 0; + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + struct dm_connector_state *dm_con_state = NULL; + struct dc_sink *sink; + struct amdgpu_device *adev = drm_to_adev(connector->dev); + struct amdgpu_hdmi_vsdb_info vsdb_info = {0}; ++ struct amdgpu_hdmi_vsdb_info vsdb_did = {0}; ++ struct dpcd_caps dpcd_caps = {0}; + const struct edid *edid; + bool freesync_capable = false; + enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; +@@ -13243,60 +13282,49 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + + edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() + ++ if (amdgpu_dm_connector->dc_link) ++ dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; ++ + /* Some eDP panels only have the refresh rate range info in DisplayID */ +- if ((connector->display_info.monitor_range.min_vfreq == 0 || +- connector->display_info.monitor_range.max_vfreq == 0)) ++ if (is_monitor_range_invalid(connector)) + parse_edid_displayid_vrr(connector, edid); + + if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || + sink->sink_signal == SIGNAL_TYPE_EDP)) { +- if (amdgpu_dm_connector->dc_link && +- amdgpu_dm_connector->dc_link->dpcd_caps.allow_invalid_MSA_timing_param) { +- amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq; +- amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq; +- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) +- freesync_capable = true; +- } + +- parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); ++ if (dpcd_caps.allow_invalid_MSA_timing_param) ++ freesync_capable = copy_range_to_amdgpu_connector(connector); + +- if (vsdb_info.replay_mode) { +- amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_info.replay_mode; +- amdgpu_dm_connector->vsdb_info.amd_vsdb_version = vsdb_info.amd_vsdb_version; ++ /* eDP */ ++ parse_amd_vsdb_did(amdgpu_dm_connector, edid, &vsdb_did); ++ if (vsdb_did.replay_mode) { ++ amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_did.replay_mode; ++ amdgpu_dm_connector->vsdb_info.amd_vsdb_version = vsdb_did.amd_vsdb_version; + amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP; + } + +- } else if (drm_edid && dc_is_hdmi_frl_signal(sink->sink_signal)) { +- i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); +- if (i >= 0 && vsdb_info.freesync_supported) { +- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz; +- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz; +- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) +- freesync_capable = true; +- +- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz; +- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz; ++ } else if (dc_is_hdmi_signal(sink->sink_signal) && ++ drm_edid) { ++ parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); ++ if (vsdb_info.freesync_supported) { ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ freesync_capable = copy_range_to_amdgpu_connector(connector); + } + } + + if (amdgpu_dm_connector->dc_link) + as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); + +- if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) { +- i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); +- if (i >= 0 && vsdb_info.freesync_supported && vsdb_info.amd_vsdb_version > 0) { +- ++ if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST && drm_edid) { ++ parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); ++ if (vsdb_info.freesync_supported) { + amdgpu_dm_connector->pack_sdp_v1_3 = true; + amdgpu_dm_connector->as_type = as_type; + amdgpu_dm_connector->vsdb_info = vsdb_info; + +- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz; +- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz; +- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) +- freesync_capable = true; +- +- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz; +- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz; ++ parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ freesync_capable = copy_range_to_amdgpu_connector(connector); + } + } + + +From f58f74cce8b0efc307426370c9567992f186d898 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Mon, 9 Feb 2026 20:10:23 +0100 +Subject: [PATCH 043/103] drm/amd/display: Remove redundant edid checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Edid parsing functions check if edid is not null themselves. In a case +where edid is not present, the structs will be left initialised to 0 +so anu possible assigment won't change the detected (or undetected) +functionality. + +[How] +Remove edid pointer checks + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 557a483a42918a..5bbdcd0e0267cf 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13289,8 +13289,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (is_monitor_range_invalid(connector)) + parse_edid_displayid_vrr(connector, edid); + +- if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || +- sink->sink_signal == SIGNAL_TYPE_EDP)) { ++ if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || ++ sink->sink_signal == SIGNAL_TYPE_EDP) { + + if (dpcd_caps.allow_invalid_MSA_timing_param) + freesync_capable = copy_range_to_amdgpu_connector(connector); +@@ -13303,8 +13303,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP; + } + +- } else if (dc_is_hdmi_signal(sink->sink_signal) && +- drm_edid) { ++ } else if (dc_is_hdmi_signal(sink->sink_signal)) { + parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); + if (vsdb_info.freesync_supported) { + monitor_range_from_vsdb(&connector->display_info, &vsdb_info); +@@ -13315,7 +13314,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (amdgpu_dm_connector->dc_link) + as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); + +- if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST && drm_edid) { ++ if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) { + parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); + if (vsdb_info.freesync_supported) { + amdgpu_dm_connector->pack_sdp_v1_3 = true; + +From 0ac499297314dfd4a61548f8987d85f2f2e048b0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Mon, 9 Feb 2026 20:25:27 +0100 +Subject: [PATCH 044/103] drm/amd/display: Move DisplayID vrr parsing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +DisplayID vrr parsing was always attempted, even though it's data is +only ever used in the DP/eDP path. + +[How] +Move the parsing to where it's actually needed + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 5bbdcd0e0267cf..ab6d6915a00f43 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13285,12 +13285,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (amdgpu_dm_connector->dc_link) + dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; + +- /* Some eDP panels only have the refresh rate range info in DisplayID */ +- if (is_monitor_range_invalid(connector)) +- parse_edid_displayid_vrr(connector, edid); +- + if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || + sink->sink_signal == SIGNAL_TYPE_EDP) { ++ /* Some eDP panels only have the refresh rate range info in DisplayID */ ++ if (is_monitor_range_invalid(connector)) ++ parse_edid_displayid_vrr(connector, edid); + + if (dpcd_caps.allow_invalid_MSA_timing_param) + freesync_capable = copy_range_to_amdgpu_connector(connector); + +From 3859c9e0d4ea67a6e2e635c9ab5c6e8ab2ea0bba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Mon, 9 Feb 2026 20:14:42 +0100 +Subject: [PATCH 045/103] drm/amd/display: Always try to parse AMD vsdb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Allows us to make the code inside amdgpu_dm_update_freesync_caps() more +concise and prepares for vsdb usage outside of HDMI and +DP -> HDMI 2.1 dongles. + +[How] +Move the parsing function outside of specific signal type blocks. +Merge signal type checks and freesync_supported checks + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++++++++----------- + 1 file changed, 11 insertions(+), 16 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index ab6d6915a00f43..d748b30dfefcfb 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13281,6 +13281,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + goto update; + + edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() ++ parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); + + if (amdgpu_dm_connector->dc_link) + dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; +@@ -13302,28 +13303,22 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP; + } + +- } else if (dc_is_hdmi_signal(sink->sink_signal)) { +- parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); +- if (vsdb_info.freesync_supported) { +- monitor_range_from_vsdb(&connector->display_info, &vsdb_info); +- freesync_capable = copy_range_to_amdgpu_connector(connector); +- } ++ } else if (dc_is_hdmi_signal(sink->sink_signal) && vsdb_info.freesync_supported) { ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ freesync_capable = copy_range_to_amdgpu_connector(connector); + } + + if (amdgpu_dm_connector->dc_link) + as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); + +- if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) { +- parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); +- if (vsdb_info.freesync_supported) { +- amdgpu_dm_connector->pack_sdp_v1_3 = true; +- amdgpu_dm_connector->as_type = as_type; +- amdgpu_dm_connector->vsdb_info = vsdb_info; ++ if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST && vsdb_info.freesync_supported) { ++ amdgpu_dm_connector->pack_sdp_v1_3 = true; ++ amdgpu_dm_connector->as_type = as_type; ++ amdgpu_dm_connector->vsdb_info = vsdb_info; + +- parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); +- monitor_range_from_vsdb(&connector->display_info, &vsdb_info); +- freesync_capable = copy_range_to_amdgpu_connector(connector); +- } ++ parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ freesync_capable = copy_range_to_amdgpu_connector(connector); + } + + update: + +From 0b4797b6eb42bea05ebf469d1308ed7743fa9fa8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Mon, 9 Feb 2026 20:23:41 +0100 +Subject: [PATCH 046/103] drm/amd/display: Check for VRR range in CEA AMD vsdb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Some monitors only expose GTF ranges (or others, without Range Limits +Only flag). This breaks VRR even though they have explicit FreeSync +support. + +Currently, if monitor ranges were missing, amdgpu only searched for AMD +vsdb in DisplayID but many monitors have it in CEA, just like HDMI. + +[How] +For DP and eDP connections, check for VRR ranges provided in AMD vendor- +specific data block if VRR range wasn't detected. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3894 +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4457 +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4747 +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4856 +Signed-off-by: Tomasz Pakuła +Reviewed-by: Harry Wentland +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index d748b30dfefcfb..4cb6584cf436f6 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13291,6 +13291,12 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + /* Some eDP panels only have the refresh rate range info in DisplayID */ + if (is_monitor_range_invalid(connector)) + parse_edid_displayid_vrr(connector, edid); ++ /* ++ * Many monitors expose AMD vsdb in CAE even for DP and their ++ * monitor ranges do not contain Range Limits Only flag ++ */ ++ if (is_monitor_range_invalid(connector)) ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); + + if (dpcd_caps.allow_invalid_MSA_timing_param) + freesync_capable = copy_range_to_amdgpu_connector(connector); + +From 5e1d0acfc25e96b4027829cd4c8db0ff1ece0a07 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Mon, 9 Feb 2026 20:23:42 +0100 +Subject: [PATCH 047/103] drm/amd/display: Use bigger VRR range if found in AMD + vsdb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Some monitors only expose their full VRR range in AMD vsdb for some +reason. + +[How] +Compare exposed ranges and use the bigger one. +Only adjust lower limit if it doesn't support LFC + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4177 +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 4cb6584cf436f6..c7941507e0f9cb 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13228,6 +13228,34 @@ static bool copy_range_to_amdgpu_connector(struct drm_connector *conn) + return is_freesync_capable(range); + } + ++static void extend_range_from_vsdb(struct drm_display_info *display, ++ const struct amdgpu_hdmi_vsdb_info *vsdb) ++{ ++ u16 vrr_min = display->monitor_range.min_vfreq; ++ u16 vrr_max = display->monitor_range.max_vfreq; ++ ++ /* Always extend upper limit */ ++ if (vsdb->max_refresh_rate_hz > vrr_max) ++ vrr_max = vsdb->max_refresh_rate_hz; ++ ++ /* ++ * Only extend lower limit if current one disables LFC. ++ ++ * During widespread testing, we found that some manufacturers probably ++ * had issues with their monitors' lower VRR boundaries and adjusted ++ * them up (Gigabyte X34GS with official range 48 - 180, AMD vsdb 48 - ++ * 180 yet Monitor Ranges 55 - 180). After setting the lower boundary ++ * from AMD vsdb, such monitors start having blanking issues. ++ * ++ * Work around that by not touching VRR min if it still supports LFC. ++ */ ++ if (vsdb->min_refresh_rate_hz < vrr_min && (vrr_min * 2 >= vrr_max)) ++ vrr_min = vsdb->min_refresh_rate_hz; ++ ++ display->monitor_range.min_vfreq = vrr_min; ++ display->monitor_range.max_vfreq = vrr_max; ++} ++ + /** + * amdgpu_dm_update_freesync_caps - Update Freesync capabilities + * +@@ -13298,6 +13326,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (is_monitor_range_invalid(connector)) + monitor_range_from_vsdb(&connector->display_info, &vsdb_info); + ++ /* Try extending range if found in AMD vsdb */ ++ extend_range_from_vsdb(&connector->display_info, &vsdb_info); ++ + if (dpcd_caps.allow_invalid_MSA_timing_param) + freesync_capable = copy_range_to_amdgpu_connector(connector); + + +From 763342d7a820a0fdd69dbd583a55fd42620decf0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Mon, 9 Feb 2026 20:36:53 +0100 +Subject: [PATCH 048/103] drm/amd/display: Separate DP/eDP and PCON paths + completely +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +DP -> HDMI PCONs need a completely separate treatment but they did fall +into DP/eDP path in amdgpu_dm_update_freesync_caps() previously. This +could sometimes result in weird values assigned to the connector even +though it doesn't support VRR at all and needs a bit of HDMI-like +treatment. + +[How] +Check if the connected sink is a HDMI -> DP converter earlier and +gate DP/eDP path + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index c7941507e0f9cb..ab17ca055bb724 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13280,6 +13280,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + struct dpcd_caps dpcd_caps = {0}; + const struct edid *edid; + bool freesync_capable = false; ++ bool is_pcon = false; + enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; + + if (!connector->state) { +@@ -13308,14 +13309,18 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version)) + goto update; + ++ /* Gather all data */ + edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() + parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); + +- if (amdgpu_dm_connector->dc_link) ++ if (amdgpu_dm_connector->dc_link) { + dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; ++ is_pcon = dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER; ++ } + +- if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || +- sink->sink_signal == SIGNAL_TYPE_EDP) { ++ /* DP & eDP excluding PCONs */ ++ if ((sink->sink_signal == SIGNAL_TYPE_EDP || ++ sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) && !is_pcon) { + /* Some eDP panels only have the refresh rate range info in DisplayID */ + if (is_monitor_range_invalid(connector)) + parse_edid_displayid_vrr(connector, edid); +@@ -13340,14 +13345,16 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP; + } + ++ /* HDMI */ + } else if (dc_is_hdmi_signal(sink->sink_signal) && vsdb_info.freesync_supported) { + monitor_range_from_vsdb(&connector->display_info, &vsdb_info); + freesync_capable = copy_range_to_amdgpu_connector(connector); + } + +- if (amdgpu_dm_connector->dc_link) ++ if (amdgpu_dm_connector->dc_link && is_pcon) + as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); + ++ /* DP -> HDMI PCON */ + if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST && vsdb_info.freesync_supported) { + amdgpu_dm_connector->pack_sdp_v1_3 = true; + amdgpu_dm_connector->as_type = as_type; + +From f8bfcccc45e2b78e171f1d6eba353e2f21d2e0a1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sun, 18 Jan 2026 14:10:22 +0100 +Subject: [PATCH 049/103] drm/amd/display: Refactor PCON VRR compatibility + check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +DP->HDMI PCONs prevously entered the DP path + +[How] +Restructure amdgpu_dm_update_freesync_caps() and move +dm_get_adaptive_sync_support_type() to dm_helpers_is_vrr_pcon_allowed() +to better reflect what this function does. It never actually gave us any +other info. + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++---- + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 39 ++++++------------- + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 2 +- + 3 files changed, 17 insertions(+), 35 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index ab17ca055bb724..5f71be75463daa 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13280,8 +13280,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + struct dpcd_caps dpcd_caps = {0}; + const struct edid *edid; + bool freesync_capable = false; ++ bool pcon_allowed = false; + bool is_pcon = false; +- enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; + + if (!connector->state) { + drm_err(adev_to_drm(adev), "%s - Connector has no state", __func__); +@@ -13316,6 +13316,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (amdgpu_dm_connector->dc_link) { + dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; + is_pcon = dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER; ++ pcon_allowed = dm_helpers_is_vrr_pcon_allowed(amdgpu_dm_connector->dc_link); + } + + /* DP & eDP excluding PCONs */ +@@ -13349,15 +13350,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + } else if (dc_is_hdmi_signal(sink->sink_signal) && vsdb_info.freesync_supported) { + monitor_range_from_vsdb(&connector->display_info, &vsdb_info); + freesync_capable = copy_range_to_amdgpu_connector(connector); +- } +- +- if (amdgpu_dm_connector->dc_link && is_pcon) +- as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); + + /* DP -> HDMI PCON */ +- if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST && vsdb_info.freesync_supported) { ++ } else if (pcon_allowed && vsdb_info.freesync_supported) { ++ amdgpu_dm_connector->as_type = FREESYNC_TYPE_PCON_IN_WHITELIST; + amdgpu_dm_connector->pack_sdp_v1_3 = true; +- amdgpu_dm_connector->as_type = as_type; + amdgpu_dm_connector->vsdb_info = vsdb_info; + + parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index 3591e494114553..7adac0797ff7f2 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -1400,40 +1400,25 @@ void dm_helpers_dp_mst_update_branch_bandwidth( + // TODO + } + +-static bool dm_is_freesync_pcon_whitelist(const uint32_t branch_dev_id) ++bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link) + { +- bool ret_val = false; ++ if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER) ++ return false; ++ ++ if (!link->dpcd_caps.allow_invalid_MSA_timing_param) ++ return false; ++ ++ if (!link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT) ++ return false; + +- switch (branch_dev_id) { ++ switch (link->dpcd_caps.branch_dev_id) { + case DP_BRANCH_DEVICE_ID_0060AD: + case DP_BRANCH_DEVICE_ID_00E04C: + case DP_BRANCH_DEVICE_ID_90CC24: +- ret_val = true; +- break; +- default: +- break; +- } +- +- return ret_val; +-} +- +-enum adaptive_sync_type dm_get_adaptive_sync_support_type(struct dc_link *link) +-{ +- struct dpcd_caps *dpcd_caps = &link->dpcd_caps; +- enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; +- +- switch (dpcd_caps->dongle_type) { +- case DISPLAY_DONGLE_DP_HDMI_CONVERTER: +- if (dpcd_caps->adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT == true && +- dpcd_caps->allow_invalid_MSA_timing_param == true && +- dm_is_freesync_pcon_whitelist(dpcd_caps->branch_dev_id)) +- as_type = FREESYNC_TYPE_PCON_IN_WHITELIST; +- break; +- default: +- break; ++ return true; + } + +- return as_type; ++ return false; + } + + bool dm_helpers_is_fullscreen(struct dc_context *ctx, struct dc_stream_state *stream) +diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h +index 9d160b39e8c5aa..f8b45a09d6806a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h ++++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h +@@ -219,10 +219,10 @@ int dm_helpers_dmub_set_config_sync(struct dc_context *ctx, + const struct dc_link *link, + struct set_config_cmd_payload *payload, + enum set_config_status *operation_result); +-enum adaptive_sync_type dm_get_adaptive_sync_support_type(struct dc_link *link); + + enum dc_edid_status dm_helpers_get_sbios_edid(struct dc_link *link, struct dc_edid *edid); + ++bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link); + bool dm_helpers_is_fullscreen(struct dc_context *ctx, struct dc_stream_state *stream); + bool dm_helpers_is_hdr_on(struct dc_context *ctx, struct dc_stream_state *stream); + + +From d304d220db66960622cc2f11a69a8542fdb9657f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:04 +0100 +Subject: [PATCH 050/103] drm/amd/display: Add PCON VRR ID check override +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +It's currently very hard to test if a random PCON supports VRR and +report it's ID. + +[How] +Adds override as part of dc debug mask. Allows faster testing and +reporting of VRR-compatible DP->HDMI adapters. + +Signed-off-by: Tomasz Pakuła +Reviewed-by: Harry Wentland +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++++- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 8 +++++++- + drivers/gpu/drm/amd/display/dc/dc.h | 1 + + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 2 +- + drivers/gpu/drm/amd/include/amd_shared.h | 6 ++++++ + 5 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 5f71be75463daa..b8a0d745e506f6 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -2069,6 +2069,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) + if (amdgpu_dc_debug_mask & DC_SKIP_DETECTION_LT) + adev->dm.dc->debug.skip_detection_link_training = true; + ++ if (amdgpu_dc_debug_mask & DC_OVERRIDE_PCON_VRR_ID_CHECK) ++ adev->dm.dc->debug.override_pcon_vrr_id_check = true; ++ + adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; + + /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ +@@ -13316,7 +13319,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (amdgpu_dm_connector->dc_link) { + dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; + is_pcon = dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER; +- pcon_allowed = dm_helpers_is_vrr_pcon_allowed(amdgpu_dm_connector->dc_link); ++ pcon_allowed = dm_helpers_is_vrr_pcon_allowed( ++ amdgpu_dm_connector->dc_link, connector->dev); + } + + /* DP & eDP excluding PCONs */ +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index 7adac0797ff7f2..8fb4d3bd2e34d5 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -1400,7 +1400,7 @@ void dm_helpers_dp_mst_update_branch_bandwidth( + // TODO + } + +-bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link) ++bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link, const struct drm_device *dev) + { + if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER) + return false; +@@ -1418,6 +1418,12 @@ bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link) + return true; + } + ++ if (link->dc->debug.override_pcon_vrr_id_check) { ++ drm_info(dev, "Overriding VRR PCON check for ID: 0x%06x\n", ++ link->dpcd_caps.branch_dev_id); ++ return true; ++ } ++ + return false; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 29edfa51ea2cc0..f24ece2eafc519 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -1039,6 +1039,7 @@ struct dc_debug_options { + bool scl_reset_length10; + bool hdmi20_disable; + bool skip_detection_link_training; ++ bool override_pcon_vrr_id_check; + uint32_t edid_read_retry_times; + unsigned int force_odm_combine; //bit vector based on otg inst + unsigned int seamless_boot_odm_combine; +diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h +index f8b45a09d6806a..ea94c52d2b8717 100644 +--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h ++++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h +@@ -222,7 +222,7 @@ int dm_helpers_dmub_set_config_sync(struct dc_context *ctx, + + enum dc_edid_status dm_helpers_get_sbios_edid(struct dc_link *link, struct dc_edid *edid); + +-bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link); ++bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link, const struct drm_device *dev); + bool dm_helpers_is_fullscreen(struct dc_context *ctx, struct dc_stream_state *stream); + bool dm_helpers_is_hdr_on(struct dc_context *ctx, struct dc_stream_state *stream); + +diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h +index 17945094a13834..839cfe2eeabe65 100644 +--- a/drivers/gpu/drm/amd/include/amd_shared.h ++++ b/drivers/gpu/drm/amd/include/amd_shared.h +@@ -411,6 +411,12 @@ enum DC_DEBUG_MASK { + * @DC_SKIP_DETECTION_LT: (0x200000) If set, skip detection link training + */ + DC_SKIP_DETECTION_LT = 0x200000, ++ ++ /** ++ * @DC_OVERRIDE_PCON_VRR_ID_CHECK: (0x400000) If set, always return true if checking for ++ * PCON VRR compatibility and print it's ID in kernel log. ++ */ ++ DC_OVERRIDE_PCON_VRR_ID_CHECK = 0x400000, + }; + + enum amd_dpm_forced_level; + +From 03c28e818196ccf1333fa2cabd87aca8220fe5fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:05 +0100 +Subject: [PATCH 051/103] drm/amd/display: Add CH7218 PCON ID +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Chrontel CH7218 found in Ugreen DP -> HDMI 2.1 adapter (model 85564) +works perfectly with VRR after testing. VRR and FreeSync compatibility +is explicitly advertised as a feature so it's addition is a formality. + +Support FreeSync info packet passthrough and "generic" HDMI VRR. + +[How] +Add CH7218's ID to dm_helpers_is_vrr_pcon_allowed() + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4773 + +Signed-off-by: Tomasz Pakuła +Reviewed-by: Harry Wentland +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 1 + + drivers/gpu/drm/amd/display/include/ddc_service_types.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index 8fb4d3bd2e34d5..dba1b9a72159fc 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -1415,6 +1415,7 @@ bool dm_helpers_is_vrr_pcon_allowed(const struct dc_link *link, const struct drm + case DP_BRANCH_DEVICE_ID_0060AD: + case DP_BRANCH_DEVICE_ID_00E04C: + case DP_BRANCH_DEVICE_ID_90CC24: ++ case DP_BRANCH_DEVICE_ID_2B02F0: + return true; + } + +diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h +index 1c603b12957f6f..e838f7c1269c4f 100644 +--- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h ++++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h +@@ -36,6 +36,7 @@ + #define DP_BRANCH_DEVICE_ID_006037 0x006037 + #define DP_BRANCH_DEVICE_ID_001CF8 0x001CF8 + #define DP_BRANCH_DEVICE_ID_0060AD 0x0060AD ++#define DP_BRANCH_DEVICE_ID_2B02F0 0x2B02F0 /* Chrontel CH7218 */ + #define DP_BRANCH_HW_REV_10 0x10 + #define DP_BRANCH_HW_REV_20 0x20 + + +From cbc0ab3e8e088409f1c8e2ce46603a72f28fb970 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:05 +0100 +Subject: [PATCH 052/103] drm/edid: Parse more info from HDMI Forum vsdb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Drivers may need info about gaming features exposed by HDMI sinks. Add +a central way of storing this information. + +[How] +Adds flags and a struct to hold HDMI VRR information. `supported` here +is an additional property which allows easier parsing in consumers and +adds a bit of logic used to detect malformed VRRmin/VRRmax values. + +Signed-off-by: Tomasz Pakuła +Tested-by: Bernhard Berger +--- + drivers/gpu/drm/drm_edid.c | 41 +++++++++++++++++++++++++++++++- + include/drm/drm_connector.h | 47 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 87 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index e987028ac443ae..50ec021dbce2bc 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -6158,6 +6158,33 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, + hdmi->y420_dc_modes = dc_mask; + } + ++static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi, const u8 *db) ++{ ++ struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap; ++ ++ if (cea_db_payload_len(db) < 8) ++ return; ++ ++ hdmi->fapa_start_location = db[8] & DRM_EDID_FAPA_START_LOCATION; ++ hdmi->allm = db[8] & DRM_EDID_ALLM; ++ vrr->fva = db[8] & DRM_EDID_FVA; ++ vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR; ++ vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR; ++ vrr->mdelta = db[8] & DRM_EDID_MDELTA; ++ ++ if (cea_db_payload_len(db) < 9) ++ return; ++ ++ vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK; ++ vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48); ++ ++ if (cea_db_payload_len(db) < 10) ++ return; ++ ++ vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10]; ++ vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100); ++} ++ + static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc, + const u8 *hf_scds) + { +@@ -6281,7 +6308,7 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, + } + + drm_parse_ycbcr420_deep_color_info(connector, hf_scds); +- ++ drm_parse_hdmi_gaming_info(&connector->display_info.hdmi, hf_scds); + if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) { + drm_parse_dsc_info(hdmi_dsc, hf_scds); + dsc_support = true; +@@ -6291,6 +6318,18 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, + "[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n", + connector->base.id, connector->name, + max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support)); ++ drm_dbg_kms(connector->dev, ++ "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support: %s, Fast Vactive support: %s\n", ++ connector->base.id, connector->name, str_yes_no(hdmi->fapa_start_location), ++ str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva)); ++ drm_dbg_kms(connector->dev, ++ "[CONNECTOR:%d:%s] Negative M VRR support: %s, CinemaVRR support: %s, Mdelta: %d\n", ++ connector->base.id, connector->name, str_yes_no(hdmi->vrr_cap.cnmvrr), ++ str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi->vrr_cap.mdelta); ++ drm_dbg_kms(connector->dev, ++ "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR supported: %s\n", ++ connector->base.id, connector->name, hdmi->vrr_cap.vrr_min, ++ hdmi->vrr_cap.vrr_max, str_yes_no(hdmi->vrr_cap.supported)); + } + + static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index f880b3097b2c3a..33dd5061f476ca 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -272,6 +272,44 @@ struct drm_hdmi_frl_cap { + u8 max_lanes; + }; + ++/* ++ * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink ++ * ++ * Describes the VRR support provided by HDMI 2.1 sink. The information is ++ * fetched fom additional HFVSDB blocks defined for HDMI 2.1. ++ */ ++struct drm_hdmi_vrr_cap { ++ /** @fva: flag for Fast VActive (Quick Frame Transport) support */ ++ bool fva; ++ ++ /** @mcnmvrr: flag for Negative M VRR support */ ++ bool cnmvrr; ++ ++ /** @mcinema_vrr: flag for Cinema VRR support */ ++ bool cinema_vrr; ++ ++ /** @mdelta: flag for limited frame-to-frame compensation support */ ++ bool mdelta; ++ ++ /** ++ * @vrr_min : minimum supported variable refresh rate in Hz. ++ * Valid values only inide 1 - 48 range ++ */ ++ u16 vrr_min; ++ ++ /** ++ * @vrr_max : maximum supported variable refresh rate in Hz (optional). ++ * Valid values are either 0 (max based on video mode) or >= 100 ++ */ ++ u16 vrr_max; ++ ++ /** ++ * @supported: flag for vrr support based on checking for VRRmin and ++ * VRRmax values having correct values. ++ */ ++ bool supported; ++}; ++ + /** + * struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink + * +@@ -342,6 +380,15 @@ struct drm_hdmi_info { + /** @frl_cap: FRL capabilities of the sink */ + struct drm_hdmi_frl_cap frl_cap; + ++ /** @fapa_start_location: flag for the FAPA in blanking support */ ++ bool fapa_start_location; ++ ++ /** @allm: flag for Auto Low Latency Mode support by sink */ ++ bool allm; ++ ++ /** @vrr_cap: VRR capabilities of the sink */ ++ struct drm_hdmi_vrr_cap vrr_cap; ++ + /** @dsc_cap: DSC capabilities of the sink */ + struct drm_hdmi_dsc_cap dsc_cap; + }; + +From 01d38158148b5a0a99730f99737386072ecfa97b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:05 +0100 +Subject: [PATCH 053/103] drm/amd/display: Rename PCON adaptive sync types +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +PCONs support sending out HDMI VRR infopackets on their own and this +makes this types not specific to FreeSync + +[How] +Make the name more generic for the upcoming HDMI VRR over PCON +implementation + +Signed-off-by: Tomasz Pakuła +Tested-by: Bernhard Berger +Reviewed-by: Harry Wentland +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- + .../gpu/drm/amd/display/modules/inc/mod_info_packet.h | 10 +++++----- + .../drm/amd/display/modules/info_packet/info_packet.c | 4 ++-- + 3 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index b8a0d745e506f6..09623f7d2c5a90 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -9624,7 +9624,8 @@ static void update_freesync_state_on_stream( + + aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context; + +- if (aconn && (aconn->as_type == FREESYNC_TYPE_PCON_IN_WHITELIST || aconn->vsdb_info.replay_mode)) { ++ if (aconn && (aconn->as_type == ADAPTIVE_SYNC_TYPE_PCON_ALLOWED || ++ aconn->vsdb_info.replay_mode)) { + pack_sdp_v1_3 = aconn->pack_sdp_v1_3; + + if (aconn->vsdb_info.amd_vsdb_version == 1) +@@ -13357,7 +13358,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + + /* DP -> HDMI PCON */ + } else if (pcon_allowed && vsdb_info.freesync_supported) { +- amdgpu_dm_connector->as_type = FREESYNC_TYPE_PCON_IN_WHITELIST; ++ amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_PCON_ALLOWED; + amdgpu_dm_connector->pack_sdp_v1_3 = true; + amdgpu_dm_connector->vsdb_info = vsdb_info; + +diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +index 66dc9a19aebe5d..040aa14cb1ce36 100644 +--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h ++++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +@@ -42,11 +42,11 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, + struct dc_info_packet *info_packet); + + enum adaptive_sync_type { +- ADAPTIVE_SYNC_TYPE_NONE = 0, +- ADAPTIVE_SYNC_TYPE_DP = 1, +- FREESYNC_TYPE_PCON_IN_WHITELIST = 2, +- FREESYNC_TYPE_PCON_NOT_IN_WHITELIST = 3, +- ADAPTIVE_SYNC_TYPE_EDP = 4, ++ ADAPTIVE_SYNC_TYPE_NONE = 0, ++ ADAPTIVE_SYNC_TYPE_DP = 1, ++ ADAPTIVE_SYNC_TYPE_PCON_ALLOWED = 2, ++ ADAPTIVE_SYNC_TYPE_PCON_NOT_ALLOWED = 3, ++ ADAPTIVE_SYNC_TYPE_EDP = 4, + }; + + enum adaptive_sync_sdp_version { +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index b3d55cac35694b..b50fb75236e936 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -535,12 +535,12 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, + if (stream != NULL) + mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet); + break; +- case FREESYNC_TYPE_PCON_IN_WHITELIST: ++ case ADAPTIVE_SYNC_TYPE_PCON_ALLOWED: + case ADAPTIVE_SYNC_TYPE_EDP: + mod_build_adaptive_sync_infopacket_v1(info_packet); + break; + case ADAPTIVE_SYNC_TYPE_NONE: +- case FREESYNC_TYPE_PCON_NOT_IN_WHITELIST: ++ case ADAPTIVE_SYNC_TYPE_PCON_NOT_ALLOWED: + default: + break; + } + +From 2d8ff80a8daffec6e39c9c77a0cb9520bb65b39b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:05 +0100 +Subject: [PATCH 054/103] drm/amd/display: Enable HDMI VRR over PCON +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Not all TVs support FreeSync and many TVs suffer from VRR flickering +while Freesync is activated. + +[How] +This works the same as FreeSync over PCON just without sending FreeSync +info packets (we're sending standard DisplayPort info packets) + reading +the VRR range from the HDMI Forum vendor specific data block. PCONs take +over HDMI VRR triggering. + +Prefer HDMI VRR over FreeSync to reduce VRR flickering on many TVs. +FreeSync over HDMI seems to be a fallback solution and not a first-class +citizen. This especially helps VMM7100. + +Tested with VMM7100 and CH7218 based adapters on multiple HDMI 2.1 and +HDMI 2.0 devices. (Samsung S95B, LG C4, Sony Bravia 8, Dell AW3423DWF) + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4805 + +Signed-off-by: Tomasz Pakuła +Tested-by: Bernhard Berger +Reviewed-by: Harry Wentland +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 +++++++++++++++---- + 1 file changed, 23 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 09623f7d2c5a90..56e87eb0b5648e 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13217,6 +13217,17 @@ static void monitor_range_from_vsdb(struct drm_display_info *display, + display->monitor_range.max_vfreq = vsdb->max_refresh_rate_hz; + } + ++/** ++ * Get VRR range from HDMI VRR info in EDID. ++ * ++ * @conn: drm_connector with HDMI VRR info ++ */ ++static void monitor_range_from_hdmi(struct drm_display_info *display) ++{ ++ display->monitor_range.min_vfreq = display->hdmi.vrr_cap.vrr_min; ++ display->monitor_range.max_vfreq = display->hdmi.vrr_cap.vrr_max; ++} ++ + /* + * Returns true if connector is capable of freesync + * Optionally, can fetch the range from AMD vsdb +@@ -13281,6 +13292,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + struct amdgpu_device *adev = drm_to_adev(connector->dev); + struct amdgpu_hdmi_vsdb_info vsdb_info = {0}; + struct amdgpu_hdmi_vsdb_info vsdb_did = {0}; ++ struct drm_hdmi_vrr_cap hdmi_vrr = {0}; + struct dpcd_caps dpcd_caps = {0}; + const struct edid *edid; + bool freesync_capable = false; +@@ -13316,6 +13328,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + /* Gather all data */ + edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() + parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); ++ hdmi_vrr = connector->display_info.hdmi.vrr_cap; + + if (amdgpu_dm_connector->dc_link) { + dpcd_caps = amdgpu_dm_connector->dc_link->dpcd_caps; +@@ -13357,13 +13370,17 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + freesync_capable = copy_range_to_amdgpu_connector(connector); + + /* DP -> HDMI PCON */ +- } else if (pcon_allowed && vsdb_info.freesync_supported) { +- amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_PCON_ALLOWED; +- amdgpu_dm_connector->pack_sdp_v1_3 = true; +- amdgpu_dm_connector->vsdb_info = vsdb_info; ++ } else if (pcon_allowed) { ++ /* Prefer HDMI VRR */ ++ if (hdmi_vrr.supported && hdmi_vrr.vrr_max > 0) ++ monitor_range_from_hdmi(&connector->display_info); ++ else if (vsdb_info.freesync_supported) { ++ amdgpu_dm_connector->vsdb_info = vsdb_info; ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ } + +- parse_amd_vsdb_cea(amdgpu_dm_connector, edid, &vsdb_info); +- monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ amdgpu_dm_connector->pack_sdp_v1_3 = true; ++ amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_PCON_ALLOWED; + freesync_capable = copy_range_to_amdgpu_connector(connector); + } + + +From 741aaa620bdd966fdee97593d844fcce894e2bf1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 14 Jan 2026 20:28:06 +0100 +Subject: [PATCH 055/103] drm/amd/display: Support HDMI VRRmax=0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +VRRmax=0 is a valid value and means that the upper bound is guared by +the selected video mode. + +[How] +In this context, saved vrr max is the max possible refresh rate ever. +Try getting upper VRR bound from AMD vsdbif it exists or rely on the +limitations of BRR in VTEM info frames. + +I found through testing, that TVs seem to reject VTEM when BRR is set +to over 1023 Hz. Use this as the last resort VRRmax. 1023 is the max +value for a 10-bit field as well. + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++++++++++++++---- + .../amd/display/modules/inc/mod_info_packet.h | 2 ++ + 2 files changed, 20 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 56e87eb0b5648e..89b377e3fc8dab 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -13218,14 +13218,27 @@ static void monitor_range_from_vsdb(struct drm_display_info *display, + } + + /** +- * Get VRR range from HDMI VRR info in EDID. ++ * Get VRR range from HDMI VRR info in EDID. If VRRmax == 0, ++ * try getting upper bound from AMD vsdb. + * + * @conn: drm_connector with HDMI VRR info ++ * @vsdb: AMD vsdb from CAE + */ +-static void monitor_range_from_hdmi(struct drm_display_info *display) ++static void monitor_range_from_hdmi(struct drm_display_info *display, ++ const struct amdgpu_hdmi_vsdb_info *vsdb) + { ++ u16 vrr_max = display->hdmi.vrr_cap.vrr_max; ++ ++ /* Try getting upper vrr bound from AMD vsdb */ ++ if (vrr_max == 0) ++ vrr_max = vsdb->max_refresh_rate_hz; ++ ++ /* Use max possible BRR value as a last resort */ ++ if (vrr_max == 0) ++ vrr_max = VTEM_BRR_MAX; ++ + display->monitor_range.min_vfreq = display->hdmi.vrr_cap.vrr_min; +- display->monitor_range.max_vfreq = display->hdmi.vrr_cap.vrr_max; ++ display->monitor_range.max_vfreq = vrr_max; + } + + /* +@@ -13372,8 +13385,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + /* DP -> HDMI PCON */ + } else if (pcon_allowed) { + /* Prefer HDMI VRR */ +- if (hdmi_vrr.supported && hdmi_vrr.vrr_max > 0) +- monitor_range_from_hdmi(&connector->display_info); ++ if (hdmi_vrr.supported) ++ monitor_range_from_hdmi(&connector->display_info, &vsdb_info); + else if (vsdb_info.freesync_supported) { + amdgpu_dm_connector->vsdb_info = vsdb_info; + monitor_range_from_vsdb(&connector->display_info, &vsdb_info); +diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +index 040aa14cb1ce36..c8f7d1b2951c42 100644 +--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h ++++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +@@ -33,6 +33,8 @@ struct dc_stream_state; + struct dc_info_packet; + struct mod_vrr_params; + ++#define VTEM_BRR_MAX 1023 ++ + void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + struct dc_info_packet *info_packet, + enum dc_color_space cs, + +From 317347b3cbd6e69aa6c6809c889ee05ac4222230 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Fri, 16 Jan 2026 16:32:52 +0100 +Subject: [PATCH 056/103] drm/amd/display: Build HDMI vsif in correct slot +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +HDMI vsif was assigned to vsp_infopacket (FreeSync) field + +[How] +Build HDMI vsif in the correct hfvsif_infopacket field + +Signed-off-by: Tomasz Pakuła +Reviewed-by: Harry Wentland +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 89b377e3fc8dab..0c4cfb7b6da0bb 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -7386,7 +7386,7 @@ create_stream_for_sink(struct drm_connector *connector, + update_stream_signal(stream, sink); + + if (dc_is_hdmi_signal(stream->signal)) +- mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); ++ mod_build_hf_vsif_infopacket(stream, &stream->hfvsif_infopacket); + + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + +From 9b3ae6ac2b870919e5f9cbe2696d4d74b6ef452f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sat, 17 Jan 2026 15:21:43 +0100 +Subject: [PATCH 057/103] drm/amd/display: Save HDMI gaming info to edid caps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +We need info about these features in parts of the driver where fishing +for drm_connector struct is infeasible. + +[How] +Add three new fields to dc_edid_caps and fill them if connected device +is HDMI based on it's EDID + +Signed-off-by: Tomasz Pakuła +Reviewed-by: Harry Wentland +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 7 ++++++- + drivers/gpu/drm/amd/display/dc/dc_types.h | 5 ++++- + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index dba1b9a72159fc..52fa54a357f4b5 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -137,7 +137,12 @@ enum dc_edid_status dm_helpers_parse_edid_caps( + edid_caps->display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); + +- edid_caps->edid_hdmi = connector->display_info.is_hdmi; ++ if (connector->display_info.is_hdmi) { ++ edid_caps->edid_hdmi = true; ++ edid_caps->allm = connector->display_info.hdmi.allm; ++ edid_caps->fva = connector->display_info.hdmi.vrr_cap.fva; ++ edid_caps->hdmi_vrr = connector->display_info.hdmi.vrr_cap.supported; ++ } + + if (edid_caps->edid_hdmi) + populate_hdmi_info_from_connector(&connector->display_info.hdmi, edid_caps); +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index ef7ee70b6180b4..8f644da9f585f8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -245,12 +245,15 @@ struct dc_edid_caps { + + uint32_t max_tmds_clk_mhz; + +- /*HDMI 2.0 caps*/ ++ /* HDMI 2.0 caps */ + bool lte_340mcsc_scramble; + + /* HDMI 2.1 caps */ + struct dc_hdmi_frl_caps frl_caps; + struct dc_hdmi_dsc_caps dsc_caps; ++ bool allm; ++ bool fva; ++ bool hdmi_vrr; + + bool edid_hdmi; + bool hdr_supported; + +From 325065a209c9c0eb8026b234eaa4ef8518907df5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Fri, 16 Jan 2026 16:11:16 +0100 +Subject: [PATCH 058/103] drm/amd/display: Restore ALLM support in HDMI vsif +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Support for triggering ALLM in modern TVs is missing. + +When HDMI vsif was added in 2019: +commit 3c2381b92cba ("drm/amd/display: add support for VSIP info packet") +it was improperly handeled as HDMI actually has two separate vsifs. The +implementation was based on H14b-vsif and ALLM bit was messing it up +because H14b-vsif doesn't support ALLM. It was later removed in: +commit 75f77aafe281 ("drm/amd/display: Send H14b-VSIF specified in HDMI") + +ALLM is supported by hf-vsif (HDMI Forum) instead. + +[How] +Add proper logic to construct either h14b-vsif or hf-vsif based on +required capabilities. Currently, only ALLM from hf-vsif is supported. + +Turns out, hf-vsif is almost identical to h14b-vsif, BUT has additional +two bytes of data after OUI. First byte is static and seems like +a version supported by leftover define. Second byte consists of 3D and +ALLM bits. + +Implement logic to offset 3D data if building hf-vsif. + +Signed-off-by: Tomasz Pakuła +--- + .../display/modules/info_packet/info_packet.c | 107 ++++++++++++------ + 1 file changed, 71 insertions(+), 36 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index b50fb75236e936..9db483a21b7ff3 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -45,7 +45,10 @@ enum vsc_packet_revision { + }; + + #define HDMI_INFOFRAME_TYPE_VENDOR 0x81 +-#define HF_VSIF_VERSION 1 ++#define HDMI_INFOFRAME_LENGTH_MASK 0x1F ++#define HF_VSIF_VERSION 1 ++#define HF_VSIF_3D_BIT 0 ++#define HF_VSIF_ALLM_BIT 1 + + // VTEM Byte Offset + #define VTEM_PB0 0 +@@ -441,9 +444,29 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + } + } + ++static bool is_hdmi_vic_mode(const struct dc_stream_state *stream) ++{ ++ if (stream->timing.hdmi_vic == 0) ++ return false; ++ ++ if (stream->timing.h_total < 3840 || ++ stream->timing.v_total < 2160) ++ return false; ++ ++ /* 3D/ALLM forces HDMI VIC -> CTA VIC translation */ ++ if (stream->view_format != VIEW_3D_FORMAT_NONE) ++ return false; ++ ++ if (stream->link->local_sink->edid_caps.allm) ++ return false; ++ ++ return true; ++} ++ + /** + * mod_build_hf_vsif_infopacket - Prepare HDMI Vendor Specific info frame. + * Follows HDMI Spec to build up Vendor Specific info frame ++ * Conforms to h14b-vsif or hf-vsif based on the capabilities + * + * @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.) + * @info_packet: output structure where to store VSIF +@@ -451,63 +474,75 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, + struct dc_info_packet *info_packet) + { +- unsigned int length = 5; + bool hdmi_vic_mode = false; ++ bool allm = false; ++ bool stereo = false; + uint8_t checksum = 0; +- uint32_t i = 0; ++ uint8_t offset = 0; ++ uint8_t i = 0; ++ uint8_t length = 5; ++ uint32_t oui = HDMI_IEEE_OUI; + enum dc_timing_3d_format format; + + info_packet->valid = false; ++ + format = stream->timing.timing_3d_format; + if (stream->view_format == VIEW_3D_FORMAT_NONE) + format = TIMING_3D_FORMAT_NONE; ++ stereo = format != TIMING_3D_FORMAT_NONE; ++ hdmi_vic_mode = is_hdmi_vic_mode(stream); + +- if (stream->timing.hdmi_vic != 0 +- && stream->timing.h_total >= 3840 +- && stream->timing.v_total >= 2160 +- && format == TIMING_3D_FORMAT_NONE) +- hdmi_vic_mode = true; +- +- if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode) ++ if (!stereo && !hdmi_vic_mode && !allm) + return; + +- info_packet->sb[1] = 0x03; +- info_packet->sb[2] = 0x0C; +- info_packet->sb[3] = 0x00; ++ if (allm) ++ oui = HDMI_FORUM_IEEE_OUI; + +- if (format != TIMING_3D_FORMAT_NONE) +- info_packet->sb[4] = (2 << 5); ++ info_packet->sb[1] = oui & 0xFF; ++ info_packet->sb[2] = (oui >> 8) & 0xFF; ++ info_packet->sb[3] = (oui >> 16) & 0xFF; + +- else if (hdmi_vic_mode) +- info_packet->sb[4] = (1 << 5); ++ if (oui == HDMI_FORUM_IEEE_OUI) { ++ offset = 2; ++ length += 2; ++ info_packet->sb[4] = HF_VSIF_VERSION; ++ info_packet->sb[5] = stereo << HF_VSIF_3D_BIT; ++ info_packet->sb[5] |= allm << HF_VSIF_ALLM_BIT; ++ } + +- switch (format) { +- case TIMING_3D_FORMAT_HW_FRAME_PACKING: +- case TIMING_3D_FORMAT_SW_FRAME_PACKING: +- info_packet->sb[5] = (0x0 << 4); +- break; ++ if (stereo) { ++ info_packet->sb[4 + offset] = (2 << 5); + +- case TIMING_3D_FORMAT_SIDE_BY_SIDE: +- case TIMING_3D_FORMAT_SBS_SW_PACKED: +- info_packet->sb[5] = (0x8 << 4); +- length = 6; +- break; ++ switch (format) { ++ case TIMING_3D_FORMAT_HW_FRAME_PACKING: ++ case TIMING_3D_FORMAT_SW_FRAME_PACKING: ++ info_packet->sb[5 + offset] = (0x0 << 4); ++ break; + +- case TIMING_3D_FORMAT_TOP_AND_BOTTOM: +- case TIMING_3D_FORMAT_TB_SW_PACKED: +- info_packet->sb[5] = (0x6 << 4); +- break; ++ case TIMING_3D_FORMAT_SIDE_BY_SIDE: ++ case TIMING_3D_FORMAT_SBS_SW_PACKED: ++ info_packet->sb[5 + offset] = (0x8 << 4); ++ ++length; ++ break; + +- default: +- break; +- } ++ case TIMING_3D_FORMAT_TOP_AND_BOTTOM: ++ case TIMING_3D_FORMAT_TB_SW_PACKED: ++ info_packet->sb[5 + offset] = (0x6 << 4); ++ break; + +- if (hdmi_vic_mode) ++ default: ++ break; ++ } ++ ++ /* Doesn't need the offset as it can't be used with hf-vsif */ ++ } else if (hdmi_vic_mode) { ++ info_packet->sb[4] = (1 << 5); + info_packet->sb[5] = stream->timing.hdmi_vic; ++ } + + info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; + info_packet->hb1 = 0x01; +- info_packet->hb2 = (uint8_t) (length); ++ info_packet->hb2 = length & HDMI_INFOFRAME_LENGTH_MASK; + + checksum += info_packet->hb0; + checksum += info_packet->hb1; + +From 16fd77a719364c1fb64b2a48779dede19b338a7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sat, 17 Jan 2026 15:25:11 +0100 +Subject: [PATCH 059/103] drm/amd/display: Trigger ALLM if it's available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +ALLM automatically puts TVs into low latency modes (gaming modes) which +we basically always want for PC use, be it gaming, or using precise +inputs like mice and keyboards. + +[How] +Read the ALLM info from HDMI caps and use it to determine if ALLM should +be indicated in HDMI Forum vsif. Additionally, make sure VIC modes are +translated in case of ALLM active as VIC cannot be used in conjunction +with hf-vsif. I learned this the hard way... + +Signed-off-by: Tomasz Pakuła +Reviewed-by: Harry Wentland +--- + .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index 9db483a21b7ff3..e362276bc3244d 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -486,9 +486,10 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, + + info_packet->valid = false; + +- format = stream->timing.timing_3d_format; +- if (stream->view_format == VIEW_3D_FORMAT_NONE) +- format = TIMING_3D_FORMAT_NONE; ++ allm = stream->link->local_sink->edid_caps.allm; ++ format = stream->view_format == VIEW_3D_FORMAT_NONE ? ++ TIMING_3D_FORMAT_NONE : ++ stream->timing.timing_3d_format; + stereo = format != TIMING_3D_FORMAT_NONE; + hdmi_vic_mode = is_hdmi_vic_mode(stream); + + +From 6c88d0d1f9acce6d0c56037fa239007c994768fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Fri, 16 Jan 2026 22:06:56 +0100 +Subject: [PATCH 060/103] drm/amd/display: Reintroduce VTEM info frame +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +VTEM info fram building was removed back in: commit a9f54ce3c603 +("drm/amd/display: Refactoring VTEM"), but it's needed to support +HDMI VRR signalling. + +[How] +Build completely new and more robust functions to build out the VTEM +infopacket. Many values are defined but could have added logic in the +future, that's shy they are not static values but already value + bit +position in it's byte. + +Reduced blanking detection was previously missing. Use possible hblank +periods defined for RB1 (from CVT 1.2), RB2 and RB3 (from CVT 2.1). + +Signed-off-by: Tomasz Pakuła +--- + .../amd/display/modules/inc/mod_info_packet.h | 4 + + .../display/modules/info_packet/info_packet.c | 179 ++++++++++++------ + 2 files changed, 125 insertions(+), 58 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +index c8f7d1b2951c42..ba83cb23b63f8f 100644 +--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h ++++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +@@ -43,6 +43,10 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, + struct dc_info_packet *info_packet); + ++void mod_build_vtem_infopacket(const struct dc_stream_state *stream, ++ const struct mod_vrr_params *vrr, ++ struct dc_info_packet *infopacket); ++ + enum adaptive_sync_type { + ADAPTIVE_SYNC_TYPE_NONE = 0, + ADAPTIVE_SYNC_TYPE_DP = 1, +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index e362276bc3244d..503c84111aea16 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -44,6 +44,7 @@ enum vsc_packet_revision { + vsc_packet_rev5 = 5, + }; + ++#define HDMI_INFOFRAME_TYPE_EMP 0x7F + #define HDMI_INFOFRAME_TYPE_VENDOR 0x81 + #define HDMI_INFOFRAME_LENGTH_MASK 0x1F + #define HF_VSIF_VERSION 1 +@@ -59,64 +60,51 @@ enum vsc_packet_revision { + #define VTEM_PB5 5 + #define VTEM_PB6 6 + +-#define VTEM_MD0 7 +-#define VTEM_MD1 8 +-#define VTEM_MD2 9 +-#define VTEM_MD3 10 +- +- +-// VTEM Byte Masks +-//PB0 +-#define MASK_VTEM_PB0__RESERVED0 0x01 +-#define MASK_VTEM_PB0__SYNC 0x02 +-#define MASK_VTEM_PB0__VFR 0x04 +-#define MASK_VTEM_PB0__AFR 0x08 +-#define MASK_VTEM_PB0__DS_TYPE 0x30 +- //0: Periodic pseudo-static EM Data Set +- //1: Periodic dynamic EM Data Set +- //2: Unique EM Data Set +- //3: Reserved +-#define MASK_VTEM_PB0__END 0x40 +-#define MASK_VTEM_PB0__NEW 0x80 +- +-//PB1 +-#define MASK_VTEM_PB1__RESERVED1 0xFF +- +-//PB2 +-#define MASK_VTEM_PB2__ORGANIZATION_ID 0xFF +- //0: This is a Vendor Specific EM Data Set +- //1: This EM Data Set is defined by This Specification (HDMI 2.1 r102.clean) +- //2: This EM Data Set is defined by CTA-861-G +- //3: This EM Data Set is defined by VESA +-//PB3 +-#define MASK_VTEM_PB3__DATA_SET_TAG_MSB 0xFF +-//PB4 +-#define MASK_VTEM_PB4__DATA_SET_TAG_LSB 0xFF +-//PB5 +-#define MASK_VTEM_PB5__DATA_SET_LENGTH_MSB 0xFF +-//PB6 +-#define MASK_VTEM_PB6__DATA_SET_LENGTH_LSB 0xFF +- +- +- +-//PB7-27 (20 bytes): +-//PB7 = MD0 +-#define MASK_VTEM_MD0__VRR_EN 0x01 +-#define MASK_VTEM_MD0__M_CONST 0x02 +-#define MASK_VTEM_MD0__QMS_EN 0x04 +-#define MASK_VTEM_MD0__RESERVED2 0x08 +-#define MASK_VTEM_MD0__FVA_FACTOR_M1 0xF0 +- +-//MD1 +-#define MASK_VTEM_MD1__BASE_VFRONT 0xFF +- +-//MD2 +-#define MASK_VTEM_MD2__BASE_REFRESH_RATE_98 0x03 +-#define MASK_VTEM_MD2__RB 0x04 +-#define MASK_VTEM_MD2__NEXT_TFR 0xF8 +- +-//MD3 +-#define MASK_VTEM_MD3__BASE_REFRESH_RATE_07 0xFF ++#define VTEM_ORG_ID 1 ++#define VTEM_DATA_SET_TAG 1 ++#define VTEM_DATA_SET_LENGTH 4 ++ ++#define VTEM_M_CONST 0 ++#define VTEM_FVA_FACTOR 0 ++ ++#define VTEM_BRR_MASK_UPPER 0x03 ++#define VTEM_BRR_MASK_LOWER 0xFF ++ ++/* VTEM Byte Offset */ ++#define VTEM_PB0 0 ++#define VTEM_PB1 1 ++#define VTEM_PB2 2 ++#define VTEM_PB3 3 ++#define VTEM_PB4 4 ++#define VTEM_PB5 5 ++#define VTEM_PB6 6 ++ ++#define VTEM_MD0 7 ++#define VTEM_MD1 8 ++#define VTEM_MD2 9 ++#define VTEM_MD3 10 ++ ++/* Extended Metadata Packet */ ++/* Header */ ++#define EMP_LAST_BIT 6 ++#define EMP_FIRST_BIT 7 ++/* PB0 */ ++#define EMP_SNC_BIT 1 ++#define EMP_VFR_BIT 2 ++#define EMP_AFR_BIT 3 ++#define EMP_DST_BIT 4 ++#define EMP_END_BIT 6 ++#define EMP_NEW_BIT 7 ++/* PB7 = MD0 */ ++#define VTEM_VRR_BIT 0 ++#define VTEM_M_CONST_BIT 1 ++#define VTEM_FVA_BIT 4 ++/* MD1 Base_Vfront */ ++/* MD2 */ ++#define VTEM_BRR_UPPER_BIT 0 ++#define VTEM_RB_BIT 2 ++/* MD3 BRR Lower */ ++ + + enum ColorimetryRGBDP { + ColorimetryRGB_DP_sRGB = 0, +@@ -557,6 +545,81 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, + info_packet->valid = true; + } + ++static void build_vtem_infopacket_header(struct dc_info_packet *infopacket) ++{ ++ uint8_t pb0 = 0; ++ ++ /* might need logic in the future */ ++ pb0 |= 0 << EMP_SNC_BIT; ++ pb0 |= 1 << EMP_VFR_BIT; ++ pb0 |= 0 << EMP_AFR_BIT; ++ pb0 |= 0 << EMP_DST_BIT; ++ pb0 |= 0 << EMP_END_BIT; ++ pb0 |= 1 << EMP_NEW_BIT; ++ ++ infopacket->hb0 = HDMI_INFOFRAME_TYPE_EMP; ++ infopacket->hb1 = (1 << EMP_FIRST_BIT) | (1 << EMP_LAST_BIT); ++ infopacket->hb2 = 0; // sequence ++ ++ infopacket->sb[VTEM_PB0] = pb0; ++ infopacket->sb[VTEM_PB2] = VTEM_ORG_ID; ++ infopacket->sb[VTEM_PB4] = VTEM_DATA_SET_TAG; ++ infopacket->sb[VTEM_PB6] = VTEM_DATA_SET_LENGTH; ++} ++ ++static void build_vtem_infopacket_data(const struct dc_stream_state *stream, ++ const struct mod_vrr_params *vrr, ++ struct dc_info_packet *infopacket) ++{ ++ unsigned int hblank = 0; ++ unsigned int brr = 0; ++ bool vrr_active = false; ++ bool rb = false; ++ ++ vrr_active = vrr->state == VRR_STATE_ACTIVE_VARIABLE || ++ vrr->state == VRR_STATE_ACTIVE_FIXED; ++ ++ infopacket->sb[VTEM_MD0] = VTEM_M_CONST << VTEM_M_CONST_BIT; ++ infopacket->sb[VTEM_MD0] |= VTEM_FVA_FACTOR << VTEM_FVA_BIT; ++ infopacket->sb[VTEM_MD0] |= vrr_active << VTEM_VRR_BIT; ++ ++ infopacket->sb[VTEM_MD1] = 0; ++ infopacket->sb[VTEM_MD2] = 0; ++ infopacket->sb[VTEM_MD3] = 0; ++ ++ if (!vrr_active || is_hdmi_vic_mode(stream)) ++ return; ++ /* ++ * In accordance with CVT 1.2 and CVT 2.1: ++ * Reduced Blanking standard defines a fixed value of ++ * 160 for hblank, further reduced to 80 in RB2. RB3 uses ++ * fixed hblank of 80 pixels + up to 120 additional pixels ++ * in 8-pixel steps. ++ */ ++ hblank = stream->timing.h_total - stream->timing.h_addressable; ++ rb = (hblank >= 80 && hblank <= 200 && hblank % 8 == 0); ++ brr = div_u64(mod_freesync_calc_nominal_field_rate(stream), 1000000); ++ ++ if (brr > VTEM_BRR_MAX) { ++ infopacket->valid = false; ++ return; ++ } ++ ++ infopacket->sb[VTEM_MD1] = (uint8_t) stream->timing.v_front_porch; ++ infopacket->sb[VTEM_MD2] = rb << VTEM_RB_BIT; ++ infopacket->sb[VTEM_MD2] |= (brr >> 8) & VTEM_BRR_MASK_UPPER; ++ infopacket->sb[VTEM_MD3] = brr & VTEM_BRR_MASK_LOWER; ++} ++ ++void mod_build_vtem_infopacket(const struct dc_stream_state *stream, ++ const struct mod_vrr_params *vrr, ++ struct dc_info_packet *infopacket) ++{ ++ infopacket->valid = true; ++ build_vtem_infopacket_header(infopacket); ++ build_vtem_infopacket_data(stream, vrr, infopacket); ++} ++ + void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, + enum adaptive_sync_type asType, + const struct AS_Df_params *param, + +From 75cffc23c2df34ab285c9303250d1a96fd60f4e2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sat, 17 Jan 2026 16:49:11 +0100 +Subject: [PATCH 061/103] drm/amd/display: Enable HDMI VRR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +We'd like to expose VRR functionality to end user if HDMI sink is +advertising it's support. + +[How] +VTEM info frame is used to signal HDMI sink that VRR is active. +Use VTEM info packet as vrr_infopacket + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 ++++++++++++--- + .../drm/amd/display/modules/freesync/freesync.c | 4 ++++ + .../drm/amd/display/modules/inc/mod_info_packet.h | 1 + + .../amd/display/modules/info_packet/info_packet.c | 1 + + 4 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 0c4cfb7b6da0bb..30d9db593b9ec0 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -9624,7 +9624,10 @@ static void update_freesync_state_on_stream( + + aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context; + +- if (aconn && (aconn->as_type == ADAPTIVE_SYNC_TYPE_PCON_ALLOWED || ++ if (aconn && aconn->as_type == ADAPTIVE_SYNC_TYPE_HDMI) ++ packet_type = PACKET_TYPE_VTEM; ++ ++ else if (aconn && (aconn->as_type == ADAPTIVE_SYNC_TYPE_PCON_ALLOWED || + aconn->vsdb_info.replay_mode)) { + pack_sdp_v1_3 = aconn->pack_sdp_v1_3; + +@@ -13378,8 +13381,14 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + } + + /* HDMI */ +- } else if (dc_is_hdmi_signal(sink->sink_signal) && vsdb_info.freesync_supported) { +- monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ } else if (dc_is_hdmi_signal(sink->sink_signal)) { ++ /* Prefer HDMI VRR */ ++ if (hdmi_vrr.supported) { ++ amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_HDMI; ++ monitor_range_from_hdmi(&connector->display_info, &vsdb_info); ++ } else if (vsdb_info.freesync_supported) ++ monitor_range_from_vsdb(&connector->display_info, &vsdb_info); ++ + freesync_capable = copy_range_to_amdgpu_connector(connector); + + /* DP -> HDMI PCON */ +diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +index 1aae46d703ba0b..db197cf048e1bd 100644 +--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c ++++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +@@ -27,6 +27,7 @@ + #include "dc.h" + #include "mod_freesync.h" + #include "core_types.h" ++#include "mod_info_packet.h" + + #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 + +@@ -955,6 +956,9 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, + return; + + switch (packet_type) { ++ case PACKET_TYPE_VTEM: ++ mod_build_vtem_infopacket(stream, vrr, infopacket); ++ break; + case PACKET_TYPE_FS_V3: + build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket, stream->freesync_on_desktop); + break; +diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +index ba83cb23b63f8f..89d412772d16a9 100644 +--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h ++++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +@@ -53,6 +53,7 @@ enum adaptive_sync_type { + ADAPTIVE_SYNC_TYPE_PCON_ALLOWED = 2, + ADAPTIVE_SYNC_TYPE_PCON_NOT_ALLOWED = 3, + ADAPTIVE_SYNC_TYPE_EDP = 4, ++ ADAPTIVE_SYNC_TYPE_HDMI = 5, + }; + + enum adaptive_sync_sdp_version { +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index 503c84111aea16..0dbe9a4e9a8da9 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -640,6 +640,7 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, + break; + case ADAPTIVE_SYNC_TYPE_NONE: + case ADAPTIVE_SYNC_TYPE_PCON_NOT_ALLOWED: ++ case ADAPTIVE_SYNC_TYPE_HDMI: + default: + break; + } + +From 73e4d233b0aceabe114a4ec77e63c66df7110b63 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Thu, 22 Jan 2026 22:02:43 +0100 +Subject: [PATCH 062/103] drm/amd/display: freesync_on_desktop support for HDMI + VRR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +Many TVs and other HDMI sinks suffer from blanking and possibly other +glitches when VRR is toggled. With FreeSync present on such sinks, they +behave like the signal is always variable, even in fixed refresh rate +situations. DisplayPort and eDP enforce seamless VRR transitions but +HDMI unfortunately doesn't. + +[How] +Keep HDMI VRR toggled if it's supported and not explicitly disabled. +Add logic that control this behavior and use this mode by default until +it can be controlled by connector KMS property. + +Functionally, for an end user, this is the same as normal, fixed refresh +rate mode. The only difference is that sink is kept in VRR state which +enables seamless transitions into/out of variable refresh rate. + +Uses the already established freesync_on_desktop field and logic. + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index 0dbe9a4e9a8da9..8df78579d12f80 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -578,6 +578,14 @@ static void build_vtem_infopacket_data(const struct dc_stream_state *stream, + + vrr_active = vrr->state == VRR_STATE_ACTIVE_VARIABLE || + vrr->state == VRR_STATE_ACTIVE_FIXED; ++ /* ++ * Enables FreeSync-like behavior by keeping HDMI VRR signalling active ++ * in fixed refresh rate conditions like normal desktop work/web browsing. ++ * Functinally behaves like non-VRR mode by keeping the actual refresh ++ * rate fixed. ++ */ ++ if (stream->freesync_on_desktop) ++ vrr_active |= vrr->state == VRR_STATE_INACTIVE; + + infopacket->sb[VTEM_MD0] = VTEM_M_CONST << VTEM_M_CONST_BIT; + infopacket->sb[VTEM_MD0] |= VTEM_FVA_FACTOR << VTEM_FVA_BIT; + +From 3afe32fdcd8e62e85ea909333e17bcc704c2852e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Fri, 13 Feb 2026 18:30:58 +0100 +Subject: [PATCH 063/103] drm: Add passive_vrr_disabled property to crtc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Many TVs and other HDMI sinks suffer from blanking and possibly other +glitches when VRR is toggled. With VRR present on such sinks and +vrr_on_desktop enabled, they behave like the signal is always variable, +even in fixed refresh rate situations. DisplayPort and eDP enforce +seamless VRR transitions but HDMI unfortunately doesn't. + +Keep VRR toggled if it's supported and not explicitly disabled. It can +be used for any VRR sinks, but this is mainly targeted for HDMI. + +Functionally, for an end user, this is the same as normal, fixed refresh +rate mode. The only difference is that sink is kept in VRR state which +enables seamless transitions into/out of variable refresh rate. + +Basically, the driver shouldn't change it's behavior around VRR_ENABLED +set to false, jut keep sending info packets/frames with VRR/FreeSync/ +G-Sync/HDMI VRR active. + +Enabled by default for sinks that claim it's support + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/drm_atomic_uapi.c | 4 ++++ + drivers/gpu/drm/drm_crtc.c | 2 ++ + drivers/gpu/drm/drm_mode_config.c | 6 ++++++ + include/drm/drm_crtc.h | 9 +++++++++ + include/drm/drm_mode_config.h | 6 ++++++ + 5 files changed, 27 insertions(+) + diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c -index dc013a22bf26..f7874005f33a 100644 +index 7320db4b8489f1..e48a7cfc21b410 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -412,6 +412,8 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, @@ -11002,9 +12706,9 @@ index dc013a22bf26..f7874005f33a 100644 + } else if (property == config->prop_passive_vrr_disabled) { + state->passive_vrr_disabled = val; } else if (property == config->degamma_lut_property) { - const size_t elem_size = sizeof(struct drm_color_lut); - u64 lut_size; -@@ -495,6 +497,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, + ret = drm_property_replace_blob_from_id(dev, + &state->degamma_lut, +@@ -477,6 +479,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = (state->mode_blob) ? state->mode_blob->base.id : 0; else if (property == config->prop_vrr_enabled) *val = state->vrr_enabled; @@ -11013,42 +12717,100 @@ index dc013a22bf26..f7874005f33a 100644 else if (property == config->degamma_lut_property) *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; else if (property == config->ctm_property) -@@ -901,6 +905,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, - state->content_type = val; - } else if (property == connector->scaling_mode_property) { - state->scaling_mode = val; -+ } else if (property == connector->allm_mode_property) { -+ state->allm_mode = val; - } else if (property == config->content_protection_property) { - if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) { - drm_dbg_kms(dev, "only drivers can set CP Enabled\n"); -@@ -998,6 +1004,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, - *val = state->colorspace; - } else if (property == connector->scaling_mode_property) { - *val = state->scaling_mode; -+ } else if (property == connector->allm_mode_property) { -+ *val = state->allm_mode; - } else if (property == config->hdr_output_metadata_property) { - *val = state->hdr_output_metadata ? - state->hdr_output_metadata->base.id : 0; +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index a7797d260f1e2f..4f2c871552e5d4 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -322,6 +322,8 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc * + config->prop_out_fence_ptr, 0); + drm_object_attach_property(&crtc->base, + config->prop_vrr_enabled, 0); ++ drm_object_attach_property(&crtc->base, ++ config->prop_passive_vrr_disabled, 0); + } + + return 0; +diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c +index d12db9b0bab810..231f54ba66f8aa 100644 +--- a/drivers/gpu/drm/drm_mode_config.c ++++ b/drivers/gpu/drm/drm_mode_config.c +@@ -345,6 +345,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) + return -ENOMEM; + dev->mode_config.prop_vrr_enabled = prop; + ++ prop = drm_property_create_bool(dev, 0, ++ "PASSIVE_VRR_DISABLED"); ++ if (!prop) ++ return -ENOMEM; ++ dev->mode_config.prop_passive_vrr_disabled = prop; ++ + prop = drm_property_create(dev, + DRM_MODE_PROP_BLOB, + "DEGAMMA_LUT", 0); +diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h +index 66278ffeebd68e..59dbb7ce135821 100644 +--- a/include/drm/drm_crtc.h ++++ b/include/drm/drm_crtc.h +@@ -299,6 +299,15 @@ struct drm_crtc_state { + */ + bool vrr_enabled; + ++ /** ++ * @passive_vrr_disabled: ++ * ++ * Indicates if variable refresh rate on desktop should be enabled for ++ * the CRTC. Support for the requested state will depend on driver and ++ * hardware capabiltiy - lacking support is not treated as failure. ++ */ ++ bool passive_vrr_disabled; ++ + /** + * @self_refresh_active: + * +diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h +index 895fb820dba073..23ce744b233bd3 100644 +--- a/include/drm/drm_mode_config.h ++++ b/include/drm/drm_mode_config.h +@@ -697,6 +697,12 @@ struct drm_mode_config { + * whether variable refresh rate should be enabled on the CRTC. + */ + struct drm_property *prop_vrr_enabled; ++ /** ++ * @prop_passive_vrr_disabled: Default atomic CRTC property to indicate ++ * whether passive variable refresh rate should be disabled ++ * on the CRTC. ++ */ ++ struct drm_property *prop_passive_vrr_disabled; + + /** + * @dvi_i_subconnector_property: Optional DVI-I property to + +From 78feb7b59cb8fec76a73b568ad5f835694a4df3e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Fri, 13 Feb 2026 18:32:40 +0100 +Subject: [PATCH 064/103] drm: Add passive_vrr_capable property to connector +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Supplement to the passive_vrr_disabled crtc property + +Drivers can add the property to a connector with +drm_connector_attach_passive_vrr_capable_property(). +The value should be updated based on driver and hardware capability +by using drm_connector_set_passive_vrr_capable_property(). + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/drm_connector.c | 73 +++++++++++++++++++++++++++++++++ + include/drm/drm_connector.h | 15 +++++++ + 2 files changed, 88 insertions(+) + diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c -index 4f5b27fab475..38d649a11a93 100644 +index 4d6dc9ebfdb5bc..198c069f5d068b 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c -@@ -1232,6 +1232,12 @@ static const struct drm_prop_enum_list drm_content_type_enum_list[] = { - { DRM_MODE_CONTENT_TYPE_GAME, "Game" }, - }; - -+static const struct drm_prop_enum_list drm_allm_mode_enum_list[] = { -+ { DRM_ALLM_MODE_DISABLED, "Disabled" }, -+ { DRM_ALLM_MODE_ENABLED_DYNAMIC, "Dynamic" }, -+ { DRM_ALLM_MODE_ENABLED_FORCED, "Always On" }, -+}; -+ - static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = { - { DRM_MODE_PANEL_ORIENTATION_NORMAL, "Normal" }, - { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down" }, -@@ -2352,6 +2358,16 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); +@@ -2346,6 +2346,16 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); * * Absence of the property should indicate absence of support. * @@ -11065,7 +12827,7 @@ index 4f5b27fab475..38d649a11a93 100644 * "VRR_ENABLED": * Default &drm_crtc boolean property that notifies the driver that the * content on the CRTC is suitable for variable refresh rate presentation. -@@ -2370,6 +2386,17 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); +@@ -2364,6 +2374,17 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); * * The driver may place further restrictions within these minimum * and maximum bounds. @@ -11083,7 +12845,7 @@ index 4f5b27fab475..38d649a11a93 100644 */ /** -@@ -2403,6 +2430,125 @@ int drm_connector_attach_vrr_capable_property( +@@ -2397,6 +2418,37 @@ int drm_connector_attach_vrr_capable_property( } EXPORT_SYMBOL(drm_connector_attach_vrr_capable_property); @@ -11118,6 +12880,151 @@ index 4f5b27fab475..38d649a11a93 100644 +} +EXPORT_SYMBOL(drm_connector_attach_passive_vrr_capable_property); + + /** + * drm_connector_attach_scaling_mode_property - attach atomic scaling mode property + * @connector: connector to attach scaling mode property on. +@@ -2968,6 +3020,27 @@ void drm_connector_set_vrr_capable_property( + } + EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); + ++/** ++ * drm_connector_set_passive_vrr_disabled_capable_property - sets the variable refresh ++ * rate on desktop capable property for a connector ++ * @connector: drm connector ++ * @capable: True if the connector is variable refresh rate on desktop capable ++ * ++ * Should be used by atomic drivers to update the indicated support for ++ * variable refresh rate on desktop over a connector. ++ */ ++void drm_connector_set_passive_vrr_capable_property( ++ struct drm_connector *connector, bool capable) ++{ ++ if (!connector->passive_vrr_capable_property) ++ return; ++ ++ drm_object_property_set_value(&connector->base, ++ connector->passive_vrr_capable_property, ++ capable); ++} ++EXPORT_SYMBOL(drm_connector_set_passive_vrr_capable_property); ++ + /** + * drm_connector_set_panel_orientation - sets the connector's panel_orientation + * @connector: connector for which to set the panel-orientation property. +diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h +index 33dd5061f476ca..1987665f8af030 100644 +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -2113,6 +2113,17 @@ struct drm_connector { + */ + struct drm_property *vrr_capable_property; + ++ /** ++ * @passive_vrr_capable_property: Optional property to help userspace ++ * query hardware support for passive variable refresh rate on a ++ * connector. Drivers can add the property to a connector by ++ * calling drm_connector_attach_passive_vrr_capable_property(). ++ * ++ * This should be updated only by calling ++ * drm_connector_set_passive_vrr_capable_property(). ++ */ ++ struct drm_property *passive_vrr_capable_property; ++ + /** + * @colorspace_property: Connector property to set the suitable + * colorspace supported by the sink. +@@ -2507,6 +2518,8 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, + u32 scaling_mode_mask); + int drm_connector_attach_vrr_capable_property( + struct drm_connector *connector); ++int drm_connector_attach_passive_vrr_capable_property( ++ struct drm_connector *connector); + int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector); + int drm_connector_attach_colorspace_property(struct drm_connector *connector); + int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector); +@@ -2529,6 +2542,8 @@ void drm_connector_set_link_status_property(struct drm_connector *connector, + uint64_t link_status); + void drm_connector_set_vrr_capable_property( + struct drm_connector *connector, bool capable); ++void drm_connector_set_passive_vrr_capable_property( ++ struct drm_connector *connector, bool capable); + int drm_connector_set_panel_orientation( + struct drm_connector *connector, + enum drm_panel_orientation panel_orientation); + +From aafeb94351e2b8ffc1a06bbd6750511041fb2d4d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Thu, 12 Feb 2026 00:19:05 +0100 +Subject: [PATCH 065/103] drm: Add ALLM properties to connector +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds HDMI Auto Low Latency Mode optional connector properties allm_mode +and allm_mode_capable. + +ALLM automatically puts TVs into low latency modes (gaming modes) and +it's part of the HDMI Gaming Features introduced in HDMI 2.1. + +allm_mode_capable indicates whether connector (sink) supports ALLM +allm_mode tells the driver which triggering mode to use. Off, dynamic +and always on. Dynamic mode should consider the content type and the +state of the crtc to discern whether ALLM should be activated. + +Recommendation is Content Type Hint == Game || VRR_ENABLED based on +testing behaviors on other operating systems and multiple GPU vendors + +how TVs behave. + +Signed-off-by: Tomasz Pakuła +--- + drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ + drivers/gpu/drm/drm_connector.c | 115 ++++++++++++++++++++++++++++++ + include/drm/drm_connector.h | 37 ++++++++++ + 3 files changed, 156 insertions(+) + +diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c +index e48a7cfc21b410..94e1b7eb65f725 100644 +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -889,6 +889,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, + state->content_type = val; + } else if (property == connector->scaling_mode_property) { + state->scaling_mode = val; ++ } else if (property == connector->allm_mode_property) { ++ state->allm_mode = val; + } else if (property == config->content_protection_property) { + if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) { + drm_dbg_kms(dev, "only drivers can set CP Enabled\n"); +@@ -986,6 +988,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, + *val = state->colorspace; + } else if (property == connector->scaling_mode_property) { + *val = state->scaling_mode; ++ } else if (property == connector->allm_mode_property) { ++ *val = state->allm_mode; + } else if (property == config->hdr_output_metadata_property) { + *val = state->hdr_output_metadata ? + state->hdr_output_metadata->base.id : 0; +diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c +index 198c069f5d068b..bdf49bb3c38e6c 100644 +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -1226,6 +1226,12 @@ static const struct drm_prop_enum_list drm_content_type_enum_list[] = { + { DRM_MODE_CONTENT_TYPE_GAME, "Game" }, + }; + ++static const struct drm_prop_enum_list drm_allm_mode_enum_list[] = { ++ { DRM_ALLM_MODE_DISABLED, "Disabled" }, ++ { DRM_ALLM_MODE_ENABLED_DYNAMIC, "Dynamic" }, ++ { DRM_ALLM_MODE_ENABLED_FORCED, "Always On" }, ++}; ++ + static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = { + { DRM_MODE_PANEL_ORIENTATION_NORMAL, "Normal" }, + { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down" }, +@@ -2449,6 +2455,94 @@ int drm_connector_attach_passive_vrr_capable_property( + } + EXPORT_SYMBOL(drm_connector_attach_passive_vrr_capable_property); + +/** + * DOC: Auto Low Latency Mode properties + * @@ -11209,31 +13116,10 @@ index 4f5b27fab475..38d649a11a93 100644 /** * drm_connector_attach_scaling_mode_property - attach atomic scaling mode property * @connector: connector to attach scaling mode property on. -@@ -2974,6 +3120,48 @@ void drm_connector_set_vrr_capable_property( +@@ -3041,6 +3135,27 @@ void drm_connector_set_passive_vrr_capable_property( } - EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); + EXPORT_SYMBOL(drm_connector_set_passive_vrr_capable_property); -+/** -+ * drm_connector_set_passive_vrr_disabled_capable_property - sets the variable refresh -+ * rate on desktop capable property for a connector -+ * @connector: drm connector -+ * @capable: True if the connector is variable refresh rate on desktop capable -+ * -+ * Should be used by atomic drivers to update the indicated support for -+ * variable refresh rate on desktop over a connector. -+ */ -+void drm_connector_set_passive_vrr_capable_property( -+ struct drm_connector *connector, bool capable) -+{ -+ if (!connector->passive_vrr_capable_property) -+ return; -+ -+ drm_object_property_set_value(&connector->base, -+ connector->passive_vrr_capable_property, -+ capable); -+} -+EXPORT_SYMBOL(drm_connector_set_passive_vrr_capable_property); -+ +/** + * drm_connector_set_allm_capable_property - sets Auto Low Latency Mode + * capable property for a connector @@ -11258,202 +13144,8 @@ index 4f5b27fab475..38d649a11a93 100644 /** * drm_connector_set_panel_orientation - sets the connector's panel_orientation * @connector: connector for which to set the panel-orientation property. -diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c -index a7797d260f1e..4f2c871552e5 100644 ---- a/drivers/gpu/drm/drm_crtc.c -+++ b/drivers/gpu/drm/drm_crtc.c -@@ -322,6 +322,8 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc * - config->prop_out_fence_ptr, 0); - drm_object_attach_property(&crtc->base, - config->prop_vrr_enabled, 0); -+ drm_object_attach_property(&crtc->base, -+ config->prop_passive_vrr_disabled, 0); - } - - return 0; -diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c -index 26bb7710a462..50ec021dbce2 100644 ---- a/drivers/gpu/drm/drm_edid.c -+++ b/drivers/gpu/drm/drm_edid.c -@@ -6108,38 +6108,44 @@ static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db) - } - - static --void drm_get_max_frl_rate(int max_frl_rate, u8 *max_lanes, u8 *max_rate_per_lane) -+void drm_parse_max_frl_rate(int max_frl_rate, struct drm_hdmi_frl_cap *frl) - { -+ u8 max_lanes, max_rate_per_lane; -+ - switch (max_frl_rate) { - case 1: -- *max_lanes = 3; -- *max_rate_per_lane = 3; -+ max_lanes = 3; -+ max_rate_per_lane = 3; - break; - case 2: -- *max_lanes = 3; -- *max_rate_per_lane = 6; -+ max_lanes = 3; -+ max_rate_per_lane = 6; - break; - case 3: -- *max_lanes = 4; -- *max_rate_per_lane = 6; -+ max_lanes = 4; -+ max_rate_per_lane = 6; - break; - case 4: -- *max_lanes = 4; -- *max_rate_per_lane = 8; -+ max_lanes = 4; -+ max_rate_per_lane = 8; - break; - case 5: -- *max_lanes = 4; -- *max_rate_per_lane = 10; -+ max_lanes = 4; -+ max_rate_per_lane = 10; - break; - case 6: -- *max_lanes = 4; -- *max_rate_per_lane = 12; -+ max_lanes = 4; -+ max_rate_per_lane = 12; - break; - case 0: - default: -- *max_lanes = 0; -- *max_rate_per_lane = 0; -+ max_lanes = 0; -+ max_rate_per_lane = 0; - } -+ -+ frl->max_lanes = max_lanes; -+ frl->max_rate = max_frl_rate; -+ frl->max_rate_per_lane = max_rate_per_lane; - } - - static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, -@@ -6152,6 +6158,33 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, - hdmi->y420_dc_modes = dc_mask; - } - -+static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi, const u8 *db) -+{ -+ struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap; -+ -+ if (cea_db_payload_len(db) < 8) -+ return; -+ -+ hdmi->fapa_start_location = db[8] & DRM_EDID_FAPA_START_LOCATION; -+ hdmi->allm = db[8] & DRM_EDID_ALLM; -+ vrr->fva = db[8] & DRM_EDID_FVA; -+ vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR; -+ vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR; -+ vrr->mdelta = db[8] & DRM_EDID_MDELTA; -+ -+ if (cea_db_payload_len(db) < 9) -+ return; -+ -+ vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK; -+ vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48); -+ -+ if (cea_db_payload_len(db) < 10) -+ return; -+ -+ vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10]; -+ vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100); -+} -+ - static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc, - const u8 *hf_scds) - { -@@ -6178,8 +6211,7 @@ static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc, - u8 dsc_max_frl_rate; - - dsc_max_frl_rate = (hf_scds[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4; -- drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes, -- &hdmi_dsc->max_frl_rate_per_lane); -+ drm_parse_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->frl_cap); - - dsc_max_slices = hf_scds[12] & DRM_EDID_DSC_MAX_SLICES; - -@@ -6272,12 +6304,11 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, - - if (hf_scds[7]) { - max_frl_rate = (hf_scds[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4; -- drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes, -- &hdmi->max_frl_rate_per_lane); -+ drm_parse_max_frl_rate(max_frl_rate, &hdmi->frl_cap); - } - - drm_parse_ycbcr420_deep_color_info(connector, hf_scds); -- -+ drm_parse_hdmi_gaming_info(&connector->display_info.hdmi, hf_scds); - if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) { - drm_parse_dsc_info(hdmi_dsc, hf_scds); - dsc_support = true; -@@ -6287,6 +6318,18 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, - "[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n", - connector->base.id, connector->name, - max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support)); -+ drm_dbg_kms(connector->dev, -+ "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support: %s, Fast Vactive support: %s\n", -+ connector->base.id, connector->name, str_yes_no(hdmi->fapa_start_location), -+ str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva)); -+ drm_dbg_kms(connector->dev, -+ "[CONNECTOR:%d:%s] Negative M VRR support: %s, CinemaVRR support: %s, Mdelta: %d\n", -+ connector->base.id, connector->name, str_yes_no(hdmi->vrr_cap.cnmvrr), -+ str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi->vrr_cap.mdelta); -+ drm_dbg_kms(connector->dev, -+ "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR supported: %s\n", -+ connector->base.id, connector->name, hdmi->vrr_cap.vrr_min, -+ hdmi->vrr_cap.vrr_max, str_yes_no(hdmi->vrr_cap.supported)); - } - - static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, -diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c -index d12db9b0bab8..231f54ba66f8 100644 ---- a/drivers/gpu/drm/drm_mode_config.c -+++ b/drivers/gpu/drm/drm_mode_config.c -@@ -345,6 +345,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) - return -ENOMEM; - dev->mode_config.prop_vrr_enabled = prop; - -+ prop = drm_property_create_bool(dev, 0, -+ "PASSIVE_VRR_DISABLED"); -+ if (!prop) -+ return -ENOMEM; -+ dev->mode_config.prop_passive_vrr_disabled = prop; -+ - prop = drm_property_create(dev, - DRM_MODE_PROP_BLOB, - "DEGAMMA_LUT", 0); -diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c -index 7e022c47e8ac..38191d2edc3c 100644 ---- a/drivers/gpu/drm/i915/display/intel_dp.c -+++ b/drivers/gpu/drm/i915/display/intel_dp.c -@@ -3945,13 +3945,13 @@ static int intel_dp_hdmi_sink_max_frl(struct intel_dp *intel_dp) - int max_lanes, rate_per_lane; - int max_dsc_lanes, dsc_rate_per_lane; - -- max_lanes = info->hdmi.max_lanes; -- rate_per_lane = info->hdmi.max_frl_rate_per_lane; -+ max_lanes = info->hdmi.frl_cap.max_lanes; -+ rate_per_lane = info->hdmi.frl_cap.max_rate_per_lane; - max_frl_rate = max_lanes * rate_per_lane; - - if (info->hdmi.dsc_cap.v_1p2) { -- max_dsc_lanes = info->hdmi.dsc_cap.max_lanes; -- dsc_rate_per_lane = info->hdmi.dsc_cap.max_frl_rate_per_lane; -+ max_dsc_lanes = info->hdmi.dsc_cap.frl_cap.max_lanes; -+ dsc_rate_per_lane = info->hdmi.dsc_cap.frl_cap.max_rate_per_lane; - if (max_dsc_lanes && dsc_rate_per_lane) - max_frl_rate = min(max_frl_rate, max_dsc_lanes * dsc_rate_per_lane); - } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h -index 7eaec37ae1c7..cc17c17e3103 100644 +index 1987665f8af030..f44f63afd9dc66 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -58,6 +58,12 @@ enum drm_connector_force { @@ -11469,110 +13161,7 @@ index 7eaec37ae1c7..cc17c17e3103 100644 /** * enum drm_connector_status - status for a &drm_connector * -@@ -254,6 +260,62 @@ struct drm_scdc { - struct drm_scrambling scrambling; - }; - -+/** -+ * struct drm_hdmi_frl_cap - FRL capabilities of HDMI sink -+ * -+ * Describes the FRL support provided by HDMI 2.1 sink. -+ * The information is fetched fom additional HFVSDB blocks defined -+ * for HDMI 2.1. -+ */ -+struct drm_hdmi_frl_cap { -+ /** @max_rate: raw max rate value without parsing */ -+ u8 max_rate; -+ -+ /** @max_frl_rate_per_lane: support fixed rate link */ -+ u8 max_rate_per_lane; -+ -+ /** @max_lanes: supported by sink */ -+ u8 max_lanes; -+}; -+ -+/* -+ * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink -+ * -+ * Describes the VRR support provided by HDMI 2.1 sink. The information is -+ * fetched fom additional HFVSDB blocks defined for HDMI 2.1. -+ */ -+struct drm_hdmi_vrr_cap { -+ /** @fva: flag for Fast VActive (Quick Frame Transport) support */ -+ bool fva; -+ -+ /** @mcnmvrr: flag for Negative M VRR support */ -+ bool cnmvrr; -+ -+ /** @mcinema_vrr: flag for Cinema VRR support */ -+ bool cinema_vrr; -+ -+ /** @mdelta: flag for limited frame-to-frame compensation support */ -+ bool mdelta; -+ -+ /** -+ * @vrr_min : minimum supported variable refresh rate in Hz. -+ * Valid values only inide 1 - 48 range -+ */ -+ u16 vrr_min; -+ -+ /** -+ * @vrr_max : maximum supported variable refresh rate in Hz (optional). -+ * Valid values are either 0 (max based on video mode) or >= 100 -+ */ -+ u16 vrr_max; -+ -+ /** -+ * @supported: flag for vrr support based on checking for VRRmin and -+ * VRRmax values having correct values. -+ */ -+ bool supported; -+}; -+ - /** - * struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink - * -@@ -285,14 +347,11 @@ struct drm_hdmi_dsc_cap { - /** @clk_per_slice : max pixel clock in MHz supported per slice */ - int clk_per_slice; - -- /** @max_lanes : dsc max lanes supported for Fixed rate Link training */ -- u8 max_lanes; -- -- /** @max_frl_rate_per_lane : maximum frl rate with DSC per lane */ -- u8 max_frl_rate_per_lane; -- - /** @total_chunk_kbytes: max size of chunks in KBs supported per line*/ - u8 total_chunk_kbytes; -+ -+ /** @frl_cap: FRL under DSC capabilities of the sink */ -+ struct drm_hdmi_frl_cap frl_cap; - }; - - /** -@@ -324,11 +383,17 @@ struct drm_hdmi_info { - /** @y420_dc_modes: bitmap of deep color support index */ - u8 y420_dc_modes; - -- /** @max_frl_rate_per_lane: support fixed rate link */ -- u8 max_frl_rate_per_lane; -+ /** @frl_cap: FRL capabilities of the sink */ -+ struct drm_hdmi_frl_cap frl_cap; - -- /** @max_lanes: supported by sink */ -- u8 max_lanes; -+ /** @fapa_start_location: flag for the FAPA in blanking support */ -+ bool fapa_start_location; -+ -+ /** @allm: flag for Auto Low Latency Mode support by sink */ -+ bool allm; -+ -+ /** @vrr_cap: VRR capabilities of the sink */ -+ struct drm_hdmi_vrr_cap vrr_cap; - - /** @dsc_cap: DSC capabilities of the sink */ - struct drm_hdmi_dsc_cap dsc_cap; -@@ -1100,6 +1165,13 @@ struct drm_connector_state { +@@ -1159,6 +1165,13 @@ struct drm_connector_state { */ unsigned int content_protection; @@ -11586,21 +13175,10 @@ index 7eaec37ae1c7..cc17c17e3103 100644 /** * @colorspace: State variable for Connector property to request * colorspace change on Sink. This is most commonly used to switch -@@ -2099,6 +2171,37 @@ struct drm_connector { +@@ -2124,6 +2137,26 @@ struct drm_connector { */ - struct drm_property *vrr_capable_property; + struct drm_property *passive_vrr_capable_property; -+ /** -+ * @passive_vrr_capable_property: Optional property to help userspace -+ * query hardware support for passive variable refresh rate on a -+ * connector. Drivers can add the property to a connector by -+ * calling drm_connector_attach_passive_vrr_capable_property(). -+ * -+ * This should be updated only by calling -+ * drm_connector_set_passive_vrr_capable_property(). -+ */ -+ struct drm_property *passive_vrr_capable_property; -+ + /** + * @allm_capable_property: Optional property to help userspace + * query hardware support for HDMI Auto Low Latency Mode on a connector. @@ -11624,62 +13202,3553 @@ index 7eaec37ae1c7..cc17c17e3103 100644 /** * @colorspace_property: Connector property to set the suitable * colorspace supported by the sink. -@@ -2493,6 +2596,10 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, - u32 scaling_mode_mask); - int drm_connector_attach_vrr_capable_property( +@@ -2520,6 +2553,8 @@ int drm_connector_attach_vrr_capable_property( + struct drm_connector *connector); + int drm_connector_attach_passive_vrr_capable_property( struct drm_connector *connector); -+int drm_connector_attach_passive_vrr_capable_property( -+ struct drm_connector *connector); +int drm_connector_attach_allm_capable_property(struct drm_connector *connector); +int drm_connector_attach_allm_mode_property(struct drm_connector *connector); int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector); int drm_connector_attach_colorspace_property(struct drm_connector *connector); int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector); -@@ -2515,6 +2622,10 @@ void drm_connector_set_link_status_property(struct drm_connector *connector, - uint64_t link_status); - void drm_connector_set_vrr_capable_property( +@@ -2544,6 +2579,8 @@ void drm_connector_set_vrr_capable_property( + struct drm_connector *connector, bool capable); + void drm_connector_set_passive_vrr_capable_property( struct drm_connector *connector, bool capable); -+void drm_connector_set_passive_vrr_capable_property( -+ struct drm_connector *connector, bool capable); +void drm_connector_set_allm_capable_property( + struct drm_connector *connector, bool capable); int drm_connector_set_panel_orientation( struct drm_connector *connector, enum drm_panel_orientation panel_orientation); -diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h -index 66278ffeebd6..59dbb7ce1358 100644 ---- a/include/drm/drm_crtc.h -+++ b/include/drm/drm_crtc.h -@@ -299,6 +299,15 @@ struct drm_crtc_state { - */ - bool vrr_enabled; + +From 4c24a137b15d4bfa6d3ecbc343459c316fc61290 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Wed, 11 Feb 2026 22:24:35 +0100 +Subject: [PATCH 066/103] drm/amd/display: Use passive_vrr properties in amdgpu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[How] +Attach and use this properties for HDMI sinks which are troublesome +with their VRR state transitions. Hook into already-established +freesync_on_desktop logic. + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 ++++++++++++++++--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + + .../display/modules/info_packet/info_packet.c | 11 +++++--- + 3 files changed, 29 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 30d9db593b9ec0..289f585b6c089d 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -7845,6 +7845,8 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) + __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); -+ /** -+ * @passive_vrr_disabled: -+ * -+ * Indicates if variable refresh rate on desktop should be enabled for -+ * the CRTC. Support for the requested state will depend on driver and -+ * hardware capabiltiy - lacking support is not treated as failure. -+ */ -+ bool passive_vrr_disabled; + new_state->freesync_capable = state->freesync_capable; ++ new_state->freesync_on_desktop_capable = ++ state->freesync_on_desktop_capable; + new_state->abm_level = state->abm_level; + new_state->scaling = state->scaling; + new_state->underscan_enable = state->underscan_enable; +@@ -9052,8 +9054,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + connector_type == DRM_MODE_CONNECTOR_eDP) { + drm_connector_attach_hdr_output_metadata_property(&aconnector->base); + +- if (!aconnector->mst_root) ++ if (!aconnector->mst_root) { + drm_connector_attach_vrr_capable_property(&aconnector->base); ++ drm_connector_attach_passive_vrr_capable_property(&aconnector->base); ++ } + + if (adev->dm.hdcp_workqueue) + drm_connector_attach_content_protection_property(&aconnector->base, true); +@@ -11333,6 +11337,12 @@ static void get_freesync_config_for_crtc( + config.vsif_supported = true; + config.btr = true; + ++ if (new_con_state->freesync_on_desktop_capable) ++ new_crtc_state->stream->freesync_on_desktop = ++ !new_crtc_state->base.passive_vrr_disabled; ++ else ++ new_crtc_state->stream->freesync_on_desktop = false; + - /** - * @self_refresh_active: - * -diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h -index 895fb820dba0..23ce744b233b 100644 ---- a/include/drm/drm_mode_config.h -+++ b/include/drm/drm_mode_config.h -@@ -697,6 +697,12 @@ struct drm_mode_config { - * whether variable refresh rate should be enabled on the CRTC. - */ - struct drm_property *prop_vrr_enabled; -+ /** -+ * @prop_passive_vrr_disabled: Default atomic CRTC property to indicate -+ * whether passive variable refresh rate should be disabled -+ * on the CRTC. -+ */ -+ struct drm_property *prop_passive_vrr_disabled; + if (fs_vid_mode) { + config.state = VRR_STATE_ACTIVE_FIXED; + config.fixed_refresh_in_uhz = new_crtc_state->freesync_config.fixed_refresh_in_uhz; +@@ -11344,6 +11354,7 @@ static void get_freesync_config_for_crtc( + } + } else { + config.state = VRR_STATE_UNSUPPORTED; ++ new_crtc_state->stream->freesync_on_desktop = false; + } + out: + new_crtc_state->freesync_config = config; +@@ -13311,6 +13322,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + struct drm_hdmi_vrr_cap hdmi_vrr = {0}; + struct dpcd_caps dpcd_caps = {0}; + const struct edid *edid; ++ bool freesync_on_desktop = false; + bool freesync_capable = false; + bool pcon_allowed = false; + bool is_pcon = false; +@@ -13390,6 +13402,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + monitor_range_from_vsdb(&connector->display_info, &vsdb_info); - /** - * @dvi_i_subconnector_property: Optional DVI-I property to + freesync_capable = copy_range_to_amdgpu_connector(connector); ++ freesync_on_desktop = freesync_capable; + + /* DP -> HDMI PCON */ + } else if (pcon_allowed) { +@@ -13407,8 +13420,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + } + + update: +- if (dm_con_state) ++ if (dm_con_state) { + dm_con_state->freesync_capable = freesync_capable; ++ dm_con_state->freesync_on_desktop_capable = freesync_on_desktop; ++ } + + if (connector->state && amdgpu_dm_connector->dc_link && !freesync_capable && + amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) { +@@ -13417,8 +13432,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + } + + if (connector->vrr_capable_property) +- drm_connector_set_vrr_capable_property(connector, +- freesync_capable); ++ drm_connector_set_vrr_capable_property(connector, freesync_capable); ++ ++ if (connector->passive_vrr_capable_property) ++ drm_connector_set_passive_vrr_capable_property(connector, freesync_on_desktop); + } + + void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index beb0d04d3e6827..bd77d1eb57b3d4 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -1001,6 +1001,7 @@ struct dm_connector_state { + uint8_t underscan_hborder; + bool underscan_enable; + bool freesync_capable; ++ bool freesync_on_desktop_capable; + bool update_hdcp; + bool abm_sysfs_forbidden; + uint8_t abm_level; +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index 8df78579d12f80..61d6cf33b09de5 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -576,16 +576,19 @@ static void build_vtem_infopacket_data(const struct dc_stream_state *stream, + bool vrr_active = false; + bool rb = false; + +- vrr_active = vrr->state == VRR_STATE_ACTIVE_VARIABLE || +- vrr->state == VRR_STATE_ACTIVE_FIXED; + /* + * Enables FreeSync-like behavior by keeping HDMI VRR signalling active + * in fixed refresh rate conditions like normal desktop work/web browsing. + * Functinally behaves like non-VRR mode by keeping the actual refresh + * rate fixed. + */ +- if (stream->freesync_on_desktop) +- vrr_active |= vrr->state == VRR_STATE_INACTIVE; ++ if (stream->freesync_on_desktop) { ++ vrr_active = vrr->state != VRR_STATE_DISABLED && ++ vrr->state != VRR_STATE_UNSUPPORTED; ++ } else { ++ vrr_active = vrr->state == VRR_STATE_ACTIVE_VARIABLE || ++ vrr->state == VRR_STATE_ACTIVE_FIXED; ++ } + + infopacket->sb[VTEM_MD0] = VTEM_M_CONST << VTEM_M_CONST_BIT; + infopacket->sb[VTEM_MD0] |= VTEM_FVA_FACTOR << VTEM_FVA_BIT; + +From c80aac2544be767d1a7e092f9f6eaf1272e8c78d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= +Date: Sat, 14 Feb 2026 00:17:22 +0100 +Subject: [PATCH 067/103] drm/amd/display: Use ALLM properties in amdgpu +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[Why] +To enable ALLM when asked for by compositor + +[How] +Attach properties to HDMI sinks, detect support and set allm_capable +property, set allm_capable property for amdgpu_dm_connector + +Signed-off-by: Tomasz Pakuła +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 54 ++++++++++++++++++- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 ++ + drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++ + .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- + drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 + + .../display/modules/info_packet/info_packet.c | 4 +- + 6 files changed, 64 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 289f585b6c089d..0b5c47d9194a92 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -8964,6 +8964,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + aconnector->audio_inst = -1; + aconnector->pack_sdp_v1_3 = false; + aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE; ++ aconnector->hdmi_allm_capable = false; + memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info)); + mutex_init(&aconnector->hpd_lock); + mutex_init(&aconnector->handle_mst_msg_ready); +@@ -9161,6 +9162,10 @@ int amdgpu_dm_initialize_hdmi_connector(struct amdgpu_dm_connector *aconnector) + struct drm_device *ddev = aconnector->base.dev; + struct device *hdmi_dev = ddev->dev; + ++ /* ALLM */ ++ drm_connector_attach_allm_capable_property(&aconnector->base); ++ drm_connector_attach_allm_mode_property(&aconnector->base); ++ + if (amdgpu_dc_debug_mask & DC_DISABLE_HDMI_CEC) { + drm_info(ddev, "HDMI-CEC feature masked\n"); + return -EINVAL; +@@ -10851,6 +10856,31 @@ static int amdgpu_dm_atomic_setup_commit(struct drm_atomic_state *state) + return 0; + } + ++static void update_allm_state_on_crtc_stream(struct dm_crtc_state *new_crtc_state, ++ const struct drm_connector_state *new_conn) ++{ ++ struct mod_freesync_config *config = &new_crtc_state->freesync_config; ++ struct dc_stream_state *new_stream = new_crtc_state->stream; ++ bool allm_active = false; ++ ++ switch (new_conn->allm_mode) { ++ case DRM_ALLM_MODE_ENABLED_DYNAMIC: ++ allm_active = config->state == VRR_STATE_ACTIVE_VARIABLE || ++ new_stream->content_type == DISPLAY_CONTENT_TYPE_GAME; ++ break; ++ ++ case DRM_ALLM_MODE_ENABLED_FORCED: ++ allm_active = true; ++ break; ++ ++ case DRM_ALLM_MODE_DISABLED: ++ default: ++ allm_active = false; ++ } ++ ++ new_stream->hdmi_allm_active = allm_active; ++} ++ + /** + * amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. + * @state: The atomic state to commit +@@ -10893,12 +10923,14 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); ++ struct amdgpu_dm_connector *dm_conn = to_amdgpu_dm_connector(connector); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); + struct dc_surface_update *dummy_updates; + struct dc_stream_update stream_update; + struct dc_info_packet hdr_packet; + struct dc_stream_status *status = NULL; + bool abm_changed, hdr_changed, scaling_changed, output_color_space_changed = false; ++ bool allm_changed = false; + + memset(&stream_update, 0, sizeof(stream_update)); + +@@ -10928,7 +10960,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + hdr_changed = + !drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state); + +- if (!scaling_changed && !abm_changed && !hdr_changed && !output_color_space_changed) ++ allm_changed = dm_conn->hdmi_allm_capable && ++ (new_con_state->allm_mode != old_con_state->allm_mode); ++ ++ if (!scaling_changed && !abm_changed && !hdr_changed && ++ !output_color_space_changed && !allm_changed) + continue; + + stream_update.stream = dm_new_crtc_state->stream; +@@ -10958,6 +10994,17 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + stream_update.hdr_static_metadata = &hdr_packet; + } + ++ if (allm_changed) { ++ update_allm_state_on_crtc_stream(dm_new_crtc_state, new_con_state); ++ mod_build_hf_vsif_infopacket(dm_new_crtc_state->stream, ++ &dm_new_crtc_state->stream->hfvsif_infopacket); ++ ++ stream_update.hdmi_allm_active = ++ &dm_new_crtc_state->stream->hdmi_allm_active; ++ stream_update.hfvsif_infopacket = ++ &dm_new_crtc_state->stream->hfvsif_infopacket; ++ } ++ + status = dc_stream_get_status(dm_new_crtc_state->stream); + + if (WARN_ON(!status)) +@@ -13436,6 +13483,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + + if (connector->passive_vrr_capable_property) + drm_connector_set_passive_vrr_capable_property(connector, freesync_on_desktop); ++ ++ amdgpu_dm_connector->hdmi_allm_capable = connector->display_info.hdmi.allm; ++ if (connector->allm_capable_property) ++ drm_connector_set_allm_capable_property( ++ connector, connector->display_info.hdmi.allm); + } + + void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index bd77d1eb57b3d4..6376d12acb72e0 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -828,6 +828,9 @@ struct amdgpu_dm_connector { + unsigned int hdmi_hpd_debounce_delay_ms; + struct delayed_work hdmi_hpd_debounce_work; + struct dc_sink *hdmi_prev_sink; ++ ++ /* HDMI ALLM */ ++ bool hdmi_allm_capable; + }; + + static inline void amdgpu_dm_set_mst_status(uint8_t *status, +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index ecb10cec539e69..488133eac246e3 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -3290,6 +3290,9 @@ static void copy_stream_update_to_stream(struct dc *dc, + if (update->vrr_active_fixed) + stream->vrr_active_fixed = *update->vrr_active_fixed; + ++ if (update->hdmi_allm_active) ++ stream->hdmi_allm_active = *update->hdmi_allm_active; ++ + if (update->crtc_timing_adjust) { + if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || + stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index b78b162cab5cf9..19dc060bd13483 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -4734,7 +4734,7 @@ static void set_avi_info_frame( + vic = 0; + format = stream->timing.timing_3d_format; + /*todo, add 3DStereo support*/ +- if (format != TIMING_3D_FORMAT_NONE) { ++ if (format != TIMING_3D_FORMAT_NONE || stream->hdmi_allm_active) { + // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled + switch (pipe_ctx->stream->timing.hdmi_vic) { + case 1: +diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h +index 321cfe92d799ad..e69c17413835ed 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h +@@ -242,6 +242,7 @@ struct dc_stream_state { + bool vrr_active_variable; + bool freesync_on_desktop; + bool vrr_active_fixed; ++ bool hdmi_allm_active; + + bool converter_disable_audio; + uint8_t qs_bit; +@@ -343,6 +344,7 @@ struct dc_stream_update { + bool *allow_freesync; + bool *vrr_active_variable; + bool *vrr_active_fixed; ++ bool *hdmi_allm_active; + + struct colorspace_transform *gamut_remap; + enum dc_color_space *output_color_space; +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index 61d6cf33b09de5..a16a94dffa8d71 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -445,7 +445,7 @@ static bool is_hdmi_vic_mode(const struct dc_stream_state *stream) + if (stream->view_format != VIEW_3D_FORMAT_NONE) + return false; + +- if (stream->link->local_sink->edid_caps.allm) ++ if (stream->hdmi_allm_active) + return false; + + return true; +@@ -474,7 +474,7 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, + + info_packet->valid = false; + +- allm = stream->link->local_sink->edid_caps.allm; ++ allm = stream->hdmi_allm_active; + format = stream->view_format == VIEW_3D_FORMAT_NONE ? + TIMING_3D_FORMAT_NONE : + stream->timing.timing_3d_format; + +From 7f3aeac71a71edd4db0299389a3fc5932d5bb8af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 19:20:33 +0100 +Subject: [PATCH 068/103] drivers/gpu/drm/amd/display/dc/link: resolve some + compilation warnings + +--- + .../drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c | 12 ++++++------ + .../display/dc/link/protocols/link_frl_training.c | 1 - + 2 files changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +index 0122d0dfd19f90..20a27f9d98f7b1 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c ++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +@@ -51,7 +51,7 @@ disable_hpo_hdmi_frl_link_output(struct dc_link *link, + enc->funcs->link_disable(enc); + } + +-void setup_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) ++static void setup_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) + { + struct hpo_hdmi_stream_encoder *stream_enc = + pipe_ctx->stream_res.hpo_hdmi_stream_enc; +@@ -60,7 +60,7 @@ void setup_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) + stream_enc->funcs->enable(stream_enc, otg_inst); + } + +-void reset_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) ++static void reset_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) + { + struct hpo_hdmi_stream_encoder *stream_enc = + pipe_ctx->stream_res.hpo_hdmi_stream_enc; +@@ -72,7 +72,7 @@ void reset_hpo_hdmi_frl_stream_encoder(struct pipe_ctx *pipe_ctx) + stream_enc->funcs->disable(stream_enc); + } + +-void setup_hpo_hdmi_frl_stream_attribute(struct pipe_ctx *pipe_ctx) ++static void setup_hpo_hdmi_frl_stream_attribute(struct pipe_ctx *pipe_ctx) + { + struct hpo_hdmi_stream_encoder *stream_enc = + pipe_ctx->stream_res.hpo_hdmi_stream_enc; +@@ -87,7 +87,7 @@ void setup_hpo_hdmi_frl_stream_attribute(struct pipe_ctx *pipe_ctx) + output_color_space); + } + +-void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, ++static void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output, + uint32_t audio_inst) + { +@@ -96,13 +96,13 @@ void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, + &pipe_ctx->stream->audio_info, &audio_output->crtc_info); + } + +-void enable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) ++static void enable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) + { + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs->hdmi_audio_enable( + pipe_ctx->stream_res.hpo_hdmi_stream_enc); + } + +-void disable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) ++static void disable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) + { + if (pipe_ctx->stream_res.audio) + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 07cd6546049296..03c20f6566f6c7 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -60,7 +60,6 @@ bool dc_link_perform_frl_training(struct dc_link *link, + uint8_t sink_version; + uint8_t update; + uint8_t status; +- uint8_t flags; + uint16_t ltp_req; + uint8_t write_buffer[2]; + int poll; + +From 804f37f1338eb8710785b73f64c036f825510a59 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 19:21:28 +0100 +Subject: [PATCH 069/103] drivers/gpu/drm/amd/display/dc/bios/command_table2.c: + remove unneeded debug print + +--- + drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +index 257358b95372c1..f2b1720a6a6600 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +@@ -374,9 +374,6 @@ static enum bp_result transmitter_control_v1_7( + DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_10khz = %d\n", + __func__, dig_v1_7.symclk_units.symclk_10khz); + } +- DC_LOG_ERROR("phyid %d action %d laneset 0x%x lanenum %d hpdsel %d digfe_sel %d connobj_id %d HPO_instance %d symclk_10khz %d\n", +- dig_v1_7.phyid, dig_v1_7.action, dig_v1_7.mode_laneset, dig_v1_7.lanenum, +- dig_v1_7.hpdsel, dig_v1_7.digfe_sel, dig_v1_7.connobj_id, dig_v1_7.HPO_instance, dig_v1_7.symclk_units.symclk_10khz); + + if (bp->base.ctx->dc->ctx->dmub_srv && + bp->base.ctx->dc->debug.dmub_command_table) { + +From 5b9f12442483f6a8d4accff671b15c4b553a2340 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 21:30:44 +0100 +Subject: [PATCH 070/103] + drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c: implement + set_hdmistreamclk + +--- + .../amd/display/dc/dccg/dcn32/dcn32_dccg.c | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c +index 21a6ca5ca19276..3db490280f09b4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c +@@ -309,6 +309,51 @@ static void dccg32_set_dpstreamclk( + } + } + ++static void dccg32_enable_hdmistreamclk(struct dccg *dccg, int otg_inst, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ REG_UPDATE_2(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_SRC_SEL, otg_inst, ++ HDMISTREAMCLK0_EN, 1); ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++static void dccg32_disable_hdmistreamclk(struct dccg *dccg, int hdmi_hpo_inst) ++{ ++ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); ++ ++ switch (hdmi_hpo_inst) { ++ case 0: ++ REG_UPDATE(HDMISTREAMCLK_CNTL, ++ HDMISTREAMCLK0_EN, 0); ++ break; ++ default: ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++} ++ ++static void dccg32_set_hdmistreamclk( ++ struct dccg *dccg, ++ enum streamclk_source src, ++ int otg_inst, ++ int hdmi_hpo_inst) ++{ ++ /* enabled to select one of the DTBCLKs for pipe */ ++ if (src == REFCLK) ++ dccg32_disable_hdmistreamclk(dccg, hdmi_hpo_inst); ++ else ++ dccg32_enable_hdmistreamclk(dccg, otg_inst, hdmi_hpo_inst); ++} ++ + static void dccg32_otg_add_pixel(struct dccg *dccg, + uint32_t otg_inst) + { +@@ -332,6 +377,7 @@ static const struct dccg_funcs dccg32_funcs = { + .get_dccg_ref_freq = dccg32_get_dccg_ref_freq, + .dccg_init = dccg31_init, + .set_dpstreamclk = dccg32_set_dpstreamclk, ++ .set_hdmistreamclk = dccg32_set_hdmistreamclk, + .enable_symclk32_se = dccg31_enable_symclk32_se, + .disable_symclk32_se = dccg31_disable_symclk32_se, + .enable_symclk32_le = dccg31_enable_symclk32_le, + +From 203f2542c71d8753579db7be32f4aad418dd8a00 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 23:13:29 +0100 +Subject: [PATCH 071/103] + drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c: Program DTBCLK for + HDMI FRL + +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index c3c0a59a00f2d2..0c2036f7f39e76 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -892,7 +892,7 @@ enum dc_status dcn20_enable_stream_timing( + return DC_ERROR_UNEXPECTED; + } + +- if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { ++ if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { + struct dccg *dccg = dc->res_pool->dccg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct dtbclk_dto_params dto_params = {0}; +@@ -3059,6 +3059,12 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + } + } else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) { ++ dto_params.otg_inst = tg->inst; ++ dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; ++ dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); ++ dto_params.timing = &pipe_ctx->stream->timing; ++ dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); ++ dccg->funcs->set_dtbclk_dto(dccg, &dto_params); + hdmi_hpo_inst = pipe_ctx->stream_res.hpo_hdmi_stream_enc->inst; + dccg->funcs->set_hdmistreamclk(dccg, DTBCLK0, tg->inst, hdmi_hpo_inst); + } else { + +From 5431238a47ad91a6d44e29825b890f4dc5435112 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 23:15:14 +0100 +Subject: [PATCH 072/103] + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c: Disable DTBCLK in + HDMI FRL case + +--- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 5c3270299cad85..4657963df68d1a 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1219,9 +1219,15 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) + } + } + } else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) && dccg) { ++ dto_params.otg_inst = tg->inst; ++ dto_params.timing = &pipe_ctx->stream->timing; + hdmi_hpo_inst = pipe_ctx->stream_res.hpo_hdmi_stream_enc->inst; + if (dccg) { + dccg->funcs->set_hdmistreamclk(dccg, REFCLK, tg->inst, hdmi_hpo_inst); ++ if (!(dc->ctx->dce_version >= DCN_VERSION_3_5)) { ++ if (dccg && dccg->funcs->set_dtbclk_dto) ++ dccg->funcs->set_dtbclk_dto(dccg, &dto_params); ++ } + } + } else if (dccg && dccg->funcs->disable_symclk_se) { + dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, + +From 57f39c51619a99f9e7a4c61f5c60a45f6212b440 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 17 Feb 2026 23:37:34 +0100 +Subject: [PATCH 073/103] drivers/gpu/drm/amd/display/dc/hpo/dcn30: handle + YUV420 properly + +--- + .../amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index 12b813c5e28945..d57a760c6e50db 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -301,6 +301,9 @@ static void dcn30_hpo_hdmi_stream_enc_setup_stream_attribute( + case PIXEL_ENCODING_YCBCR444: + pixel_encoding = 2; + break; ++ case PIXEL_ENCODING_YCBCR420: ++ pixel_encoding = 3; ++ break; + default: /* RGB */ + pixel_encoding = 0; + break; + +From ab5a26562bb3569eb8b949a627cff5320de4f998 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Thu, 19 Feb 2026 00:30:49 +0100 +Subject: [PATCH 074/103] drivers/gpu/drm/amd/display/dc/core/dc_resource.c: + FRL DFM + +--- + .../gpu/drm/amd/display/dc/core/dc_resource.c | 329 ++++++++++++++++-- + 1 file changed, 297 insertions(+), 32 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 19dc060bd13483..417a867dbb1584 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -3974,48 +3974,313 @@ static bool acquire_otg_master_pipe_for_stream( + return pipe_idx != FREE_PIPE_INDEX_NOT_FOUND; + } + +-static uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) ++/* DFM calc ++ * References: ++ * https://github.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_linux/drv/mpp/component/hdmi/src/mkp/drv_hdmi_dfm.c#L264 ++ * https://github.com/jelyoussefi/intel-gpu-i915/blob/e366083d562341ce15d5fe1a39bb6e07f18a4745/drivers/gpu/drm/i915/display/intel_hdmi.c#L4217 ++ * TODO Move to separate file in protocols */ ++ ++#define DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000 5 /* +0.50% -> 5/1000 */ ++#define DFM_TOLERANCE_AUDIO_CLOCK_PPM 1000 /* +/- 1000 ppm */ ++#define DFM_TOLERANCE_FRL_BIT_RATE_PPM 300 /* +/- 300 ppm */ ++#define DFM_TB_BORROWED_MAX 400 ++#define DFM_FRL_CFRL_CB 510 ++ ++struct dfm_config { ++ /* Video Timing */ ++ uint32_t pixel_clock_khz; /* Nominal */ ++ uint32_t hactive; ++ uint32_t hblank; ++ uint32_t bpc; /* Bits per component */ ++ enum dc_pixel_encoding encoding; ++ ++ /* FRL Configuration */ ++ uint32_t frl_bit_rate_gbps; /* 3, 6, 8, 10, 12 */ ++ uint8_t lanes; /* 3 or 4 */ ++ ++ /* Audio */ ++ bool audio_enable; ++ uint32_t audio_freq_hz; ++ uint8_t audio_channels; ++}; ++ ++struct dfm_results { ++ /* Calculated Parameters */ ++ uint64_t f_pixel_clock_max; ++ uint64_t r_frl_char_min; ++ uint32_t overhead_ppm; ++ ++ /* Audio */ ++ uint32_t audio_packets_line; ++ uint32_t hblank_audio_min; ++ ++ /* Tri-Bytes */ ++ uint32_t tb_active; ++ uint32_t tb_blank; ++ ++ /* Compression */ ++ uint32_t cfrl_rc_savings; ++ ++ /* Timing (ns) */ ++ uint64_t t_active_min; ++ uint64_t t_active_ref; ++ uint64_t t_blank_min; ++ uint64_t t_blank_ref; ++ ++ /* Borrowing */ ++ uint64_t tb_borrowed; ++ ++ /* Utilization */ ++ uint32_t cfrl_line; ++ uint32_t cfrl_actual_payload; ++ int32_t margin_ppm; /* Can be negative */ ++ ++ /* Pass/Fail Flags */ ++ bool audio_supported; ++ bool dfm_supported; ++ bool utilization_supported; ++ bool total_supported; ++}; ++ ++ ++#define CEILING(x, y) (((x) + (y) - 1) / (y)) ++#define MAX(a, b) ((a) > (b) ? (a) : (b)) ++ ++static uint32_t calc_overhead_ppm(uint8_t lanes) + { +- static const uint8_t frl_lane_rate_gbps[] = { +- [1] = 3, [2] = 6, [3] = 6, [4] = 8, [5] = 10, [6] = 12, +- }; ++ uint32_t cfrl_sb = (4 * 510) + lanes; + +- uint32_t lane_rate_gbps; +- uint32_t lane_count; ++ uint64_t oh_sb_num = (uint64_t)lanes * 1000000ULL; ++ uint32_t oh_sb = (uint32_t)((oh_sb_num + (cfrl_sb/2)) / cfrl_sb); /* Rounding */ + +- if (frl_rate < 1 || frl_rate > 6) +- return 0; ++ uint64_t oh_rs_num = 32ULL * 1000000ULL; ++ uint32_t oh_rs = (uint32_t)((oh_rs_num + (cfrl_sb/2)) / cfrl_sb); ++ ++ uint64_t oh_map_num = 2500000ULL; /* 2.5 * 1M */ ++ uint32_t oh_map = (uint32_t)((oh_map_num + (cfrl_sb/2)) / cfrl_sb); + +- lane_count = (frl_rate <= 2) ? 3 : 4; +- lane_rate_gbps = frl_lane_rate_gbps[frl_rate]; ++ uint32_t oh_m = 3000; + +- return lane_count * lane_rate_gbps * 1000000 * 16 / 18; ++ return oh_sb + oh_rs + oh_map + oh_m; + } + +-static bool hdmi_decide_link_settings( +- struct dc_stream_state *stream, +- struct pipe_ctx *pipe_ctx) +-{ +- uint8_t frl_rate; +- uint32_t rate_bw; +- uint32_t req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing, +- dc_link_get_highest_encoding_format(stream->link)); +- +- for (frl_rate = 1; +- frl_rate <= stream->link->local_sink->edid_caps.frl_caps.max_rate; +- ++frl_rate) +- { +- rate_bw = hdmi_get_max_frl_bw_kbps(frl_rate); +- pr_err("HDMI FRL: rate_bw %u, req_bw %u\n", rate_bw, req_bw); +- if (rate_bw >= req_bw) { +- pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; +- pipe_ctx->link_config.dp_link_settings.lane_count = frl_rate <= 2 ? 3 : 4; ++static void calc_audio(const struct dfm_config *cfg, ++ uint64_t t_line_ns, ++ struct dfm_results *res) ++{ ++ if (!cfg->audio_enable) { ++ res->audio_packets_line = 0; ++ res->hblank_audio_min = 64; ++ return; ++ } + +- return true; +- } ++ uint32_t ap = 1; ++ if (cfg->audio_channels > 22) { ++ ap = 4; /* ACAT 3 (up to 30.2ch) */ ++ } else if (cfg->audio_channels > 10) { ++ ap = 3; /* ACAT 2 (up to 22.2ch) */ ++ } else if (cfg->audio_channels > 8) { ++ ap = 2; /* ACAT 1 (up to 10.2ch) */ ++ } else { ++ ap = 1; /* Layout 0/1 */ ++ } ++ ++ uint64_t rap = (uint64_t)cfg->audio_freq_hz * (1000000 + DFM_TOLERANCE_AUDIO_CLOCK_PPM); ++ rap = (rap * ap) / 1000000; ++ ++ uint64_t avg_pkts_x1000 = (rap * t_line_ns) / 1000000; /* ns to ms scale */ ++ ++ res->audio_packets_line = (uint32_t)((avg_pkts_x1000 + 999) / 1000); ++ ++ res->hblank_audio_min = 64 + (32 * res->audio_packets_line); ++} ++ ++/* Table 6-44: RC Compression Savings */ ++static void calc_rc_compression(const struct dfm_config *cfg, struct dfm_results *res) ++{ ++ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; ++ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; ++ ++ uint64_t raw_num = (uint64_t)cfg->hblank * kcd * 8; ++ uint64_t raw_den = (uint64_t)k420 * 7; ++ uint32_t raw_capacity = (uint32_t)(raw_num / raw_den); /* FLOOR */ ++ ++ uint32_t deduct = 32 * (1 + res->audio_packets_line) + 7; ++ int32_t free_chars = (int32_t)raw_capacity - (int32_t)deduct; ++ ++ if (free_chars < 0) free_chars = 0; ++ ++ int32_t margin = 4; ++ ++ int32_t base = free_chars - margin; ++ if (base < 0) base = 0; ++ ++ res->cfrl_rc_savings = (uint32_t)((base * 7) / 8); ++} ++ ++/* Core DFM Check Function */ ++static void perform_dfm_check(const struct dfm_config *cfg, struct dfm_results *res) ++{ ++ memset(res, 0, sizeof(struct dfm_results)); ++ ++ uint32_t htotal = cfg->hactive + cfg->hblank; ++ ++ res->overhead_ppm = calc_overhead_ppm(cfg->lanes); ++ ++ res->f_pixel_clock_max = (uint64_t)cfg->pixel_clock_khz * 1000; ++ res->f_pixel_clock_max = res->f_pixel_clock_max * (1000 + DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000) / 1000; ++ ++ uint64_t t_line_ns = ((uint64_t)htotal * 1000000000ULL) / res->f_pixel_clock_max; ++ ++ uint64_t r_bit_nominal = (uint64_t)cfg->frl_bit_rate_gbps * 1000000000ULL; ++ uint64_t r_bit_min = r_bit_nominal * (1000000 - DFM_TOLERANCE_FRL_BIT_RATE_PPM) / 1000000; ++ ++ res->r_frl_char_min = r_bit_min / 18; ++ ++ uint64_t cap_calc = (t_line_ns * res->r_frl_char_min * cfg->lanes) / 1000000000ULL; ++ res->cfrl_line = (uint32_t)cap_calc; ++ ++ calc_audio(cfg, t_line_ns, res); ++ ++ calc_rc_compression(cfg, res); ++ ++ uint32_t bpp; ++ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; ++ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; ++ ++ bpp = (24 * kcd) / (k420 * 8); ++ ++ uint64_t bytes_line = ((uint64_t)bpp * cfg->hactive) / 8; ++ ++ res->tb_active = (uint32_t)CEILING(bytes_line, 3); ++ ++ uint64_t tb_blank_num = (uint64_t)cfg->hblank * kcd; ++ uint64_t tb_blank_den = (uint64_t)k420 * 8; ++ res->tb_blank = (uint32_t)CEILING(tb_blank_num, tb_blank_den); ++ ++ if (res->hblank_audio_min <= res->tb_blank) { ++ res->audio_supported = true; ++ } else { ++ res->audio_supported = false; ++ res->total_supported = false; ++ return; ++ } ++ ++ uint64_t tb_total = res->tb_active + res->tb_blank; ++ uint64_t f_tb_avg = (res->f_pixel_clock_max * tb_total) / htotal; ++ ++ res->t_active_ref = (t_line_ns * cfg->hactive) / htotal; ++ ++ res->t_blank_ref = (t_line_ns * cfg->hblank) / htotal; ++ ++ uint64_t r_frl_eff = res->r_frl_char_min * (1000000 - res->overhead_ppm) / 1000000; ++ ++ res->t_active_min = (3ULL * res->tb_active * 1000000000ULL) / (2ULL * cfg->lanes * r_frl_eff); ++ ++ res->t_blank_min = (res->tb_blank * 1000000000ULL) / (cfg->lanes * r_frl_eff); ++ ++ if (res->t_active_ref >= res->t_active_min && res->t_blank_ref >= res->t_blank_min) { ++ res->tb_borrowed = 0; ++ res->dfm_supported = true; ++ } else if (res->t_active_ref < res->t_active_min) { ++ uint64_t borrow_time_ns = res->t_active_min - res->t_active_ref; ++ ++ res->tb_borrowed = CEILING(borrow_time_ns * f_tb_avg, 1000000000ULL); ++ ++ if (res->tb_borrowed <= DFM_TB_BORROWED_MAX) { ++ res->dfm_supported = true; ++ } else { ++ res->dfm_supported = false; ++ } ++ } else { ++ /* Blanking needs more time than available */ ++ res->dfm_supported = false; ++ } ++ ++ if (!res->dfm_supported) { ++ res->total_supported = false; ++ return; ++ } ++ ++ uint64_t total_chars_req = (3 * tb_total) / 2; ++ if (total_chars_req > res->cfrl_rc_savings) { ++ res->cfrl_actual_payload = (uint32_t)CEILING((total_chars_req - res->cfrl_rc_savings), 1); ++ } else { ++ res->cfrl_actual_payload = 0; ++ } ++ ++ uint64_t util_ppm = ((uint64_t)res->cfrl_actual_payload * 1000000ULL) / res->cfrl_line; ++ ++ int32_t margin_ppm = 1000000 - (int32_t)util_ppm + (int32_t)res->overhead_ppm; ++ res->margin_ppm = margin_ppm; ++ ++ if (margin_ppm >= 0) { ++ res->utilization_supported = true; ++ res->total_supported = true; ++ } else { ++ res->utilization_supported = false; ++ res->total_supported = false; ++ } ++} ++ ++static bool hdmi_decide_link_settings( ++ struct dc_stream_state *stream, ++ struct pipe_ctx *pipe_ctx) ++{ ++ struct dfm_config cfg; ++ struct dfm_results res; ++ uint8_t frl_rate; ++ static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; ++ uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; ++ ++ if (max_rate == 0 || max_rate > 6) ++ return false; ++ ++ memset(&cfg, 0, sizeof(cfg)); ++ ++ cfg.pixel_clock_khz = stream->timing.pix_clk_100hz / 10; ++ cfg.hactive = stream->timing.h_addressable; ++ cfg.hblank = stream->timing.h_total - stream->timing.h_addressable; ++ cfg.encoding = stream->timing.pixel_encoding; ++ ++ switch (stream->timing.display_color_depth) { ++ case COLOR_DEPTH_888: cfg.bpc = 8; break; ++ case COLOR_DEPTH_101010: cfg.bpc = 10; break; ++ case COLOR_DEPTH_121212: cfg.bpc = 12; break; ++ case COLOR_DEPTH_161616: cfg.bpc = 16; break; ++ default: ++ cfg.bpc = 8; ++ break; ++ } ++ ++ if (stream->audio_info.mode_count) { ++ cfg.audio_enable = true; ++ /* If we assume the worst case (e.g. 192KHz 32 channel audio) we risk ++ * unfairly pruning low res modes with short Hblank periods. Instead, ++ * assume a standard surround sound mode that should allow all video ++ * modes to work. ++ */ ++ cfg.audio_freq_hz = 48000; ++ cfg.audio_channels = 8; + } + +- return false; ++ for (frl_rate = 1; frl_rate <= max_rate; frl_rate++) { ++ cfg.frl_bit_rate_gbps = frl_rates_gbps[frl_rate - 1]; ++ cfg.lanes = (frl_rate <= 2) ? 3 : 4; ++ ++ perform_dfm_check(&cfg, &res); ++ ++ if (res.total_supported) { ++ pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; ++ ++ pr_info("HDMI FRL: Rate %d Supported. Borrowed: %lu, Margin: %d ppm\n", ++ frl_rate, res.tb_borrowed, res.margin_ppm); ++ return true; ++ } ++ } ++ ++ return false; + } + + enum dc_status resource_map_pool_resources( + +From 21c8a7d8c0980d0e4c67e86120174ba366beda97 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Thu, 19 Feb 2026 00:56:04 +0100 +Subject: [PATCH 075/103] + drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c: properly set + set_hdmistreamclk for dccg35 + +--- + drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c +index 14a54d013fe32f..9224645eaf8deb 100644 +--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c ++++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c +@@ -2487,6 +2487,7 @@ static const struct dccg_funcs dccg35_funcs = { + .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, + .dccg_init = dccg35_init, + .set_dpstreamclk = dccg35_set_dpstreamclk, ++ .set_hdmistreamclk = dccg35_set_hdmistreamclk, + .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, + .enable_symclk32_se = dccg31_enable_symclk32_se, + .disable_symclk32_se = dccg35_disable_symclk32_se, + +From 8860e3b28244264b8d6309603b63f6e9612439a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Thu, 19 Feb 2026 15:56:34 +0100 +Subject: [PATCH 076/103] + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c: handle FRL like + HPO DP + +--- + .../gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +index dfd0c9505af096..8c05f403293df7 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +@@ -231,13 +231,16 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state * + + if (old_pipe->stream && new_pipe->stream && old_pipe->stream == new_pipe->stream) { + has_active_hpo = dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(old_pipe) && +- dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(new_pipe); ++ dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(new_pipe); + ++ has_active_hpo |= dc_is_hdmi_frl_signal(old_pipe->stream->signal) && ++ dc_is_hdmi_frl_signal(new_pipe->stream->signal); + } + + if (!has_active_hpo && !stream_changed_otg_dig_on && pipe->stream && + (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) || !pipe_link_enc) && +- !dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe)) { ++ !dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe) && ++ !dc_is_hdmi_frl_signal(pipe->stream->signal)) { + /* This w/a should not trigger when we have a dig active */ + if (disable) { + if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc) + +From a291fb28e068ad859504525ed9d4495476c3ea9e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Thu, 19 Feb 2026 17:54:14 +0100 +Subject: [PATCH 077/103] + drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c: ignore + FRL_START + +--- + .../drm/amd/display/dc/link/protocols/link_frl_training.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 03c20f6566f6c7..a35c8f49217423 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -137,14 +137,6 @@ bool dc_link_perform_frl_training(struct dc_link *link, + + pr_err("FRL DEBUG: UPDATE_0 = 0x%02x\n", update); + +- if (update & SCDC_FRL_START_BIT) { +- pr_err("FRL DEBUG: FRL_START asserted\n"); +- DC_LOG_HW_LINK_TRAINING( +- "HDMI FRL: Link already trained\n"); +- enc->funcs->set_training_enable(enc, false); +- return true; +- } +- + if (!(update & SCDC_FLT_UPDATE_BIT)) { + pr_err("FRL DEBUG: FLT_UPDATE not set\n"); + msleep(FRL_POLL_DELAY_MS); + +From e79e6e40a0634ef9ecf00e2f70cc7204ca8b7d2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Thu, 19 Feb 2026 19:07:41 +0100 +Subject: [PATCH 078/103] drivers/gpu/drm/amd/display/dc/core/dc_resource.c: + resolve some compilation warnings + +--- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 417a867dbb1584..93ae090b21cb40 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -4044,7 +4044,6 @@ struct dfm_results { + + + #define CEILING(x, y) (((x) + (y) - 1) / (y)) +-#define MAX(a, b) ((a) > (b) ? (a) : (b)) + + static uint32_t calc_overhead_ppm(uint8_t lanes) + { +@@ -4274,7 +4273,7 @@ static bool hdmi_decide_link_settings( + pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; + pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; + +- pr_info("HDMI FRL: Rate %d Supported. Borrowed: %lu, Margin: %d ppm\n", ++ pr_info("HDMI FRL: Rate %d Supported. Borrowed: %llu, Margin: %d ppm\n", + frl_rate, res.tb_borrowed, res.margin_ppm); + return true; + } + +From d53ad8ae006a68a22515b1e49c7077e27950dfd7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Thu, 19 Feb 2026 19:55:51 +0100 +Subject: [PATCH 079/103] + drivers/gpu/drm/amd/display/dc/link/link_validation.c: skip HDMI link + validation + +already done in dc_resource.c +--- + .../drm/amd/display/dc/link/link_validation.c | 53 +------------------ + 1 file changed, 1 insertion(+), 52 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +index 2a06dbccf0f531..acdc162de5353b 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +@@ -329,51 +329,6 @@ static bool dp_validate_mode_timing( + return false; + } + +-static uint32_t hdmi_get_max_frl_bw_kbps(uint8_t frl_rate) +-{ +- static const uint8_t frl_lane_rate_gbps[] = { +- [1] = 3, [2] = 6, [3] = 6, [4] = 8, [5] = 10, [6] = 12, +- }; +- +- uint32_t lane_rate_gbps; +- uint32_t lane_count; +- +- if (frl_rate < 1 || frl_rate > 6) +- return 0; +- +- lane_count = (frl_rate <= 2) ? 3 : 4; +- lane_rate_gbps = frl_lane_rate_gbps[frl_rate]; +- +- return lane_count * lane_rate_gbps * 1000000; +-} +- +-static bool hdmi_validate_mode_timing( +- struct dc_link *link, +- const struct dc_crtc_timing *timing) +-{ +- uint32_t pix_clk_100hz; +- uint32_t mode_bw_kbps; +- uint32_t max_frl_bw_kbps; +- +- memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings)); +- +- pix_clk_100hz = get_tmds_output_pixel_clock_100hz(timing); +- mode_bw_kbps = dc_bandwidth_in_kbps_from_timing(timing, +- dc_link_get_highest_encoding_format(link)); +- +- max_frl_bw_kbps = hdmi_get_max_frl_bw_kbps( +- link->local_sink->edid_caps.frl_caps.max_rate); +- +- /* TMDS is always allowed. */ +- if (pix_clk_100hz <= 6000000) +- return true; +- /* FRL is allowed if the sink supports the required FRL rate. */ +- else if (mode_bw_kbps <= max_frl_bw_kbps) +- return true; +- +- return false; +-} +- + enum dc_status link_validate_mode_timing( + const struct dc_stream_state *stream, + struct dc_link *link, +@@ -404,13 +359,7 @@ enum dc_status link_validate_mode_timing( + timing)) + return DC_NO_DP_LINK_BANDWIDTH; + break; +- case SIGNAL_TYPE_HDMI_TYPE_A: +- case SIGNAL_TYPE_HDMI_FRL: +- if (!hdmi_validate_mode_timing( +- link, +- timing)) +- return DC_NO_DP_LINK_BANDWIDTH; +- break; ++ + default: + break; + } + +From e86b56a54a3a6054fa0cc5ef5e5280c43cc9ada9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Fri, 20 Feb 2026 02:51:36 +0100 +Subject: [PATCH 080/103] + drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c: Wait and + clear final status update + +--- + .../dc/link/protocols/link_frl_training.c | 38 ++++++++++++++++--- + 1 file changed, 32 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index a35c8f49217423..59aedde725d164 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -64,6 +64,7 @@ bool dc_link_perform_frl_training(struct dc_link *link, + uint8_t write_buffer[2]; + int poll; + int lane; ++ int post_training_timeout; + + if (!enc || lane_count == 0 || lane_count > FRL_MAX_LANES) + return false; +@@ -89,6 +90,7 @@ bool dc_link_perform_frl_training(struct dc_link *link, + write_buffer[0] = 0x01; + frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, &write_buffer[0], 1); + ++retrain: + /* Reset FRL rate */ + write_buffer[0] = 0; + write_buffer[1] = 0; +@@ -98,13 +100,14 @@ bool dc_link_perform_frl_training(struct dc_link *link, + /* Step 2: Wait for FLT_READY */ + /* ------------------------------------------------------------------ */ + for (poll = 0; poll < FRL_MAX_POLLS; poll++) { +- if (!frl_read_scdc(link, HDMI_SCDC_STATUS_FLAGS_0, &status, 1)) +- goto poll_delay; ++ if (!frl_read_scdc(link, HDMI_SCDC_STATUS_FLAGS_0, &status, 1)) { ++ msleep(FRL_POLL_DELAY_MS); ++ continue; ++ } + + if (status & SCDC_FLT_READY_BIT) + break; + +-poll_delay: + msleep(FRL_POLL_DELAY_MS); + } + +@@ -172,10 +175,33 @@ bool dc_link_perform_frl_training(struct dc_link *link, + } + + if (lane == lane_count) { +- DC_LOG_HW_LINK_TRAINING( +- "HDMI FRL: training successful\n"); + enc->funcs->set_training_enable(enc, false); +- return true; ++ for (post_training_timeout = 0; ++ post_training_timeout < FRL_MAX_POLLS; ++ post_training_timeout++) { ++ if (!frl_read_scdc(link, HDMI_SCDC_UPDATE_0, &update, 1)) { ++ msleep(FRL_POLL_DELAY_MS); ++ continue; ++ } ++ ++ if (update & (SCDC_FLT_UPDATE_BIT | SCDC_FRL_START_BIT)) ++ break; ++ ++ msleep(FRL_POLL_DELAY_MS); ++ } ++ ++ frl_write_scdc(link, HDMI_SCDC_UPDATE_0, &update, 1); ++ ++ if (update & SCDC_FRL_START_BIT) { ++ DC_LOG_HW_LINK_TRAINING("HDMI FRL: training successful\n"); ++ return true; ++ } else if (update & SCDC_FLT_UPDATE_BIT) { ++ DC_LOG_HW_LINK_TRAINING("HDMI FRL: retraining needed\n"); ++ goto retrain; ++ } else { ++ DC_LOG_HW_LINK_TRAINING("HDMI FRL: did not receive status update!\n"); ++ return false; ++ } + } + + /* Program requested training patterns */ + +From 1f077266ceebeda59dbada5a19959839d8c5a013 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Fri, 20 Feb 2026 03:30:16 +0100 +Subject: [PATCH 081/103] drivers/gpu/drm/amd/display/dc/core/dc_resource.c: + prefer nonborrowing rates + +--- + .../gpu/drm/amd/display/dc/core/dc_resource.c | 428 +++++++++--------- + 1 file changed, 223 insertions(+), 205 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 93ae090b21cb40..21381ccc31fc60 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -3987,59 +3987,59 @@ static bool acquire_otg_master_pipe_for_stream( + #define DFM_FRL_CFRL_CB 510 + + struct dfm_config { +- /* Video Timing */ +- uint32_t pixel_clock_khz; /* Nominal */ +- uint32_t hactive; +- uint32_t hblank; +- uint32_t bpc; /* Bits per component */ +- enum dc_pixel_encoding encoding; +- +- /* FRL Configuration */ +- uint32_t frl_bit_rate_gbps; /* 3, 6, 8, 10, 12 */ +- uint8_t lanes; /* 3 or 4 */ +- +- /* Audio */ +- bool audio_enable; +- uint32_t audio_freq_hz; +- uint8_t audio_channels; ++ /* Video Timing */ ++ uint32_t pixel_clock_khz; /* Nominal */ ++ uint32_t hactive; ++ uint32_t hblank; ++ uint32_t bpc; /* Bits per component */ ++ enum dc_pixel_encoding encoding; ++ ++ /* FRL Configuration */ ++ uint32_t frl_bit_rate_gbps; /* 3, 6, 8, 10, 12 */ ++ uint8_t lanes; /* 3 or 4 */ ++ ++ /* Audio */ ++ bool audio_enable; ++ uint32_t audio_freq_hz; ++ uint8_t audio_channels; + }; + + struct dfm_results { +- /* Calculated Parameters */ +- uint64_t f_pixel_clock_max; +- uint64_t r_frl_char_min; +- uint32_t overhead_ppm; +- +- /* Audio */ +- uint32_t audio_packets_line; +- uint32_t hblank_audio_min; +- +- /* Tri-Bytes */ +- uint32_t tb_active; +- uint32_t tb_blank; +- +- /* Compression */ +- uint32_t cfrl_rc_savings; +- +- /* Timing (ns) */ +- uint64_t t_active_min; +- uint64_t t_active_ref; +- uint64_t t_blank_min; +- uint64_t t_blank_ref; +- +- /* Borrowing */ +- uint64_t tb_borrowed; +- +- /* Utilization */ +- uint32_t cfrl_line; +- uint32_t cfrl_actual_payload; +- int32_t margin_ppm; /* Can be negative */ +- +- /* Pass/Fail Flags */ +- bool audio_supported; +- bool dfm_supported; +- bool utilization_supported; +- bool total_supported; ++ /* Calculated Parameters */ ++ uint64_t f_pixel_clock_max; ++ uint64_t r_frl_char_min; ++ uint32_t overhead_ppm; ++ ++ /* Audio */ ++ uint32_t audio_packets_line; ++ uint32_t hblank_audio_min; ++ ++ /* Tri-Bytes */ ++ uint32_t tb_active; ++ uint32_t tb_blank; ++ ++ /* Compression */ ++ uint32_t cfrl_rc_savings; ++ ++ /* Timing (ns) */ ++ uint64_t t_active_min; ++ uint64_t t_active_ref; ++ uint64_t t_blank_min; ++ uint64_t t_blank_ref; ++ ++ /* Borrowing */ ++ uint64_t tb_borrowed; ++ ++ /* Utilization */ ++ uint32_t cfrl_line; ++ uint32_t cfrl_actual_payload; ++ int32_t margin_ppm; /* Can be negative */ ++ ++ /* Pass/Fail Flags */ ++ bool audio_supported; ++ bool dfm_supported; ++ bool utilization_supported; ++ bool total_supported; + }; + + +@@ -4047,210 +4047,213 @@ struct dfm_results { + + static uint32_t calc_overhead_ppm(uint8_t lanes) + { +- uint32_t cfrl_sb = (4 * 510) + lanes; ++ uint32_t cfrl_sb = (4 * 510) + lanes; + +- uint64_t oh_sb_num = (uint64_t)lanes * 1000000ULL; +- uint32_t oh_sb = (uint32_t)((oh_sb_num + (cfrl_sb/2)) / cfrl_sb); /* Rounding */ ++ uint64_t oh_sb_num = (uint64_t)lanes * 1000000ULL; ++ uint32_t oh_sb = (uint32_t)((oh_sb_num + (cfrl_sb/2)) / cfrl_sb); /* Rounding */ + +- uint64_t oh_rs_num = 32ULL * 1000000ULL; +- uint32_t oh_rs = (uint32_t)((oh_rs_num + (cfrl_sb/2)) / cfrl_sb); ++ uint64_t oh_rs_num = 32ULL * 1000000ULL; ++ uint32_t oh_rs = (uint32_t)((oh_rs_num + (cfrl_sb/2)) / cfrl_sb); + +- uint64_t oh_map_num = 2500000ULL; /* 2.5 * 1M */ +- uint32_t oh_map = (uint32_t)((oh_map_num + (cfrl_sb/2)) / cfrl_sb); ++ uint64_t oh_map_num = 2500000ULL; /* 2.5 * 1M */ ++ uint32_t oh_map = (uint32_t)((oh_map_num + (cfrl_sb/2)) / cfrl_sb); + +- uint32_t oh_m = 3000; ++ uint32_t oh_m = 3000; + +- return oh_sb + oh_rs + oh_map + oh_m; ++ return oh_sb + oh_rs + oh_map + oh_m; + } + + static void calc_audio(const struct dfm_config *cfg, +- uint64_t t_line_ns, +- struct dfm_results *res) ++ uint64_t t_line_ns, ++ struct dfm_results *res) + { +- if (!cfg->audio_enable) { +- res->audio_packets_line = 0; +- res->hblank_audio_min = 64; +- return; +- } ++ if (!cfg->audio_enable) { ++ res->audio_packets_line = 0; ++ res->hblank_audio_min = 64; ++ return; ++ } + +- uint32_t ap = 1; +- if (cfg->audio_channels > 22) { +- ap = 4; /* ACAT 3 (up to 30.2ch) */ +- } else if (cfg->audio_channels > 10) { +- ap = 3; /* ACAT 2 (up to 22.2ch) */ +- } else if (cfg->audio_channels > 8) { +- ap = 2; /* ACAT 1 (up to 10.2ch) */ +- } else { +- ap = 1; /* Layout 0/1 */ +- } ++ uint32_t ap = 1; ++ if (cfg->audio_channels > 22) { ++ ap = 4; /* ACAT 3 (up to 30.2ch) */ ++ } else if (cfg->audio_channels > 10) { ++ ap = 3; /* ACAT 2 (up to 22.2ch) */ ++ } else if (cfg->audio_channels > 8) { ++ ap = 2; /* ACAT 1 (up to 10.2ch) */ ++ } else { ++ ap = 1; /* Layout 0/1 */ ++ } + +- uint64_t rap = (uint64_t)cfg->audio_freq_hz * (1000000 + DFM_TOLERANCE_AUDIO_CLOCK_PPM); +- rap = (rap * ap) / 1000000; ++ uint64_t rap = (uint64_t)cfg->audio_freq_hz * (1000000 + DFM_TOLERANCE_AUDIO_CLOCK_PPM); ++ rap = (rap * ap) / 1000000; + +- uint64_t avg_pkts_x1000 = (rap * t_line_ns) / 1000000; /* ns to ms scale */ ++ uint64_t avg_pkts_x1000 = (rap * t_line_ns) / 1000000; /* ns to ms scale */ + +- res->audio_packets_line = (uint32_t)((avg_pkts_x1000 + 999) / 1000); ++ res->audio_packets_line = (uint32_t)((avg_pkts_x1000 + 999) / 1000); + +- res->hblank_audio_min = 64 + (32 * res->audio_packets_line); ++ res->hblank_audio_min = 64 + (32 * res->audio_packets_line); + } + + /* Table 6-44: RC Compression Savings */ + static void calc_rc_compression(const struct dfm_config *cfg, struct dfm_results *res) + { +- uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; +- uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; ++ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; ++ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; + +- uint64_t raw_num = (uint64_t)cfg->hblank * kcd * 8; +- uint64_t raw_den = (uint64_t)k420 * 7; +- uint32_t raw_capacity = (uint32_t)(raw_num / raw_den); /* FLOOR */ ++ uint64_t raw_num = (uint64_t)cfg->hblank * kcd * 8; ++ uint64_t raw_den = (uint64_t)k420 * 7; ++ uint32_t raw_capacity = (uint32_t)(raw_num / raw_den); /* FLOOR */ + +- uint32_t deduct = 32 * (1 + res->audio_packets_line) + 7; +- int32_t free_chars = (int32_t)raw_capacity - (int32_t)deduct; ++ uint32_t deduct = 32 * (1 + res->audio_packets_line) + 7; ++ int32_t free_chars = (int32_t)raw_capacity - (int32_t)deduct; + +- if (free_chars < 0) free_chars = 0; ++ if (free_chars < 0) free_chars = 0; + +- int32_t margin = 4; ++ int32_t margin = 4; + +- int32_t base = free_chars - margin; +- if (base < 0) base = 0; ++ int32_t base = free_chars - margin; ++ if (base < 0) base = 0; + +- res->cfrl_rc_savings = (uint32_t)((base * 7) / 8); ++ res->cfrl_rc_savings = (uint32_t)((base * 7) / 8); + } + + /* Core DFM Check Function */ + static void perform_dfm_check(const struct dfm_config *cfg, struct dfm_results *res) + { +- memset(res, 0, sizeof(struct dfm_results)); ++ memset(res, 0, sizeof(struct dfm_results)); + +- uint32_t htotal = cfg->hactive + cfg->hblank; ++ uint32_t htotal = cfg->hactive + cfg->hblank; + +- res->overhead_ppm = calc_overhead_ppm(cfg->lanes); ++ res->overhead_ppm = calc_overhead_ppm(cfg->lanes); + +- res->f_pixel_clock_max = (uint64_t)cfg->pixel_clock_khz * 1000; +- res->f_pixel_clock_max = res->f_pixel_clock_max * (1000 + DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000) / 1000; ++ res->f_pixel_clock_max = (uint64_t)cfg->pixel_clock_khz * 1000; ++ res->f_pixel_clock_max = res->f_pixel_clock_max * (1000 + DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000) / 1000; + +- uint64_t t_line_ns = ((uint64_t)htotal * 1000000000ULL) / res->f_pixel_clock_max; ++ uint64_t t_line_ns = ((uint64_t)htotal * 1000000000ULL) / res->f_pixel_clock_max; + +- uint64_t r_bit_nominal = (uint64_t)cfg->frl_bit_rate_gbps * 1000000000ULL; +- uint64_t r_bit_min = r_bit_nominal * (1000000 - DFM_TOLERANCE_FRL_BIT_RATE_PPM) / 1000000; ++ uint64_t r_bit_nominal = (uint64_t)cfg->frl_bit_rate_gbps * 1000000000ULL; ++ uint64_t r_bit_min = r_bit_nominal * (1000000 - DFM_TOLERANCE_FRL_BIT_RATE_PPM) / 1000000; + +- res->r_frl_char_min = r_bit_min / 18; ++ res->r_frl_char_min = r_bit_min / 18; + +- uint64_t cap_calc = (t_line_ns * res->r_frl_char_min * cfg->lanes) / 1000000000ULL; +- res->cfrl_line = (uint32_t)cap_calc; ++ uint64_t cap_calc = (t_line_ns * res->r_frl_char_min * cfg->lanes) / 1000000000ULL; ++ res->cfrl_line = (uint32_t)cap_calc; + +- calc_audio(cfg, t_line_ns, res); ++ calc_audio(cfg, t_line_ns, res); + +- calc_rc_compression(cfg, res); ++ calc_rc_compression(cfg, res); + +- uint32_t bpp; +- uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; +- uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; ++ uint32_t bpp; ++ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; ++ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; + +- bpp = (24 * kcd) / (k420 * 8); ++ bpp = (24 * kcd) / (k420 * 8); + +- uint64_t bytes_line = ((uint64_t)bpp * cfg->hactive) / 8; ++ uint64_t bytes_line = ((uint64_t)bpp * cfg->hactive) / 8; + +- res->tb_active = (uint32_t)CEILING(bytes_line, 3); ++ res->tb_active = (uint32_t)CEILING(bytes_line, 3); + +- uint64_t tb_blank_num = (uint64_t)cfg->hblank * kcd; +- uint64_t tb_blank_den = (uint64_t)k420 * 8; +- res->tb_blank = (uint32_t)CEILING(tb_blank_num, tb_blank_den); ++ uint64_t tb_blank_num = (uint64_t)cfg->hblank * kcd; ++ uint64_t tb_blank_den = (uint64_t)k420 * 8; ++ res->tb_blank = (uint32_t)CEILING(tb_blank_num, tb_blank_den); + +- if (res->hblank_audio_min <= res->tb_blank) { +- res->audio_supported = true; +- } else { +- res->audio_supported = false; +- res->total_supported = false; +- return; +- } ++ if (res->hblank_audio_min <= res->tb_blank) { ++ res->audio_supported = true; ++ } else { ++ res->audio_supported = false; ++ res->total_supported = false; ++ return; ++ } + +- uint64_t tb_total = res->tb_active + res->tb_blank; +- uint64_t f_tb_avg = (res->f_pixel_clock_max * tb_total) / htotal; ++ uint64_t tb_total = res->tb_active + res->tb_blank; ++ uint64_t f_tb_avg = (res->f_pixel_clock_max * tb_total) / htotal; + +- res->t_active_ref = (t_line_ns * cfg->hactive) / htotal; ++ res->t_active_ref = (t_line_ns * cfg->hactive) / htotal; + +- res->t_blank_ref = (t_line_ns * cfg->hblank) / htotal; ++ res->t_blank_ref = (t_line_ns * cfg->hblank) / htotal; + +- uint64_t r_frl_eff = res->r_frl_char_min * (1000000 - res->overhead_ppm) / 1000000; ++ uint64_t r_frl_eff = res->r_frl_char_min * (1000000 - res->overhead_ppm) / 1000000; + +- res->t_active_min = (3ULL * res->tb_active * 1000000000ULL) / (2ULL * cfg->lanes * r_frl_eff); ++ res->t_active_min = (3ULL * res->tb_active * 1000000000ULL) / (2ULL * cfg->lanes * r_frl_eff); + +- res->t_blank_min = (res->tb_blank * 1000000000ULL) / (cfg->lanes * r_frl_eff); ++ res->t_blank_min = (res->tb_blank * 1000000000ULL) / (cfg->lanes * r_frl_eff); + +- if (res->t_active_ref >= res->t_active_min && res->t_blank_ref >= res->t_blank_min) { +- res->tb_borrowed = 0; +- res->dfm_supported = true; +- } else if (res->t_active_ref < res->t_active_min) { +- uint64_t borrow_time_ns = res->t_active_min - res->t_active_ref; ++ if (res->t_active_ref >= res->t_active_min && res->t_blank_ref >= res->t_blank_min) { ++ res->tb_borrowed = 0; ++ res->dfm_supported = true; ++ } else if (res->t_active_ref < res->t_active_min) { ++ uint64_t borrow_time_ns = res->t_active_min - res->t_active_ref; + +- res->tb_borrowed = CEILING(borrow_time_ns * f_tb_avg, 1000000000ULL); ++ res->tb_borrowed = CEILING(borrow_time_ns * f_tb_avg, 1000000000ULL); + +- if (res->tb_borrowed <= DFM_TB_BORROWED_MAX) { +- res->dfm_supported = true; +- } else { +- res->dfm_supported = false; +- } +- } else { +- /* Blanking needs more time than available */ +- res->dfm_supported = false; +- } ++ if (res->tb_borrowed <= DFM_TB_BORROWED_MAX) { ++ res->dfm_supported = true; ++ } else { ++ res->dfm_supported = false; ++ } ++ } else { ++ /* Blanking needs more time than available */ ++ res->dfm_supported = false; ++ } + +- if (!res->dfm_supported) { +- res->total_supported = false; +- return; +- } ++ if (!res->dfm_supported) { ++ res->total_supported = false; ++ return; ++ } + +- uint64_t total_chars_req = (3 * tb_total) / 2; +- if (total_chars_req > res->cfrl_rc_savings) { +- res->cfrl_actual_payload = (uint32_t)CEILING((total_chars_req - res->cfrl_rc_savings), 1); +- } else { +- res->cfrl_actual_payload = 0; +- } ++ uint64_t total_chars_req = (3 * tb_total) / 2; ++ if (total_chars_req > res->cfrl_rc_savings) { ++ res->cfrl_actual_payload = (uint32_t)CEILING((total_chars_req - res->cfrl_rc_savings), 1); ++ } else { ++ res->cfrl_actual_payload = 0; ++ } + +- uint64_t util_ppm = ((uint64_t)res->cfrl_actual_payload * 1000000ULL) / res->cfrl_line; ++ uint64_t util_ppm = ((uint64_t)res->cfrl_actual_payload * 1000000ULL) / res->cfrl_line; + +- int32_t margin_ppm = 1000000 - (int32_t)util_ppm + (int32_t)res->overhead_ppm; +- res->margin_ppm = margin_ppm; ++ int32_t margin_ppm = 1000000 - (int32_t)util_ppm + (int32_t)res->overhead_ppm; ++ res->margin_ppm = margin_ppm; + +- if (margin_ppm >= 0) { +- res->utilization_supported = true; +- res->total_supported = true; +- } else { +- res->utilization_supported = false; +- res->total_supported = false; +- } ++ if (margin_ppm >= 0) { ++ res->utilization_supported = true; ++ res->total_supported = true; ++ } else { ++ res->utilization_supported = false; ++ res->total_supported = false; ++ } + } + + static bool hdmi_decide_link_settings( +- struct dc_stream_state *stream, +- struct pipe_ctx *pipe_ctx) +-{ +- struct dfm_config cfg; +- struct dfm_results res; +- uint8_t frl_rate; +- static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; +- uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; +- +- if (max_rate == 0 || max_rate > 6) +- return false; +- +- memset(&cfg, 0, sizeof(cfg)); +- +- cfg.pixel_clock_khz = stream->timing.pix_clk_100hz / 10; +- cfg.hactive = stream->timing.h_addressable; +- cfg.hblank = stream->timing.h_total - stream->timing.h_addressable; +- cfg.encoding = stream->timing.pixel_encoding; +- +- switch (stream->timing.display_color_depth) { +- case COLOR_DEPTH_888: cfg.bpc = 8; break; +- case COLOR_DEPTH_101010: cfg.bpc = 10; break; +- case COLOR_DEPTH_121212: cfg.bpc = 12; break; +- case COLOR_DEPTH_161616: cfg.bpc = 16; break; +- default: +- cfg.bpc = 8; +- break; +- } ++ struct dc_stream_state *stream, ++ struct pipe_ctx *pipe_ctx) ++{ ++ struct dfm_config cfg; ++ struct dfm_results res; ++ uint8_t frl_rate; ++ static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; ++ uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; ++ uint8_t best_borrow_rate = 0; ++ uint8_t best_borrow_lanes = 0; ++ struct dfm_results best_borrow_res = {0}; ++ ++ if (max_rate == 0 || max_rate > 6) ++ return false; ++ ++ memset(&cfg, 0, sizeof(cfg)); ++ ++ cfg.pixel_clock_khz = stream->timing.pix_clk_100hz / 10; ++ cfg.hactive = stream->timing.h_addressable; ++ cfg.hblank = stream->timing.h_total - stream->timing.h_addressable; ++ cfg.encoding = stream->timing.pixel_encoding; ++ ++ switch (stream->timing.display_color_depth) { ++ case COLOR_DEPTH_888: cfg.bpc = 8; break; ++ case COLOR_DEPTH_101010: cfg.bpc = 10; break; ++ case COLOR_DEPTH_121212: cfg.bpc = 12; break; ++ case COLOR_DEPTH_161616: cfg.bpc = 16; break; ++ default: ++ cfg.bpc = 8; ++ break; ++ } + + if (stream->audio_info.mode_count) { + cfg.audio_enable = true; +@@ -4263,23 +4266,38 @@ static bool hdmi_decide_link_settings( + cfg.audio_channels = 8; + } + +- for (frl_rate = 1; frl_rate <= max_rate; frl_rate++) { +- cfg.frl_bit_rate_gbps = frl_rates_gbps[frl_rate - 1]; +- cfg.lanes = (frl_rate <= 2) ? 3 : 4; ++ for (frl_rate = 1; frl_rate <= max_rate; frl_rate++) { ++ cfg.frl_bit_rate_gbps = frl_rates_gbps[frl_rate - 1]; ++ cfg.lanes = (frl_rate <= 2) ? 3 : 4; ++ ++ perform_dfm_check(&cfg, &res); + +- perform_dfm_check(&cfg, &res); ++ if (res.total_supported) { ++ if (res.tb_borrowed == 0) { ++ pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; + +- if (res.total_supported) { +- pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; +- pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; ++ pr_info("HDMI FRL: Rate %d Supported. Borrowed: 0, Margin: %d ppm\n", ++ frl_rate, res.margin_ppm); ++ return true; ++ } else if (best_borrow_rate == 0) { ++ best_borrow_rate = frl_rate; ++ best_borrow_lanes = cfg.lanes; ++ best_borrow_res = res; ++ } ++ } ++ } + +- pr_info("HDMI FRL: Rate %d Supported. Borrowed: %llu, Margin: %d ppm\n", +- frl_rate, res.tb_borrowed, res.margin_ppm); +- return true; +- } +- } ++ if (best_borrow_rate > 0) { ++ pipe_ctx->link_config.dp_link_settings.frl_rate = best_borrow_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = best_borrow_lanes; + +- return false; ++ pr_info("HDMI FRL: Rate %d Supported (with borrowing). Borrowed: %llu, Margin: %d ppm\n", ++ best_borrow_rate, best_borrow_res.tb_borrowed, best_borrow_res.margin_ppm); ++ return true; ++ } ++ ++ return false; + } + + enum dc_status resource_map_pool_resources( + +From fe9d4bc6c5072ab776fd2d6c263e72200109f0e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Fri, 20 Feb 2026 04:24:21 +0100 +Subject: [PATCH 082/103] .github/workflows/genpatch.yml: Add workflow + +--- + .github/workflows/genpatch.yml | 22 ++++++++++++++++++++++ + .gitignore | 2 +- + 2 files changed, 23 insertions(+), 1 deletion(-) + create mode 100644 .github/workflows/genpatch.yml + +diff --git a/.github/workflows/genpatch.yml b/.github/workflows/genpatch.yml +new file mode 100644 +index 00000000000000..75731cf60b2e92 +--- /dev/null ++++ b/.github/workflows/genpatch.yml +@@ -0,0 +1,22 @@ ++name: Generate patch ++on: ++ push: ++ branches: hdmi_frl ++ ++jobs: ++ generate_patch: ++ runs-on: ubuntu-24.04 ++ steps: ++ - name: Checkout repository ++ uses: actions/checkout@v4 ++ with: ++ ref: hdmi_frl ++ fetch-depth: 0 ++ - name: Generate patch ++ run: git diff origin/master > 0001-amdgpu-frl.patch ++ - name: Save artifacts ++ uses: actions/upload-artifact@v4 ++ with: ++ name: "Patch" ++ path: 0001-amdgpu-frl.patch ++ retention-days: 30 +diff --git a/.gitignore b/.gitignore +index 3a7241c941f5e6..d5dbc2628e85af 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -10,7 +10,7 @@ + # + # Normal rules (sorted alphabetically) + # +-.* ++. + *.a + *.asn1.[ch] + *.bin + +From b621ffb3c07ed3d3cd7b64e0c6c39976abcfa418 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Fri, 20 Feb 2026 06:58:27 +0100 +Subject: [PATCH 083/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c: fix + pixel encoding + +--- + .../display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index d57a760c6e50db..9a661b36e00bf0 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -298,12 +298,10 @@ static void dcn30_hpo_hdmi_stream_enc_setup_stream_attribute( + case PIXEL_ENCODING_YCBCR422: + pixel_encoding = 1; + break; +- case PIXEL_ENCODING_YCBCR444: +- pixel_encoding = 2; +- break; + case PIXEL_ENCODING_YCBCR420: +- pixel_encoding = 3; ++ pixel_encoding = 2; + break; ++ case PIXEL_ENCODING_YCBCR444: + default: /* RGB */ + pixel_encoding = 0; + break; + +From 3955b6e2aff6db496e70ad4eef952f9efb060be0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Fri, 20 Feb 2026 15:14:38 +0100 +Subject: [PATCH 084/103] .github/workflows/genpatch.yml: Update branch + +--- + .github/workflows/genpatch.yml | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/.github/workflows/genpatch.yml b/.github/workflows/genpatch.yml +index 75731cf60b2e92..8630a9893ddb7b 100644 +--- a/.github/workflows/genpatch.yml ++++ b/.github/workflows/genpatch.yml +@@ -1,7 +1,7 @@ +-name: Generate patch ++name: Generate patch - Stable branch + on: + push: +- branches: hdmi_frl ++ branches: hdmi_frl_stable + + jobs: + generate_patch: +@@ -10,10 +10,10 @@ jobs: + - name: Checkout repository + uses: actions/checkout@v4 + with: +- ref: hdmi_frl ++ ref: hdmi_frl_stable + fetch-depth: 0 + - name: Generate patch +- run: git diff origin/master > 0001-amdgpu-frl.patch ++ run: git diff tags/stable > 0001-amdgpu-frl.patch + - name: Save artifacts + uses: actions/upload-artifact@v4 + with: + +From 1ab1b3b1d05531de5e2942dd221cfdf2cb6a93fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 21 Feb 2026 22:35:06 +0100 +Subject: [PATCH 085/103] drivers/gpu/drm/amd/display/dc/link/link_dpms.c: set + otg_out_mux correctly for stream->link->link_state_valid = true; + + if (pipe_ctx->stream_res.tg->funcs->set_out_mux) { +- if (dp_is_128b_132b_signal(pipe_ctx) || dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) ++ if (dp_is_128b_132b_signal(pipe_ctx)) + otg_out_dest = OUT_MUX_HPO_DP; ++ else if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) ++ /* DCN401 unified the DP and HDMI output mux values */ ++ otg_out_dest = (dc->ctx->dce_version < DCN_VERSION_4_01) ? ++ OUT_MUX_HPO_HDMI : OUT_MUX_HPO_DP; + else + otg_out_dest = OUT_MUX_DIO; + pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest); + +From 6016221dc4a887de1efa81cf57adcd063581de87 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 21 Feb 2026 23:28:32 +0100 +Subject: [PATCH 086/103] drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c: + mark DTBCLK required for DCN32 + +--- + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index 8a0f128722b05d..29cbc6db6cd201 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -1606,6 +1606,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) + continue; + if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + return true; ++ if (dc_is_hdmi_frl_signal(context->res_ctx.pipe_ctx[i].stream->signal)) ++ return true; + } + return false; + } + +From 09acf34be958f8310e8a4ba804eb9c9100d10e7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sat, 21 Feb 2026 23:28:54 +0100 +Subject: [PATCH 087/103] + drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c: set ODM H div mode + to manual on FRL + +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +index 27593e9988348f..089ba5700d2b43 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +@@ -1148,6 +1148,11 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * + pipe_ctx->stream_res.tg->funcs->set_odm_bypass( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + ++ /* no idea if this is the correct logic. but windows seems to pick manual mode */ ++ if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) ++ pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode( ++ pipe_ctx->stream_res.tg, true); ++ + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { + odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control( + odm_pipe->stream_res.opp, + +From 3cb22f0f137ee51cc1586be4c785a697ede5cbe4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 22 Feb 2026 00:16:24 +0100 +Subject: [PATCH 088/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c: set + audio N and CTS correctly for FRL + +Values dumped by running the Windows driver at different FRL rates. +--- + .../hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 60 +++++++++++++++---- + .../amd/display/dc/inc/hw/stream_encoder.h | 5 +- + .../display/dc/link/hwss/link_hwss_hpo_frl.c | 3 +- + 3 files changed, 52 insertions(+), 16 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index 9a661b36e00bf0..a17fae96971954 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -384,13 +384,55 @@ static void dcn30_hpo_hdmi_stream_enc_setup_stream_attribute( + REG_UPDATE(HDMI_TB_ENC_GC_CONTROL, HDMI_GC_AVMUTE, 0); + } + ++struct frl_audio_clock_info { ++ uint32_t frl_lane_rate; ++ /* N - 32KHz audio */ ++ uint32_t n_32khz; ++ /* CTS - 32KHz audio*/ ++ uint32_t cts_32khz; ++ uint32_t n_44khz; ++ uint32_t cts_44khz; ++ uint32_t n_48khz; ++ uint32_t cts_48khz; ++}; ++ ++/* Values set by the Windows driver seem to depend only on FRL rate*/ ++static const struct frl_audio_clock_info frl_audio_clock_info_table[5] = { ++ {3, 4224, 171875, 5292, 156250, 5760, 156250}, ++ {6, 4032, 328125, 5292, 312500, 6048, 328125}, ++ {8, 4032, 437500, 3969, 312500, 6048, 437500}, ++ {10, 3456, 468750, 3969, 390625, 5184, 468750}, ++ {12, 3072, 500000, 3969, 468750, 4752, 515625}, ++}; ++ ++static void get_frl_audio_clock_info( ++ struct frl_audio_clock_info *audio_clock_info, ++ uint8_t frl_rate) ++{ ++ uint32_t index; ++ uint32_t frl_lane_rates[] = { 3, 6, 8, 10, 12 }; ++ uint32_t frl_lane_rate; ++ ++ ASSERT(frl_rate >= 0 && frl_rate <= 6); ++ ++ frl_lane_rate = frl_lane_rates[frl_rate - 1]; ++ ++ /* search for FRL rate in table */ ++ for (index = 0; index < sizeof(frl_lane_rates) / sizeof(uint32_t); index++) ++ if (frl_audio_clock_info_table[index].frl_lane_rate == frl_lane_rate) ++ *audio_clock_info = frl_audio_clock_info_table[index]; ++ ++ /* Should never happen */ ++ *audio_clock_info = frl_audio_clock_info_table[0]; ++} ++ + static void setup_hdmi_audio(struct hpo_hdmi_stream_encoder *enc, +- const struct audio_crtc_info *crtc_info) ++ const struct audio_crtc_info *crtc_info, uint8_t frl_rate) + { + struct dcn30_hpo_hdmi_stream_encoder *enc3 = + DCN3_0_HPO_HDMI_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + +- struct audio_clock_info audio_clock_info = { 0 }; ++ struct frl_audio_clock_info audio_clock_info = { 0 }; + + /* Setup audio in AFMT - program AFMT block associated with HPO */ + ASSERT(enc->afmt); +@@ -400,14 +442,7 @@ static void setup_hdmi_audio(struct hpo_hdmi_stream_encoder *enc, + HDMI_ACR_SOURCE, 0, HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ +- get_audio_clock_info(crtc_info->color_depth, +- crtc_info->requested_pixel_clock_100Hz, +- crtc_info->calculated_pixel_clock_100Hz, +- &audio_clock_info); +- DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d" +- "calculated_pixel_clock_100Hz = %d \n", +- __func__, crtc_info->requested_pixel_clock_100Hz, +- crtc_info->calculated_pixel_clock_100Hz); ++ get_frl_audio_clock_info(&audio_clock_info, frl_rate); + + REG_UPDATE(HDMI_TB_ENC_ACR_32_0, HDMI_ACR_CTS_32, + audio_clock_info.cts_32khz); +@@ -427,9 +462,10 @@ static void setup_hdmi_audio(struct hpo_hdmi_stream_encoder *enc, + + static void dcn30_hpo_hdmi_stream_enc_hdmi_audio_setup( + struct hpo_hdmi_stream_encoder *enc, unsigned int az_inst, +- struct audio_info *info, struct audio_crtc_info *audio_crtc_info) ++ struct audio_info *info, struct audio_crtc_info *audio_crtc_info, ++ uint8_t frl_rate) + { +- setup_hdmi_audio(enc, audio_crtc_info); ++ setup_hdmi_audio(enc, audio_crtc_info, frl_rate); + ASSERT(enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); + } +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +index be3a0c25e56cdf..d45d7b024e75f6 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +@@ -380,8 +380,6 @@ struct hpo_dp_stream_encoder_funcs { + }; + + struct hpo_hdmi_stream_encoder_funcs { +- +- /* Core lifecycle */ + void (*enable)( + struct hpo_hdmi_stream_encoder *enc, + uint8_t source_select); +@@ -405,7 +403,8 @@ struct hpo_hdmi_stream_encoder_funcs { + struct hpo_hdmi_stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, +- struct audio_crtc_info *audio_crtc_info); ++ struct audio_crtc_info *audio_crtc_info, ++ uint8_t frl_rate); + + void (*hdmi_audio_enable)( + struct hpo_hdmi_stream_encoder *enc); +diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +index 20a27f9d98f7b1..175bd956572041 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c ++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +@@ -93,7 +93,8 @@ static void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, + { + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.hpo_hdmi_stream_enc, audio_inst, +- &pipe_ctx->stream->audio_info, &audio_output->crtc_info); ++ &pipe_ctx->stream->audio_info, &audio_output->crtc_info, ++ pipe_ctx->stream->link->cur_link_settings.frl_rate); + } + + static void enable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) + +From 69aea24cfedd2fff19dd1b67bb4e67af632bb251 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 22 Feb 2026 01:28:46 +0100 +Subject: [PATCH 089/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c: fix + hdmi rate list + +FRL 6 appears twice, once for 3 lanes and once for 4 lanes +--- + .../amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index a17fae96971954..0a3bad3643baa0 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -410,7 +410,7 @@ static void get_frl_audio_clock_info( + uint8_t frl_rate) + { + uint32_t index; +- uint32_t frl_lane_rates[] = { 3, 6, 8, 10, 12 }; ++ uint32_t frl_lane_rates[] = { 3, 6, 6, 8, 10, 12 }; + uint32_t frl_lane_rate; + + ASSERT(frl_rate >= 0 && frl_rate <= 6); + +From e772ddc55b36f868647c04d039e08ba8948db1c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 22 Feb 2026 15:37:50 +0100 +Subject: [PATCH 090/103] HPO HDMI: Fix FRL Rate in audio config lookup + +--- + .../amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 4 +++- + drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c | 2 +- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index 0a3bad3643baa0..65ee214c338599 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -418,7 +418,9 @@ static void get_frl_audio_clock_info( + frl_lane_rate = frl_lane_rates[frl_rate - 1]; + + /* search for FRL rate in table */ +- for (index = 0; index < sizeof(frl_lane_rates) / sizeof(uint32_t); index++) ++ for (index = 0; ++ index < sizeof(frl_audio_clock_info_table) / sizeof(struct frl_audio_clock_info); ++ index++) + if (frl_audio_clock_info_table[index].frl_lane_rate == frl_lane_rate) + *audio_clock_info = frl_audio_clock_info_table[index]; + +diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +index 175bd956572041..c3e66e66e43ebc 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c ++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_frl.c +@@ -94,7 +94,7 @@ static void setup_hpo_hdmi_frl_audio_output(struct pipe_ctx *pipe_ctx, + pipe_ctx->stream_res.hpo_hdmi_stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.hpo_hdmi_stream_enc, audio_inst, + &pipe_ctx->stream->audio_info, &audio_output->crtc_info, +- pipe_ctx->stream->link->cur_link_settings.frl_rate); ++ pipe_ctx->link_config.dp_link_settings.frl_rate); + } + + static void enable_hpo_hdmi_frl_audio_packet(struct pipe_ctx *pipe_ctx) + +From 010da7b1de1224e8eaa283b5de6b20c1ede0072c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 22 Feb 2026 17:34:44 +0100 +Subject: [PATCH 091/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h: add + missing enable field + +--- + .../drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h +index 2e32a0e09ad01f..134d2ca1dc179f 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_link_encoder.h +@@ -32,6 +32,7 @@ struct dcn30_hpo_hdmi_link_encoder_registers { + }; + + #define DCN3_0_HPO_HDMI_LINK_ENC_MASK_SH_LIST(mask_sh) \ ++ SE_SF(HDMI_LINK_ENC_CONTROL, HDMI_LINK_ENC_ENABLE, mask_sh), \ + SE_SF(HDMI_LINK_ENC_CONTROL, HDMI_LINK_ENC_SOFT_RESET, mask_sh), \ + SE_SF(HDMI_LINK_ENC_CLK_CTRL, HDMI_LINK_ENC_CLOCK_EN, \ + mask_sh), \ + +From eae783e2487033155fdd2216cd38ca241b055a78 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Sun, 22 Feb 2026 17:56:50 +0100 +Subject: [PATCH 092/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c: + don't double-set audio info + +--- + .../display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index 65ee214c338599..3cc437683b2c88 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -420,9 +420,12 @@ static void get_frl_audio_clock_info( + /* search for FRL rate in table */ + for (index = 0; + index < sizeof(frl_audio_clock_info_table) / sizeof(struct frl_audio_clock_info); +- index++) +- if (frl_audio_clock_info_table[index].frl_lane_rate == frl_lane_rate) ++ index++) { ++ if (frl_audio_clock_info_table[index].frl_lane_rate == frl_lane_rate) { + *audio_clock_info = frl_audio_clock_info_table[index]; ++ return; ++ } ++ } + + /* Should never happen */ + *audio_clock_info = frl_audio_clock_info_table[0]; + +From f9ef038db6d1497c829e7dfe4ee1c489d49e64ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Mon, 23 Feb 2026 00:34:43 +0100 +Subject: [PATCH 093/103] drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c: + mark DTBCLK required for DCN20+ + +--- + drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +index 7aaf13bbd4e4c1..867e5a198155f6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +@@ -1050,6 +1050,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) + continue; + if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + return true; ++ if (dc_is_hdmi_frl_signal(context->res_ctx.pipe_ctx[i].stream->signal)) ++ return true; + } + return false; + } + +From fce87a1f32054da5570067f047e0a1a9d1166757 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Mon, 23 Feb 2026 00:35:23 +0100 +Subject: [PATCH 094/103] + drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn313_hwseq.c: set ODM H div mode + to manual on FRL + +--- + drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +index 5350f480870aff..8dd7b752f06be2 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +@@ -191,6 +191,11 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx + pipe_ctx->stream_res.tg->funcs->set_odm_bypass( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + ++ /* no idea if this is the correct logic. but windows seems to pick manual mode */ ++ if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal)) ++ pipe_ctx->stream_res.tg->funcs->set_h_timing_div_manual_mode( ++ pipe_ctx->stream_res.tg, true); ++ + if (mpc->funcs->set_out_rate_control) { + for (i = 0; i < opp_cnt; ++i) { + mpc->funcs->set_out_rate_control( + +From ad4a2bf6fc753bc63aaf8dc3226480b4812e343b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Mon, 23 Feb 2026 01:52:12 +0100 +Subject: [PATCH 095/103] + drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c: set + HDMI_AUDIO_INFO_CONT + +--- + .../drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index 3cc437683b2c88..1eb1ce557ac22e 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -371,6 +371,7 @@ static void dcn30_hpo_hdmi_stream_enc_setup_stream_attribute( + /* following belongs to audio */ + /* Enable Audio InfoFrame packet transmission. */ + REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_SEND, 1); ++ REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_CONT, 1); + + /* update double-buffered AUDIO_INFO registers immediately */ + ASSERT(enc->afmt); + +From 32f1a57223c2db688e1d8e2df274486e7d3c667d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 24 Feb 2026 00:41:21 +0100 +Subject: [PATCH 096/103] Revert + "drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c: + set HDMI_AUDIO_INFO_CONT" + +This reverts commit cb823648ef035d0886a3a1a4d2b9ba465a76635e. +--- + .../drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +index 1eb1ce557ac22e..3cc437683b2c88 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_hdmi_stream_encoder.c +@@ -371,7 +371,6 @@ static void dcn30_hpo_hdmi_stream_enc_setup_stream_attribute( + /* following belongs to audio */ + /* Enable Audio InfoFrame packet transmission. */ + REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_SEND, 1); +- REG_UPDATE(HDMI_TB_ENC_VBI_PACKET_CONTROL1, HDMI_AUDIO_INFO_CONT, 1); + + /* update double-buffered AUDIO_INFO registers immediately */ + ASSERT(enc->afmt); + +From 435360c1b00bd445061f55cb734fbe2ded0cb4c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 24 Feb 2026 02:16:23 +0100 +Subject: [PATCH 097/103] + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c: Program audio + clock correctly for FRL + +Needed when FRL is the only connected display +--- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 4657963df68d1a..83886a85bbf79e 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1493,7 +1493,8 @@ void build_audio_output( + + if (state->clk_mgr && + (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || +- pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) { ++ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || ++ pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_FRL)) { + audio_output->pll_info.audio_dto_source_clock_in_khz = + state->clk_mgr->funcs->get_dp_ref_clk_frequency( + state->clk_mgr); +@@ -2450,7 +2451,7 @@ static void dce110_setup_audio_dto( + + if (pipe_ctx->top_pipe) + continue; +- if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) ++ if (!dc_is_hdmi_signal(pipe_ctx->stream->signal)) + continue; + if (pipe_ctx->stream_res.audio != NULL) { + struct audio_output audio_output; + +From e4de13dee10b8d99dc521e2892a4e415f0cd03c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 24 Feb 2026 19:04:11 +0100 +Subject: [PATCH 098/103] drivers/gpu/drm/amd/display/dc/link/link_dpms.c: + Disable FRL on dpms off + +--- + drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 3 +++ + .../display/dc/link/protocols/link_frl_training.c | 14 ++++++++++++-- + .../display/dc/link/protocols/link_frl_training.h | 5 +++++ + 3 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +index 830591503e0086..bd6654e2ae5c04 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +@@ -2453,6 +2453,9 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) + } + } + ++ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) ++ dc_link_disable_frl(pipe_ctx->stream->link); ++ + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && + !dp_is_128b_132b_signal(pipe_ctx)) { + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 59aedde725d164..39574f87fa92e6 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -88,13 +88,13 @@ bool dc_link_perform_frl_training(struct dc_link *link, + + /* Write source version = 1 */ + write_buffer[0] = 0x01; +- frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, &write_buffer[0], 1); ++ frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, write_buffer, 1); + + retrain: + /* Reset FRL rate */ + write_buffer[0] = 0; + write_buffer[1] = 0; +- frl_write_scdc(link, 0x30, &write_buffer[0], 2); ++ frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2); + + /* ------------------------------------------------------------------ */ + /* Step 2: Wait for FLT_READY */ +@@ -243,3 +243,13 @@ bool dc_link_perform_frl_training(struct dc_link *link, + + return false; + } ++ ++void dc_link_disable_frl(struct dc_link *link) ++{ ++ uint8_t write_buffer[2]; ++ ++ /* Inform the sink not to expect an FRL signal */ ++ write_buffer[0] = 0; ++ write_buffer[1] = 0; ++ frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2); ++} +\ No newline at end of file +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +index 91ec5049448cc2..4a913a3d2511eb 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +@@ -34,4 +34,9 @@ struct link_resource; + bool dc_link_perform_frl_training(struct dc_link *link, + const struct link_resource *link_res); + ++/* ++ * Disable FRL mode in the sink. Allows fallback to TMDS. ++ */ ++void dc_link_disable_frl(struct dc_link *link); ++ + #endif /* __LINK_HDMI_FRL_TRAINING_H__ */ + +From fb9ee8144acdc8172cd96a197aef6914e8020512 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 24 Feb 2026 20:51:54 +0100 +Subject: [PATCH 099/103] Move DFM calc to link_frl_training + +--- + .../gpu/drm/amd/display/dc/core/dc_resource.c | 328 +----------------- + .../dc/link/protocols/link_frl_training.c | 326 +++++++++++++++++ + .../dc/link/protocols/link_frl_training.h | 11 + + 3 files changed, 339 insertions(+), 326 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 21381ccc31fc60..beeaeae4810e17 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -53,6 +53,8 @@ + #include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h" + #include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h" + ++#include "link/protocols/link_frl_training.h" ++ + #if defined(CONFIG_DRM_AMD_DC_SI) + #include "dce60/dce60_resource.h" + #endif +@@ -3974,332 +3976,6 @@ static bool acquire_otg_master_pipe_for_stream( + return pipe_idx != FREE_PIPE_INDEX_NOT_FOUND; + } + +-/* DFM calc +- * References: +- * https://github.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_linux/drv/mpp/component/hdmi/src/mkp/drv_hdmi_dfm.c#L264 +- * https://github.com/jelyoussefi/intel-gpu-i915/blob/e366083d562341ce15d5fe1a39bb6e07f18a4745/drivers/gpu/drm/i915/display/intel_hdmi.c#L4217 +- * TODO Move to separate file in protocols */ +- +-#define DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000 5 /* +0.50% -> 5/1000 */ +-#define DFM_TOLERANCE_AUDIO_CLOCK_PPM 1000 /* +/- 1000 ppm */ +-#define DFM_TOLERANCE_FRL_BIT_RATE_PPM 300 /* +/- 300 ppm */ +-#define DFM_TB_BORROWED_MAX 400 +-#define DFM_FRL_CFRL_CB 510 +- +-struct dfm_config { +- /* Video Timing */ +- uint32_t pixel_clock_khz; /* Nominal */ +- uint32_t hactive; +- uint32_t hblank; +- uint32_t bpc; /* Bits per component */ +- enum dc_pixel_encoding encoding; +- +- /* FRL Configuration */ +- uint32_t frl_bit_rate_gbps; /* 3, 6, 8, 10, 12 */ +- uint8_t lanes; /* 3 or 4 */ +- +- /* Audio */ +- bool audio_enable; +- uint32_t audio_freq_hz; +- uint8_t audio_channels; +-}; +- +-struct dfm_results { +- /* Calculated Parameters */ +- uint64_t f_pixel_clock_max; +- uint64_t r_frl_char_min; +- uint32_t overhead_ppm; +- +- /* Audio */ +- uint32_t audio_packets_line; +- uint32_t hblank_audio_min; +- +- /* Tri-Bytes */ +- uint32_t tb_active; +- uint32_t tb_blank; +- +- /* Compression */ +- uint32_t cfrl_rc_savings; +- +- /* Timing (ns) */ +- uint64_t t_active_min; +- uint64_t t_active_ref; +- uint64_t t_blank_min; +- uint64_t t_blank_ref; +- +- /* Borrowing */ +- uint64_t tb_borrowed; +- +- /* Utilization */ +- uint32_t cfrl_line; +- uint32_t cfrl_actual_payload; +- int32_t margin_ppm; /* Can be negative */ +- +- /* Pass/Fail Flags */ +- bool audio_supported; +- bool dfm_supported; +- bool utilization_supported; +- bool total_supported; +-}; +- +- +-#define CEILING(x, y) (((x) + (y) - 1) / (y)) +- +-static uint32_t calc_overhead_ppm(uint8_t lanes) +-{ +- uint32_t cfrl_sb = (4 * 510) + lanes; +- +- uint64_t oh_sb_num = (uint64_t)lanes * 1000000ULL; +- uint32_t oh_sb = (uint32_t)((oh_sb_num + (cfrl_sb/2)) / cfrl_sb); /* Rounding */ +- +- uint64_t oh_rs_num = 32ULL * 1000000ULL; +- uint32_t oh_rs = (uint32_t)((oh_rs_num + (cfrl_sb/2)) / cfrl_sb); +- +- uint64_t oh_map_num = 2500000ULL; /* 2.5 * 1M */ +- uint32_t oh_map = (uint32_t)((oh_map_num + (cfrl_sb/2)) / cfrl_sb); +- +- uint32_t oh_m = 3000; +- +- return oh_sb + oh_rs + oh_map + oh_m; +-} +- +-static void calc_audio(const struct dfm_config *cfg, +- uint64_t t_line_ns, +- struct dfm_results *res) +-{ +- if (!cfg->audio_enable) { +- res->audio_packets_line = 0; +- res->hblank_audio_min = 64; +- return; +- } +- +- uint32_t ap = 1; +- if (cfg->audio_channels > 22) { +- ap = 4; /* ACAT 3 (up to 30.2ch) */ +- } else if (cfg->audio_channels > 10) { +- ap = 3; /* ACAT 2 (up to 22.2ch) */ +- } else if (cfg->audio_channels > 8) { +- ap = 2; /* ACAT 1 (up to 10.2ch) */ +- } else { +- ap = 1; /* Layout 0/1 */ +- } +- +- uint64_t rap = (uint64_t)cfg->audio_freq_hz * (1000000 + DFM_TOLERANCE_AUDIO_CLOCK_PPM); +- rap = (rap * ap) / 1000000; +- +- uint64_t avg_pkts_x1000 = (rap * t_line_ns) / 1000000; /* ns to ms scale */ +- +- res->audio_packets_line = (uint32_t)((avg_pkts_x1000 + 999) / 1000); +- +- res->hblank_audio_min = 64 + (32 * res->audio_packets_line); +-} +- +-/* Table 6-44: RC Compression Savings */ +-static void calc_rc_compression(const struct dfm_config *cfg, struct dfm_results *res) +-{ +- uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; +- uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; +- +- uint64_t raw_num = (uint64_t)cfg->hblank * kcd * 8; +- uint64_t raw_den = (uint64_t)k420 * 7; +- uint32_t raw_capacity = (uint32_t)(raw_num / raw_den); /* FLOOR */ +- +- uint32_t deduct = 32 * (1 + res->audio_packets_line) + 7; +- int32_t free_chars = (int32_t)raw_capacity - (int32_t)deduct; +- +- if (free_chars < 0) free_chars = 0; +- +- int32_t margin = 4; +- +- int32_t base = free_chars - margin; +- if (base < 0) base = 0; +- +- res->cfrl_rc_savings = (uint32_t)((base * 7) / 8); +-} +- +-/* Core DFM Check Function */ +-static void perform_dfm_check(const struct dfm_config *cfg, struct dfm_results *res) +-{ +- memset(res, 0, sizeof(struct dfm_results)); +- +- uint32_t htotal = cfg->hactive + cfg->hblank; +- +- res->overhead_ppm = calc_overhead_ppm(cfg->lanes); +- +- res->f_pixel_clock_max = (uint64_t)cfg->pixel_clock_khz * 1000; +- res->f_pixel_clock_max = res->f_pixel_clock_max * (1000 + DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000) / 1000; +- +- uint64_t t_line_ns = ((uint64_t)htotal * 1000000000ULL) / res->f_pixel_clock_max; +- +- uint64_t r_bit_nominal = (uint64_t)cfg->frl_bit_rate_gbps * 1000000000ULL; +- uint64_t r_bit_min = r_bit_nominal * (1000000 - DFM_TOLERANCE_FRL_BIT_RATE_PPM) / 1000000; +- +- res->r_frl_char_min = r_bit_min / 18; +- +- uint64_t cap_calc = (t_line_ns * res->r_frl_char_min * cfg->lanes) / 1000000000ULL; +- res->cfrl_line = (uint32_t)cap_calc; +- +- calc_audio(cfg, t_line_ns, res); +- +- calc_rc_compression(cfg, res); +- +- uint32_t bpp; +- uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; +- uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; +- +- bpp = (24 * kcd) / (k420 * 8); +- +- uint64_t bytes_line = ((uint64_t)bpp * cfg->hactive) / 8; +- +- res->tb_active = (uint32_t)CEILING(bytes_line, 3); +- +- uint64_t tb_blank_num = (uint64_t)cfg->hblank * kcd; +- uint64_t tb_blank_den = (uint64_t)k420 * 8; +- res->tb_blank = (uint32_t)CEILING(tb_blank_num, tb_blank_den); +- +- if (res->hblank_audio_min <= res->tb_blank) { +- res->audio_supported = true; +- } else { +- res->audio_supported = false; +- res->total_supported = false; +- return; +- } +- +- uint64_t tb_total = res->tb_active + res->tb_blank; +- uint64_t f_tb_avg = (res->f_pixel_clock_max * tb_total) / htotal; +- +- res->t_active_ref = (t_line_ns * cfg->hactive) / htotal; +- +- res->t_blank_ref = (t_line_ns * cfg->hblank) / htotal; +- +- uint64_t r_frl_eff = res->r_frl_char_min * (1000000 - res->overhead_ppm) / 1000000; +- +- res->t_active_min = (3ULL * res->tb_active * 1000000000ULL) / (2ULL * cfg->lanes * r_frl_eff); +- +- res->t_blank_min = (res->tb_blank * 1000000000ULL) / (cfg->lanes * r_frl_eff); +- +- if (res->t_active_ref >= res->t_active_min && res->t_blank_ref >= res->t_blank_min) { +- res->tb_borrowed = 0; +- res->dfm_supported = true; +- } else if (res->t_active_ref < res->t_active_min) { +- uint64_t borrow_time_ns = res->t_active_min - res->t_active_ref; +- +- res->tb_borrowed = CEILING(borrow_time_ns * f_tb_avg, 1000000000ULL); +- +- if (res->tb_borrowed <= DFM_TB_BORROWED_MAX) { +- res->dfm_supported = true; +- } else { +- res->dfm_supported = false; +- } +- } else { +- /* Blanking needs more time than available */ +- res->dfm_supported = false; +- } +- +- if (!res->dfm_supported) { +- res->total_supported = false; +- return; +- } +- +- uint64_t total_chars_req = (3 * tb_total) / 2; +- if (total_chars_req > res->cfrl_rc_savings) { +- res->cfrl_actual_payload = (uint32_t)CEILING((total_chars_req - res->cfrl_rc_savings), 1); +- } else { +- res->cfrl_actual_payload = 0; +- } +- +- uint64_t util_ppm = ((uint64_t)res->cfrl_actual_payload * 1000000ULL) / res->cfrl_line; +- +- int32_t margin_ppm = 1000000 - (int32_t)util_ppm + (int32_t)res->overhead_ppm; +- res->margin_ppm = margin_ppm; +- +- if (margin_ppm >= 0) { +- res->utilization_supported = true; +- res->total_supported = true; +- } else { +- res->utilization_supported = false; +- res->total_supported = false; +- } +-} +- +-static bool hdmi_decide_link_settings( +- struct dc_stream_state *stream, +- struct pipe_ctx *pipe_ctx) +-{ +- struct dfm_config cfg; +- struct dfm_results res; +- uint8_t frl_rate; +- static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; +- uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; +- uint8_t best_borrow_rate = 0; +- uint8_t best_borrow_lanes = 0; +- struct dfm_results best_borrow_res = {0}; +- +- if (max_rate == 0 || max_rate > 6) +- return false; +- +- memset(&cfg, 0, sizeof(cfg)); +- +- cfg.pixel_clock_khz = stream->timing.pix_clk_100hz / 10; +- cfg.hactive = stream->timing.h_addressable; +- cfg.hblank = stream->timing.h_total - stream->timing.h_addressable; +- cfg.encoding = stream->timing.pixel_encoding; +- +- switch (stream->timing.display_color_depth) { +- case COLOR_DEPTH_888: cfg.bpc = 8; break; +- case COLOR_DEPTH_101010: cfg.bpc = 10; break; +- case COLOR_DEPTH_121212: cfg.bpc = 12; break; +- case COLOR_DEPTH_161616: cfg.bpc = 16; break; +- default: +- cfg.bpc = 8; +- break; +- } +- +- if (stream->audio_info.mode_count) { +- cfg.audio_enable = true; +- /* If we assume the worst case (e.g. 192KHz 32 channel audio) we risk +- * unfairly pruning low res modes with short Hblank periods. Instead, +- * assume a standard surround sound mode that should allow all video +- * modes to work. +- */ +- cfg.audio_freq_hz = 48000; +- cfg.audio_channels = 8; +- } +- +- for (frl_rate = 1; frl_rate <= max_rate; frl_rate++) { +- cfg.frl_bit_rate_gbps = frl_rates_gbps[frl_rate - 1]; +- cfg.lanes = (frl_rate <= 2) ? 3 : 4; +- +- perform_dfm_check(&cfg, &res); +- +- if (res.total_supported) { +- if (res.tb_borrowed == 0) { +- pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; +- pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; +- +- pr_info("HDMI FRL: Rate %d Supported. Borrowed: 0, Margin: %d ppm\n", +- frl_rate, res.margin_ppm); +- return true; +- } else if (best_borrow_rate == 0) { +- best_borrow_rate = frl_rate; +- best_borrow_lanes = cfg.lanes; +- best_borrow_res = res; +- } +- } +- } +- +- if (best_borrow_rate > 0) { +- pipe_ctx->link_config.dp_link_settings.frl_rate = best_borrow_rate; +- pipe_ctx->link_config.dp_link_settings.lane_count = best_borrow_lanes; +- +- pr_info("HDMI FRL: Rate %d Supported (with borrowing). Borrowed: %llu, Margin: %d ppm\n", +- best_borrow_rate, best_borrow_res.tb_borrowed, best_borrow_res.margin_ppm); +- return true; +- } +- +- return false; +-} +- + enum dc_status resource_map_pool_resources( + const struct dc *dc, + struct dc_state *context, +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 39574f87fa92e6..5e83c2bb4256a6 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -252,4 +252,330 @@ void dc_link_disable_frl(struct dc_link *link) + write_buffer[0] = 0; + write_buffer[1] = 0; + frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2); ++} ++ ++/* DFM calc ++ * References: ++ * https://github.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_linux/drv/mpp/component/hdmi/src/mkp/drv_hdmi_dfm.c#L264 ++ * https://github.com/jelyoussefi/intel-gpu-i915/blob/e366083d562341ce15d5fe1a39bb6e07f18a4745/drivers/gpu/drm/i915/display/intel_hdmi.c#L4217 ++ * TODO Move to generic DRM */ ++ ++#define DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000 5 /* +0.50% -> 5/1000 */ ++#define DFM_TOLERANCE_AUDIO_CLOCK_PPM 1000 /* +/- 1000 ppm */ ++#define DFM_TOLERANCE_FRL_BIT_RATE_PPM 300 /* +/- 300 ppm */ ++#define DFM_TB_BORROWED_MAX 400 ++#define DFM_FRL_CFRL_CB 510 ++ ++struct dfm_config { ++ /* Video Timing */ ++ uint32_t pixel_clock_khz; /* Nominal */ ++ uint32_t hactive; ++ uint32_t hblank; ++ uint32_t bpc; /* Bits per component */ ++ enum dc_pixel_encoding encoding; ++ ++ /* FRL Configuration */ ++ uint32_t frl_bit_rate_gbps; /* 3, 6, 8, 10, 12 */ ++ uint8_t lanes; /* 3 or 4 */ ++ ++ /* Audio */ ++ bool audio_enable; ++ uint32_t audio_freq_hz; ++ uint8_t audio_channels; ++}; ++ ++struct dfm_results { ++ /* Calculated Parameters */ ++ uint64_t f_pixel_clock_max; ++ uint64_t r_frl_char_min; ++ uint32_t overhead_ppm; ++ ++ /* Audio */ ++ uint32_t audio_packets_line; ++ uint32_t hblank_audio_min; ++ ++ /* Tri-Bytes */ ++ uint32_t tb_active; ++ uint32_t tb_blank; ++ ++ /* Compression */ ++ uint32_t cfrl_rc_savings; ++ ++ /* Timing (ns) */ ++ uint64_t t_active_min; ++ uint64_t t_active_ref; ++ uint64_t t_blank_min; ++ uint64_t t_blank_ref; ++ ++ /* Borrowing */ ++ uint64_t tb_borrowed; ++ ++ /* Utilization */ ++ uint32_t cfrl_line; ++ uint32_t cfrl_actual_payload; ++ int32_t margin_ppm; /* Can be negative */ ++ ++ /* Pass/Fail Flags */ ++ bool audio_supported; ++ bool dfm_supported; ++ bool utilization_supported; ++ bool total_supported; ++}; ++ ++ ++#define CEILING(x, y) (((x) + (y) - 1) / (y)) ++ ++static uint32_t calc_overhead_ppm(uint8_t lanes) ++{ ++ uint32_t cfrl_sb = (4 * 510) + lanes; ++ ++ uint64_t oh_sb_num = (uint64_t)lanes * 1000000ULL; ++ uint32_t oh_sb = (uint32_t)((oh_sb_num + (cfrl_sb/2)) / cfrl_sb); /* Rounding */ ++ ++ uint64_t oh_rs_num = 32ULL * 1000000ULL; ++ uint32_t oh_rs = (uint32_t)((oh_rs_num + (cfrl_sb/2)) / cfrl_sb); ++ ++ uint64_t oh_map_num = 2500000ULL; /* 2.5 * 1M */ ++ uint32_t oh_map = (uint32_t)((oh_map_num + (cfrl_sb/2)) / cfrl_sb); ++ ++ uint32_t oh_m = 3000; ++ ++ return oh_sb + oh_rs + oh_map + oh_m; ++} ++ ++static void calc_audio(const struct dfm_config *cfg, ++ uint64_t t_line_ns, ++ struct dfm_results *res) ++{ ++ if (!cfg->audio_enable) { ++ res->audio_packets_line = 0; ++ res->hblank_audio_min = 64; ++ return; ++ } ++ ++ uint32_t ap = 1; ++ if (cfg->audio_channels > 22) { ++ ap = 4; /* ACAT 3 (up to 30.2ch) */ ++ } else if (cfg->audio_channels > 10) { ++ ap = 3; /* ACAT 2 (up to 22.2ch) */ ++ } else if (cfg->audio_channels > 8) { ++ ap = 2; /* ACAT 1 (up to 10.2ch) */ ++ } else { ++ ap = 1; /* Layout 0/1 */ ++ } ++ ++ uint64_t rap = (uint64_t)cfg->audio_freq_hz * (1000000 + DFM_TOLERANCE_AUDIO_CLOCK_PPM); ++ rap = (rap * ap) / 1000000; ++ ++ uint64_t avg_pkts_x1000 = (rap * t_line_ns) / 1000000; /* ns to ms scale */ ++ ++ res->audio_packets_line = (uint32_t)((avg_pkts_x1000 + 999) / 1000); ++ ++ res->hblank_audio_min = 64 + (32 * res->audio_packets_line); ++} ++ ++/* Table 6-44: RC Compression Savings */ ++static void calc_rc_compression(const struct dfm_config *cfg, struct dfm_results *res) ++{ ++ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; ++ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; ++ ++ uint64_t raw_num = (uint64_t)cfg->hblank * kcd * 8; ++ uint64_t raw_den = (uint64_t)k420 * 7; ++ uint32_t raw_capacity = (uint32_t)(raw_num / raw_den); /* FLOOR */ ++ ++ uint32_t deduct = 32 * (1 + res->audio_packets_line) + 7; ++ int32_t free_chars = (int32_t)raw_capacity - (int32_t)deduct; ++ ++ if (free_chars < 0) free_chars = 0; ++ ++ int32_t margin = 4; ++ ++ int32_t base = free_chars - margin; ++ if (base < 0) base = 0; ++ ++ res->cfrl_rc_savings = (uint32_t)((base * 7) / 8); ++} ++ ++/* Core DFM Check Function */ ++static void perform_dfm_check(const struct dfm_config *cfg, struct dfm_results *res) ++{ ++ memset(res, 0, sizeof(struct dfm_results)); ++ ++ uint32_t htotal = cfg->hactive + cfg->hblank; ++ ++ res->overhead_ppm = calc_overhead_ppm(cfg->lanes); ++ ++ res->f_pixel_clock_max = (uint64_t)cfg->pixel_clock_khz * 1000; ++ res->f_pixel_clock_max = res->f_pixel_clock_max * (1000 + DFM_TOLERANCE_PIXEL_CLOCK_PCT_X1000) / 1000; ++ ++ uint64_t t_line_ns = ((uint64_t)htotal * 1000000000ULL) / res->f_pixel_clock_max; ++ ++ uint64_t r_bit_nominal = (uint64_t)cfg->frl_bit_rate_gbps * 1000000000ULL; ++ uint64_t r_bit_min = r_bit_nominal * (1000000 - DFM_TOLERANCE_FRL_BIT_RATE_PPM) / 1000000; ++ ++ res->r_frl_char_min = r_bit_min / 18; ++ ++ uint64_t cap_calc = (t_line_ns * res->r_frl_char_min * cfg->lanes) / 1000000000ULL; ++ res->cfrl_line = (uint32_t)cap_calc; ++ ++ calc_audio(cfg, t_line_ns, res); ++ ++ calc_rc_compression(cfg, res); ++ ++ uint32_t bpp; ++ uint32_t k420 = (cfg->encoding == PIXEL_ENCODING_YCBCR420) ? 2 : 1; ++ uint32_t kcd = (cfg->encoding == PIXEL_ENCODING_YCBCR422) ? 1 : cfg->bpc; ++ ++ bpp = (24 * kcd) / (k420 * 8); ++ ++ uint64_t bytes_line = ((uint64_t)bpp * cfg->hactive) / 8; ++ ++ res->tb_active = (uint32_t)CEILING(bytes_line, 3); ++ ++ uint64_t tb_blank_num = (uint64_t)cfg->hblank * kcd; ++ uint64_t tb_blank_den = (uint64_t)k420 * 8; ++ res->tb_blank = (uint32_t)CEILING(tb_blank_num, tb_blank_den); ++ ++ if (res->hblank_audio_min <= res->tb_blank) { ++ res->audio_supported = true; ++ } else { ++ res->audio_supported = false; ++ res->total_supported = false; ++ return; ++ } ++ ++ uint64_t tb_total = res->tb_active + res->tb_blank; ++ uint64_t f_tb_avg = (res->f_pixel_clock_max * tb_total) / htotal; ++ ++ res->t_active_ref = (t_line_ns * cfg->hactive) / htotal; ++ ++ res->t_blank_ref = (t_line_ns * cfg->hblank) / htotal; ++ ++ uint64_t r_frl_eff = res->r_frl_char_min * (1000000 - res->overhead_ppm) / 1000000; ++ ++ res->t_active_min = (3ULL * res->tb_active * 1000000000ULL) / (2ULL * cfg->lanes * r_frl_eff); ++ ++ res->t_blank_min = (res->tb_blank * 1000000000ULL) / (cfg->lanes * r_frl_eff); ++ ++ if (res->t_active_ref >= res->t_active_min && res->t_blank_ref >= res->t_blank_min) { ++ res->tb_borrowed = 0; ++ res->dfm_supported = true; ++ } else if (res->t_active_ref < res->t_active_min) { ++ uint64_t borrow_time_ns = res->t_active_min - res->t_active_ref; ++ ++ res->tb_borrowed = CEILING(borrow_time_ns * f_tb_avg, 1000000000ULL); ++ ++ if (res->tb_borrowed <= DFM_TB_BORROWED_MAX) { ++ res->dfm_supported = true; ++ } else { ++ res->dfm_supported = false; ++ } ++ } else { ++ /* Blanking needs more time than available */ ++ res->dfm_supported = false; ++ } ++ ++ if (!res->dfm_supported) { ++ res->total_supported = false; ++ return; ++ } ++ ++ uint64_t total_chars_req = (3 * tb_total) / 2; ++ if (total_chars_req > res->cfrl_rc_savings) { ++ res->cfrl_actual_payload = (uint32_t)CEILING((total_chars_req - res->cfrl_rc_savings), 1); ++ } else { ++ res->cfrl_actual_payload = 0; ++ } ++ ++ uint64_t util_ppm = ((uint64_t)res->cfrl_actual_payload * 1000000ULL) / res->cfrl_line; ++ ++ int32_t margin_ppm = 1000000 - (int32_t)util_ppm + (int32_t)res->overhead_ppm; ++ res->margin_ppm = margin_ppm; ++ ++ if (margin_ppm >= 0) { ++ res->utilization_supported = true; ++ res->total_supported = true; ++ } else { ++ res->utilization_supported = false; ++ res->total_supported = false; ++ } ++} ++ ++bool hdmi_decide_link_settings( ++ struct dc_stream_state *stream, ++ struct pipe_ctx *pipe_ctx) ++{ ++ struct dfm_config cfg; ++ struct dfm_results res; ++ uint8_t frl_rate; ++ static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; ++ uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; ++ uint8_t best_borrow_rate = 0; ++ uint8_t best_borrow_lanes = 0; ++ struct dfm_results best_borrow_res = {0}; ++ ++ if (max_rate == 0 || max_rate > 6) ++ return false; ++ ++ memset(&cfg, 0, sizeof(cfg)); ++ ++ cfg.pixel_clock_khz = stream->timing.pix_clk_100hz / 10; ++ cfg.hactive = stream->timing.h_addressable; ++ cfg.hblank = stream->timing.h_total - stream->timing.h_addressable; ++ cfg.encoding = stream->timing.pixel_encoding; ++ ++ switch (stream->timing.display_color_depth) { ++ case COLOR_DEPTH_888: cfg.bpc = 8; break; ++ case COLOR_DEPTH_101010: cfg.bpc = 10; break; ++ case COLOR_DEPTH_121212: cfg.bpc = 12; break; ++ case COLOR_DEPTH_161616: cfg.bpc = 16; break; ++ default: ++ cfg.bpc = 8; ++ break; ++ } ++ ++ if (stream->audio_info.mode_count) { ++ cfg.audio_enable = true; ++ /* If we assume the worst case (e.g. 192KHz 32 channel audio) we risk ++ * unfairly pruning low res modes with short Hblank periods. Instead, ++ * assume a standard surround sound mode that should allow all video ++ * modes to work. ++ */ ++ cfg.audio_freq_hz = 48000; ++ cfg.audio_channels = 8; ++ } ++ ++ for (frl_rate = 1; frl_rate <= max_rate; frl_rate++) { ++ cfg.frl_bit_rate_gbps = frl_rates_gbps[frl_rate - 1]; ++ cfg.lanes = (frl_rate <= 2) ? 3 : 4; ++ ++ perform_dfm_check(&cfg, &res); ++ ++ if (res.total_supported) { ++ if (res.tb_borrowed == 0) { ++ pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; ++ ++ pr_info("HDMI FRL: Rate %d Supported. Borrowed: 0, Margin: %d ppm\n", ++ frl_rate, res.margin_ppm); ++ return true; ++ } else if (best_borrow_rate == 0) { ++ best_borrow_rate = frl_rate; ++ best_borrow_lanes = cfg.lanes; ++ best_borrow_res = res; ++ } ++ } ++ } ++ ++ if (best_borrow_rate > 0) { ++ pipe_ctx->link_config.dp_link_settings.frl_rate = best_borrow_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = best_borrow_lanes; ++ ++ pr_info("HDMI FRL: Rate %d Supported (with borrowing). Borrowed: %llu, Margin: %d ppm\n", ++ best_borrow_rate, best_borrow_res.tb_borrowed, best_borrow_res.margin_ppm); ++ return true; ++ } ++ ++ return false; + } +\ No newline at end of file +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +index 4a913a3d2511eb..b6f23e6d83945b 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +@@ -39,4 +39,15 @@ bool dc_link_perform_frl_training(struct dc_link *link, + */ + void dc_link_disable_frl(struct dc_link *link); + ++/* ++ * Perform HDMI DFM calculation to determine the optimal link settings. ++ * ++ * Returns: ++ * true - Link verification succeeded, link can be configured ++ * false - Link verification failed, link cannot be configured ++ */ ++bool hdmi_decide_link_settings( ++ struct dc_stream_state *stream, ++ struct pipe_ctx *pipe_ctx); ++ + #endif /* __LINK_HDMI_FRL_TRAINING_H__ */ + +From 284a3e3a2966cb4e5d068fe88ffebbcdd69247ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 24 Feb 2026 22:58:48 +0100 +Subject: [PATCH 100/103] FRL training: Add retry loop, don't prefer + non-borrowing rates + +--- + .../gpu/drm/amd/display/dc/link/link_dpms.c | 2 +- + .../dc/link/protocols/link_frl_training.c | 56 +++++++++---------- + .../dc/link/protocols/link_frl_training.h | 22 ++++++++ + 3 files changed, 49 insertions(+), 31 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +index bd6654e2ae5c04..92aa129054121a 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +@@ -1998,7 +1998,7 @@ static enum dc_status enable_link_hdmi(struct pipe_ctx *pipe_ctx) + pipe_ctx->stream->signal, + &link->cur_link_settings); + +- if (!dc_link_perform_frl_training(link, &pipe_ctx->link_res)) { ++ if (!dc_link_perform_frl_training_with_retries(link, &pipe_ctx->link_res)) { + DC_LOG_HW_LINK_TRAINING("HDMI FRL: training failed\n"); + return DC_ERROR_UNEXPECTED; + } +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 5e83c2bb4256a6..420d4e24b0ca6a 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -25,6 +25,8 @@ + #define FRL_POLL_DELAY_MS 2 + #define FRL_MAX_POLLS 100 + ++#define FRL_TRAINING_RETRIES 10 ++ + static bool frl_read_scdc(struct dc_link *link, uint8_t offset, void *buf, + uint32_t size) + { +@@ -90,12 +92,6 @@ bool dc_link_perform_frl_training(struct dc_link *link, + write_buffer[0] = 0x01; + frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, write_buffer, 1); + +-retrain: +- /* Reset FRL rate */ +- write_buffer[0] = 0; +- write_buffer[1] = 0; +- frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2); +- + /* ------------------------------------------------------------------ */ + /* Step 2: Wait for FLT_READY */ + /* ------------------------------------------------------------------ */ +@@ -197,7 +193,7 @@ bool dc_link_perform_frl_training(struct dc_link *link, + return true; + } else if (update & SCDC_FLT_UPDATE_BIT) { + DC_LOG_HW_LINK_TRAINING("HDMI FRL: retraining needed\n"); +- goto retrain; ++ return false; + } else { + DC_LOG_HW_LINK_TRAINING("HDMI FRL: did not receive status update!\n"); + return false; +@@ -244,6 +240,24 @@ bool dc_link_perform_frl_training(struct dc_link *link, + return false; + } + ++bool dc_link_perform_frl_training_with_retries(struct dc_link *link, ++ const struct link_resource *link_res) ++{ ++ bool success; ++ int i; ++ ++ for (i = 0; i < FRL_TRAINING_RETRIES; ++i) { ++ success = dc_link_perform_frl_training(link, link_res); ++ ++ if (success) ++ break; ++ ++ DC_LOG_HW_LINK_TRAINING("FRL: Training attempt %d failed!"); ++ } ++ ++ return success; ++} ++ + void dc_link_disable_frl(struct dc_link *link) + { + uint8_t write_buffer[2]; +@@ -511,9 +525,6 @@ bool hdmi_decide_link_settings( + uint8_t frl_rate; + static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12}; + uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate; +- uint8_t best_borrow_rate = 0; +- uint8_t best_borrow_lanes = 0; +- struct dfm_results best_borrow_res = {0}; + + if (max_rate == 0 || max_rate > 6) + return false; +@@ -553,29 +564,14 @@ bool hdmi_decide_link_settings( + perform_dfm_check(&cfg, &res); + + if (res.total_supported) { +- if (res.tb_borrowed == 0) { +- pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; +- pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; ++ pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; ++ pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; + +- pr_info("HDMI FRL: Rate %d Supported. Borrowed: 0, Margin: %d ppm\n", +- frl_rate, res.margin_ppm); +- return true; +- } else if (best_borrow_rate == 0) { +- best_borrow_rate = frl_rate; +- best_borrow_lanes = cfg.lanes; +- best_borrow_res = res; +- } ++ pr_info("HDMI FRL: Rate %d Supported. Borrowed: %d, Margin: %d ppm\n", ++ frl_rate, res.tb_borrowed, res.margin_ppm); ++ return true; + } + } + +- if (best_borrow_rate > 0) { +- pipe_ctx->link_config.dp_link_settings.frl_rate = best_borrow_rate; +- pipe_ctx->link_config.dp_link_settings.lane_count = best_borrow_lanes; +- +- pr_info("HDMI FRL: Rate %d Supported (with borrowing). Borrowed: %llu, Margin: %d ppm\n", +- best_borrow_rate, best_borrow_res.tb_borrowed, best_borrow_res.margin_ppm); +- return true; +- } +- + return false; + } +\ No newline at end of file +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +index b6f23e6d83945b..a147a40a5918d7 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h +@@ -35,6 +35,28 @@ bool dc_link_perform_frl_training(struct dc_link *link, + const struct link_resource *link_res); + + /* ++ * Attempt HDMI 2.1 FRL link training up to FRL_TRAINING_RETRIES times. ++ * ++ * @link: ++ * DC link representing the HDMI connection. ++ * ++ * @link_res: ++ * Link resources containing the HPO HDMI FRL link encoder. ++ * ++ * @frl_rate: ++ * FRL rate index as defined by HDMI 2.1 (1–6). ++ * ++ * @lane_count: ++ * Number of FRL lanes (3 or 4). ++ * ++ * Returns: ++ * true - training completed successfully, link is active ++ * false - training failed, link is disabled ++ */ ++bool dc_link_perform_frl_training_with_retries(struct dc_link *link, ++ const struct link_resource *link_res); ++ ++ /* + * Disable FRL mode in the sink. Allows fallback to TMDS. + */ + void dc_link_disable_frl(struct dc_link *link); + +From 55b86007e517bdf81f22fd223977b73f4a22e9b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Tue, 24 Feb 2026 23:53:03 +0100 +Subject: [PATCH 101/103] + drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c: combined + retry and rate fallback loop + +--- + .../dc/link/protocols/link_frl_training.c | 22 +++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 420d4e24b0ca6a..4d547b6e263396 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -243,16 +243,34 @@ bool dc_link_perform_frl_training(struct dc_link *link, + bool dc_link_perform_frl_training_with_retries(struct dc_link *link, + const struct link_resource *link_res) + { ++ uint8_t min_rate; + bool success; + int i; + ++ /* ++ * We will attempt the highest rate first, then fall back to a lower rate ++ * Ideally, the sink would respond with a lower rate request, but my ++ * Samsung S95B just doesn't. So we do this here instead. ++ */ ++ ++ min_rate = link->cur_link_settings.frl_rate; ++ link->cur_link_settings.frl_rate = link->local_sink->edid_caps.frl_caps.max_rate; ++ link->cur_link_settings.lane_count = link->cur_link_settings.frl_rate <= 2 ? 3 : 4; ++ + for (i = 0; i < FRL_TRAINING_RETRIES; ++i) { + success = dc_link_perform_frl_training(link, link_res); + + if (success) + break; + +- DC_LOG_HW_LINK_TRAINING("FRL: Training attempt %d failed!"); ++ if (link->cur_link_settings.frl_rate > min_rate) { ++ link->cur_link_settings.frl_rate--; ++ link->cur_link_settings.lane_count = ++ link->cur_link_settings.frl_rate <= 2 ? 3 : 4; ++ } ++ ++ DC_LOG_HW_LINK_TRAINING("FRL: Training attempt %d failed! Will attempt rate %d next", ++ i, link->cur_link_settings.frl_rate); + } + + return success; +@@ -567,7 +585,7 @@ bool hdmi_decide_link_settings( + pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate; + pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes; + +- pr_info("HDMI FRL: Rate %d Supported. Borrowed: %d, Margin: %d ppm\n", ++ DC_LOG_HW_LINK_TRAINING("HDMI FRL: Rate %d Supported. Borrowed: %llu, Margin: %d ppm\n", + frl_rate, res.tb_borrowed, res.margin_ppm); + return true; + } + +From fb9bb553cde12611c816cac5979d0f1752b45727 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Wed, 25 Feb 2026 02:42:06 +0100 +Subject: [PATCH 102/103] + drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c: Delay + before finalizing training + +--- + .../drm/amd/display/dc/link/protocols/link_frl_training.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +index 4d547b6e263396..16bbf28a9b347a 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c +@@ -172,6 +172,8 @@ bool dc_link_perform_frl_training(struct dc_link *link, + + if (lane == lane_count) { + enc->funcs->set_training_enable(enc, false); ++ /* Delay to let the sink settle after clearing SCDC_UPDATE_0 */ ++ msleep(FRL_POLL_DELAY_MS); + for (post_training_timeout = 0; + post_training_timeout < FRL_MAX_POLLS; + post_training_timeout++) { +@@ -270,7 +272,7 @@ bool dc_link_perform_frl_training_with_retries(struct dc_link *link, + } + + DC_LOG_HW_LINK_TRAINING("FRL: Training attempt %d failed! Will attempt rate %d next", +- i, link->cur_link_settings.frl_rate); ++ i + 1, link->cur_link_settings.frl_rate); + } + + return success; +@@ -592,4 +594,4 @@ bool hdmi_decide_link_settings( + } + + return false; +-} +\ No newline at end of file ++} + +From 17d577b4821e3fa033f1baf5fda54b3ed5a40426 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= +Date: Wed, 25 Feb 2026 19:18:17 +0100 +Subject: [PATCH 103/103] drivers/gpu/drm/amd/display/dc/link/link_dpms.c: + don't disable FRL on dpms off + +Causes issues for LG users +--- + drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +index 92aa129054121a..210ccf7f138a94 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +@@ -2453,9 +2453,6 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) + } + } + +- if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) +- dc_link_disable_frl(pipe_ctx->stream->link); +- + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && + !dp_is_128b_132b_signal(pipe_ctx)) { + +