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>
This commit is contained in:
Bob Paauwe 2015-08-27 10:04:13 -07:00 committed by Daniel Vetter
parent f8aeb41c4b
commit 96206e2922
2 changed files with 42 additions and 14 deletions

View File

@ -927,11 +927,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
The filter can be disabled or changed to another The filter can be disabled or changed to another
driver later using sysfs. driver later using sysfs.
drm_kms_helper.edid_firmware=[<connector>:]<file> drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
Broken monitors, graphic adapters and KVMs may Broken monitors, graphic adapters, KVMs and EDIDless
send no or incorrect EDID data sets. This parameter panels may send no or incorrect EDID data sets.
allows to specify an EDID data set in the This parameter allows to specify an EDID data sets
/lib/firmware directory that is used instead. in the /lib/firmware directory that are used instead.
Generic built-in EDID data sets are used, if one of Generic built-in EDID data sets are used, if one of
edid/1024x768.bin, edid/1280x1024.bin, edid/1024x768.bin, edid/1280x1024.bin,
edid/1680x1050.bin, or edid/1920x1080.bin is given edid/1680x1050.bin, or edid/1920x1080.bin is given
@ -940,7 +940,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
available in Documentation/EDID/HOWTO.txt. An EDID available in Documentation/EDID/HOWTO.txt. An EDID
data set will only be used for a particular connector, data set will only be used for a particular connector,
if its name and a colon are prepended to the EDID if its name and a colon are prepended to the EDID
name. name. Each connector may use a unique EDID data
set by separating the files with a comma. An EDID
data set with no connector name will be used for
any connectors not explicitly specified.
dscc4.setup= [NET] dscc4.setup= [NET]

View File

@ -264,20 +264,43 @@ static void *edid_load(struct drm_connector *connector, const char *name,
int drm_load_edid_firmware(struct drm_connector *connector) int drm_load_edid_firmware(struct drm_connector *connector)
{ {
const char *connector_name = connector->name; const char *connector_name = connector->name;
char *edidname = edid_firmware, *last, *colon; char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
int ret; int ret;
struct edid *edid; struct edid *edid;
if (*edidname == '\0') if (edid_firmware[0] == '\0')
return 0; return 0;
colon = strchr(edidname, ':'); /*
if (colon != NULL) { * If there are multiple edid files specified and separated
if (strncmp(connector_name, edidname, colon - edidname)) * by commas, search through the list looking for one that
return 0; * matches the connector.
edidname = colon + 1; *
if (*edidname == '\0') * If there's one or more that don't't specify a connector, keep
* the last one found one as a fallback.
*/
fwstr = kstrdup(edid_firmware, GFP_KERNEL);
edidstr = fwstr;
while ((edidname = strsep(&edidstr, ","))) {
colon = strchr(edidname, ':');
if (colon != NULL) {
if (strncmp(connector_name, edidname, colon - edidname))
continue;
edidname = colon + 1;
break;
}
if (*edidname != '\0') /* corner case: multiple ',' */
fallback = edidname;
}
if (!edidname) {
if (!fallback) {
kfree(fwstr);
return 0; return 0;
}
edidname = fallback;
} }
last = edidname + strlen(edidname) - 1; last = edidname + strlen(edidname) - 1;
@ -285,6 +308,8 @@ int drm_load_edid_firmware(struct drm_connector *connector)
*last = '\0'; *last = '\0';
edid = edid_load(connector, edidname, connector_name); edid = edid_load(connector, edidname, connector_name);
kfree(fwstr);
if (IS_ERR_OR_NULL(edid)) if (IS_ERR_OR_NULL(edid))
return 0; return 0;