aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fbdev.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2014-02-12 15:26:25 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-02-12 17:42:17 -0500
commiteb1bfe807cb7b62a326fa20df5e3118a32c6f923 (patch)
tree97bf9ad3b0eaf19cfe582b59ce4aa334d3bc582a /drivers/gpu/drm/i915/intel_fbdev.c
parent2f1046f304b1ab14ea611a01b85f3486f2b9ce5b (diff)
drm/i915: allow re-use BIOS connector config for initial fbdev config v3
The BIOS or boot loader will generally create an initial display configuration for us that includes some set of active pipes and displays. This routine tries to figure out which pipes and connectors are active and stuffs them into the crtcs and modes array given to us by the drm_fb_helper code. The overall sequence is: intel_fbdev_init - from driver load intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data drm_fb_helper_init - build fb helper structs drm_fb_helper_single_add_all_connectors - more fb helper structs intel_fbdev_initial_config - apply the config drm_fb_helper_initial_config - call ->probe then register_framebuffer() drm_setup_crtcs - build crtc config for fbdev intel_fb_initial_config - find active connectors etc drm_fb_helper_single_fb_probe - set up fbdev intelfb_create - re-use or alloc fb, build out fbdev structs v2: use BIOS connector config unconditionally if possible (Daniel) check for crtc cloning and reject (Daniel) fix up comments (Daniel) v3: use command line args and preferred modes first (Ville) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [danvet: Re-add the WARN_ON for a missing encoder crtc - the state sanitizer should take care of this. And spell-ocd the comments.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbdev.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c123
1 files changed, 123 insertions, 0 deletions
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
245static struct drm_fb_helper_crtc *
246intel_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 */
284static 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
245static struct drm_fb_helper_funcs intel_fb_helper_funcs = { 367static 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,