diff options
author | Bob Paauwe <bob.j.paauwe@intel.com> | 2015-08-27 13:04:13 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-09-08 07:45:51 -0400 |
commit | 96206e2922c114b13cadefa03b9f340b58fee13c (patch) | |
tree | 7c3853455297f4511fa7aba5337f229fbf84f1ef | |
parent | f8aeb41c4b7e9de0a4df4ed1ba78cd6ee5c87281 (diff) |
dtrm/edid: Allow comma separated edid binaries. (v3)
Allow comma separated filenames in the edid_firmware parameter.
For example:
edid_firmware=eDP-1:edid/1280x480.bin,DP-2:edid/1920x1080.bin
v2: Use strsep() to simplify parsing of comma seperated string. (Matt)
Move initial bail before strdup. (Matt)
v3: Changed conditionals after while loop to make more readable (Jani)
Updated kernel-parameters.txt to reflect changes (Jani)
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
[danvet: Flatten else control flow and appease checkpatch.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | Documentation/kernel-parameters.txt | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_edid_load.c | 41 |
2 files changed, 42 insertions, 14 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1d6f0459cd7b..caf0fd4cdecd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -927,11 +927,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
927 | The filter can be disabled or changed to another | 927 | The filter can be disabled or changed to another |
928 | driver later using sysfs. | 928 | driver later using sysfs. |
929 | 929 | ||
930 | drm_kms_helper.edid_firmware=[<connector>:]<file> | 930 | drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>] |
931 | Broken monitors, graphic adapters and KVMs may | 931 | Broken monitors, graphic adapters, KVMs and EDIDless |
932 | send no or incorrect EDID data sets. This parameter | 932 | panels may send no or incorrect EDID data sets. |
933 | allows to specify an EDID data set in the | 933 | This parameter allows to specify an EDID data sets |
934 | /lib/firmware directory that is used instead. | 934 | in the /lib/firmware directory that are used instead. |
935 | Generic built-in EDID data sets are used, if one of | 935 | Generic built-in EDID data sets are used, if one of |
936 | edid/1024x768.bin, edid/1280x1024.bin, | 936 | edid/1024x768.bin, edid/1280x1024.bin, |
937 | edid/1680x1050.bin, or edid/1920x1080.bin is given | 937 | edid/1680x1050.bin, or edid/1920x1080.bin is given |
@@ -940,7 +940,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
940 | available in Documentation/EDID/HOWTO.txt. An EDID | 940 | available in Documentation/EDID/HOWTO.txt. An EDID |
941 | data set will only be used for a particular connector, | 941 | data set will only be used for a particular connector, |
942 | if its name and a colon are prepended to the EDID | 942 | if its name and a colon are prepended to the EDID |
943 | name. | 943 | name. Each connector may use a unique EDID data |
944 | set by separating the files with a comma. An EDID | ||
945 | data set with no connector name will be used for | ||
946 | any connectors not explicitly specified. | ||
944 | 947 | ||
945 | dscc4.setup= [NET] | 948 | dscc4.setup= [NET] |
946 | 949 | ||
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index c5605fe4907e..1f445e9bd768 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c | |||
@@ -264,20 +264,43 @@ out: | |||
264 | int drm_load_edid_firmware(struct drm_connector *connector) | 264 | int drm_load_edid_firmware(struct drm_connector *connector) |
265 | { | 265 | { |
266 | const char *connector_name = connector->name; | 266 | const char *connector_name = connector->name; |
267 | char *edidname = edid_firmware, *last, *colon; | 267 | char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL; |
268 | int ret; | 268 | int ret; |
269 | struct edid *edid; | 269 | struct edid *edid; |
270 | 270 | ||
271 | if (*edidname == '\0') | 271 | if (edid_firmware[0] == '\0') |
272 | return 0; | 272 | return 0; |
273 | 273 | ||
274 | colon = strchr(edidname, ':'); | 274 | /* |
275 | if (colon != NULL) { | 275 | * If there are multiple edid files specified and separated |
276 | if (strncmp(connector_name, edidname, colon - edidname)) | 276 | * by commas, search through the list looking for one that |
277 | return 0; | 277 | * matches the connector. |
278 | edidname = colon + 1; | 278 | * |
279 | if (*edidname == '\0') | 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); | ||
280 | return 0; | 301 | return 0; |
302 | } | ||
303 | edidname = fallback; | ||
281 | } | 304 | } |
282 | 305 | ||
283 | last = edidname + strlen(edidname) - 1; | 306 | last = edidname + strlen(edidname) - 1; |
@@ -285,6 +308,8 @@ int drm_load_edid_firmware(struct drm_connector *connector) | |||
285 | *last = '\0'; | 308 | *last = '\0'; |
286 | 309 | ||
287 | edid = edid_load(connector, edidname, connector_name); | 310 | edid = edid_load(connector, edidname, connector_name); |
311 | kfree(fwstr); | ||
312 | |||
288 | if (IS_ERR_OR_NULL(edid)) | 313 | if (IS_ERR_OR_NULL(edid)) |
289 | return 0; | 314 | return 0; |
290 | 315 | ||