Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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 *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->bad_edid_counter++;
221                 DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
222                     name);
223                 kfree(edid);
224                 edid = ERR_PTR(-EINVAL);
225                 goto out;
226         }
227
228         for (i = 1; i <= edid[0x7e]; i++) {
229                 if (i != valid_extensions + 1)
230                         memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
231                             edid + i * EDID_LENGTH, EDID_LENGTH);
232                 if (drm_edid_block_valid(edid + i * EDID_LENGTH, i, print_bad_edid))
233                         valid_extensions++;
234         }
235
236         if (valid_extensions != edid[0x7e]) {
237                 u8 *new_edid;
238
239                 edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
240                 DRM_INFO("Found %d valid extensions instead of %d in EDID data "
241                     "\"%s\" for connector \"%s\"\n", valid_extensions,
242                     edid[0x7e], name, connector_name);
243                 edid[0x7e] = valid_extensions;
244
245                 new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
246                                     GFP_KERNEL);
247                 if (new_edid)
248                         edid = new_edid;
249         }
250
251         DRM_INFO("Got %s EDID base block and %d extension%s from "
252             "\"%s\" for connector \"%s\"\n", builtin ? "built-in" :
253             "external", valid_extensions, valid_extensions == 1 ? "" : "s",
254             name, connector_name);
255
256 out:
257         release_firmware(fw);
258         return edid;
259 }
260
261 int drm_load_edid_firmware(struct drm_connector *connector)
262 {
263         const char *connector_name = connector->name;
264         char *edidname = edid_firmware, *last, *colon;
265         int ret;
266         struct edid *edid;
267
268         if (*edidname == '\0')
269                 return 0;
270
271         colon = strchr(edidname, ':');
272         if (colon != NULL) {
273                 if (strncmp(connector_name, edidname, colon - edidname))
274                         return 0;
275                 edidname = colon + 1;
276                 if (*edidname == '\0')
277                         return 0;
278         }
279
280         last = edidname + strlen(edidname) - 1;
281         if (*last == '\n')
282                 *last = '\0';
283
284         edid = edid_load(connector, edidname, connector_name);
285         if (IS_ERR_OR_NULL(edid))
286                 return 0;
287
288         drm_mode_connector_update_edid_property(connector, edid);
289         ret = drm_add_edid_modes(connector, edid);
290         drm_edid_to_eld(connector, edid);
291         kfree(edid);
292
293         return ret;
294 }