diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_fbdev.c | 123 |
2 files changed, 127 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2cc18e516a2a..ede87aa3b24b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -51,7 +51,10 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, | |||
51 | 51 | ||
52 | static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, | 52 | static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, |
53 | int x, int y, struct drm_framebuffer *old_fb); | 53 | int x, int y, struct drm_framebuffer *old_fb); |
54 | 54 | static int intel_framebuffer_init(struct drm_device *dev, | |
55 | struct intel_framebuffer *ifb, | ||
56 | struct drm_mode_fb_cmd2 *mode_cmd, | ||
57 | struct drm_i915_gem_object *obj); | ||
55 | 58 | ||
56 | typedef struct { | 59 | typedef struct { |
57 | int min, max; | 60 | int min, max; |
@@ -7692,11 +7695,6 @@ static struct drm_display_mode load_detect_mode = { | |||
7692 | 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), | 7695 | 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), |
7693 | }; | 7696 | }; |
7694 | 7697 | ||
7695 | static int intel_framebuffer_init(struct drm_device *dev, | ||
7696 | struct intel_framebuffer *ifb, | ||
7697 | struct drm_mode_fb_cmd2 *mode_cmd, | ||
7698 | struct drm_i915_gem_object *obj); | ||
7699 | |||
7700 | struct drm_framebuffer * | 7698 | struct drm_framebuffer * |
7701 | __intel_framebuffer_create(struct drm_device *dev, | 7699 | __intel_framebuffer_create(struct drm_device *dev, |
7702 | struct drm_mode_fb_cmd2 *mode_cmd, | 7700 | struct drm_mode_fb_cmd2 *mode_cmd, |
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 3a53ee307065..25d2746fe695 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c | |||
@@ -242,7 +242,130 @@ static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
242 | *blue = intel_crtc->lut_b[regno] << 8; | 242 | *blue = intel_crtc->lut_b[regno] << 8; |
243 | } | 243 | } |
244 | 244 | ||
245 | static struct drm_fb_helper_crtc * | ||
246 | intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) | ||
247 | { | ||
248 | int i; | ||
249 | |||
250 | for (i = 0; i < fb_helper->crtc_count; i++) | ||
251 | if (fb_helper->crtc_info[i].mode_set.crtc == crtc) | ||
252 | return &fb_helper->crtc_info[i]; | ||
253 | |||
254 | return NULL; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * Try to read the BIOS display configuration and use it for the initial | ||
259 | * fb configuration. | ||
260 | * | ||
261 | * The BIOS or boot loader will generally create an initial display | ||
262 | * configuration for us that includes some set of active pipes and displays. | ||
263 | * This routine tries to figure out which pipes and connectors are active | ||
264 | * and stuffs them into the crtcs and modes array given to us by the | ||
265 | * drm_fb_helper code. | ||
266 | * | ||
267 | * The overall sequence is: | ||
268 | * intel_fbdev_init - from driver load | ||
269 | * intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data | ||
270 | * drm_fb_helper_init - build fb helper structs | ||
271 | * drm_fb_helper_single_add_all_connectors - more fb helper structs | ||
272 | * intel_fbdev_initial_config - apply the config | ||
273 | * drm_fb_helper_initial_config - call ->probe then register_framebuffer() | ||
274 | * drm_setup_crtcs - build crtc config for fbdev | ||
275 | * intel_fb_initial_config - find active connectors etc | ||
276 | * drm_fb_helper_single_fb_probe - set up fbdev | ||
277 | * intelfb_create - re-use or alloc fb, build out fbdev structs | ||
278 | * | ||
279 | * Note that we don't make special consideration whether we could actually | ||
280 | * switch to the selected modes without a full modeset. E.g. when the display | ||
281 | * is in VGA mode we need to recalculate watermarks and set a new high-res | ||
282 | * framebuffer anyway. | ||
283 | */ | ||
284 | static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, | ||
285 | struct drm_fb_helper_crtc **crtcs, | ||
286 | struct drm_display_mode **modes, | ||
287 | bool *enabled, int width, int height) | ||
288 | { | ||
289 | int i, j; | ||
290 | |||
291 | for (i = 0; i < fb_helper->connector_count; i++) { | ||
292 | struct drm_fb_helper_connector *fb_conn; | ||
293 | struct drm_connector *connector; | ||
294 | struct drm_encoder *encoder; | ||
295 | struct drm_fb_helper_crtc *new_crtc; | ||
296 | |||
297 | fb_conn = fb_helper->connector_info[i]; | ||
298 | connector = fb_conn->connector; | ||
299 | if (!enabled[i]) { | ||
300 | DRM_DEBUG_KMS("connector %d not enabled, skipping\n", | ||
301 | connector->base.id); | ||
302 | continue; | ||
303 | } | ||
304 | |||
305 | encoder = connector->encoder; | ||
306 | if (!encoder || WARN_ON(!encoder->crtc)) { | ||
307 | DRM_DEBUG_KMS("connector %d has no encoder or crtc, skipping\n", | ||
308 | connector->base.id); | ||
309 | enabled[i] = false; | ||
310 | continue; | ||
311 | } | ||
312 | |||
313 | new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc); | ||
314 | |||
315 | /* | ||
316 | * Make sure we're not trying to drive multiple connectors | ||
317 | * with a single CRTC, since our cloning support may not | ||
318 | * match the BIOS. | ||
319 | */ | ||
320 | for (j = 0; j < fb_helper->connector_count; j++) { | ||
321 | if (crtcs[j] == new_crtc) | ||
322 | return false; | ||
323 | } | ||
324 | |||
325 | DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", | ||
326 | fb_conn->connector->base.id); | ||
327 | |||
328 | /* go for command line mode first */ | ||
329 | modes[i] = drm_pick_cmdline_mode(fb_conn, width, height); | ||
330 | |||
331 | /* try for preferred next */ | ||
332 | if (!modes[i]) { | ||
333 | DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", | ||
334 | fb_conn->connector->base.id); | ||
335 | modes[i] = drm_has_preferred_mode(fb_conn, width, | ||
336 | height); | ||
337 | } | ||
338 | |||
339 | /* last resort: use current mode */ | ||
340 | if (!modes[i]) { | ||
341 | /* | ||
342 | * IMPORTANT: We want to use the adjusted mode (i.e. | ||
343 | * after the panel fitter upscaling) as the initial | ||
344 | * config, not the input mode, which is what crtc->mode | ||
345 | * usually contains. But since our current fastboot | ||
346 | * code puts a mode derived from the post-pfit timings | ||
347 | * into crtc->mode this works out correctly. We don't | ||
348 | * use hwmode anywhere right now, so use it for this | ||
349 | * since the fb helper layer wants a pointer to | ||
350 | * something we own. | ||
351 | */ | ||
352 | intel_mode_from_pipe_config(&encoder->crtc->hwmode, | ||
353 | &to_intel_crtc(encoder->crtc)->config); | ||
354 | modes[i] = &encoder->crtc->hwmode; | ||
355 | } | ||
356 | crtcs[i] = new_crtc; | ||
357 | |||
358 | DRM_DEBUG_KMS("connector %s on crtc %d: %s\n", | ||
359 | drm_get_connector_name(connector), | ||
360 | encoder->crtc->base.id, | ||
361 | modes[i]->name); | ||
362 | } | ||
363 | |||
364 | return true; | ||
365 | } | ||
366 | |||
245 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { | 367 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { |
368 | .initial_config = intel_fb_initial_config, | ||
246 | .gamma_set = intel_crtc_fb_gamma_set, | 369 | .gamma_set = intel_crtc_fb_gamma_set, |
247 | .gamma_get = intel_crtc_fb_gamma_get, | 370 | .gamma_get = intel_crtc_fb_gamma_get, |
248 | .fb_probe = intelfb_create, | 371 | .fb_probe = intelfb_create, |