Commit eaf99c749d43ae74ac7ffece5512f3c73f01dfd2

Authored by Chris Wilson
Committed by Daniel Vetter
1 parent ea6763c104

drm: Perform cmdline mode parsing during connector initialisation

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.

v3: Adapt mga200 to look for the cmdline mode in the new place. Nicely
simplifies things while at that.

v4: Fix checkpatch.

v5: Select FB_CMDLINE to adapt to the changed fbdev patch.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73154
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (v2)
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> (v2)
Cc: dri-devel@lists.freedesktop.org
Cc: Julia Lemire <jlemire@matrox.com>
Cc: Dave Airlie <airlied@redhat.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Showing 8 changed files with 83 additions and 78 deletions Side-by-side Diff

drivers/gpu/drm/Kconfig
... ... @@ -8,6 +8,7 @@
8 8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
9 9 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
10 10 select HDMI
  11 + select FB_CMDLINE
11 12 select I2C
12 13 select I2C_ALGOBIT
13 14 select DMA_SHARED_BUFFER
drivers/gpu/drm/drm_crtc.c
... ... @@ -863,6 +863,59 @@
863 863 }
864 864  
865 865 /**
  866 + * drm_connector_get_cmdline_mode - reads the user's cmdline mode
  867 + * @connector: connector to quwery
  868 + * @mode: returned mode
  869 + *
  870 + * The kernel supports per-connector configration of its consoles through
  871 + * use of the video= parameter. This function parses that option and
  872 + * extracts the user's specified mode (or enable/disable status) for a
  873 + * particular connector. This is typically only used during the early fbdev
  874 + * setup.
  875 + */
  876 +static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
  877 +{
  878 + struct drm_cmdline_mode *mode = &connector->cmdline_mode;
  879 + char *option = NULL;
  880 +
  881 + if (fb_get_options(connector->name, &option))
  882 + return;
  883 +
  884 + if (!drm_mode_parse_command_line_for_connector(option,
  885 + connector,
  886 + mode))
  887 + return;
  888 +
  889 + if (mode->force) {
  890 + const char *s;
  891 +
  892 + switch (mode->force) {
  893 + case DRM_FORCE_OFF:
  894 + s = "OFF";
  895 + break;
  896 + case DRM_FORCE_ON_DIGITAL:
  897 + s = "ON - dig";
  898 + break;
  899 + default:
  900 + case DRM_FORCE_ON:
  901 + s = "ON";
  902 + break;
  903 + }
  904 +
  905 + DRM_INFO("forcing %s connector %s\n", connector->name, s);
  906 + connector->force = mode->force;
  907 + }
  908 +
  909 + DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
  910 + connector->name,
  911 + mode->xres, mode->yres,
  912 + mode->refresh_specified ? mode->refresh : 60,
  913 + mode->rb ? " reduced blanking" : "",
  914 + mode->margins ? " with margins" : "",
  915 + mode->interlace ? " interlaced" : "");
  916 +}
  917 +
  918 +/**
866 919 * drm_connector_init - Init a preallocated connector
867 920 * @dev: DRM device
868 921 * @connector: the connector to init
... ... @@ -913,6 +966,8 @@
913 966 INIT_LIST_HEAD(&connector->modes);
914 967 connector->edid_blob_ptr = NULL;
915 968 connector->status = connector_status_unknown;
  969 +
  970 + drm_connector_get_cmdline_mode(connector);
916 971  
917 972 list_add_tail(&connector->head, &dev->mode_config.connector_list);
918 973 dev->mode_config.num_connector++;
drivers/gpu/drm/drm_fb_helper.c
... ... @@ -171,60 +171,6 @@
171 171 }
172 172 EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
173 173  
174   -static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
175   -{
176   - struct drm_fb_helper_connector *fb_helper_conn;
177   - int i;
178   -
179   - for (i = 0; i < fb_helper->connector_count; i++) {
180   - struct drm_cmdline_mode *mode;
181   - struct drm_connector *connector;
182   - char *option = NULL;
183   -
184   - fb_helper_conn = fb_helper->connector_info[i];
185   - connector = fb_helper_conn->connector;
186   - mode = &fb_helper_conn->cmdline_mode;
187   -
188   - /* do something on return - turn off connector maybe */
189   - if (fb_get_options(connector->name, &option))
190   - continue;
191   -
192   - if (drm_mode_parse_command_line_for_connector(option,
193   - connector,
194   - mode)) {
195   - if (mode->force) {
196   - const char *s;
197   - switch (mode->force) {
198   - case DRM_FORCE_OFF:
199   - s = "OFF";
200   - break;
201   - case DRM_FORCE_ON_DIGITAL:
202   - s = "ON - dig";
203   - break;
204   - default:
205   - case DRM_FORCE_ON:
206   - s = "ON";
207   - break;
208   - }
209   -
210   - DRM_INFO("forcing %s connector %s\n",
211   - connector->name, s);
212   - connector->force = mode->force;
213   - }
214   -
215   - DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
216   - connector->name,
217   - mode->xres, mode->yres,
218   - mode->refresh_specified ? mode->refresh : 60,
219   - mode->rb ? " reduced blanking" : "",
220   - mode->margins ? " with margins" : "",
221   - mode->interlace ? " interlaced" : "");
222   - }
223   -
224   - }
225   - return 0;
226   -}
227   -
228 174 static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
229 175 {
230 176 uint16_t *r_base, *g_base, *b_base;
... ... @@ -1013,7 +959,7 @@
1013 959 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
1014 960 struct drm_cmdline_mode *cmdline_mode;
1015 961  
1016   - cmdline_mode = &fb_helper_conn->cmdline_mode;
  962 + cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1017 963  
1018 964 if (cmdline_mode->bpp_specified) {
1019 965 switch (cmdline_mode->bpp) {
... ... @@ -1260,9 +1206,7 @@
1260 1206  
1261 1207 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1262 1208 {
1263   - struct drm_cmdline_mode *cmdline_mode;
1264   - cmdline_mode = &fb_connector->cmdline_mode;
1265   - return cmdline_mode->specified;
  1209 + return fb_connector->connector->cmdline_mode.specified;
1266 1210 }
1267 1211  
1268 1212 struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
... ... @@ -1272,7 +1216,7 @@
1272 1216 struct drm_display_mode *mode = NULL;
1273 1217 bool prefer_non_interlace;
1274 1218  
1275   - cmdline_mode = &fb_helper_conn->cmdline_mode;
  1219 + cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1276 1220 if (cmdline_mode->specified == false)
1277 1221 return mode;
1278 1222  
... ... @@ -1656,8 +1600,6 @@
1656 1600 {
1657 1601 struct drm_device *dev = fb_helper->dev;
1658 1602 int count = 0;
1659   -
1660   - drm_fb_helper_parse_command_line(fb_helper);
1661 1603  
1662 1604 mutex_lock(&dev->mode_config.mutex);
1663 1605 count = drm_fb_helper_probe_connector_modes(fb_helper,
drivers/gpu/drm/drm_modes.c
... ... @@ -1259,6 +1259,7 @@
1259 1259 if (!mode)
1260 1260 return NULL;
1261 1261  
  1262 + mode->type |= DRM_MODE_TYPE_USERDEF;
1262 1263 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1263 1264 return mode;
1264 1265 }
drivers/gpu/drm/drm_probe_helper.c
... ... @@ -82,6 +82,22 @@
82 82 return;
83 83 }
84 84  
  85 +static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
  86 +{
  87 + struct drm_display_mode *mode;
  88 +
  89 + if (!connector->cmdline_mode.specified)
  90 + return 0;
  91 +
  92 + mode = drm_mode_create_from_cmdline_mode(connector->dev,
  93 + &connector->cmdline_mode);
  94 + if (mode == NULL)
  95 + return 0;
  96 +
  97 + drm_mode_probed_add(connector, mode);
  98 + return 1;
  99 +}
  100 +
85 101 static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
86 102 uint32_t maxX, uint32_t maxY, bool merge_type_bits)
87 103 {
... ... @@ -141,6 +157,7 @@
141 157  
142 158 if (count == 0 && connector->status == connector_status_connected)
143 159 count = drm_add_modes_noedid(connector, 1024, 768);
  160 + count += drm_helper_probe_add_cmdline_mode(connector);
144 161 if (count == 0)
145 162 goto prune;
146 163  
drivers/gpu/drm/mgag200/mgag200_mode.c
... ... @@ -1483,11 +1483,7 @@
1483 1483 {
1484 1484 struct drm_device *dev = connector->dev;
1485 1485 struct mga_device *mdev = (struct mga_device*)dev->dev_private;
1486   - struct mga_fbdev *mfbdev = mdev->mfbdev;
1487   - struct drm_fb_helper *fb_helper = &mfbdev->helper;
1488   - struct drm_fb_helper_connector *fb_helper_conn = NULL;
1489 1486 int bpp = 32;
1490   - int i = 0;
1491 1487  
1492 1488 if (IS_G200_SE(mdev)) {
1493 1489 if (mdev->unique_rev_id == 0x01) {
1494 1490  
... ... @@ -1537,21 +1533,14 @@
1537 1533 }
1538 1534  
1539 1535 /* Validate the mode input by the user */
1540   - for (i = 0; i < fb_helper->connector_count; i++) {
1541   - if (fb_helper->connector_info[i]->connector == connector) {
1542   - /* Found the helper for this connector */
1543   - fb_helper_conn = fb_helper->connector_info[i];
1544   - if (fb_helper_conn->cmdline_mode.specified) {
1545   - if (fb_helper_conn->cmdline_mode.bpp_specified) {
1546   - bpp = fb_helper_conn->cmdline_mode.bpp;
1547   - }
1548   - }
1549   - }
  1536 + if (connector->cmdline_mode.specified) {
  1537 + if (connector->cmdline_mode.bpp_specified)
  1538 + bpp = connector->cmdline_mode.bpp;
1550 1539 }
1551 1540  
1552 1541 if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
1553   - if (fb_helper_conn)
1554   - fb_helper_conn->cmdline_mode.specified = false;
  1542 + if (connector->cmdline_mode.specified)
  1543 + connector->cmdline_mode.specified = false;
1555 1544 return MODE_BAD;
1556 1545 }
1557 1546  
include/drm/drm_crtc.h
... ... @@ -548,6 +548,7 @@
548 548 void *helper_private;
549 549  
550 550 /* forced on connector */
  551 + struct drm_cmdline_mode cmdline_mode;
551 552 enum drm_connector_force force;
552 553 bool override_edid;
553 554 uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
include/drm/drm_fb_helper.h
... ... @@ -77,7 +77,6 @@
77 77  
78 78 struct drm_fb_helper_connector {
79 79 struct drm_connector *connector;
80   - struct drm_cmdline_mode cmdline_mode;
81 80 };
82 81  
83 82 struct drm_fb_helper {