From: Dave Airlie Date: Wed, 2 Apr 2014 21:51:54 +0000 (+1000) Subject: Merge tag 'drm-intel-next-2014-03-21' of git://anongit.freedesktop.org/drm-intel... X-Git-Tag: v3.15-rc1~51^2~18 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=66e514c14a1cb9c2540c685c40d94dc6ef6b6bb5;p=linux.git Merge tag 'drm-intel-next-2014-03-21' of git://anongit.freedesktop.org/drm-intel into drm-next - Inherit/reuse firmwar framebuffers (for real this time) from Jesse, less flicker for fastbooting. - More flexible cloning for hdmi (Ville). - Some PPGTT fixes from Ben. - Ring init fixes from Naresh Kumar. - set_cache_level regression fixes for the vma conversion from Ville&Chris. - Conversion to the new dp aux helpers (Jani). - Unification of runtime pm with pc8 support from Paulo, prep work for runtime pm on other platforms than HSW. - Larger cursor sizes (Sagar Kamble). - Piles of improvements and fixes all over, as usual. * tag 'drm-intel-next-2014-03-21' of git://anongit.freedesktop.org/drm-intel: (75 commits) drm/i915: Include a note about the dangers of I915_READ64/I915_WRITE64 drm/i915/sdvo: fix questionable return value check drm/i915: Fix unsafe loop iteration over vma whilst unbinding them drm/i915: Enabling 128x128 and 256x256 ARGB Cursor Support drm/i915: Print how many objects are shared in per-process stats drm/i915: Per-process stats work better when evaluated per-process drm/i915: remove rps local variables drm/i915: Remove extraneous MMIO for RPS drm/i915: Rename and comment all the RPS *stuff* drm/i915: Store the HW min frequency as min_freq drm/i915: Fix coding style for RPS drm/i915: Reorganize the overclock code drm/i915: init pm.suspended earlier drm/i915: update the PC8 and runtime PM documentation drm/i915: rename __hsw_do_{en, dis}able_pc8 drm/i915: kill struct i915_package_c8 drm/i915: move pc8.irqs_disabled to pm.irqs_disabled drm/i915: remove dev_priv->pc8.enabled drm/i915: don't get/put PC8 when getting/putting power wells drm/i915: make intel_aux_display_runtime_get get runtime PM, not PC8 ... Conflicts: drivers/gpu/drm/i915/intel_display.c drivers/gpu/drm/i915/intel_dp.c --- 66e514c14a1cb9c2540c685c40d94dc6ef6b6bb5 diff --cc drivers/gpu/drm/i915/i915_cmd_parser.c index 69c1287f1262,0eaed44aee6d..4cf6d020d513 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@@ -402,10 -402,10 +402,10 @@@ int i915_parse_cmds(struct intel_ring_b length = ((*cmd & desc->length.mask) + LENGTH_BIAS); if ((batch_end - cmd) < length) { - DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%ld\n", + DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%td\n", *cmd, length, - batch_end - cmd); + (unsigned long)(batch_end - cmd)); ret = -EINVAL; break; } diff --cc drivers/gpu/drm/i915/intel_display.c index 3ffe5a6124f1,7be5984431bb..6332383abae9 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@@ -741,10 -741,10 +741,10 @@@ bool intel_crtc_active(struct drm_crtc * We can ditch the adjusted_mode.crtc_clock check as soon * as Haswell has gained clock readout/fastboot support. * -- * We can ditch the crtc->fb check as soon as we can ++ * We can ditch the crtc->primary->fb check as soon as we can * properly reconstruct framebuffers. */ - return intel_crtc->active && crtc->fb && + return intel_crtc->active && crtc->primary->fb && intel_crtc->config.adjusted_mode.crtc_clock; } @@@ -2047,8 -2047,114 +2047,114 @@@ unsigned long intel_gen4_compute_page_o } } - static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) + int intel_format_to_fourcc(int format) + { + switch (format) { + case DISPPLANE_8BPP: + return DRM_FORMAT_C8; + case DISPPLANE_BGRX555: + return DRM_FORMAT_XRGB1555; + case DISPPLANE_BGRX565: + return DRM_FORMAT_RGB565; + default: + case DISPPLANE_BGRX888: + return DRM_FORMAT_XRGB8888; + case DISPPLANE_RGBX888: + return DRM_FORMAT_XBGR8888; + case DISPPLANE_BGRX101010: + return DRM_FORMAT_XRGB2101010; + case DISPPLANE_RGBX101010: + return DRM_FORMAT_XBGR2101010; + } + } + + static bool intel_alloc_plane_obj(struct intel_crtc *crtc, + struct intel_plane_config *plane_config) + { + struct drm_device *dev = crtc->base.dev; + struct drm_i915_gem_object *obj = NULL; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + u32 base = plane_config->base; + + if (plane_config->size == 0) + return false; + + obj = i915_gem_object_create_stolen_for_preallocated(dev, base, base, + plane_config->size); + if (!obj) + return false; + + if (plane_config->tiled) { + obj->tiling_mode = I915_TILING_X; - obj->stride = crtc->base.fb->pitches[0]; ++ obj->stride = crtc->base.primary->fb->pitches[0]; + } + - mode_cmd.pixel_format = crtc->base.fb->pixel_format; - mode_cmd.width = crtc->base.fb->width; - mode_cmd.height = crtc->base.fb->height; - mode_cmd.pitches[0] = crtc->base.fb->pitches[0]; ++ mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format; ++ mode_cmd.width = crtc->base.primary->fb->width; ++ mode_cmd.height = crtc->base.primary->fb->height; ++ mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0]; + + mutex_lock(&dev->struct_mutex); + - if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb), ++ if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.primary->fb), + &mode_cmd, obj)) { + DRM_DEBUG_KMS("intel fb init failed\n"); + goto out_unref_obj; + } + + mutex_unlock(&dev->struct_mutex); + + DRM_DEBUG_KMS("plane fb obj %p\n", obj); + return true; + + out_unref_obj: + drm_gem_object_unreference(&obj->base); + mutex_unlock(&dev->struct_mutex); + return false; + } + + static void intel_find_plane_obj(struct intel_crtc *intel_crtc, + struct intel_plane_config *plane_config) + { + struct drm_device *dev = intel_crtc->base.dev; + struct drm_crtc *c; + struct intel_crtc *i; + struct intel_framebuffer *fb; + - if (!intel_crtc->base.fb) ++ if (!intel_crtc->base.primary->fb) + return; + + if (intel_alloc_plane_obj(intel_crtc, plane_config)) + return; + - kfree(intel_crtc->base.fb); - intel_crtc->base.fb = NULL; ++ kfree(intel_crtc->base.primary->fb); ++ intel_crtc->base.primary->fb = NULL; + + /* + * Failed to alloc the obj, check to see if we should share + * an fb with another CRTC instead + */ + list_for_each_entry(c, &dev->mode_config.crtc_list, head) { + i = to_intel_crtc(c); + + if (c == &intel_crtc->base) + continue; + - if (!i->active || !c->fb) ++ if (!i->active || !c->primary->fb) + continue; + - fb = to_intel_framebuffer(c->fb); ++ fb = to_intel_framebuffer(c->primary->fb); + if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) { - drm_framebuffer_reference(c->fb); - intel_crtc->base.fb = c->fb; ++ drm_framebuffer_reference(c->primary->fb); ++ intel_crtc->base.primary->fb = c->primary->fb; + break; + } + } + } + + static int i9xx_update_primary_plane(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@@ -2289,11 -2396,13 +2396,13 @@@ void intel_display_handle_reset(struct /* * FIXME: Once we have proper support for primary planes (and * disabling them without disabling the entire crtc) allow again -- * a NULL crtc->fb. ++ * a NULL crtc->primary->fb. */ - if (intel_crtc->active && crtc->fb) + if (intel_crtc->active && crtc->primary->fb) - dev_priv->display.update_plane(crtc, crtc->primary->fb, - crtc->x, crtc->y); + dev_priv->display.update_primary_plane(crtc, - crtc->fb, ++ crtc->primary->fb, + crtc->x, + crtc->y); mutex_unlock(&crtc->mutex); } } @@@ -5611,6 -5718,67 +5724,67 @@@ static void vlv_crtc_clock_get(struct i pipe_config->port_clock = clock.dot / 5; } + static void i9xx_get_plane_config(struct intel_crtc *crtc, + struct intel_plane_config *plane_config) + { + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val, base, offset; + int pipe = crtc->pipe, plane = crtc->plane; + int fourcc, pixel_format; + int aligned_height; + - crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); - if (!crtc->base.fb) { ++ crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); ++ if (!crtc->base.primary->fb) { + DRM_DEBUG_KMS("failed to alloc fb\n"); + return; + } + + val = I915_READ(DSPCNTR(plane)); + + if (INTEL_INFO(dev)->gen >= 4) + if (val & DISPPLANE_TILED) + plane_config->tiled = true; + + pixel_format = val & DISPPLANE_PIXFORMAT_MASK; + fourcc = intel_format_to_fourcc(pixel_format); - crtc->base.fb->pixel_format = fourcc; - crtc->base.fb->bits_per_pixel = ++ crtc->base.primary->fb->pixel_format = fourcc; ++ crtc->base.primary->fb->bits_per_pixel = + drm_format_plane_cpp(fourcc, 0) * 8; + + if (INTEL_INFO(dev)->gen >= 4) { + if (plane_config->tiled) + offset = I915_READ(DSPTILEOFF(plane)); + else + offset = I915_READ(DSPLINOFF(plane)); + base = I915_READ(DSPSURF(plane)) & 0xfffff000; + } else { + base = I915_READ(DSPADDR(plane)); + } + plane_config->base = base; + + val = I915_READ(PIPESRC(pipe)); - crtc->base.fb->width = ((val >> 16) & 0xfff) + 1; - crtc->base.fb->height = ((val >> 0) & 0xfff) + 1; ++ crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1; ++ crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1; + + val = I915_READ(DSPSTRIDE(pipe)); - crtc->base.fb->pitches[0] = val & 0xffffff80; ++ crtc->base.primary->fb->pitches[0] = val & 0xffffff80; + - aligned_height = intel_align_height(dev, crtc->base.fb->height, ++ aligned_height = intel_align_height(dev, crtc->base.primary->fb->height, + plane_config->tiled); + - plane_config->size = ALIGN(crtc->base.fb->pitches[0] * ++ plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] * + aligned_height, PAGE_SIZE); + + DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe, plane, crtc->base.fb->width, - crtc->base.fb->height, - crtc->base.fb->bits_per_pixel, base, - crtc->base.fb->pitches[0], ++ pipe, plane, crtc->base.primary->fb->width, ++ crtc->base.primary->fb->height, ++ crtc->base.primary->fb->bits_per_pixel, base, ++ crtc->base.primary->fb->pitches[0], + plane_config->size); + + } + static bool i9xx_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { @@@ -6558,6 -6726,66 +6732,66 @@@ static void ironlake_get_pfit_config(st } } + static void ironlake_get_plane_config(struct intel_crtc *crtc, + struct intel_plane_config *plane_config) + { + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val, base, offset; + int pipe = crtc->pipe, plane = crtc->plane; + int fourcc, pixel_format; + int aligned_height; + - crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); - if (!crtc->base.fb) { ++ crtc->base.primary->fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL); ++ if (!crtc->base.primary->fb) { + DRM_DEBUG_KMS("failed to alloc fb\n"); + return; + } + + val = I915_READ(DSPCNTR(plane)); + + if (INTEL_INFO(dev)->gen >= 4) + if (val & DISPPLANE_TILED) + plane_config->tiled = true; + + pixel_format = val & DISPPLANE_PIXFORMAT_MASK; + fourcc = intel_format_to_fourcc(pixel_format); - crtc->base.fb->pixel_format = fourcc; - crtc->base.fb->bits_per_pixel = ++ crtc->base.primary->fb->pixel_format = fourcc; ++ crtc->base.primary->fb->bits_per_pixel = + drm_format_plane_cpp(fourcc, 0) * 8; + + base = I915_READ(DSPSURF(plane)) & 0xfffff000; + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + offset = I915_READ(DSPOFFSET(plane)); + } else { + if (plane_config->tiled) + offset = I915_READ(DSPTILEOFF(plane)); + else + offset = I915_READ(DSPLINOFF(plane)); + } + plane_config->base = base; + + val = I915_READ(PIPESRC(pipe)); - crtc->base.fb->width = ((val >> 16) & 0xfff) + 1; - crtc->base.fb->height = ((val >> 0) & 0xfff) + 1; ++ crtc->base.primary->fb->width = ((val >> 16) & 0xfff) + 1; ++ crtc->base.primary->fb->height = ((val >> 0) & 0xfff) + 1; + + val = I915_READ(DSPSTRIDE(pipe)); - crtc->base.fb->pitches[0] = val & 0xffffff80; ++ crtc->base.primary->fb->pitches[0] = val & 0xffffff80; + - aligned_height = intel_align_height(dev, crtc->base.fb->height, ++ aligned_height = intel_align_height(dev, crtc->base.primary->fb->height, + plane_config->tiled); + - plane_config->size = ALIGN(crtc->base.fb->pitches[0] * ++ plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] * + aligned_height, PAGE_SIZE); + + DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe, plane, crtc->base.fb->width, - crtc->base.fb->height, - crtc->base.fb->bits_per_pixel, base, - crtc->base.fb->pitches[0], ++ pipe, plane, crtc->base.primary->fb->width, ++ crtc->base.primary->fb->height, ++ crtc->base.primary->fb->bits_per_pixel, base, ++ crtc->base.primary->fb->pitches[0], + plane_config->size); + } + static bool ironlake_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { @@@ -11487,6 -11737,26 +11743,26 @@@ void intel_modeset_gem_init(struct drm_ intel_modeset_init_hw(dev); intel_setup_overlay(dev); + + /* + * Make sure any fbs we allocated at startup are properly + * pinned & fenced. When we do the allocation it's too early + * for this. + */ + mutex_lock(&dev->struct_mutex); + list_for_each_entry(c, &dev->mode_config.crtc_list, head) { - if (!c->fb) ++ if (!c->primary->fb) + continue; + - fb = to_intel_framebuffer(c->fb); ++ fb = to_intel_framebuffer(c->primary->fb); + if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) { + DRM_ERROR("failed to pin boot fb on pipe %d\n", + to_intel_crtc(c)->pipe); - drm_framebuffer_unreference(c->fb); - c->fb = NULL; ++ drm_framebuffer_unreference(c->primary->fb); ++ c->primary->fb = NULL; + } + } + mutex_unlock(&dev->struct_mutex); } void intel_connector_unregister(struct intel_connector *intel_connector) diff --cc drivers/gpu/drm/i915/intel_dp.c index f2fedc06976b,bbb1327644d4..5ce5e5be7e88 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@@ -3763,8 -3646,7 +3646,8 @@@ static bool intel_edp_init_connector(st /* We now know it's not a ghost, init power sequence regs. */ intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); + mutex_lock(&dev->mode_config.mutex); - edid = drm_get_edid(connector, &intel_dp->adapter); + edid = drm_get_edid(connector, &intel_dp->aux.ddc); if (edid) { if (drm_add_edid_modes(connector, edid)) { drm_mode_connector_update_edid_property(connector, diff --cc drivers/gpu/drm/i915/intel_fbdev.c index 6b5beed28d70,d6d78c86c232..2b1d42dbfe13 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@@ -454,6 -456,124 +456,124 @@@ static void intel_fbdev_destroy(struct drm_framebuffer_remove(&ifbdev->fb->base); } + /* + * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible. + * The core display code will have read out the current plane configuration, + * so we use that to figure out if there's an object for us to use as the + * fb, and if so, we re-use it for the fbdev configuration. + * + * Note we only support a single fb shared across pipes for boot (mostly for + * fbcon), so we just find the biggest and use that. + */ + static bool intel_fbdev_init_bios(struct drm_device *dev, + struct intel_fbdev *ifbdev) + { + struct intel_framebuffer *fb = NULL; + struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; + struct intel_plane_config *plane_config = NULL; + unsigned int max_size = 0; + + if (!i915.fastboot) + return false; + + /* Find the largest fb */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + intel_crtc = to_intel_crtc(crtc); + - if (!intel_crtc->active || !crtc->fb) { ++ if (!intel_crtc->active || !crtc->primary->fb) { + DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", + pipe_name(intel_crtc->pipe)); + continue; + } + + if (intel_crtc->plane_config.size > max_size) { + DRM_DEBUG_KMS("found possible fb from plane %c\n", + pipe_name(intel_crtc->pipe)); + plane_config = &intel_crtc->plane_config; - fb = to_intel_framebuffer(crtc->fb); ++ fb = to_intel_framebuffer(crtc->primary->fb); + max_size = plane_config->size; + } + } + + if (!fb) { + DRM_DEBUG_KMS("no active fbs found, not using BIOS config\n"); + goto out; + } + + /* Now make sure all the pipes will fit into it */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + unsigned int cur_size; + + intel_crtc = to_intel_crtc(crtc); + + if (!intel_crtc->active) { + DRM_DEBUG_KMS("pipe %c not active, skipping\n", + pipe_name(intel_crtc->pipe)); + continue; + } + + DRM_DEBUG_KMS("checking plane %c for BIOS fb\n", + pipe_name(intel_crtc->pipe)); + + /* + * See if the plane fb we found above will fit on this + * pipe. Note we need to use the selected fb's bpp rather + * than the current pipe's, since they could be different. + */ + cur_size = intel_crtc->config.adjusted_mode.crtc_hdisplay * + intel_crtc->config.adjusted_mode.crtc_vdisplay; + DRM_DEBUG_KMS("pipe %c area: %d\n", pipe_name(intel_crtc->pipe), + cur_size); + cur_size *= fb->base.bits_per_pixel / 8; + DRM_DEBUG_KMS("total size %d (bpp %d)\n", cur_size, + fb->base.bits_per_pixel / 8); + + if (cur_size > max_size) { + DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n", + pipe_name(intel_crtc->pipe), + cur_size, max_size); + plane_config = NULL; + fb = NULL; + break; + } + + DRM_DEBUG_KMS("fb big enough for plane %c (%d >= %d)\n", + pipe_name(intel_crtc->pipe), + max_size, cur_size); + } + + if (!fb) { + DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n"); + goto out; + } + + ifbdev->preferred_bpp = fb->base.bits_per_pixel; + ifbdev->fb = fb; + + drm_framebuffer_reference(&ifbdev->fb->base); + + /* Final pass to check if any active pipes don't have fbs */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + intel_crtc = to_intel_crtc(crtc); + + if (!intel_crtc->active) + continue; + - WARN(!crtc->fb, ++ WARN(!crtc->primary->fb, + "re-used BIOS config but lost an fb on crtc %d\n", + crtc->base.id); + } + + + DRM_DEBUG_KMS("using BIOS fb for initial console\n"); + return true; + + out: + + return false; + } + int intel_fbdev_init(struct drm_device *dev) { struct intel_fbdev *ifbdev;