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