diff options
| -rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 79 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 224 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_modes.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_fb.c | 26 | ||||
| -rw-r--r-- | include/drm/drm_crtc.h | 14 | ||||
| -rw-r--r-- | include/drm/drm_fb_helper.h | 24 |
10 files changed, 386 insertions, 21 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index ba728ad77f2a..8e7b0ebece0c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -482,6 +482,7 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
| 482 | list_for_each_entry_safe(mode, t, &connector->user_modes, head) | 482 | list_for_each_entry_safe(mode, t, &connector->user_modes, head) |
| 483 | drm_mode_remove(connector, mode); | 483 | drm_mode_remove(connector, mode); |
| 484 | 484 | ||
| 485 | kfree(connector->fb_helper_private); | ||
| 485 | mutex_lock(&dev->mode_config.mutex); | 486 | mutex_lock(&dev->mode_config.mutex); |
| 486 | drm_mode_object_put(dev, &connector->base); | 487 | drm_mode_object_put(dev, &connector->base); |
| 487 | list_del(&connector->head); | 488 | list_del(&connector->head); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index fe8697447f32..82fd6e82450f 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "drmP.h" | 32 | #include "drmP.h" |
| 33 | #include "drm_crtc.h" | 33 | #include "drm_crtc.h" |
| 34 | #include "drm_crtc_helper.h" | 34 | #include "drm_crtc_helper.h" |
| 35 | #include "drm_fb_helper.h" | ||
| 35 | 36 | ||
| 36 | static void drm_mode_validate_flag(struct drm_connector *connector, | 37 | static void drm_mode_validate_flag(struct drm_connector *connector, |
| 37 | int flags) | 38 | int flags) |
| @@ -90,7 +91,15 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
| 90 | list_for_each_entry_safe(mode, t, &connector->modes, head) | 91 | list_for_each_entry_safe(mode, t, &connector->modes, head) |
| 91 | mode->status = MODE_UNVERIFIED; | 92 | mode->status = MODE_UNVERIFIED; |
| 92 | 93 | ||
| 93 | connector->status = connector->funcs->detect(connector); | 94 | if (connector->force) { |
| 95 | if (connector->force == DRM_FORCE_ON) | ||
| 96 | connector->status = connector_status_connected; | ||
| 97 | else | ||
| 98 | connector->status = connector_status_disconnected; | ||
| 99 | if (connector->funcs->force) | ||
| 100 | connector->funcs->force(connector); | ||
| 101 | } else | ||
| 102 | connector->status = connector->funcs->detect(connector); | ||
| 94 | 103 | ||
| 95 | if (connector->status == connector_status_disconnected) { | 104 | if (connector->status == connector_status_disconnected) { |
| 96 | DRM_DEBUG_KMS("%s is disconnected\n", | 105 | DRM_DEBUG_KMS("%s is disconnected\n", |
| @@ -267,6 +276,56 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con | |||
| 267 | return NULL; | 276 | return NULL; |
| 268 | } | 277 | } |
| 269 | 278 | ||
| 279 | static bool drm_has_cmdline_mode(struct drm_connector *connector) | ||
| 280 | { | ||
| 281 | struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; | ||
| 282 | struct drm_fb_helper_cmdline_mode *cmdline_mode = &fb_help_conn->cmdline_mode; | ||
| 283 | return cmdline_mode->specified; | ||
| 284 | } | ||
| 285 | |||
| 286 | static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height) | ||
| 287 | { | ||
| 288 | struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; | ||
| 289 | struct drm_fb_helper_cmdline_mode *cmdline_mode = &fb_help_conn->cmdline_mode; | ||
| 290 | struct drm_display_mode *mode = NULL; | ||
| 291 | |||
| 292 | if (cmdline_mode->specified == false) | ||
| 293 | return mode; | ||
| 294 | |||
| 295 | /* attempt to find a matching mode in the list of modes | ||
| 296 | * we have gotten so far, if not add a CVT mode that conforms | ||
| 297 | */ | ||
| 298 | if (cmdline_mode->rb || cmdline_mode->margins) | ||
| 299 | goto create_mode; | ||
| 300 | |||
| 301 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 302 | /* check width/height */ | ||
| 303 | if (mode->hdisplay != cmdline_mode->xres || | ||
| 304 | mode->vdisplay != cmdline_mode->yres) | ||
| 305 | continue; | ||
| 306 | |||
| 307 | if (cmdline_mode->refresh_specified) { | ||
| 308 | if (mode->vrefresh != cmdline_mode->refresh) | ||
| 309 | continue; | ||
| 310 | } | ||
| 311 | |||
| 312 | if (cmdline_mode->interlace) { | ||
| 313 | if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) | ||
| 314 | continue; | ||
| 315 | } | ||
| 316 | return mode; | ||
| 317 | } | ||
| 318 | |||
| 319 | create_mode: | ||
| 320 | mode = drm_cvt_mode(connector->dev, cmdline_mode->xres, | ||
| 321 | cmdline_mode->yres, | ||
| 322 | cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, | ||
| 323 | cmdline_mode->rb, cmdline_mode->interlace, | ||
| 324 | cmdline_mode->margins); | ||
| 325 | list_add(&mode->head, &connector->modes); | ||
| 326 | return mode; | ||
| 327 | } | ||
| 328 | |||
| 270 | static bool drm_connector_enabled(struct drm_connector *connector, bool strict) | 329 | static bool drm_connector_enabled(struct drm_connector *connector, bool strict) |
| 271 | { | 330 | { |
| 272 | bool enable; | 331 | bool enable; |
| @@ -317,10 +376,16 @@ static bool drm_target_preferred(struct drm_device *dev, | |||
| 317 | continue; | 376 | continue; |
| 318 | } | 377 | } |
| 319 | 378 | ||
| 320 | DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", | 379 | DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", |
| 321 | connector->base.id); | 380 | connector->base.id); |
| 322 | 381 | ||
| 323 | modes[i] = drm_has_preferred_mode(connector, width, height); | 382 | /* got for command line mode first */ |
| 383 | modes[i] = drm_pick_cmdline_mode(connector, width, height); | ||
| 384 | if (!modes[i]) { | ||
| 385 | DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", | ||
| 386 | connector->base.id); | ||
| 387 | modes[i] = drm_has_preferred_mode(connector, width, height); | ||
| 388 | } | ||
| 324 | /* No preferred modes, pick one off the list */ | 389 | /* No preferred modes, pick one off the list */ |
| 325 | if (!modes[i] && !list_empty(&connector->modes)) { | 390 | if (!modes[i] && !list_empty(&connector->modes)) { |
| 326 | list_for_each_entry(modes[i], &connector->modes, head) | 391 | list_for_each_entry(modes[i], &connector->modes, head) |
| @@ -369,6 +434,8 @@ static int drm_pick_crtcs(struct drm_device *dev, | |||
| 369 | my_score = 1; | 434 | my_score = 1; |
| 370 | if (connector->status == connector_status_connected) | 435 | if (connector->status == connector_status_connected) |
| 371 | my_score++; | 436 | my_score++; |
| 437 | if (drm_has_cmdline_mode(connector)) | ||
| 438 | my_score++; | ||
| 372 | if (drm_has_preferred_mode(connector, width, height)) | 439 | if (drm_has_preferred_mode(connector, width, height)) |
| 373 | my_score++; | 440 | my_score++; |
| 374 | 441 | ||
| @@ -943,6 +1010,8 @@ bool drm_helper_initial_config(struct drm_device *dev) | |||
| 943 | { | 1010 | { |
| 944 | int count = 0; | 1011 | int count = 0; |
| 945 | 1012 | ||
| 1013 | drm_fb_helper_parse_command_line(dev); | ||
| 1014 | |||
| 946 | count = drm_helper_probe_connector_modes(dev, | 1015 | count = drm_helper_probe_connector_modes(dev, |
| 947 | dev->mode_config.max_width, | 1016 | dev->mode_config.max_width, |
| 948 | dev->mode_config.max_height); | 1017 | dev->mode_config.max_height); |
| @@ -950,7 +1019,7 @@ bool drm_helper_initial_config(struct drm_device *dev) | |||
| 950 | /* | 1019 | /* |
| 951 | * we shouldn't end up with no modes here. | 1020 | * we shouldn't end up with no modes here. |
| 952 | */ | 1021 | */ |
| 953 | WARN(!count, "Connected connector with 0 modes\n"); | 1022 | WARN(!count, "No connectors reported connected with modes\n"); |
| 954 | 1023 | ||
| 955 | drm_setup_crtcs(dev); | 1024 | drm_setup_crtcs(dev); |
| 956 | 1025 | ||
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9888c2076b2e..3c0d2b3aed76 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -560,7 +560,8 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, | |||
| 560 | vsize = (hsize * 9) / 16; | 560 | vsize = (hsize * 9) / 16; |
| 561 | /* HDTV hack */ | 561 | /* HDTV hack */ |
| 562 | if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) { | 562 | if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) { |
| 563 | mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); | 563 | mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0, |
| 564 | false); | ||
| 564 | mode->hdisplay = 1366; | 565 | mode->hdisplay = 1366; |
| 565 | mode->vsync_start = mode->vsync_start - 1; | 566 | mode->vsync_start = mode->vsync_start - 1; |
| 566 | mode->vsync_end = mode->vsync_end - 1; | 567 | mode->vsync_end = mode->vsync_end - 1; |
| @@ -579,7 +580,8 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, | |||
| 579 | mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); | 580 | mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
| 580 | break; | 581 | break; |
| 581 | case LEVEL_CVT: | 582 | case LEVEL_CVT: |
| 582 | mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); | 583 | mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0, |
| 584 | false); | ||
| 583 | break; | 585 | break; |
| 584 | } | 586 | } |
| 585 | return mode; | 587 | return mode; |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 2c4671314884..2537d2e81849 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
| @@ -40,6 +40,196 @@ MODULE_LICENSE("GPL and additional rights"); | |||
| 40 | 40 | ||
| 41 | static LIST_HEAD(kernel_fb_helper_list); | 41 | static LIST_HEAD(kernel_fb_helper_list); |
| 42 | 42 | ||
| 43 | int drm_fb_helper_add_connector(struct drm_connector *connector) | ||
| 44 | { | ||
| 45 | connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); | ||
| 46 | if (!connector->fb_helper_private) | ||
| 47 | return -ENOMEM; | ||
| 48 | |||
| 49 | return 0; | ||
| 50 | |||
| 51 | } | ||
| 52 | EXPORT_SYMBOL(drm_fb_helper_add_connector); | ||
| 53 | |||
| 54 | static int my_atoi(const char *name) | ||
| 55 | { | ||
| 56 | int val = 0; | ||
| 57 | |||
| 58 | for (;; name++) { | ||
| 59 | switch (*name) { | ||
| 60 | case '0' ... '9': | ||
| 61 | val = 10*val+(*name-'0'); | ||
| 62 | break; | ||
| 63 | default: | ||
| 64 | return val; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * drm_fb_helper_connector_parse_command_line - parse command line for connector | ||
| 71 | * @connector - connector to parse line for | ||
| 72 | * @mode_option - per connector mode option | ||
| 73 | * | ||
| 74 | * This parses the connector specific then generic command lines for | ||
| 75 | * modes and options to configure the connector. | ||
| 76 | * | ||
| 77 | * This uses the same parameters as the fb modedb.c, except for extra | ||
| 78 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] | ||
| 79 | * | ||
| 80 | * enable/enable Digital/disable bit at the end | ||
| 81 | */ | ||
| 82 | static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *connector, | ||
| 83 | const char *mode_option) | ||
| 84 | { | ||
| 85 | const char *name; | ||
| 86 | unsigned int namelen; | ||
| 87 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | ||
| 88 | unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0; | ||
| 89 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; | ||
| 90 | int i; | ||
| 91 | enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; | ||
| 92 | struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; | ||
| 93 | struct drm_fb_helper_cmdline_mode *cmdline_mode = &fb_help_conn->cmdline_mode; | ||
| 94 | |||
| 95 | if (!mode_option) | ||
| 96 | mode_option = fb_mode_option; | ||
| 97 | |||
| 98 | if (!mode_option) { | ||
| 99 | cmdline_mode->specified = false; | ||
| 100 | return false; | ||
| 101 | } | ||
| 102 | |||
| 103 | name = mode_option; | ||
| 104 | namelen = strlen(name); | ||
| 105 | for (i = namelen-1; i >= 0; i--) { | ||
| 106 | switch (name[i]) { | ||
| 107 | case '@': | ||
| 108 | namelen = i; | ||
| 109 | if (!refresh_specified && !bpp_specified && | ||
| 110 | !yres_specified) { | ||
| 111 | refresh = my_atoi(&name[i+1]); | ||
| 112 | refresh_specified = 1; | ||
| 113 | if (cvt || rb) | ||
| 114 | cvt = 0; | ||
| 115 | } else | ||
| 116 | goto done; | ||
| 117 | break; | ||
| 118 | case '-': | ||
| 119 | namelen = i; | ||
| 120 | if (!bpp_specified && !yres_specified) { | ||
| 121 | bpp = my_atoi(&name[i+1]); | ||
| 122 | bpp_specified = 1; | ||
| 123 | if (cvt || rb) | ||
| 124 | cvt = 0; | ||
| 125 | } else | ||
| 126 | goto done; | ||
| 127 | break; | ||
| 128 | case 'x': | ||
| 129 | if (!yres_specified) { | ||
| 130 | yres = my_atoi(&name[i+1]); | ||
| 131 | yres_specified = 1; | ||
| 132 | } else | ||
| 133 | goto done; | ||
| 134 | case '0' ... '9': | ||
| 135 | break; | ||
| 136 | case 'M': | ||
| 137 | if (!yres_specified) | ||
| 138 | cvt = 1; | ||
| 139 | break; | ||
| 140 | case 'R': | ||
| 141 | if (!cvt) | ||
| 142 | rb = 1; | ||
| 143 | break; | ||
| 144 | case 'm': | ||
| 145 | if (!cvt) | ||
| 146 | margins = 1; | ||
| 147 | break; | ||
| 148 | case 'i': | ||
| 149 | if (!cvt) | ||
| 150 | interlace = 1; | ||
| 151 | break; | ||
| 152 | case 'e': | ||
| 153 | force = DRM_FORCE_ON; | ||
| 154 | break; | ||
| 155 | case 'D': | ||
| 156 | if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) || | ||
| 157 | (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) | ||
| 158 | force = DRM_FORCE_ON; | ||
| 159 | else | ||
| 160 | force = DRM_FORCE_ON_DIGITAL; | ||
| 161 | break; | ||
| 162 | case 'd': | ||
| 163 | force = DRM_FORCE_OFF; | ||
| 164 | break; | ||
| 165 | default: | ||
| 166 | goto done; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | if (i < 0 && yres_specified) { | ||
| 170 | xres = my_atoi(name); | ||
| 171 | res_specified = 1; | ||
| 172 | } | ||
| 173 | done: | ||
| 174 | |||
| 175 | DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", | ||
| 176 | drm_get_connector_name(connector), xres, yres, | ||
| 177 | (refresh) ? refresh : 60, (rb) ? " reduced blanking" : | ||
| 178 | "", (margins) ? " with margins" : "", (interlace) ? | ||
| 179 | " interlaced" : ""); | ||
| 180 | |||
| 181 | if (force) { | ||
| 182 | const char *s; | ||
| 183 | switch (force) { | ||
| 184 | case DRM_FORCE_OFF: s = "OFF"; break; | ||
| 185 | case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break; | ||
| 186 | default: | ||
| 187 | case DRM_FORCE_ON: s = "ON"; break; | ||
| 188 | } | ||
| 189 | |||
| 190 | DRM_INFO("forcing %s connector %s\n", | ||
| 191 | drm_get_connector_name(connector), s); | ||
| 192 | connector->force = force; | ||
| 193 | } | ||
| 194 | |||
| 195 | if (res_specified) { | ||
| 196 | cmdline_mode->specified = true; | ||
| 197 | cmdline_mode->xres = xres; | ||
| 198 | cmdline_mode->yres = yres; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (refresh_specified) { | ||
| 202 | cmdline_mode->refresh_specified = true; | ||
| 203 | cmdline_mode->refresh = refresh; | ||
| 204 | } | ||
| 205 | |||
| 206 | if (bpp_specified) { | ||
| 207 | cmdline_mode->bpp_specified = true; | ||
| 208 | cmdline_mode->bpp = bpp; | ||
| 209 | } | ||
| 210 | cmdline_mode->rb = rb ? true : false; | ||
| 211 | cmdline_mode->cvt = cvt ? true : false; | ||
| 212 | cmdline_mode->interlace = interlace ? true : false; | ||
| 213 | |||
| 214 | return true; | ||
| 215 | } | ||
| 216 | |||
| 217 | int drm_fb_helper_parse_command_line(struct drm_device *dev) | ||
| 218 | { | ||
| 219 | struct drm_connector *connector; | ||
| 220 | |||
| 221 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 222 | char *option = NULL; | ||
| 223 | |||
| 224 | /* do something on return - turn off connector maybe */ | ||
| 225 | if (fb_get_options(drm_get_connector_name(connector), &option)) | ||
| 226 | continue; | ||
| 227 | |||
| 228 | drm_fb_helper_connector_parse_command_line(connector, option); | ||
| 229 | } | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 43 | bool drm_fb_helper_force_kernel_mode(void) | 233 | bool drm_fb_helper_force_kernel_mode(void) |
| 44 | { | 234 | { |
| 45 | int i = 0; | 235 | int i = 0; |
| @@ -484,6 +674,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, | |||
| 484 | uint32_t fb_height, | 674 | uint32_t fb_height, |
| 485 | uint32_t surface_width, | 675 | uint32_t surface_width, |
| 486 | uint32_t surface_height, | 676 | uint32_t surface_height, |
| 677 | uint32_t surface_depth, | ||
| 678 | uint32_t surface_bpp, | ||
| 487 | struct drm_framebuffer **fb_ptr)) | 679 | struct drm_framebuffer **fb_ptr)) |
| 488 | { | 680 | { |
| 489 | struct drm_crtc *crtc; | 681 | struct drm_crtc *crtc; |
| @@ -497,8 +689,37 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, | |||
| 497 | struct drm_framebuffer *fb; | 689 | struct drm_framebuffer *fb; |
| 498 | struct drm_mode_set *modeset = NULL; | 690 | struct drm_mode_set *modeset = NULL; |
| 499 | struct drm_fb_helper *fb_helper; | 691 | struct drm_fb_helper *fb_helper; |
| 692 | uint32_t surface_depth = 24, surface_bpp = 32; | ||
| 500 | 693 | ||
| 501 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ | 694 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ |
| 695 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 696 | struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; | ||
| 697 | struct drm_fb_helper_cmdline_mode *cmdline_mode = &fb_help_conn->cmdline_mode; | ||
| 698 | |||
| 699 | if (cmdline_mode->bpp_specified) { | ||
| 700 | switch (cmdline_mode->bpp) { | ||
| 701 | case 8: | ||
| 702 | surface_depth = surface_bpp = 8; | ||
| 703 | break; | ||
| 704 | case 15: | ||
| 705 | surface_depth = 15; | ||
| 706 | surface_bpp = 16; | ||
| 707 | break; | ||
| 708 | case 16: | ||
| 709 | surface_depth = surface_bpp = 16; | ||
| 710 | break; | ||
| 711 | case 24: | ||
| 712 | surface_depth = surface_bpp = 24; | ||
| 713 | break; | ||
| 714 | case 32: | ||
| 715 | surface_depth = 24; | ||
| 716 | surface_bpp = 32; | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 502 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 723 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 503 | if (drm_helper_crtc_in_use(crtc)) { | 724 | if (drm_helper_crtc_in_use(crtc)) { |
| 504 | if (crtc->desired_mode) { | 725 | if (crtc->desired_mode) { |
| @@ -527,7 +748,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, | |||
| 527 | /* do we have an fb already? */ | 748 | /* do we have an fb already? */ |
| 528 | if (list_empty(&dev->mode_config.fb_kernel_list)) { | 749 | if (list_empty(&dev->mode_config.fb_kernel_list)) { |
| 529 | ret = (*fb_create)(dev, fb_width, fb_height, surface_width, | 750 | ret = (*fb_create)(dev, fb_width, fb_height, surface_width, |
| 530 | surface_height, &fb); | 751 | surface_height, surface_depth, surface_bpp, |
| 752 | &fb); | ||
| 531 | if (ret) | 753 | if (ret) |
| 532 | return -EINVAL; | 754 | return -EINVAL; |
| 533 | new_fb = 1; | 755 | new_fb = 1; |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 49404ce1666e..51f677215f1d 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
| @@ -88,7 +88,7 @@ EXPORT_SYMBOL(drm_mode_debug_printmodeline); | |||
| 88 | #define HV_FACTOR 1000 | 88 | #define HV_FACTOR 1000 |
| 89 | struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, | 89 | struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, |
| 90 | int vdisplay, int vrefresh, | 90 | int vdisplay, int vrefresh, |
| 91 | bool reduced, bool interlaced) | 91 | bool reduced, bool interlaced, bool margins) |
| 92 | { | 92 | { |
| 93 | /* 1) top/bottom margin size (% of height) - default: 1.8, */ | 93 | /* 1) top/bottom margin size (% of height) - default: 1.8, */ |
| 94 | #define CVT_MARGIN_PERCENTAGE 18 | 94 | #define CVT_MARGIN_PERCENTAGE 18 |
| @@ -101,7 +101,6 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, | |||
| 101 | /* Pixel Clock step (kHz) */ | 101 | /* Pixel Clock step (kHz) */ |
| 102 | #define CVT_CLOCK_STEP 250 | 102 | #define CVT_CLOCK_STEP 250 |
| 103 | struct drm_display_mode *drm_mode; | 103 | struct drm_display_mode *drm_mode; |
| 104 | bool margins = false; | ||
| 105 | unsigned int vfieldrate, hperiod; | 104 | unsigned int vfieldrate, hperiod; |
| 106 | int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; | 105 | int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; |
| 107 | int interlace; | 106 | int interlace; |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 7ba4a232a97f..e85d7e9eed7d 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -110,6 +110,7 @@ EXPORT_SYMBOL(intelfb_resize); | |||
| 110 | static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | 110 | static int intelfb_create(struct drm_device *dev, uint32_t fb_width, |
| 111 | uint32_t fb_height, uint32_t surface_width, | 111 | uint32_t fb_height, uint32_t surface_width, |
| 112 | uint32_t surface_height, | 112 | uint32_t surface_height, |
| 113 | uint32_t surface_depth, uint32_t surface_bpp, | ||
| 113 | struct drm_framebuffer **fb_p) | 114 | struct drm_framebuffer **fb_p) |
| 114 | { | 115 | { |
| 115 | struct fb_info *info; | 116 | struct fb_info *info; |
| @@ -125,9 +126,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 125 | mode_cmd.width = surface_width; | 126 | mode_cmd.width = surface_width; |
| 126 | mode_cmd.height = surface_height; | 127 | mode_cmd.height = surface_height; |
| 127 | 128 | ||
| 128 | mode_cmd.bpp = 32; | 129 | mode_cmd.bpp = surface_bpp; |
| 129 | mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); | 130 | mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); |
| 130 | mode_cmd.depth = 24; | 131 | mode_cmd.depth = surface_depth; |
| 131 | 132 | ||
| 132 | size = mode_cmd.pitch * mode_cmd.height; | 133 | size = mode_cmd.pitch * mode_cmd.height; |
| 133 | size = ALIGN(size, PAGE_SIZE); | 134 | size = ALIGN(size, PAGE_SIZE); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index f8cb8b4e2b17..db155d5e60ce 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include "drmP.h" | 26 | #include "drmP.h" |
| 27 | #include "drm_edid.h" | 27 | #include "drm_edid.h" |
| 28 | #include "drm_crtc_helper.h" | 28 | #include "drm_crtc_helper.h" |
| 29 | #include "drm_fb_helper.h" | ||
| 29 | #include "radeon_drm.h" | 30 | #include "radeon_drm.h" |
| 30 | #include "radeon.h" | 31 | #include "radeon.h" |
| 31 | #include "atom.h" | 32 | #include "atom.h" |
| @@ -245,7 +246,7 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn | |||
| 245 | if (common_modes[i].w < 320 || common_modes[i].h < 200) | 246 | if (common_modes[i].w < 320 || common_modes[i].h < 200) |
| 246 | continue; | 247 | continue; |
| 247 | 248 | ||
| 248 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false); | 249 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); |
| 249 | drm_mode_probed_add(connector, mode); | 250 | drm_mode_probed_add(connector, mode); |
| 250 | } | 251 | } |
| 251 | } | 252 | } |
| @@ -559,7 +560,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector) | |||
| 559 | radeon_add_common_modes(encoder, connector); | 560 | radeon_add_common_modes(encoder, connector); |
| 560 | else { | 561 | else { |
| 561 | /* only 800x600 is supported right now on pre-avivo chips */ | 562 | /* only 800x600 is supported right now on pre-avivo chips */ |
| 562 | tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false); | 563 | tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false); |
| 563 | tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; | 564 | tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; |
| 564 | drm_mode_probed_add(connector, tv_mode); | 565 | drm_mode_probed_add(connector, tv_mode); |
| 565 | } | 566 | } |
| @@ -743,6 +744,15 @@ struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) | |||
| 743 | return NULL; | 744 | return NULL; |
| 744 | } | 745 | } |
| 745 | 746 | ||
| 747 | static void radeon_dvi_force(struct drm_connector *connector) | ||
| 748 | { | ||
| 749 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 750 | if (connector->force == DRM_FORCE_ON) | ||
| 751 | radeon_connector->use_digital = false; | ||
| 752 | if (connector->force == DRM_FORCE_ON_DIGITAL) | ||
| 753 | radeon_connector->use_digital = true; | ||
| 754 | } | ||
| 755 | |||
| 746 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { | 756 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { |
| 747 | .get_modes = radeon_dvi_get_modes, | 757 | .get_modes = radeon_dvi_get_modes, |
| 748 | .mode_valid = radeon_vga_mode_valid, | 758 | .mode_valid = radeon_vga_mode_valid, |
| @@ -755,6 +765,7 @@ struct drm_connector_funcs radeon_dvi_connector_funcs = { | |||
| 755 | .fill_modes = drm_helper_probe_single_connector_modes, | 765 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 756 | .set_property = radeon_connector_set_property, | 766 | .set_property = radeon_connector_set_property, |
| 757 | .destroy = radeon_connector_destroy, | 767 | .destroy = radeon_connector_destroy, |
| 768 | .force = radeon_dvi_force, | ||
| 758 | }; | 769 | }; |
| 759 | 770 | ||
| 760 | void | 771 | void |
| @@ -771,6 +782,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 771 | struct radeon_connector *radeon_connector; | 782 | struct radeon_connector *radeon_connector; |
| 772 | struct radeon_connector_atom_dig *radeon_dig_connector; | 783 | struct radeon_connector_atom_dig *radeon_dig_connector; |
| 773 | uint32_t subpixel_order = SubPixelNone; | 784 | uint32_t subpixel_order = SubPixelNone; |
| 785 | int ret; | ||
| 774 | 786 | ||
| 775 | /* fixme - tv/cv/din */ | 787 | /* fixme - tv/cv/din */ |
| 776 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) | 788 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
| @@ -914,6 +926,10 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 914 | break; | 926 | break; |
| 915 | } | 927 | } |
| 916 | 928 | ||
| 929 | ret = drm_fb_helper_add_connector(connector); | ||
| 930 | if (ret) | ||
| 931 | goto failed; | ||
| 932 | |||
| 917 | connector->display_info.subpixel_order = subpixel_order; | 933 | connector->display_info.subpixel_order = subpixel_order; |
| 918 | drm_sysfs_connector_add(connector); | 934 | drm_sysfs_connector_add(connector); |
| 919 | return; | 935 | return; |
| @@ -936,6 +952,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 936 | struct drm_connector *connector; | 952 | struct drm_connector *connector; |
| 937 | struct radeon_connector *radeon_connector; | 953 | struct radeon_connector *radeon_connector; |
| 938 | uint32_t subpixel_order = SubPixelNone; | 954 | uint32_t subpixel_order = SubPixelNone; |
| 955 | int ret; | ||
| 939 | 956 | ||
| 940 | /* fixme - tv/cv/din */ | 957 | /* fixme - tv/cv/din */ |
| 941 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) | 958 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
| @@ -1027,6 +1044,10 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 1027 | break; | 1044 | break; |
| 1028 | } | 1045 | } |
| 1029 | 1046 | ||
| 1047 | ret = drm_fb_helper_add_connector(connector); | ||
| 1048 | if (ret) | ||
| 1049 | goto failed; | ||
| 1050 | |||
| 1030 | connector->display_info.subpixel_order = subpixel_order; | 1051 | connector->display_info.subpixel_order = subpixel_order; |
| 1031 | drm_sysfs_connector_add(connector); | 1052 | drm_sysfs_connector_add(connector); |
| 1032 | return; | 1053 | return; |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 944e4fa78db5..1ba704eedefb 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -128,6 +128,7 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { | |||
| 128 | int radeonfb_create(struct drm_device *dev, | 128 | int radeonfb_create(struct drm_device *dev, |
| 129 | uint32_t fb_width, uint32_t fb_height, | 129 | uint32_t fb_width, uint32_t fb_height, |
| 130 | uint32_t surface_width, uint32_t surface_height, | 130 | uint32_t surface_width, uint32_t surface_height, |
| 131 | uint32_t surface_depth, uint32_t surface_bpp, | ||
| 131 | struct drm_framebuffer **fb_p) | 132 | struct drm_framebuffer **fb_p) |
| 132 | { | 133 | { |
| 133 | struct radeon_device *rdev = dev->dev_private; | 134 | struct radeon_device *rdev = dev->dev_private; |
| @@ -148,10 +149,10 @@ int radeonfb_create(struct drm_device *dev, | |||
| 148 | 149 | ||
| 149 | mode_cmd.width = surface_width; | 150 | mode_cmd.width = surface_width; |
| 150 | mode_cmd.height = surface_height; | 151 | mode_cmd.height = surface_height; |
| 151 | mode_cmd.bpp = 32; | 152 | mode_cmd.bpp = surface_bpp; |
| 152 | /* need to align pitch with crtc limits */ | 153 | /* need to align pitch with crtc limits */ |
| 153 | mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); | 154 | mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); |
| 154 | mode_cmd.depth = 24; | 155 | mode_cmd.depth = surface_depth; |
| 155 | 156 | ||
| 156 | size = mode_cmd.pitch * mode_cmd.height; | 157 | size = mode_cmd.pitch * mode_cmd.height; |
| 157 | aligned_size = ALIGN(size, PAGE_SIZE); | 158 | aligned_size = ALIGN(size, PAGE_SIZE); |
| @@ -290,13 +291,26 @@ out: | |||
| 290 | return ret; | 291 | return ret; |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 294 | static char *mode_option; | ||
| 295 | int radeon_parse_options(char *options) | ||
| 296 | { | ||
| 297 | char *this_opt; | ||
| 298 | |||
| 299 | if (!options || !*options) | ||
| 300 | return 0; | ||
| 301 | |||
| 302 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
| 303 | if (!*this_opt) | ||
| 304 | continue; | ||
| 305 | mode_option = this_opt; | ||
| 306 | } | ||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 293 | int radeonfb_probe(struct drm_device *dev) | 310 | int radeonfb_probe(struct drm_device *dev) |
| 294 | { | 311 | { |
| 295 | int ret; | 312 | return drm_fb_helper_single_fb_probe(dev, &radeonfb_create); |
| 296 | ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create); | ||
| 297 | return ret; | ||
| 298 | } | 313 | } |
| 299 | EXPORT_SYMBOL(radeonfb_probe); | ||
| 300 | 314 | ||
| 301 | int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | 315 | int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) |
| 302 | { | 316 | { |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ae1e9e166959..b69347b8904f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -387,6 +387,7 @@ struct drm_crtc { | |||
| 387 | * @get_modes: get mode list for this connector | 387 | * @get_modes: get mode list for this connector |
| 388 | * @set_property: property for this connector may need update | 388 | * @set_property: property for this connector may need update |
| 389 | * @destroy: make object go away | 389 | * @destroy: make object go away |
| 390 | * @force: notify the driver the connector is forced on | ||
| 390 | * | 391 | * |
| 391 | * Each CRTC may have one or more connectors attached to it. The functions | 392 | * Each CRTC may have one or more connectors attached to it. The functions |
| 392 | * below allow the core DRM code to control connectors, enumerate available modes, | 393 | * below allow the core DRM code to control connectors, enumerate available modes, |
| @@ -401,6 +402,7 @@ struct drm_connector_funcs { | |||
| 401 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, | 402 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, |
| 402 | uint64_t val); | 403 | uint64_t val); |
| 403 | void (*destroy)(struct drm_connector *connector); | 404 | void (*destroy)(struct drm_connector *connector); |
| 405 | void (*force)(struct drm_connector *connector); | ||
| 404 | }; | 406 | }; |
| 405 | 407 | ||
| 406 | struct drm_encoder_funcs { | 408 | struct drm_encoder_funcs { |
| @@ -429,6 +431,13 @@ struct drm_encoder { | |||
| 429 | void *helper_private; | 431 | void *helper_private; |
| 430 | }; | 432 | }; |
| 431 | 433 | ||
| 434 | enum drm_connector_force { | ||
| 435 | DRM_FORCE_UNSPECIFIED, | ||
| 436 | DRM_FORCE_OFF, | ||
| 437 | DRM_FORCE_ON, /* force on analog part normally */ | ||
| 438 | DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ | ||
| 439 | }; | ||
| 440 | |||
| 432 | /** | 441 | /** |
| 433 | * drm_connector - central DRM connector control structure | 442 | * drm_connector - central DRM connector control structure |
| 434 | * @crtc: CRTC this connector is currently connected to, NULL if none | 443 | * @crtc: CRTC this connector is currently connected to, NULL if none |
| @@ -478,9 +487,12 @@ struct drm_connector { | |||
| 478 | 487 | ||
| 479 | void *helper_private; | 488 | void *helper_private; |
| 480 | 489 | ||
| 490 | /* forced on connector */ | ||
| 491 | enum drm_connector_force force; | ||
| 481 | uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; | 492 | uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; |
| 482 | uint32_t force_encoder_id; | 493 | uint32_t force_encoder_id; |
| 483 | struct drm_encoder *encoder; /* currently active encoder */ | 494 | struct drm_encoder *encoder; /* currently active encoder */ |
| 495 | void *fb_helper_private; | ||
| 484 | }; | 496 | }; |
| 485 | 497 | ||
| 486 | /** | 498 | /** |
| @@ -746,7 +758,7 @@ extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
| 746 | extern bool drm_detect_hdmi_monitor(struct edid *edid); | 758 | extern bool drm_detect_hdmi_monitor(struct edid *edid); |
| 747 | extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, | 759 | extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, |
| 748 | int hdisplay, int vdisplay, int vrefresh, | 760 | int hdisplay, int vdisplay, int vrefresh, |
| 749 | bool reduced, bool interlaced); | 761 | bool reduced, bool interlaced, bool margins); |
| 750 | extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, | 762 | extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, |
| 751 | int hdisplay, int vdisplay, int vrefresh, | 763 | int hdisplay, int vdisplay, int vrefresh, |
| 752 | bool interlaced, int margins); | 764 | bool interlaced, int margins); |
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 88fffbdfa26f..4aa5740ce59f 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
| @@ -35,11 +35,30 @@ struct drm_fb_helper_crtc { | |||
| 35 | struct drm_mode_set mode_set; | 35 | struct drm_mode_set mode_set; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | |||
| 38 | struct drm_fb_helper_funcs { | 39 | struct drm_fb_helper_funcs { |
| 39 | void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, | 40 | void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, |
| 40 | u16 blue, int regno); | 41 | u16 blue, int regno); |
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 44 | /* mode specified on the command line */ | ||
| 45 | struct drm_fb_helper_cmdline_mode { | ||
| 46 | bool specified; | ||
| 47 | bool refresh_specified; | ||
| 48 | bool bpp_specified; | ||
| 49 | int xres, yres; | ||
| 50 | int bpp; | ||
| 51 | int refresh; | ||
| 52 | bool rb; | ||
| 53 | bool interlace; | ||
| 54 | bool cvt; | ||
| 55 | bool margins; | ||
| 56 | }; | ||
| 57 | |||
| 58 | struct drm_fb_helper_connector { | ||
| 59 | struct drm_fb_helper_cmdline_mode cmdline_mode; | ||
| 60 | }; | ||
| 61 | |||
| 43 | struct drm_fb_helper { | 62 | struct drm_fb_helper { |
| 44 | struct drm_framebuffer *fb; | 63 | struct drm_framebuffer *fb; |
| 45 | struct drm_device *dev; | 64 | struct drm_device *dev; |
| @@ -57,6 +76,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, | |||
| 57 | uint32_t fb_height, | 76 | uint32_t fb_height, |
| 58 | uint32_t surface_width, | 77 | uint32_t surface_width, |
| 59 | uint32_t surface_height, | 78 | uint32_t surface_height, |
| 79 | uint32_t surface_depth, | ||
| 80 | uint32_t surface_bpp, | ||
| 60 | struct drm_framebuffer **fb_ptr)); | 81 | struct drm_framebuffer **fb_ptr)); |
| 61 | int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, | 82 | int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, |
| 62 | int max_conn); | 83 | int max_conn); |
| @@ -79,4 +100,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb, | |||
| 79 | uint32_t fb_width, uint32_t fb_height); | 100 | uint32_t fb_width, uint32_t fb_height); |
| 80 | void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch); | 101 | void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch); |
| 81 | 102 | ||
| 103 | int drm_fb_helper_add_connector(struct drm_connector *connector); | ||
| 104 | int drm_fb_helper_parse_command_line(struct drm_device *dev); | ||
| 105 | |||
| 82 | #endif | 106 | #endif |
