Merge branch 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel

* 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel:
  drm/i915: Add new GET_PIPE_FROM_CRTC_ID ioctl.
  drm/i915: Set HDMI hot plug interrupt enable for only the output in question.
  drm/i915: Include 965GME pci ID in IS_I965GM(dev) to match UMS.
  drm/i915: Use the GM45 VGA hotplug workaround on G45 as well.
  drm/i915: ignore LVDS on intel graphics systems that lie about having it
  drm/i915: sanity check IER at wait_request time
  drm/i915: workaround IGD i2c bus issue in kernel side (v2)
  drm/i915: Don't allow binding objects into the last page of the aperture.
  drm/i915: save/restore fence registers across suspend/resume
  drm/i915: x86 always has writeq. Add I915_READ64 for symmetry.
This commit is contained in:
Linus Torvalds 2009-05-15 13:22:11 -07:00
commit 40f293ff83
13 changed files with 175 additions and 24 deletions

View File

@ -1011,8 +1011,16 @@ static int i915_load_modeset_init(struct drm_device *dev)
/* Basic memrange allocator for stolen space (aka vram) */
drm_mm_init(&dev_priv->vram, 0, prealloc_size);
/* Let GEM Manage from end of prealloc space to end of aperture */
i915_gem_do_init(dev, prealloc_size, agp_size);
/* Let GEM Manage from end of prealloc space to end of aperture.
*
* However, leave one page at the end still bound to the scratch page.
* There are a number of places where the hardware apparently
* prefetches past the end of the object, and we've seen multiple
* hangs with the GPU head pointer stuck in a batchbuffer bound
* at the last page of the aperture. One page should be enough to
* keep any prefetching inside of the aperture.
*/
i915_gem_do_init(dev, prealloc_size, agp_size - 4096);
ret = i915_gem_init_ringbuffer(dev);
if (ret)
@ -1350,6 +1358,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);

View File

@ -283,6 +283,7 @@ typedef struct drm_i915_private {
u8 saveAR[21];
u8 saveDACMASK;
u8 saveCR[37];
uint64_t saveFENCE[16];
struct {
struct drm_mm gtt_space;
@ -705,13 +706,8 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
#define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg))
#define I915_READ8(reg) readb(dev_priv->regs + (reg))
#define I915_WRITE8(reg, val) writeb(val, dev_priv->regs + (reg))
#ifdef writeq
#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg))
#else
#define I915_WRITE64(reg, val) (writel(val, dev_priv->regs + (reg)), \
writel(upper_32_bits(val), dev_priv->regs + \
(reg) + 4))
#endif
#define I915_READ64(reg) readq(dev_priv->regs + (reg))
#define POSTING_READ(reg) (void)I915_READ(reg)
#define I915_VERBOSE 0
@ -790,7 +786,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x2E22 || \
(dev)->pci_device == 0x2E32)
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
(dev)->pci_device == 0x2A12)
#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)

View File

@ -1691,11 +1691,20 @@ static int
i915_wait_request(struct drm_device *dev, uint32_t seqno)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 ier;
int ret = 0;
BUG_ON(seqno == 0);
if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
ier = I915_READ(IER);
if (!ier) {
DRM_ERROR("something (likely vbetool) disabled "
"interrupts, re-enabling\n");
i915_driver_irq_preinstall(dev);
i915_driver_irq_postinstall(dev);
}
dev_priv->mm.waiting_gem_seqno = seqno;
i915_user_irq_get(dev);
ret = wait_event_interruptible(dev_priv->irq_queue,

View File

@ -526,6 +526,7 @@
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
#define D_STATE 0x6104
#define CG_2D_DIS 0x6200
#define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24)
#define CG_3D_DIS 0x6204
/*

View File

@ -349,6 +349,18 @@ int i915_save_state(struct drm_device *dev)
for (i = 0; i < 3; i++)
dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
/* Fences */
if (IS_I965G(dev)) {
for (i = 0; i < 16; i++)
dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
} else {
for (i = 0; i < 8; i++)
dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
for (i = 0; i < 8; i++)
dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
}
i915_save_vga(dev);
return 0;
@ -371,6 +383,18 @@ int i915_restore_state(struct drm_device *dev)
/* Display arbitration */
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
/* Fences */
if (IS_I965G(dev)) {
for (i = 0; i < 16; i++)
I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
} else {
for (i = 0; i < 8; i++)
I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
for (i = 0; i < 8; i++)
I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
}
/* Pipe & plane A info */
/* Prime the clock */
if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {

View File

@ -161,7 +161,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
if (IS_GM45(dev))
if (IS_G4X(dev))
hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;

View File

@ -1804,6 +1804,37 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
}
}
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
struct drm_crtc *crtc = NULL;
int pipe = -1;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
if (crtc->base.id == pipe_from_crtc_id->crtc_id) {
pipe = intel_crtc->pipe;
break;
}
}
if (pipe == -1) {
DRM_ERROR("no such CRTC id\n");
return -EINVAL;
}
pipe_from_crtc_id->pipe = pipe;
return 0;
}
struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
{
struct drm_crtc *crtc = NULL;

View File

@ -109,7 +109,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
void intel_i2c_destroy(struct intel_i2c_chan *chan);
int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
@ -125,6 +125,8 @@ extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc);
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void intel_wait_for_vblank(struct drm_device *dev);
extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,

View File

@ -155,11 +155,18 @@ intel_hdmi_detect(struct drm_connector *connector)
temp = I915_READ(PORT_HOTPLUG_EN);
I915_WRITE(PORT_HOTPLUG_EN,
temp |
HDMIB_HOTPLUG_INT_EN |
HDMIC_HOTPLUG_INT_EN |
HDMID_HOTPLUG_INT_EN);
switch (hdmi_priv->sdvox_reg) {
case SDVOB:
temp |= HDMIB_HOTPLUG_INT_EN;
break;
case SDVOC:
temp |= HDMIC_HOTPLUG_INT_EN;
break;
default:
return connector_status_unknown;
}
I915_WRITE(PORT_HOTPLUG_EN, temp);
POSTING_READ(PORT_HOTPLUG_EN);

View File

@ -34,6 +34,21 @@
#include "i915_drm.h"
#include "i915_drv.h"
void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
/* When using bit bashing for I2C, this bit needs to be set to 1 */
if (!IS_IGD(dev))
return;
if (enable)
I915_WRITE(CG_2D_DIS,
I915_READ(CG_2D_DIS) | DPCUNIT_CLOCK_GATE_DISABLE);
else
I915_WRITE(CG_2D_DIS,
I915_READ(CG_2D_DIS) & (~DPCUNIT_CLOCK_GATE_DISABLE));
}
/*
* Intel GPIO access functions
*/
@ -153,8 +168,10 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
goto out_free;
/* JJJ: raise SCL and SDA? */
intel_i2c_quirk_set(dev, true);
set_data(chan, 1);
set_clock(chan, 1);
intel_i2c_quirk_set(dev, false);
udelay(20);
return chan;

View File

@ -384,7 +384,51 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
.destroy = intel_lvds_enc_destroy,
};
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
{
DRM_DEBUG("Skipping LVDS initialization for %s\n", id->ident);
return 1;
}
/* These systems claim to have LVDS, but really don't */
static const struct dmi_system_id __initdata intel_no_lvds[] = {
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Apple Mac Mini (Core series)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Apple Mac Mini (Core 2 series)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "MSI IM-945GSE-A",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Dell Studio Hybrid",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
},
},
/* FIXME: add a check for the Aopen Mini PC */
{ } /* terminating entry */
};
/**
* intel_lvds_init - setup LVDS connectors on this device
@ -404,15 +448,9 @@ void intel_lvds_init(struct drm_device *dev)
u32 lvds;
int pipe;
/* Blacklist machines that we know falsely report LVDS. */
/* FIXME: add a check for the Aopen Mini PC */
/* Apple Mac Mini Core Duo and Mac Mini Core 2 Duo */
if(dmi_match(DMI_PRODUCT_NAME, "Macmini1,1") ||
dmi_match(DMI_PRODUCT_NAME, "Macmini2,1")) {
DRM_DEBUG("Skipping LVDS initialization for Apple Mac Mini\n");
/* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds))
return;
}
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
if (!intel_output) {

View File

@ -27,6 +27,7 @@
#include <linux/fb.h>
#include "drmP.h"
#include "intel_drv.h"
#include "i915_drv.h"
/**
* intel_ddc_probe
@ -52,7 +53,10 @@ bool intel_ddc_probe(struct intel_output *intel_output)
}
};
intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
if (ret == 2)
return true;
@ -70,8 +74,10 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
struct edid *edid;
int ret = 0;
intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
edid = drm_get_edid(&intel_output->base,
&intel_output->ddc_bus->adapter);
intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
if (edid) {
drm_mode_connector_update_edid_property(&intel_output->base,
edid);

View File

@ -184,6 +184,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_GET_TILING 0x22
#define DRM_I915_GEM_GET_APERTURE 0x23
#define DRM_I915_GEM_MMAP_GTT 0x24
#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@ -219,6 +220,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_intel_get_pipe_from_crtc_id)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@ -657,4 +659,12 @@ struct drm_i915_gem_get_aperture {
__u64 aper_available_size;
};
struct drm_i915_get_pipe_from_crtc_id {
/** ID of CRTC being requested **/
__u32 crtc_id;
/** pipe of requested CRTC **/
__u32 pipe;
};
#endif /* _I915_DRM_H_ */