Message ID | 1402484106-397-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
When getting this patch for -collector I noticed it conflicts with mgag200 and break its compilation. On Wed, Jun 11, 2014 at 3:55 AM, Chris Wilson <chris@chris-wilson.co.uk> wrote: > i915.ko has a custom fbdev initialisation routine that aims to preserve > the current mode set by the BIOS, unless overruled by the user. The > user's wishes are determined by what, if any, mode is specified on the > command line (via the video= parameter). However, that command line mode > is first parsed by drm_fb_helper_initial_config() which is called after > i915.ko's custom initial_config() as a fallback method. So in order for > us to honour it, we need to move the cmdline parser earlier. If we > perform the connector cmdline parsing as soon as we initialise the > connector, that cmdline mode and forced status is then available even if > the fbdev helper is not compiled in or never called. > > We also then expose the cmdline user mode in the connector mode lists. > > v2: Rebase after connector->name upheaval. > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73154 > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> > Cc: Jesse Barnes <jbarnes@virtuousgeek.org> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch> > Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> > Cc: dri-devel@lists.freedesktop.org > --- > drivers/gpu/drm/drm_crtc.c | 55 ++++++++++++++++++++++++++++++++ > drivers/gpu/drm/drm_fb_helper.c | 64 > ++------------------------------------ > drivers/gpu/drm/drm_modes.c | 1 + > drivers/gpu/drm/drm_probe_helper.c | 17 ++++++++++ > include/drm/drm_crtc.h | 1 + > include/drm/drm_fb_helper.h | 1 - > 6 files changed, 77 insertions(+), 62 deletions(-) > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index fe94cc10cd35..b9de156515b6 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -819,6 +819,59 @@ static void drm_mode_remove(struct drm_connector > *connector, > } > > /** > + * drm_connector_get_cmdline_mode - reads the user's cmdline mode > + * @connector: connector to quwery > + * @mode: returned mode > + * > + * The kernel supports per-connector configration of its consoles through > + * use of the video= parameter. This function parses that option and > + * extracts the user's specified mode (or enable/disable status) for a > + * particular connector. This is typically only used during the early > fbdev > + * setup. > + */ > +static void drm_connector_get_cmdline_mode(struct drm_connector > *connector) > +{ > + struct drm_cmdline_mode *mode = &connector->cmdline_mode; > + char *option = NULL; > + > + if (fb_get_options(connector->name, &option)) > + return; > + > + if (!drm_mode_parse_command_line_for_connector(option, > + connector, > + mode)) > + return; > + > + if (mode->force) { > + const char *s; > + > + switch (mode->force) { > + case DRM_FORCE_OFF: > + s = "OFF"; > + break; > + case DRM_FORCE_ON_DIGITAL: > + s = "ON - dig"; > + break; > + default: > + case DRM_FORCE_ON: > + s = "ON"; > + break; > + } > + > + DRM_INFO("forcing %s connector %s\n", connector->name, s); > + connector->force = mode->force; > + } > + > + DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", > + connector->name, > + mode->xres, mode->yres, > + mode->refresh_specified ? mode->refresh : 60, > + mode->rb ? " reduced blanking" : "", > + mode->margins ? " with margins" : "", > + mode->interlace ? " interlaced" : ""); > +} > + > +/** > * drm_connector_init - Init a preallocated connector > * @dev: DRM device > * @connector: the connector to init > @@ -870,6 +923,8 @@ int drm_connector_init(struct drm_device *dev, > connector->edid_blob_ptr = NULL; > connector->status = connector_status_unknown; > > + drm_connector_get_cmdline_mode(connector); > + > list_add_tail(&connector->head, &dev->mode_config.connector_list); > dev->mode_config.num_connector++; > > diff --git a/drivers/gpu/drm/drm_fb_helper.c > b/drivers/gpu/drm/drm_fb_helper.c > index d5d8cea1a679..18988dc3de91 100644 > --- a/drivers/gpu/drm/drm_fb_helper.c > +++ b/drivers/gpu/drm/drm_fb_helper.c > @@ -105,60 +105,6 @@ fail: > } > EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); > > -static int drm_fb_helper_parse_command_line(struct drm_fb_helper > *fb_helper) > -{ > - struct drm_fb_helper_connector *fb_helper_conn; > - int i; > - > - for (i = 0; i < fb_helper->connector_count; i++) { > - struct drm_cmdline_mode *mode; > - struct drm_connector *connector; > - char *option = NULL; > - > - fb_helper_conn = fb_helper->connector_info[i]; > - connector = fb_helper_conn->connector; > - mode = &fb_helper_conn->cmdline_mode; > - > - /* do something on return - turn off connector maybe */ > - if (fb_get_options(connector->name, &option)) > - continue; > - > - if (drm_mode_parse_command_line_for_connector(option, > - connector, > - mode)) { > - if (mode->force) { > - const char *s; > - switch (mode->force) { > - case DRM_FORCE_OFF: > - s = "OFF"; > - break; > - case DRM_FORCE_ON_DIGITAL: > - s = "ON - dig"; > - break; > - default: > - case DRM_FORCE_ON: > - s = "ON"; > - break; > - } > - > - DRM_INFO("forcing %s connector %s\n", > - connector->name, s); > - connector->force = mode->force; > - } > - > - DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@ > %dHz%s%s%s\n", > - connector->name, > - mode->xres, mode->yres, > - mode->refresh_specified ? > mode->refresh : 60, > - mode->rb ? " reduced blanking" : "", > - mode->margins ? " with margins" : "", > - mode->interlace ? " interlaced" : > ""); > - } > - > - } > - return 0; > -} > - > static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct > drm_fb_helper *helper) > { > uint16_t *r_base, *g_base, *b_base; > @@ -936,7 +882,7 @@ static int drm_fb_helper_single_fb_probe(struct > drm_fb_helper *fb_helper, > struct drm_fb_helper_connector *fb_helper_conn = > fb_helper->connector_info[i]; > struct drm_cmdline_mode *cmdline_mode; > > - cmdline_mode = &fb_helper_conn->cmdline_mode; > + cmdline_mode = &fb_helper_conn->connector->cmdline_mode; > > if (cmdline_mode->bpp_specified) { > switch (cmdline_mode->bpp) { > @@ -1184,9 +1130,7 @@ EXPORT_SYMBOL(drm_has_preferred_mode); > > static bool drm_has_cmdline_mode(struct drm_fb_helper_connector > *fb_connector) > { > - struct drm_cmdline_mode *cmdline_mode; > - cmdline_mode = &fb_connector->cmdline_mode; > - return cmdline_mode->specified; > + return fb_connector->connector->cmdline_mode.specified; > } > > struct drm_display_mode *drm_pick_cmdline_mode(struct > drm_fb_helper_connector *fb_helper_conn, > @@ -1196,7 +1140,7 @@ struct drm_display_mode > *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f > struct drm_display_mode *mode = NULL; > bool prefer_non_interlace; > > - cmdline_mode = &fb_helper_conn->cmdline_mode; > + cmdline_mode = &fb_helper_conn->connector->cmdline_mode; > if (cmdline_mode->specified == false) > return mode; > > @@ -1581,8 +1525,6 @@ bool drm_fb_helper_initial_config(struct > drm_fb_helper *fb_helper, int bpp_sel) > struct drm_device *dev = fb_helper->dev; > int count = 0; > > - drm_fb_helper_parse_command_line(fb_helper); > - > mutex_lock(&dev->mode_config.mutex); > count = drm_fb_helper_probe_connector_modes(fb_helper, > > dev->mode_config.max_width, > diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c > index bedf1894e17e..d1b7d2006529 100644 > --- a/drivers/gpu/drm/drm_modes.c > +++ b/drivers/gpu/drm/drm_modes.c > @@ -1259,6 +1259,7 @@ drm_mode_create_from_cmdline_mode(struct drm_device > *dev, > if (!mode) > return NULL; > > + mode->type |= DRM_MODE_TYPE_USERDEF; > drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); > return mode; > } > diff --git a/drivers/gpu/drm/drm_probe_helper.c > b/drivers/gpu/drm/drm_probe_helper.c > index d22676b89cbb..59f663879fd4 100644 > --- a/drivers/gpu/drm/drm_probe_helper.c > +++ b/drivers/gpu/drm/drm_probe_helper.c > @@ -82,6 +82,22 @@ static void drm_mode_validate_flag(struct drm_connector > *connector, > return; > } > > +static int drm_helper_probe_add_cmdline_mode(struct drm_connector > *connector) > +{ > + struct drm_display_mode *mode; > + > + if (!connector->cmdline_mode.specified) > + return 0; > + > + mode = drm_mode_create_from_cmdline_mode(connector->dev, > + &connector->cmdline_mode); > + if (mode == NULL) > + return 0; > + > + drm_mode_probed_add(connector, mode); > + return 1; > +} > + > static int drm_helper_probe_single_connector_modes_merge_bits(struct > drm_connector *connector, > uint32_t > maxX, uint32_t maxY, bool merge_type_bits) > { > @@ -134,6 +150,7 @@ static int > drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect > > if (count == 0 && connector->status == connector_status_connected) > count = drm_add_modes_noedid(connector, 1024, 768); > + count += drm_helper_probe_add_cmdline_mode(connector); > if (count == 0) > goto prune; > > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h > index 251b75e6bf7a..abaed07a4b3b 100644 > --- a/include/drm/drm_crtc.h > +++ b/include/drm/drm_crtc.h > @@ -532,6 +532,7 @@ struct drm_connector { > void *helper_private; > > /* forced on connector */ > + struct drm_cmdline_mode cmdline_mode; > enum drm_connector_force force; > uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; > struct drm_encoder *encoder; /* currently active encoder */ > diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h > index 7997246d4039..28ead2b6f59b 100644 > --- a/include/drm/drm_fb_helper.h > +++ b/include/drm/drm_fb_helper.h > @@ -77,7 +77,6 @@ struct drm_fb_helper_funcs { > > struct drm_fb_helper_connector { > struct drm_connector *connector; > - struct drm_cmdline_mode cmdline_mode; > }; > > struct drm_fb_helper { > -- > 2.0.0 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx >
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fe94cc10cd35..b9de156515b6 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -819,6 +819,59 @@ static void drm_mode_remove(struct drm_connector *connector, } /** + * drm_connector_get_cmdline_mode - reads the user's cmdline mode + * @connector: connector to quwery + * @mode: returned mode + * + * The kernel supports per-connector configration of its consoles through + * use of the video= parameter. This function parses that option and + * extracts the user's specified mode (or enable/disable status) for a + * particular connector. This is typically only used during the early fbdev + * setup. + */ +static void drm_connector_get_cmdline_mode(struct drm_connector *connector) +{ + struct drm_cmdline_mode *mode = &connector->cmdline_mode; + char *option = NULL; + + if (fb_get_options(connector->name, &option)) + return; + + if (!drm_mode_parse_command_line_for_connector(option, + connector, + mode)) + return; + + if (mode->force) { + const char *s; + + switch (mode->force) { + case DRM_FORCE_OFF: + s = "OFF"; + break; + case DRM_FORCE_ON_DIGITAL: + s = "ON - dig"; + break; + default: + case DRM_FORCE_ON: + s = "ON"; + break; + } + + DRM_INFO("forcing %s connector %s\n", connector->name, s); + connector->force = mode->force; + } + + DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", + connector->name, + mode->xres, mode->yres, + mode->refresh_specified ? mode->refresh : 60, + mode->rb ? " reduced blanking" : "", + mode->margins ? " with margins" : "", + mode->interlace ? " interlaced" : ""); +} + +/** * drm_connector_init - Init a preallocated connector * @dev: DRM device * @connector: the connector to init @@ -870,6 +923,8 @@ int drm_connector_init(struct drm_device *dev, connector->edid_blob_ptr = NULL; connector->status = connector_status_unknown; + drm_connector_get_cmdline_mode(connector); + list_add_tail(&connector->head, &dev->mode_config.connector_list); dev->mode_config.num_connector++; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d5d8cea1a679..18988dc3de91 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -105,60 +105,6 @@ fail: } EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); -static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) -{ - struct drm_fb_helper_connector *fb_helper_conn; - int i; - - for (i = 0; i < fb_helper->connector_count; i++) { - struct drm_cmdline_mode *mode; - struct drm_connector *connector; - char *option = NULL; - - fb_helper_conn = fb_helper->connector_info[i]; - connector = fb_helper_conn->connector; - mode = &fb_helper_conn->cmdline_mode; - - /* do something on return - turn off connector maybe */ - if (fb_get_options(connector->name, &option)) - continue; - - if (drm_mode_parse_command_line_for_connector(option, - connector, - mode)) { - if (mode->force) { - const char *s; - switch (mode->force) { - case DRM_FORCE_OFF: - s = "OFF"; - break; - case DRM_FORCE_ON_DIGITAL: - s = "ON - dig"; - break; - default: - case DRM_FORCE_ON: - s = "ON"; - break; - } - - DRM_INFO("forcing %s connector %s\n", - connector->name, s); - connector->force = mode->force; - } - - DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", - connector->name, - mode->xres, mode->yres, - mode->refresh_specified ? mode->refresh : 60, - mode->rb ? " reduced blanking" : "", - mode->margins ? " with margins" : "", - mode->interlace ? " interlaced" : ""); - } - - } - return 0; -} - static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) { uint16_t *r_base, *g_base, *b_base; @@ -936,7 +882,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; struct drm_cmdline_mode *cmdline_mode; - cmdline_mode = &fb_helper_conn->cmdline_mode; + cmdline_mode = &fb_helper_conn->connector->cmdline_mode; if (cmdline_mode->bpp_specified) { switch (cmdline_mode->bpp) { @@ -1184,9 +1130,7 @@ EXPORT_SYMBOL(drm_has_preferred_mode); static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) { - struct drm_cmdline_mode *cmdline_mode; - cmdline_mode = &fb_connector->cmdline_mode; - return cmdline_mode->specified; + return fb_connector->connector->cmdline_mode.specified; } struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, @@ -1196,7 +1140,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f struct drm_display_mode *mode = NULL; bool prefer_non_interlace; - cmdline_mode = &fb_helper_conn->cmdline_mode; + cmdline_mode = &fb_helper_conn->connector->cmdline_mode; if (cmdline_mode->specified == false) return mode; @@ -1581,8 +1525,6 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) struct drm_device *dev = fb_helper->dev; int count = 0; - drm_fb_helper_parse_command_line(fb_helper); - mutex_lock(&dev->mode_config.mutex); count = drm_fb_helper_probe_connector_modes(fb_helper, dev->mode_config.max_width, diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index bedf1894e17e..d1b7d2006529 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1259,6 +1259,7 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev, if (!mode) return NULL; + mode->type |= DRM_MODE_TYPE_USERDEF; drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); return mode; } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index d22676b89cbb..59f663879fd4 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -82,6 +82,22 @@ static void drm_mode_validate_flag(struct drm_connector *connector, return; } +static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector) +{ + struct drm_display_mode *mode; + + if (!connector->cmdline_mode.specified) + return 0; + + mode = drm_mode_create_from_cmdline_mode(connector->dev, + &connector->cmdline_mode); + if (mode == NULL) + return 0; + + drm_mode_probed_add(connector, mode); + return 1; +} + static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, uint32_t maxX, uint32_t maxY, bool merge_type_bits) { @@ -134,6 +150,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect if (count == 0 && connector->status == connector_status_connected) count = drm_add_modes_noedid(connector, 1024, 768); + count += drm_helper_probe_add_cmdline_mode(connector); if (count == 0) goto prune; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 251b75e6bf7a..abaed07a4b3b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -532,6 +532,7 @@ struct drm_connector { void *helper_private; /* forced on connector */ + struct drm_cmdline_mode cmdline_mode; enum drm_connector_force force; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; struct drm_encoder *encoder; /* currently active encoder */ diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 7997246d4039..28ead2b6f59b 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -77,7 +77,6 @@ struct drm_fb_helper_funcs { struct drm_fb_helper_connector { struct drm_connector *connector; - struct drm_cmdline_mode cmdline_mode; }; struct drm_fb_helper {