diff options
-rw-r--r-- | drivers/gpu/drm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 64 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_probe_helper.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_mode.c | 21 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 1 | ||||
-rw-r--r-- | include/drm/drm_fb_helper.h | 1 |
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 | */ | ||
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 | * 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 | } |
172 | EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); | 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 | static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) | 174 | static 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 | ||
1261 | static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) | 1207 | static 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 | ||
1268 | struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, | 1212 | struct 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 | ||
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 | static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, | 101 | static 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 | ||
78 | struct drm_fb_helper_connector { | 78 | struct 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 | ||
83 | struct drm_fb_helper { | 82 | struct drm_fb_helper { |