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
32 struct amdgpu_dm_quirks {
33 bool aux_hpd_discon;
34 bool support_edp0_on_dp1;
35 };
36
37 static struct amdgpu_dm_quirks quirk_entries = {
38 .aux_hpd_discon = false,
39 .support_edp0_on_dp1 = false
40 };
41
edp0_on_dp1_callback(const struct dmi_system_id * id)42 static int edp0_on_dp1_callback(const struct dmi_system_id *id)
43 {
44 quirk_entries.support_edp0_on_dp1 = true;
45 return 0;
46 }
47
aux_hpd_discon_callback(const struct dmi_system_id * id)48 static int aux_hpd_discon_callback(const struct dmi_system_id *id)
49 {
50 quirk_entries.aux_hpd_discon = true;
51 return 0;
52 }
53
54 static const struct dmi_system_id dmi_quirk_table[] = {
55 {
56 .callback = aux_hpd_discon_callback,
57 .matches = {
58 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
59 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"),
60 },
61 },
62 {
63 .callback = aux_hpd_discon_callback,
64 .matches = {
65 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
66 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"),
67 },
68 },
69 {
70 .callback = aux_hpd_discon_callback,
71 .matches = {
72 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
73 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"),
74 },
75 },
76 {
77 .callback = aux_hpd_discon_callback,
78 .matches = {
79 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
80 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower Plus 7010"),
81 },
82 },
83 {
84 .callback = aux_hpd_discon_callback,
85 .matches = {
86 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
87 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower 7010"),
88 },
89 },
90 {
91 .callback = aux_hpd_discon_callback,
92 .matches = {
93 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
94 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF Plus 7010"),
95 },
96 },
97 {
98 .callback = aux_hpd_discon_callback,
99 .matches = {
100 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
101 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF 7010"),
102 },
103 },
104 {
105 .callback = aux_hpd_discon_callback,
106 .matches = {
107 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
108 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro Plus 7010"),
109 },
110 },
111 {
112 .callback = aux_hpd_discon_callback,
113 .matches = {
114 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
115 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro 7010"),
116 },
117 },
118 {
119 .callback = edp0_on_dp1_callback,
120 .matches = {
121 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
122 DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite mt645 G8 Mobile Thin Client"),
123 },
124 },
125 {
126 .callback = edp0_on_dp1_callback,
127 .matches = {
128 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
129 DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 645 14 inch G11 Notebook PC"),
130 },
131 },
132 {
133 .callback = edp0_on_dp1_callback,
134 .matches = {
135 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
136 DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 665 16 inch G11 Notebook PC"),
137 },
138 },
139 {
140 .callback = edp0_on_dp1_callback,
141 .matches = {
142 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
143 DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook 445 14 inch G11 Notebook PC"),
144 },
145 },
146 {
147 .callback = edp0_on_dp1_callback,
148 .matches = {
149 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
150 DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook 465 16 inch G11 Notebook PC"),
151 },
152 },
153 {}
154 /* TODO: refactor this from a fixed table to a dynamic option */
155 };
156
retrieve_dmi_info(struct amdgpu_display_manager * dm)157 void retrieve_dmi_info(struct amdgpu_display_manager *dm)
158 {
159 struct drm_device *dev = dm->ddev;
160 int dmi_id;
161
162 dm->aux_hpd_discon_quirk = false;
163 dm->edp0_on_dp1_quirk = false;
164
165 dmi_id = dmi_check_system(dmi_quirk_table);
166
167 if (!dmi_id)
168 return;
169
170 if (quirk_entries.aux_hpd_discon) {
171 dm->aux_hpd_discon_quirk = true;
172 drm_info(dev, "aux_hpd_discon_quirk attached\n");
173 }
174 if (quirk_entries.support_edp0_on_dp1) {
175 dm->edp0_on_dp1_quirk = true;
176 drm_info(dev, "support_edp0_on_dp1 attached\n");
177 }
178 }
179