projects/linux·blob master · refs

212 lines · 5.4 KiB

1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2025 Advanced Micro Devices, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: AMD
24 *
25 */
26
27#include <linux/dmi.h>
28
29#include "amdgpu.h"
30#include "amdgpu_dm.h"
31#include "dm_helpers.h"
32
33struct amdgpu_dm_quirks {
34 bool aux_hpd_discon;
35 bool support_edp0_on_dp1;
36};
37
38static struct amdgpu_dm_quirks quirk_entries = {
39 .aux_hpd_discon = false,
40 .support_edp0_on_dp1 = false
41};
42
43static int edp0_on_dp1_callback(const struct dmi_system_id *id)
44{
45 quirk_entries.support_edp0_on_dp1 = true;
46 return 0;
47}
48
49static int aux_hpd_discon_callback(const struct dmi_system_id *id)
50{
51 quirk_entries.aux_hpd_discon = true;
52 return 0;
53}
54
55static const struct dmi_system_id dmi_quirk_table[] = {
56 {
57 .callback = aux_hpd_discon_callback,
58 .matches = {
59 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
60 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"),
61 },
62 },
63 {
64 .callback = aux_hpd_discon_callback,
65 .matches = {
66 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
67 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"),
68 },
69 },
70 {
71 .callback = aux_hpd_discon_callback,
72 .matches = {
73 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
74 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"),
75 },
76 },
77 {
78 .callback = aux_hpd_discon_callback,
79 .matches = {
80 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
81 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower Plus 7010"),
82 },
83 },
84 {
85 .callback = aux_hpd_discon_callback,
86 .matches = {
87 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
88 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower 7010"),
89 },
90 },
91 {
92 .callback = aux_hpd_discon_callback,
93 .matches = {
94 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
95 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF Plus 7010"),
96 },
97 },
98 {
99 .callback = aux_hpd_discon_callback,
100 .matches = {
101 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
102 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF 7010"),
103 },
104 },
105 {
106 .callback = aux_hpd_discon_callback,
107 .matches = {
108 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
109 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro Plus 7010"),
110 },
111 },
112 {
113 .callback = aux_hpd_discon_callback,
114 .matches = {
115 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
116 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro 7010"),
117 },
118 },
119 {
120 .callback = edp0_on_dp1_callback,
121 .matches = {
122 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
123 DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite mt645 G8 Mobile Thin Client"),
124 },
125 },
126 {
127 .callback = edp0_on_dp1_callback,
128 .matches = {
129 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
130 DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 645 14 inch G11 Notebook PC"),
131 },
132 },
133 {
134 .callback = edp0_on_dp1_callback,
135 .matches = {
136 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
137 DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 665 16 inch G11 Notebook PC"),
138 },
139 },
140 {
141 .callback = edp0_on_dp1_callback,
142 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
144 DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook 445 14 inch G11 Notebook PC"),
145 },
146 },
147 {
148 .callback = edp0_on_dp1_callback,
149 .matches = {
150 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
151 DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook 465 16 inch G11 Notebook PC"),
152 },
153 },
154 {}
155 /* TODO: refactor this from a fixed table to a dynamic option */
156};
157
158void retrieve_dmi_info(struct amdgpu_display_manager *dm)
159{
160 struct drm_device *dev = dm->ddev;
161 int dmi_id;
162
163 dm->aux_hpd_discon_quirk = false;
164 dm->edp0_on_dp1_quirk = false;
165
166 dmi_id = dmi_check_system(dmi_quirk_table);
167
168 if (!dmi_id)
169 return;
170
171 if (quirk_entries.aux_hpd_discon) {
172 dm->aux_hpd_discon_quirk = true;
173 drm_info(dev, "aux_hpd_discon_quirk attached\n");
174 }
175 if (quirk_entries.support_edp0_on_dp1) {
176 dm->edp0_on_dp1_quirk = true;
177 drm_info(dev, "support_edp0_on_dp1 attached\n");
178 }
179}
180EXPORT_IF_KUNIT(retrieve_dmi_info);
181
182struct amdgpu_stutter_quirk {
183 u16 chip_vendor;
184 u16 chip_device;
185 u16 subsys_vendor;
186 u16 subsys_device;
187 u8 revision;
188};
189
190static const struct amdgpu_stutter_quirk amdgpu_stutter_quirk_list[] = {
191 /* https://bugzilla.kernel.org/show_bug.cgi?id=214417 */
192 { 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc8 },
193 { 0, 0, 0, 0, 0 },
194};
195
196bool dm_should_disable_stutter(struct pci_dev *pdev)
197{
198 const struct amdgpu_stutter_quirk *p = amdgpu_stutter_quirk_list;
199
200 while (p && p->chip_device != 0) {
201 if (pdev->vendor == p->chip_vendor &&
202 pdev->device == p->chip_device &&
203 pdev->subsystem_vendor == p->subsys_vendor &&
204 pdev->subsystem_device == p->subsys_device &&
205 pdev->revision == p->revision) {
206 return true;
207 }
208 ++p;
209 }
210 return false;
211}
212EXPORT_IF_KUNIT(dm_should_disable_stutter);