Commit 1e19ec6c authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2019-09-05' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes for v5.3 final:
- Make ingenic panel type DPI insteado f unknown.
- Fixes for command line parser modes.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/606d87b2-1840-c893-eb30-d6c471c9e50a@linux.intel.com
parents 7610bb0b 424c38a4
...@@ -1454,6 +1454,7 @@ static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr, ...@@ -1454,6 +1454,7 @@ static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
} }
static int drm_mode_parse_cmdline_extra(const char *str, int length, static int drm_mode_parse_cmdline_extra(const char *str, int length,
bool freestanding,
const struct drm_connector *connector, const struct drm_connector *connector,
struct drm_cmdline_mode *mode) struct drm_cmdline_mode *mode)
{ {
...@@ -1462,9 +1463,15 @@ static int drm_mode_parse_cmdline_extra(const char *str, int length, ...@@ -1462,9 +1463,15 @@ static int drm_mode_parse_cmdline_extra(const char *str, int length,
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
switch (str[i]) { switch (str[i]) {
case 'i': case 'i':
if (freestanding)
return -EINVAL;
mode->interlace = true; mode->interlace = true;
break; break;
case 'm': case 'm':
if (freestanding)
return -EINVAL;
mode->margins = true; mode->margins = true;
break; break;
case 'D': case 'D':
...@@ -1542,6 +1549,7 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length, ...@@ -1542,6 +1549,7 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
if (extras) { if (extras) {
int ret = drm_mode_parse_cmdline_extra(end_ptr + i, int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
1, 1,
false,
connector, connector,
mode); mode);
if (ret) if (ret)
...@@ -1669,6 +1677,22 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, ...@@ -1669,6 +1677,22 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
return 0; return 0;
} }
static const char *drm_named_modes_whitelist[] = {
"NTSC",
"PAL",
};
static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
{
int i;
for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
if (!strncmp(mode, drm_named_modes_whitelist[i], size))
return true;
return false;
}
/** /**
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
* @mode_option: optional per connector mode option * @mode_option: optional per connector mode option
...@@ -1725,16 +1749,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, ...@@ -1725,16 +1749,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
* bunch of things: * bunch of things:
* - We need to make sure that the first character (which * - We need to make sure that the first character (which
* would be our resolution in X) is a digit. * would be our resolution in X) is a digit.
* - However, if the X resolution is missing, then we end up * - If not, then it's either a named mode or a force on/off.
* with something like x<yres>, with our first character * To distinguish between the two, we need to run the
* being an alpha-numerical character, which would be * extra parsing function, and if not, then we consider it
* considered a named mode. * a named mode.
* *
* If this isn't enough, we should add more heuristics here, * If this isn't enough, we should add more heuristics here,
* and matching unit-tests. * and matching unit-tests.
*/ */
if (!isdigit(name[0]) && name[0] != 'x') if (!isdigit(name[0]) && name[0] != 'x') {
unsigned int namelen = strlen(name);
/*
* Only the force on/off options can be in that case,
* and they all take a single character.
*/
if (namelen == 1) {
ret = drm_mode_parse_cmdline_extra(name, namelen, true,
connector, mode);
if (!ret)
return true;
}
named_mode = true; named_mode = true;
}
/* Try to locate the bpp and refresh specifiers, if any */ /* Try to locate the bpp and refresh specifiers, if any */
bpp_ptr = strchr(name, '-'); bpp_ptr = strchr(name, '-');
...@@ -1772,6 +1810,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, ...@@ -1772,6 +1810,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
if (named_mode) { if (named_mode) {
if (mode_end + 1 > DRM_DISPLAY_MODE_LEN) if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
return false; return false;
if (!drm_named_mode_is_in_whitelist(name, mode_end))
return false;
strscpy(mode->name, name, mode_end + 1); strscpy(mode->name, name, mode_end + 1);
} else { } else {
ret = drm_mode_parse_cmdline_res_mode(name, mode_end, 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,7 +1853,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
extra_ptr != options_ptr) { extra_ptr != options_ptr) {
int len = strlen(name) - (extra_ptr - name); int len = strlen(name) - (extra_ptr - name);
ret = drm_mode_parse_cmdline_extra(extra_ptr, len, ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
connector, mode); connector, mode);
if (ret) if (ret)
return false; return false;
......
...@@ -656,10 +656,9 @@ static int ingenic_drm_probe(struct platform_device *pdev) ...@@ -656,10 +656,9 @@ static int ingenic_drm_probe(struct platform_device *pdev)
return ret; return ret;
} }
if (panel) { if (panel)
bridge = devm_drm_panel_bridge_add(dev, panel, bridge = devm_drm_panel_bridge_add(dev, panel,
DRM_MODE_CONNECTOR_Unknown); DRM_MODE_CONNECTOR_DPI);
}
priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc), priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc),
&priv->dma_hwdesc_phys, &priv->dma_hwdesc_phys,
......
...@@ -9,6 +9,13 @@ ...@@ -9,6 +9,13 @@
#define cmdline_test(test) selftest(test, test) #define cmdline_test(test) selftest(test, test)
cmdline_test(drm_cmdline_test_force_d_only)
cmdline_test(drm_cmdline_test_force_D_only_dvi)
cmdline_test(drm_cmdline_test_force_D_only_hdmi)
cmdline_test(drm_cmdline_test_force_D_only_not_digital)
cmdline_test(drm_cmdline_test_force_e_only)
cmdline_test(drm_cmdline_test_margin_only)
cmdline_test(drm_cmdline_test_interlace_only)
cmdline_test(drm_cmdline_test_res) cmdline_test(drm_cmdline_test_res)
cmdline_test(drm_cmdline_test_res_missing_x) cmdline_test(drm_cmdline_test_res_missing_x)
cmdline_test(drm_cmdline_test_res_missing_y) cmdline_test(drm_cmdline_test_res_missing_y)
......
...@@ -17,6 +17,136 @@ ...@@ -17,6 +17,136 @@
static const struct drm_connector no_connector = {}; static const struct drm_connector no_connector = {};
static int drm_cmdline_test_force_e_only(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(!drm_mode_parse_command_line_for_connector("e",
&no_connector,
&mode));
FAIL_ON(mode.specified);
FAIL_ON(mode.refresh_specified);
FAIL_ON(mode.bpp_specified);
FAIL_ON(mode.rb);
FAIL_ON(mode.cvt);
FAIL_ON(mode.interlace);
FAIL_ON(mode.margins);
FAIL_ON(mode.force != DRM_FORCE_ON);
return 0;
}
static int drm_cmdline_test_force_D_only_not_digital(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
&no_connector,
&mode));
FAIL_ON(mode.specified);
FAIL_ON(mode.refresh_specified);
FAIL_ON(mode.bpp_specified);
FAIL_ON(mode.rb);
FAIL_ON(mode.cvt);
FAIL_ON(mode.interlace);
FAIL_ON(mode.margins);
FAIL_ON(mode.force != DRM_FORCE_ON);
return 0;
}
static const struct drm_connector connector_hdmi = {
.connector_type = DRM_MODE_CONNECTOR_HDMIB,
};
static int drm_cmdline_test_force_D_only_hdmi(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
&connector_hdmi,
&mode));
FAIL_ON(mode.specified);
FAIL_ON(mode.refresh_specified);
FAIL_ON(mode.bpp_specified);
FAIL_ON(mode.rb);
FAIL_ON(mode.cvt);
FAIL_ON(mode.interlace);
FAIL_ON(mode.margins);
FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
return 0;
}
static const struct drm_connector connector_dvi = {
.connector_type = DRM_MODE_CONNECTOR_DVII,
};
static int drm_cmdline_test_force_D_only_dvi(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
&connector_dvi,
&mode));
FAIL_ON(mode.specified);
FAIL_ON(mode.refresh_specified);
FAIL_ON(mode.bpp_specified);
FAIL_ON(mode.rb);
FAIL_ON(mode.cvt);
FAIL_ON(mode.interlace);
FAIL_ON(mode.margins);
FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
return 0;
}
static int drm_cmdline_test_force_d_only(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(!drm_mode_parse_command_line_for_connector("d",
&no_connector,
&mode));
FAIL_ON(mode.specified);
FAIL_ON(mode.refresh_specified);
FAIL_ON(mode.bpp_specified);
FAIL_ON(mode.rb);
FAIL_ON(mode.cvt);
FAIL_ON(mode.interlace);
FAIL_ON(mode.margins);
FAIL_ON(mode.force != DRM_FORCE_OFF);
return 0;
}
static int drm_cmdline_test_margin_only(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(drm_mode_parse_command_line_for_connector("m",
&no_connector,
&mode));
return 0;
}
static int drm_cmdline_test_interlace_only(void *ignored)
{
struct drm_cmdline_mode mode = { };
FAIL_ON(drm_mode_parse_command_line_for_connector("i",
&no_connector,
&mode));
return 0;
}
static int drm_cmdline_test_res(void *ignored) static int drm_cmdline_test_res(void *ignored)
{ {
struct drm_cmdline_mode mode = { }; struct drm_cmdline_mode mode = { };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment