aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_modes.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-09-15 08:17:27 -0400
committerDavid S. Miller <davem@davemloft.net>2019-09-15 08:17:27 -0400
commitaa2eaa8c272a3211dec07ce9c6c863a7e355c10e (patch)
tree8454a23d36b2ff36133c276ee0ba80eabc00850e /drivers/gpu/drm/drm_modes.c
parenta3d3c74da49c65fc63a937fa559186b0e16adca3 (diff)
parent1609d7604b847a9820e63393d1a3b6cac7286d40 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Minor overlapping changes in the btusb and ixgbe drivers. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r--drivers/gpu/drm/drm_modes.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index b0369e690f36..c814bcef18a4 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1454,6 +1454,7 @@ static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
1454} 1454}
1455 1455
1456static int drm_mode_parse_cmdline_extra(const char *str, int length, 1456static int drm_mode_parse_cmdline_extra(const char *str, int length,
1457 bool freestanding,
1457 const struct drm_connector *connector, 1458 const struct drm_connector *connector,
1458 struct drm_cmdline_mode *mode) 1459 struct drm_cmdline_mode *mode)
1459{ 1460{
@@ -1462,9 +1463,15 @@ static int drm_mode_parse_cmdline_extra(const char *str, int length,
1462 for (i = 0; i < length; i++) { 1463 for (i = 0; i < length; i++) {
1463 switch (str[i]) { 1464 switch (str[i]) {
1464 case 'i': 1465 case 'i':
1466 if (freestanding)
1467 return -EINVAL;
1468
1465 mode->interlace = true; 1469 mode->interlace = true;
1466 break; 1470 break;
1467 case 'm': 1471 case 'm':
1472 if (freestanding)
1473 return -EINVAL;
1474
1468 mode->margins = true; 1475 mode->margins = true;
1469 break; 1476 break;
1470 case 'D': 1477 case 'D':
@@ -1542,6 +1549,7 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
1542 if (extras) { 1549 if (extras) {
1543 int ret = drm_mode_parse_cmdline_extra(end_ptr + i, 1550 int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
1544 1, 1551 1,
1552 false,
1545 connector, 1553 connector,
1546 mode); 1554 mode);
1547 if (ret) 1555 if (ret)
@@ -1669,6 +1677,22 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
1669 return 0; 1677 return 0;
1670} 1678}
1671 1679
1680static const char * const drm_named_modes_whitelist[] = {
1681 "NTSC",
1682 "PAL",
1683};
1684
1685static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
1686{
1687 int i;
1688
1689 for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
1690 if (!strncmp(mode, drm_named_modes_whitelist[i], size))
1691 return true;
1692
1693 return false;
1694}
1695
1672/** 1696/**
1673 * drm_mode_parse_command_line_for_connector - parse command line modeline for connector 1697 * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
1674 * @mode_option: optional per connector mode option 1698 * @mode_option: optional per connector mode option
@@ -1725,16 +1749,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
1725 * bunch of things: 1749 * bunch of things:
1726 * - We need to make sure that the first character (which 1750 * - We need to make sure that the first character (which
1727 * would be our resolution in X) is a digit. 1751 * would be our resolution in X) is a digit.
1728 * - However, if the X resolution is missing, then we end up 1752 * - If not, then it's either a named mode or a force on/off.
1729 * with something like x<yres>, with our first character 1753 * To distinguish between the two, we need to run the
1730 * being an alpha-numerical character, which would be 1754 * extra parsing function, and if not, then we consider it
1731 * considered a named mode. 1755 * a named mode.
1732 * 1756 *
1733 * If this isn't enough, we should add more heuristics here, 1757 * If this isn't enough, we should add more heuristics here,
1734 * and matching unit-tests. 1758 * and matching unit-tests.
1735 */ 1759 */
1736 if (!isdigit(name[0]) && name[0] != 'x') 1760 if (!isdigit(name[0]) && name[0] != 'x') {
1761 unsigned int namelen = strlen(name);
1762
1763 /*
1764 * Only the force on/off options can be in that case,
1765 * and they all take a single character.
1766 */
1767 if (namelen == 1) {
1768 ret = drm_mode_parse_cmdline_extra(name, namelen, true,
1769 connector, mode);
1770 if (!ret)
1771 return true;
1772 }
1773
1737 named_mode = true; 1774 named_mode = true;
1775 }
1738 1776
1739 /* Try to locate the bpp and refresh specifiers, if any */ 1777 /* Try to locate the bpp and refresh specifiers, if any */
1740 bpp_ptr = strchr(name, '-'); 1778 bpp_ptr = strchr(name, '-');
@@ -1772,6 +1810,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
1772 if (named_mode) { 1810 if (named_mode) {
1773 if (mode_end + 1 > DRM_DISPLAY_MODE_LEN) 1811 if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
1774 return false; 1812 return false;
1813
1814 if (!drm_named_mode_is_in_whitelist(name, mode_end))
1815 return false;
1816
1775 strscpy(mode->name, name, mode_end + 1); 1817 strscpy(mode->name, name, mode_end + 1);
1776 } else { 1818 } else {
1777 ret = drm_mode_parse_cmdline_res_mode(name, mode_end, 1819 ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
@@ -1811,7 +1853,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
1811 extra_ptr != options_ptr) { 1853 extra_ptr != options_ptr) {
1812 int len = strlen(name) - (extra_ptr - name); 1854 int len = strlen(name) - (extra_ptr - name);
1813 1855
1814 ret = drm_mode_parse_cmdline_extra(extra_ptr, len, 1856 ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
1815 connector, mode); 1857 connector, mode);
1816 if (ret) 1858 if (ret)
1817 return false; 1859 return false;