aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-08-06 04:08:32 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-08-06 08:50:12 -0400
commiteaf99c749d43ae74ac7ffece5512f3c73f01dfd2 (patch)
treeb4e9e44920af793735b81481b50a1d54a6099ef9
parentea6763c104c93acb6554659fe4a3c9e9328a4b51 (diff)
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>
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/drm_crtc.c55
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c64
-rw-r--r--drivers/gpu/drm/drm_modes.c1
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c17
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c21
-rw-r--r--include/drm/drm_crtc.h1
-rw-r--r--include/drm/drm_fb_helper.h1
8 files changed, 83 insertions, 78 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 31894c8c1773..367f5dd23291 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -8,6 +8,7 @@ menuconfig DRM
8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" 8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
9 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA 9 depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
10 select HDMI 10 select HDMI
11 select FB_CMDLINE
11 select I2C 12 select I2C
12 select I2C_ALGOBIT 13 select I2C_ALGOBIT
13 select DMA_SHARED_BUFFER 14 select DMA_SHARED_BUFFER
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 33ff631c8d23..66d3bfb8d264 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -863,6 +863,59 @@ static void drm_mode_remove(struct drm_connector *connector,
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 */
876static 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 * drm_connector_init - Init a preallocated connector 919 * drm_connector_init - Init a preallocated connector
867 * @dev: DRM device 920 * @dev: DRM device
868 * @connector: the connector to init 921 * @connector: the connector to init
@@ -914,6 +967,8 @@ int drm_connector_init(struct drm_device *dev,
914 connector->edid_blob_ptr = NULL; 967 connector->edid_blob_ptr = NULL;
915 connector->status = connector_status_unknown; 968 connector->status = connector_status_unknown;
916 969
970 drm_connector_get_cmdline_mode(connector);
971
917 list_add_tail(&connector->head, &dev->mode_config.connector_list); 972 list_add_tail(&connector->head, &dev->mode_config.connector_list);
918 dev->mode_config.num_connector++; 973 dev->mode_config.num_connector++;
919 974
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3144db9dc0f1..3a6b6635e3f5 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -171,60 +171,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
171} 171}
172EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); 172EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
173 173
174static 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
228static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) 174static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
229{ 175{
230 uint16_t *r_base, *g_base, *b_base; 176 uint16_t *r_base, *g_base, *b_base;
@@ -1013,7 +959,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
1013 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; 959 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
1014 struct drm_cmdline_mode *cmdline_mode; 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 if (cmdline_mode->bpp_specified) { 964 if (cmdline_mode->bpp_specified) {
1019 switch (cmdline_mode->bpp) { 965 switch (cmdline_mode->bpp) {
@@ -1260,9 +1206,7 @@ EXPORT_SYMBOL(drm_has_preferred_mode);
1260 1206
1261static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) 1207static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1262{ 1208{
1263 struct drm_cmdline_mode *cmdline_mode; 1209 return fb_connector->connector->cmdline_mode.specified;
1264 cmdline_mode = &fb_connector->cmdline_mode;
1265 return cmdline_mode->specified;
1266} 1210}
1267 1211
1268struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, 1212struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
@@ -1272,7 +1216,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
1272 struct drm_display_mode *mode = NULL; 1216 struct drm_display_mode *mode = NULL;
1273 bool prefer_non_interlace; 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 if (cmdline_mode->specified == false) 1220 if (cmdline_mode->specified == false)
1277 return mode; 1221 return mode;
1278 1222
@@ -1657,8 +1601,6 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1657 struct drm_device *dev = fb_helper->dev; 1601 struct drm_device *dev = fb_helper->dev;
1658 int count = 0; 1602 int count = 0;
1659 1603
1660 drm_fb_helper_parse_command_line(fb_helper);
1661
1662 mutex_lock(&dev->mode_config.mutex); 1604 mutex_lock(&dev->mode_config.mutex);
1663 count = drm_fb_helper_probe_connector_modes(fb_helper, 1605 count = drm_fb_helper_probe_connector_modes(fb_helper,
1664 dev->mode_config.max_width, 1606 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,
1259 if (!mode) 1259 if (!mode)
1260 return NULL; 1260 return NULL;
1261 1261
1262 mode->type |= DRM_MODE_TYPE_USERDEF;
1262 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1263 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1263 return mode; 1264 return mode;
1264} 1265}
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index db7d250f7ac7..6857e9ad6339 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,
82 return; 82 return;
83} 83}
84 84
85static 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
85static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, 101static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
86 uint32_t maxX, uint32_t maxY, bool merge_type_bits) 102 uint32_t maxX, uint32_t maxY, bool merge_type_bits)
87{ 103{
@@ -141,6 +157,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
141 157
142 if (count == 0 && connector->status == connector_status_connected) 158 if (count == 0 && connector->status == connector_status_connected)
143 count = drm_add_modes_noedid(connector, 1024, 768); 159 count = drm_add_modes_noedid(connector, 1024, 768);
160 count += drm_helper_probe_add_cmdline_mode(connector);
144 if (count == 0) 161 if (count == 0)
145 goto prune; 162 goto prune;
146 163
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 45f04dea0ac2..83485ab81ce8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1483,11 +1483,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1483{ 1483{
1484 struct drm_device *dev = connector->dev; 1484 struct drm_device *dev = connector->dev;
1485 struct mga_device *mdev = (struct mga_device*)dev->dev_private; 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 int bpp = 32; 1486 int bpp = 32;
1490 int i = 0;
1491 1487
1492 if (IS_G200_SE(mdev)) { 1488 if (IS_G200_SE(mdev)) {
1493 if (mdev->unique_rev_id == 0x01) { 1489 if (mdev->unique_rev_id == 0x01) {
@@ -1537,21 +1533,14 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
1537 } 1533 }
1538 1534
1539 /* Validate the mode input by the user */ 1535 /* Validate the mode input by the user */
1540 for (i = 0; i < fb_helper->connector_count; i++) { 1536 if (connector->cmdline_mode.specified) {
1541 if (fb_helper->connector_info[i]->connector == connector) { 1537 if (connector->cmdline_mode.bpp_specified)
1542 /* Found the helper for this connector */ 1538 bpp = connector->cmdline_mode.bpp;
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 }
1550 } 1539 }
1551 1540
1552 if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) { 1541 if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
1553 if (fb_helper_conn) 1542 if (connector->cmdline_mode.specified)
1554 fb_helper_conn->cmdline_mode.specified = false; 1543 connector->cmdline_mode.specified = false;
1555 return MODE_BAD; 1544 return MODE_BAD;
1556 } 1545 }
1557 1546
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index f1105d0da059..c530b4920a09 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -548,6 +548,7 @@ struct drm_connector {
548 void *helper_private; 548 void *helper_private;
549 549
550 /* forced on connector */ 550 /* forced on connector */
551 struct drm_cmdline_mode cmdline_mode;
551 enum drm_connector_force force; 552 enum drm_connector_force force;
552 bool override_edid; 553 bool override_edid;
553 uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; 554 uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index bfd329d613c4..f4ad254e3488 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -77,7 +77,6 @@ struct drm_fb_helper_funcs {
77 77
78struct drm_fb_helper_connector { 78struct drm_fb_helper_connector {
79 struct drm_connector *connector; 79 struct drm_connector *connector;
80 struct drm_cmdline_mode cmdline_mode;
81}; 80};
82 81
83struct drm_fb_helper { 82struct drm_fb_helper {