DRM: clean up and document parsing of video= parameter
The video= parameter of the DRM drivers supports some additional flags that the normal fb drivers do not have. They also allow to limit these flags to specific outputs. Both things were previously undocumented. Also the parsing of the line had some oddities: -A lot of misplaced options were silently ignored or partly rejected instead of stopping the parsing immediately -The 'R' option is documented to follow the 'M' option if specified. It is not documented that 'M' is needed to specify 'R' (also this is the case for normal fb drivers). In fact the code is correct for normal fb drivers but wrong for DRM ones. The old code allowed 'R' only _before_ 'M' (since it parses backwards) and only if 'M' is given at all which is not needed for the DRM drivers. -the margins option ('m') was parsed but later ignored even if the later functions support it. -specifying multiple enable options at the same time did not lead to an error. -specifying something bogus for horizontal resolution (i.e. other things as digits) did not lead to an error but an invalid resolution was used. If any errors are encountered the position of the faulting string is now printed to the user and the complete mode is ignored. This gives much more consistent error behaviour. I also removed some useless assignments and changed the local flag variables to be bool. Signed-off-by: Rolf Eike Beer <eike-kernel@sf-tec.de> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
ee2762916f
commit
04fee895ef
|
@ -20,7 +20,7 @@ in a video= option, fbmem considers that to be a global video mode option.
|
||||||
|
|
||||||
Valid mode specifiers (mode_option argument):
|
Valid mode specifiers (mode_option argument):
|
||||||
|
|
||||||
<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
|
<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
|
||||||
<name>[-<bpp>][@<refresh>]
|
<name>[-<bpp>][@<refresh>]
|
||||||
|
|
||||||
with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
|
with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
|
||||||
|
@ -36,6 +36,21 @@ pixels and 1.8% of yres).
|
||||||
|
|
||||||
Sample usage: 1024x768M@60m - CVT timing with margins
|
Sample usage: 1024x768M@60m - CVT timing with margins
|
||||||
|
|
||||||
|
DRM drivers also add options to enable or disable outputs:
|
||||||
|
|
||||||
|
'e' will force the display to be enabled, i.e. it will override the detection
|
||||||
|
if a display is connected. 'D' will force the display to be enabled and use
|
||||||
|
digital output. This is useful for outputs that have both analog and digital
|
||||||
|
signals (e.g. HDMI and DVI-I). For other outputs it behaves like 'e'. If 'd'
|
||||||
|
is specified the output is disabled.
|
||||||
|
|
||||||
|
You can additionally specify which output the options matches to.
|
||||||
|
To force the VGA output to be enabled and drive a specific mode say:
|
||||||
|
video=VGA-1:1280x1024@60me
|
||||||
|
|
||||||
|
Specifying the option multiple times for different ports is possible, e.g.:
|
||||||
|
video=LVDS-1:d video=HDMI-1:D
|
||||||
|
|
||||||
***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
|
***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
|
||||||
|
|
||||||
What is the VESA(TM) Coordinated Video Timings (CVT)?
|
What is the VESA(TM) Coordinated Video Timings (CVT)?
|
||||||
|
@ -132,5 +147,5 @@ There may be more modes.
|
||||||
tridentfb - Trident (Cyber)blade chipset frame buffer
|
tridentfb - Trident (Cyber)blade chipset frame buffer
|
||||||
vt8623fb - VIA 8623 frame buffer
|
vt8623fb - VIA 8623 frame buffer
|
||||||
|
|
||||||
BTW, only a few drivers use this at the moment. Others are to follow
|
BTW, only a few fb drivers use this at the moment. Others are to follow
|
||||||
(feel free to send patches).
|
(feel free to send patches). The DRM drivers also support this.
|
||||||
|
|
|
@ -994,9 +994,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int namelen;
|
unsigned int namelen;
|
||||||
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
|
bool res_specified = false, bpp_specified = false, refresh_specified = false;
|
||||||
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
|
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
|
||||||
int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
|
bool yres_specified = false, cvt = false, rb = false;
|
||||||
|
bool interlace = false, margins = false, was_digit = false;
|
||||||
int i;
|
int i;
|
||||||
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
|
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
|
||||||
|
|
||||||
|
@ -1015,54 +1016,65 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||||
for (i = namelen-1; i >= 0; i--) {
|
for (i = namelen-1; i >= 0; i--) {
|
||||||
switch (name[i]) {
|
switch (name[i]) {
|
||||||
case '@':
|
case '@':
|
||||||
namelen = i;
|
|
||||||
if (!refresh_specified && !bpp_specified &&
|
if (!refresh_specified && !bpp_specified &&
|
||||||
!yres_specified) {
|
!yres_specified && !cvt && !rb && was_digit) {
|
||||||
refresh = simple_strtol(&name[i+1], NULL, 10);
|
refresh = simple_strtol(&name[i+1], NULL, 10);
|
||||||
refresh_specified = 1;
|
refresh_specified = true;
|
||||||
if (cvt || rb)
|
was_digit = false;
|
||||||
cvt = 0;
|
|
||||||
} else
|
} else
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
namelen = i;
|
if (!bpp_specified && !yres_specified && !cvt &&
|
||||||
if (!bpp_specified && !yres_specified) {
|
!rb && was_digit) {
|
||||||
bpp = simple_strtol(&name[i+1], NULL, 10);
|
bpp = simple_strtol(&name[i+1], NULL, 10);
|
||||||
bpp_specified = 1;
|
bpp_specified = true;
|
||||||
if (cvt || rb)
|
was_digit = false;
|
||||||
cvt = 0;
|
|
||||||
} else
|
} else
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
if (!yres_specified) {
|
if (!yres_specified && was_digit) {
|
||||||
yres = simple_strtol(&name[i+1], NULL, 10);
|
yres = simple_strtol(&name[i+1], NULL, 10);
|
||||||
yres_specified = 1;
|
yres_specified = true;
|
||||||
|
was_digit = false;
|
||||||
} else
|
} else
|
||||||
goto done;
|
goto done;
|
||||||
case '0' ... '9':
|
case '0' ... '9':
|
||||||
|
was_digit = true;
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
if (!yres_specified)
|
if (yres_specified || cvt || was_digit)
|
||||||
cvt = 1;
|
goto done;
|
||||||
|
cvt = true;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
if (cvt)
|
if (yres_specified || cvt || rb || was_digit)
|
||||||
rb = 1;
|
goto done;
|
||||||
|
rb = true;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
if (!cvt)
|
if (cvt || yres_specified || was_digit)
|
||||||
margins = 1;
|
goto done;
|
||||||
|
margins = true;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
if (!cvt)
|
if (cvt || yres_specified || was_digit)
|
||||||
interlace = 1;
|
goto done;
|
||||||
|
interlace = true;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
if (yres_specified || bpp_specified || refresh_specified ||
|
||||||
|
was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||||
|
goto done;
|
||||||
|
|
||||||
force = DRM_FORCE_ON;
|
force = DRM_FORCE_ON;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
|
if (yres_specified || bpp_specified || refresh_specified ||
|
||||||
|
was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||||
|
goto done;
|
||||||
|
|
||||||
if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
|
if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
|
||||||
(connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
|
(connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
|
||||||
force = DRM_FORCE_ON;
|
force = DRM_FORCE_ON;
|
||||||
|
@ -1070,17 +1082,37 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||||
force = DRM_FORCE_ON_DIGITAL;
|
force = DRM_FORCE_ON_DIGITAL;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
|
if (yres_specified || bpp_specified || refresh_specified ||
|
||||||
|
was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||||
|
goto done;
|
||||||
|
|
||||||
force = DRM_FORCE_OFF;
|
force = DRM_FORCE_OFF;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < 0 && yres_specified) {
|
if (i < 0 && yres_specified) {
|
||||||
xres = simple_strtol(name, NULL, 10);
|
char *ch;
|
||||||
res_specified = 1;
|
xres = simple_strtol(name, &ch, 10);
|
||||||
|
if ((ch != NULL) && (*ch == 'x'))
|
||||||
|
res_specified = true;
|
||||||
|
else
|
||||||
|
i = ch - name;
|
||||||
|
} else if (!yres_specified && was_digit) {
|
||||||
|
/* catch mode that begins with digits but has no 'x' */
|
||||||
|
i = 0;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
if (i >= 0) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"parse error at position %i in video mode '%s'\n",
|
||||||
|
i, name);
|
||||||
|
mode->specified = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (res_specified) {
|
if (res_specified) {
|
||||||
mode->specified = true;
|
mode->specified = true;
|
||||||
mode->xres = xres;
|
mode->xres = xres;
|
||||||
|
@ -1096,9 +1128,10 @@ done:
|
||||||
mode->bpp_specified = true;
|
mode->bpp_specified = true;
|
||||||
mode->bpp = bpp;
|
mode->bpp = bpp;
|
||||||
}
|
}
|
||||||
mode->rb = rb ? true : false;
|
mode->rb = rb;
|
||||||
mode->cvt = cvt ? true : false;
|
mode->cvt = cvt;
|
||||||
mode->interlace = interlace ? true : false;
|
mode->interlace = interlace;
|
||||||
|
mode->margins = margins;
|
||||||
mode->force = force;
|
mode->force = force;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue