Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/i915: i915 cannot provide switcher services.
  drm/radeon/kms: fix vram base calculation on rs780/rs880
  drm/radeon/kms: fix formatting of vram and gtt info
  drm/radeon/kms: forbid big bo allocation (fdo 31708) v3
  drm: Don't try and disable an encoder that was never enabled
  drm: Add missing drm_vblank_put() along queue vblank error path
  drm/i915/dp: Only apply the workaround if the select is still active
  drm/i915: Emit a request to clear a flushed and idle ring for unbusy bo
  drm/i915/lvds: Always restore panel-fitter when enabling the LVDS
  drm/i915/ringbuffer: Only print an error on the second attempt to reset head
  drm/i915: announce to userspace that the bsd ring is coherent
  agp/intel: Fix wrong kunmap in i830_cleanup()
  drm/i915: Factor in pixel-repeat in FDI M/N calculation
  drm/i915: Death to the unnecessary 64bit divide
  drm/i915: Clean conflicting modesetting registers upon init
  drm/i915: Apply a workaround for transitioning from DP on pipe B to HDMI.
  drm/i915: Always set the DP transcoder config to 8BPC.
  • Loading branch information
Linus Torvalds committed Dec 8, 2010
2 parents f8f5d4f + 599bbb9 commit 6dde39b
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 121 deletions.
6 changes: 4 additions & 2 deletions drivers/char/agp/intel-gtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void)

static void i830_cleanup(void)
{
kunmap(intel_private.i8xx_page);
intel_private.i8xx_flush_page = NULL;
if (intel_private.i8xx_flush_page) {
kunmap(intel_private.i8xx_flush_page);
intel_private.i8xx_flush_page = NULL;
}

__free_page(intel_private.i8xx_page);
intel_private.i8xx_page = NULL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_crtc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
}

list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (!drm_helper_encoder_in_use(encoder)) {
if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
drm_encoder_disable(encoder);
/* disconnector encoder from any connector */
encoder->crtc = NULL;
Expand Down
19 changes: 14 additions & 5 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
struct timeval now;
unsigned long flags;
unsigned int seq;
int ret;

e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL)
return -ENOMEM;
if (e == NULL) {
ret = -ENOMEM;
goto err_put;
}

e->pipe = pipe;
e->base.pid = current->pid;
Expand All @@ -603,9 +606,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
spin_lock_irqsave(&dev->event_lock, flags);

if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
return -ENOMEM;
ret = -EBUSY;
goto err_unlock;
}

file_priv->event_space -= sizeof e->event;
Expand Down Expand Up @@ -638,6 +640,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
spin_unlock_irqrestore(&dev->event_lock, flags);

return 0;

err_unlock:
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
err_put:
drm_vblank_put(dev, e->pipe);
return ret;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_BLT:
value = HAS_BLT(dev);
break;
case I915_PARAM_HAS_COHERENT_RINGS:
value = 1;
break;
default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param);
Expand Down
12 changes: 11 additions & 1 deletion drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -4374,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
* use this buffer rather sooner than later, so issuing the required
* flush earlier is beneficial.
*/
if (obj->write_domain & I915_GEM_GPU_DOMAINS)
if (obj->write_domain & I915_GEM_GPU_DOMAINS) {
i915_gem_flush_ring(dev, file_priv,
obj_priv->ring,
0, obj->write_domain);
} else if (obj_priv->ring->outstanding_lazy_request) {
/* This ring is not being cleared by active usage,
* so emit a request to do so.
*/
u32 seqno = i915_add_request(dev,
NULL, NULL,
obj_priv->ring);
if (seqno == 0)
ret = -ENOMEM;
}

/* Update the active list for the hardware's current position.
* Otherwise this only updates on a delayed timer or when irqs
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,7 @@
#define TRANS_DP_10BPC (1<<9)
#define TRANS_DP_6BPC (2<<9)
#define TRANS_DP_12BPC (3<<9)
#define TRANS_DP_BPC_MASK (3<<9)
#define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4)
#define TRANS_DP_VSYNC_ACTIVE_LOW 0
#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3)
Expand Down
34 changes: 0 additions & 34 deletions drivers/gpu/drm/i915/intel_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,37 +190,6 @@ static void intel_dsm_platform_mux_info(void)
kfree(output.pointer);
}

static int intel_dsm_switchto(enum vga_switcheroo_client_id id)
{
return 0;
}

static int intel_dsm_power_state(enum vga_switcheroo_client_id id,
enum vga_switcheroo_state state)
{
return 0;
}

static int intel_dsm_init(void)
{
return 0;
}

static int intel_dsm_get_client_id(struct pci_dev *pdev)
{
if (intel_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
return VGA_SWITCHEROO_IGD;
else
return VGA_SWITCHEROO_DIS;
}

static struct vga_switcheroo_handler intel_dsm_handler = {
.switchto = intel_dsm_switchto,
.power_state = intel_dsm_power_state,
.init = intel_dsm_init,
.get_client_id = intel_dsm_get_client_id,
};

static bool intel_dsm_pci_probe(struct pci_dev *pdev)
{
acpi_handle dhandle, intel_handle;
Expand Down Expand Up @@ -276,11 +245,8 @@ void intel_register_dsm_handler(void)
{
if (!intel_dsm_detect())
return;

vga_switcheroo_register_handler(&intel_dsm_handler);
}

void intel_unregister_dsm_handler(void)
{
vga_switcheroo_unregister_handler();
}
76 changes: 62 additions & 14 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2120,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK |
TRANS_DP_SYNC_MASK);
TRANS_DP_SYNC_MASK |
TRANS_DP_BPC_MASK);
temp |= (TRANS_DP_OUTPUT_ENABLE |
TRANS_DP_ENH_FRAMING);
temp |= TRANS_DP_8BPC;

if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
Expand Down Expand Up @@ -2712,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den)
}
}

#define DATA_N 0x800000
#define LINK_N 0x80000

static void
ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
int link_clock, struct fdi_m_n *m_n)
{
u64 temp;

m_n->tu = 64; /* default size */

