13cdbfb991eb38b88c23d85d300de34ca53c9e32
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / drm_edid_load.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3    drm_edid_load.c: use a built-in EDID data set or load it via the firmware
4                     interface
5
6    Copyright (C) 2012 Carsten Emde <C.Emde@osadl.org>
7
8 */
9
10 #include <linux/firmware.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13
14 #include <drm/drm_crtc.h>
15 #include <drm/drm_crtc_helper.h>
16 #include <drm/drm_drv.h>
17 #include <drm/drm_edid.h>
18 #include <drm/drm_print.h>
19
20 static char edid_firmware[PATH_MAX];
21 module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644);
22 MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob "
23         "from built-in data or /lib/firmware instead. ");
24
25 /* Use only for backward compatibility with drm_kms_helper.edid_firmware */
26 int __drm_set_edid_firmware_path(const char *path)
27 {
28         scnprintf(edid_firmware, sizeof(edid_firmware), "%s", path);
29
30         return 0;
31 }
32 EXPORT_SYMBOL(__drm_set_edid_firmware_path);
33
34 /* Use only for backward compatibility with drm_kms_helper.edid_firmware */
35 int __drm_get_edid_firmware_path(char *buf, size_t bufsize)
36 {
37         return scnprintf(buf, bufsize, "%s", edid_firmware);
38 }
39 EXPORT_SYMBOL(__drm_get_edid_firmware_path);
40
41 #define GENERIC_EDIDS 6
42 static const char * const generic_edid_name[GENERIC_EDIDS] = {
43         "edid/800x600.bin",
44         "edid/1024x768.bin",
45         "edid/1280x1024.bin",
46         "edid/1600x1200.bin",
47         "edid/1680x1050.bin",
48         "edid/1920x1080.bin",
49 };
50
51 static const u8 generic_edid[GENERIC_EDIDS][128] = {
52         {
53         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
54         0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55         0x05, 0x16, 0x01, 0x03, 0x6d, 0x1b, 0x14, 0x78,
56         0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
57         0x20, 0x50, 0x54, 0x01, 0x00, 0x00, 0x45, 0x40,
58         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
59         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xa0, 0x0f,
60         0x20, 0x00, 0x31, 0x58, 0x1c, 0x20, 0x28, 0x80,
61         0x14, 0x00, 0x15, 0xd0, 0x10, 0x00, 0x00, 0x1e,
62         0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
63         0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
64         0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
65         0x3d, 0x24, 0x26, 0x05, 0x00, 0x0a, 0x20, 0x20,
66         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
67         0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x53,
68         0x56, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0xc2,
69         },
70         {
71         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
72         0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73         0x05, 0x16, 0x01, 0x03, 0x6d, 0x23, 0x1a, 0x78,
74         0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
75         0x20, 0x50, 0x54, 0x00, 0x08, 0x00, 0x61, 0x40,
76         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
77         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0x19,
78         0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x08, 0x90,
79         0x36, 0x00, 0x63, 0x0a, 0x11, 0x00, 0x00, 0x18,
80         0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
81         0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
82         0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
83         0x3d, 0x2f, 0x31, 0x07, 0x00, 0x0a, 0x20, 0x20,
84         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
85         0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x58,
86         0x47, 0x41, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x55,
87         },
88         {
89         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
90         0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91         0x05, 0x16, 0x01, 0x03, 0x6d, 0x2c, 0x23, 0x78,
92         0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
93         0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0x81, 0x80,
94         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
95         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x30, 0x2a,
96         0x00, 0x98, 0x51, 0x00, 0x2a, 0x40, 0x30, 0x70,
97         0x13, 0x00, 0xbc, 0x63, 0x11, 0x00, 0x00, 0x1e,
98         0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
99         0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
100         0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
101         0x3d, 0x3e, 0x40, 0x0b, 0x00, 0x0a, 0x20, 0x20,
102         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
103         0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x53,
104         0x58, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0xa0,
105         },
106         {
107         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
108         0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109         0x05, 0x16, 0x01, 0x03, 0x6d, 0x37, 0x29, 0x78,
110         0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
111         0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xa9, 0x40,
112         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
113         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x48, 0x3f,
114         0x40, 0x30, 0x62, 0xb0, 0x32, 0x40, 0x40, 0xc0,
115         0x13, 0x00, 0x2b, 0xa0, 0x21, 0x00, 0x00, 0x1e,
116         0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
117         0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
118         0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
119         0x3d, 0x4a, 0x4c, 0x11, 0x00, 0x0a, 0x20, 0x20,
120         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
121         0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x55,
122         0x58, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0x9d,
123         },
124         {
125         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
126         0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127         0x05, 0x16, 0x01, 0x03, 0x6d, 0x2b, 0x1b, 0x78,
128         0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
129         0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xb3, 0x00,
130         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
131         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x21, 0x39,
132         0x90, 0x30, 0x62, 0x1a, 0x27, 0x40, 0x68, 0xb0,
133         0x36, 0x00, 0xb5, 0x11, 0x11, 0x00, 0x00, 0x1e,
134         0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
135         0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
136         0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
137         0x3d, 0x40, 0x42, 0x0f, 0x00, 0x0a, 0x20, 0x20,
138         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
139         0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x57,
140         0x53, 0x58, 0x47, 0x41, 0x0a, 0x20, 0x00, 0x26,
141         },
142         {
143         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
144         0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145         0x05, 0x16, 0x01, 0x03, 0x6d, 0x32, 0x1c, 0x78,
146         0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
147         0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xd1, 0xc0,
148         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
149         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
150         0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
151         0x45, 0x00, 0xf4, 0x19, 0x11, 0x00, 0x00, 0x1e,
152         0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
153         0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
154         0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
155         0x3d, 0x42, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20,
156         0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
157         0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x46,
158         0x48, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x05,
159         },
160 };
161
162 static int edid_size(const u8 *edid, int data_size)
163 {
164         if (data_size < EDID_LENGTH)
165                 return 0;
166
167         return (edid[0x7e] + 1) * EDID_LENGTH;
168 }
169
170 static void *edid_load(struct drm_connector *connector, const char *name)
171 {
172         const struct firmware *fw = NULL;
173         const u8 *fwdata;
174         u8 *edid;
175         int fwsize, builtin;
176         int i, valid_extensions = 0;
177         bool print_bad_edid = !connector->bad_edid_counter || drm_debug_enabled(DRM_UT_KMS);
178
179         builtin = match_string(generic_edid_name, GENERIC_EDIDS, name);
180         if (builtin >= 0) {
181                 fwdata = generic_edid[builtin];
182                 fwsize = sizeof(generic_edid[builtin]);
183         } else {
184                 struct platform_device *pdev;
185                 int err;
186
187                 pdev = platform_device_register_simple(connector->name, -1, NULL, 0);
188                 if (IS_ERR(pdev)) {
189                         DRM_ERROR("Failed to register EDID firmware platform device "
190                                   "for connector \"%s\"\n", connector->name);
191                         return ERR_CAST(pdev);
192                 }
193
194                 err = request_firmware(&fw, name, &pdev->dev);
195                 platform_device_unregister(pdev);
196                 if (err) {
197                         DRM_ERROR("Requesting EDID firmware \"%s\" failed (err=%d)\n",
198                                   name, err);
199                         return ERR_PTR(err);
200                 }
201
202                 fwdata = fw->data;
203                 fwsize = fw->size;
204         }
205
206         if (edid_size(fwdata, fwsize) != fwsize) {
207                 DRM_ERROR("Size of EDID firmware \"%s\" is invalid "
208                           "(expected %d, got %d\n", name,
209                           edid_size(fwdata, fwsize), (int)fwsize);
210                 edid = ERR_PTR(-EINVAL);
211                 goto out;
212         }
213
214         edid = kmemdup(fwdata, fwsize, GFP_KERNEL);
215         if (edid == NULL) {
216                 edid = ERR_PTR(-ENOMEM);
217                 goto out;
218         }
219
220         if (!drm_edid_block_valid(edid, 0, print_bad_edid,
221                                   &connector->edid_corrupt)) {
222                 connector->bad_edid_counter++;
223                 DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
224                     name);
225                 kfree(edid);
226                 edid = ERR_PTR(-EINVAL);
227                 goto out;
228         }
229
230         for (i = 1; i <= edid[0x7e]; i++) {
231                 if (i != valid_extensions + 1)
232                         memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
233                             edid + i * EDID_LENGTH, EDID_LENGTH);
234                 if (drm_edid_block_valid(edid + i * EDID_LENGTH, i,
235                                          print_bad_edid,
236                                          NULL))
237                         valid_extensions++;
238         }
239
240         if (valid_extensions != edid[0x7e]) {
241                 u8 *new_edid;
242
243                 edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
244                 DRM_INFO("Found %d valid extensions instead of %d in EDID data "
245                     "\"%s\" for connector \"%s\"\n", valid_extensions,
246                     edid[0x7e], name, connector->name);
247                 edid[0x7e] = valid_extensions;
248
249                 new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
250                                     GFP_KERNEL);
251                 if (new_edid)
252                         edid = new_edid;
253         }
254
255         DRM_INFO("Got %s EDID base block and %d extension%s from "
256             "\"%s\" for connector \"%s\"\n", (builtin >= 0) ? "built-in" :
257             "external", valid_extensions, valid_extensions == 1 ? "" : "s",
258             name, connector->name);
259
260 out:
261         release_firmware(fw);
262         return edid;
263 }
264
265 struct edid *drm_load_edid_firmware(struct drm_connector *connector)
266 {
267         char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
268         struct edid *edid;
269
270         if (edid_firmware[0] == '\0')
271                 return ERR_PTR(-ENOENT);
272
273         /*
274          * If there are multiple edid files specified and separated
275          * by commas, search through the list looking for one that
276          * matches the connector.
277          *
278          * If there's one or more that doesn't specify a connector, keep
279          * the last one found one as a fallback.
280          */
281         fwstr = kstrdup(edid_firmware, GFP_KERNEL);
282         if (!fwstr)
283                 return ERR_PTR(-ENOMEM);
284         edidstr = fwstr;
285
286         while ((edidname = strsep(&edidstr, ","))) {
287                 colon = strchr(edidname, ':');
288                 if (colon != NULL) {
289                         if (strncmp(connector->name, edidname, colon - edidname))
290                                 continue;
291                         edidname = colon + 1;
292                         break;
293                 }
294
295                 if (*edidname != '\0') /* corner case: multiple ',' */
296                         fallback = edidname;
297         }
298
299         if (!edidname) {
300                 if (!fallback) {
301                         kfree(fwstr);
302                         return ERR_PTR(-ENOENT);
303                 }
304                 edidname = fallback;
305         }
306
307         last = edidname + strlen(edidname) - 1;
308         if (*last == '\n')
309                 *last = '\0';
310
311         edid = edid_load(connector, edidname);
312         kfree(fwstr);
313
314         return edid;
315 }