aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2009-09-23 00:44:08 -0400
committerDave Airlie <airlied@linux.ie>2009-09-24 23:08:20 -0400
commitd50ba256b5f1478e15accfcfda9b72fd7a661364 (patch)
tree7148b1294057a734ecdbc62b7df7ed0397adfeb4 /drivers/gpu/drm
parentf80330357284c908e1f67cc8b4d8e56a3e2f6fc6 (diff)
drm/kms: start adding command line interface using fb.
[note this requires an fb patch posted to linux-fbdev-devel already] This uses the normal video= command line option to control the kms output setup at boot time. It is used to override the autodetection done by kms. video= normally takes a framebuffer as the first parameter, in kms it will take a connector name, DVI-I-1, or LVDS-1 etc. If no output connector is specified the mode string will apply to all connectors. The mode specification used will match down the probed modes, and if no mode is found it will add a CVT mode that matches. video=1024x768 - all connectors match a 1024x768 mode or add a CVT on video=VGA-1:1024x768, VGA-1 connector gets mode only. The same strings as used in current fb modedb.c are used, except I've added three more letters, e, D, d, e = enable, D = enable Digital, d = disable, which allow a connector to be forced into a certain state. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_crtc.c1
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c79
-rw-r--r--drivers/gpu/drm/drm_edid.c6
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c224
-rw-r--r--drivers/gpu/drm/drm_modes.c3
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c25
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c26
8 files changed, 349 insertions, 20 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
36static void drm_mode_validate_flag(struct drm_connector *connector, 37static 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
279static 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
286static 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
319create_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
270static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 329static 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
41static LIST_HEAD(kernel_fb_helper_list); 41static LIST_HEAD(kernel_fb_helper_list);
42 42
43int 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}
52EXPORT_SYMBOL(drm_fb_helper_add_connector);
53
54static 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 */
82static 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 }
173done:
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
217int 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
43bool drm_fb_helper_force_kernel_mode(void) 233bool 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
89struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, 89struct 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);
110static int intelfb_create(struct drm_device *dev, uint32_t fb_width, 110static 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
747static 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
746struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { 756struct 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
760void 771void
@@ -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 = {
128int radeonfb_create(struct drm_device *dev, 128int 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
294static char *mode_option;
295int 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
293int radeonfb_probe(struct drm_device *dev) 310int 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}
299EXPORT_SYMBOL(radeonfb_probe);
300 314
301int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) 315int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
302{ 316{