temp = (u64) DATA_N * pixel_clock;
temp = div_u64(temp, link_clock);
m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes);
m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
m_n->gmch_n = DATA_N;
/* BUG_ON(pixel_clock > INT_MAX / 36); */
m_n->gmch_m = bits_per_pixel * pixel_clock;
m_n->gmch_n = link_clock * nlanes * 8;
fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);

temp = (u64) LINK_N * pixel_clock;
m_n->link_m = div_u64(temp, link_clock);
m_n->link_n = LINK_N;
m_n->link_m = pixel_clock;
m_n->link_n = link_clock;
fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
}

Expand Down Expand Up @@ -3716,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,

/* FDI link */
if (HAS_PCH_SPLIT(dev)) {
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
int lane = 0, link_bw, bpp;
/* CPU eDP doesn't require FDI link, so just set DP M/N
according to current link config */
Expand Down Expand Up @@ -3799,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,

intel_crtc->fdi_lanes = lane;

if (pixel_multiplier > 1)
link_bw *= pixel_multiplier;
ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
}

Expand Down Expand Up @@ -5236,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
.page_flip = intel_crtc_page_flip,
};

static void intel_sanitize_modesetting(struct drm_device *dev,
int pipe, int plane)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg, val;

if (HAS_PCH_SPLIT(dev))
return;

/* Who knows what state these registers were left in by the BIOS or
* grub?
*
* If we leave the registers in a conflicting state (e.g. with the
* display plane reading from the other pipe than the one we intend
* to use) then when we attempt to teardown the active mode, we will
* not disable the pipes and planes in the correct order -- leaving
* a plane reading from a disabled pipe and possibly leading to
* undefined behaviour.
*/

reg = DSPCNTR(plane);
val = I915_READ(reg);

if ((val & DISPLAY_PLANE_ENABLE) == 0)
return;
if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
return;

/* This display plane is active and attached to the other CPU pipe. */
pipe = !pipe;

/* Disable the plane and wait for it to stop reading from the pipe. */
I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
intel_flush_display_plane(dev, plane);

if (IS_GEN2(dev))
intel_wait_for_vblank(dev, pipe);

if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
return;

/* Switch off the pipe. */
reg = PIPECONF(pipe);
val = I915_READ(reg);
if (val & PIPECONF_ENABLE) {
I915_WRITE(reg, val & ~PIPECONF_ENABLE);
intel_wait_for_pipe_off(dev, pipe);
}
}

static void intel_crtc_init(struct drm_device *dev, int pipe)
{
Expand Down Expand Up @@ -5287,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)

setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
(unsigned long)intel_crtc);

intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
}

int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
Expand Down
25 changes: 25 additions & 0 deletions drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t DP = intel_dp->DP;

if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
return;

DRM_DEBUG_KMS("\n");

if (is_edp(intel_dp)) {
Expand All @@ -1398,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)

if (is_edp(intel_dp))
DP |= DP_LINK_TRAIN_OFF;

if (!HAS_PCH_CPT(dev) &&
I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
/* Hardware workaround: leaving our transcoder select
* set to transcoder B while it's off will prevent the
* corresponding HDMI output on transcoder A.
*
* Combine this with another hardware workaround:
* transcoder select bit can only be cleared while the
* port is enabled.
*/
DP &= ~DP_PIPEB_SELECT;
I915_WRITE(intel_dp->output_reg, DP);

/* Changes to enable or select take place the vblank
* after being written.
*/
intel_wait_for_vblank(intel_dp->base.base.dev,
intel_crtc->pipe);
}

I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg);
}
Expand Down
Loading

0 comments on commit 6dde39b

Please sign in to comment.