Skip to content

Commit

Permalink
Merge branch 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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.
  • Loading branch information
Linus Torvalds committed May 15, 2009
2 parents 8c21f34 + 08d7b3d commit 40f293f
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 24 deletions.
13 changes: 11 additions & 2 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 4 additions & 7 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
9 changes: 9 additions & 0 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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 @@ -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

/*
Expand Down
24 changes: 24 additions & 0 deletions drivers/gpu/drm/i915/i915_suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/intel_crt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
31 changes: 31 additions & 0 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down
17 changes: 12 additions & 5 deletions drivers/gpu/drm/i915/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/i915/intel_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
Expand Down
54 changes: 46 additions & 8 deletions drivers/gpu/drm/i915/intel_lvds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/i915/intel_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/fb.h>
#include "drmP.h"
#include "intel_drv.h"
#include "i915_drv.h"

/**
* intel_ddc_probe
Expand All @@ -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;

Expand All @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions include/drm/i915_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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_ */

0 comments on commit 40f293f

Please sign in to comment.