xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_quirks.c (revision b08494a8f7416e5f09907318c5460ad6f6e2a548)
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 
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 
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 
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