i915 preview #3

git-svn-id: svn://kolibrios.org@2342 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2012-02-03 06:54:20 +00:00
parent 5491cb4d99
commit 9566458ddb
32 changed files with 4677 additions and 2315 deletions

View File

@ -6,6 +6,16 @@
#include "intel_drv.h" #include "intel_drv.h"
#include "bitmap.h" #include "bitmap.h"
void __attribute__((regparm(1))) destroy_bitmap(bitmap_t *bitmap)
{
/*
*
*
*
*/
__DestroyObject(bitmap);
};
extern struct drm_device *main_device; extern struct drm_device *main_device;
struct hman bm_man; struct hman bm_man;
@ -20,12 +30,14 @@ int init_bitmaps()
}; };
int create_bitmap(struct ubitmap *pbitmap, int width, int height) int create_bitmap(struct ubitmap *pbitmap)
{ {
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
bitmap_t *bitmap; bitmap_t *bitmap;
u32 handle; u32 handle;
u32 width;
u32 height;
u32 size; u32 size;
u32 pitch; u32 pitch;
void *uaddr; void *uaddr;
@ -35,15 +47,24 @@ int create_bitmap(struct ubitmap *pbitmap, int width, int height)
pbitmap->handle = 0; pbitmap->handle = 0;
pbitmap->data = NULL; pbitmap->data = NULL;
width = pbitmap->width;
height = pbitmap->height;
if((width==0)||(height==0)||(width>4096)||(height>4096)) if((width==0)||(height==0)||(width>4096)||(height>4096))
goto err1; goto err1;
handle = alloc_handle(&bm_man); handle = alloc_handle(&bm_man);
// printf("%s %d\n",__FUNCTION__, handle);
if(handle == 0) if(handle == 0)
goto err1; goto err1;
bitmap = CreateObject(GetPid(), sizeof(*bitmap)); bitmap = CreateObject(GetPid(), sizeof(*bitmap));
bitmap->handle = handle;
bitmap->header.destroy = destroy_bitmap;
bitmap->obj = NULL;
// printf("bitmap %x\n", bitmap);
if( bitmap == NULL) if( bitmap == NULL)
goto err1; goto err1;
@ -52,6 +73,7 @@ int create_bitmap(struct ubitmap *pbitmap, int width, int height)
pitch = ALIGN(width*4,64); pitch = ALIGN(width*4,64);
size = roundup(pitch*height, PAGE_SIZE); size = roundup(pitch*height, PAGE_SIZE);
// printf("pitch %d size %d\n", pitch, size);
obj = i915_gem_alloc_object(main_device, size); obj = i915_gem_alloc_object(main_device, size);
if (obj == NULL) if (obj == NULL)
@ -88,9 +110,15 @@ int create_bitmap(struct ubitmap *pbitmap, int width, int height)
bitmap->gaddr = obj->gtt_offset; bitmap->gaddr = obj->gtt_offset;
bitmap->uaddr = uaddr; bitmap->uaddr = uaddr;
bitmap->obj = obj; bitmap->obj = obj;
bitmap->header.destroy = destroy_bitmap;
pbitmap->pitch = pitch;
pbitmap->handle = handle; pbitmap->handle = handle;
pbitmap->data = uaddr; pbitmap->data = uaddr;
// printf("%s handle %d pitch %d gpu %x user %x\n",
// __FUNCTION__, handle, pitch, obj->gtt_offset, uaddr);
return 0; return 0;
err4: err4:
@ -99,74 +127,13 @@ err3:
// drm_gem_object_unreference(&obj->base); // drm_gem_object_unreference(&obj->base);
err2: err2:
free_handle(&bm_man, handle); free_handle(&bm_man, handle);
DestroyObject(bitmap); __DestroyObject(bitmap);
err1: err1:
return -1; return -1;
}; };
int create_video(int width, int height, u32_t *outp)
{
struct drm_i915_gem_object *obj;
size_t size;
size_t pitch;
void *uaddr;
int ret;
if((width==0)||(height==0)||(width>4096)||(height>4096))
goto err1;
pitch = ALIGN(width*4,64);
size = roundup(pitch*height, PAGE_SIZE);
obj = i915_gem_alloc_object(main_device, size);
if (obj == NULL)
goto err2;
ret = i915_gem_object_pin(obj, 4096, true);
if (ret)
goto err3;
uaddr = UserAlloc(size);
if( uaddr == NULL)
goto err4;
else
{
u32_t *src, *dst;
int count;
#define page_tabs 0xFDC00000 /* really dirty hack */
src = (u32_t*)obj->pages;
dst = &((u32_t*)page_tabs)[(u32_t)uaddr >> 12];
count = size/4096;
while(count--)
{
*dst++ = (0xFFFFF000 & *src++) | 0x207 ; // map as shared page
};
}
outp[0] = obj->gtt_offset;
outp[2] = (u32)uaddr;
outp[3] = pitch;
return 0;
err4:
// drm_gem_object_unpin;
err3:
// drm_gem_object_unreference(&obj->base);
err2:
err1:
return -1;
};
int init_hman(struct hman *man, u32 count) int init_hman(struct hman *man, u32 count)
{ {
u32* data; u32* data;

View File

@ -55,5 +55,6 @@ struct ubitmap
void *data; void *data;
}; };
int create_bitmap(struct ubitmap *pbitmap, int width, int height); int create_bitmap(struct ubitmap *pbitmap);
int init_bitmaps();

View File

@ -560,11 +560,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
// if (!IS_I945G(dev) && !IS_I945GM(dev)) // if (!IS_I945G(dev) && !IS_I945GM(dev))
// pci_enable_msi(dev->pdev); // pci_enable_msi(dev->pdev);
spin_lock_init(&dev_priv->gt_lock);
spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->error_lock);
spin_lock_init(&dev_priv->rps_lock); spin_lock_init(&dev_priv->rps_lock);
if (IS_MOBILE(dev) || !IS_GEN2(dev)) if (IS_IVYBRIDGE(dev))
dev_priv->num_pipe = 3;
else if (IS_MOBILE(dev) || !IS_GEN2(dev))
dev_priv->num_pipe = 2; dev_priv->num_pipe = 2;
else else
dev_priv->num_pipe = 1; dev_priv->num_pipe = 1;

View File

@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 #define DRM_I915_OVERLAY_PUT_IMAGE 0x27
#define DRM_I915_OVERLAY_ATTRS 0x28 #define DRM_I915_OVERLAY_ATTRS 0x28
#define DRM_I915_GEM_EXECBUFFER2 0x29 #define DRM_I915_GEM_EXECBUFFER2 0x29
#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #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) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@ -239,6 +241,8 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) #define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
/* Allow drivers to submit batchbuffers directly to hardware, relying /* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware. * on the security mechanisms provided by hardware.
@ -291,6 +295,7 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_COHERENT_RINGS 13 #define I915_PARAM_HAS_COHERENT_RINGS 13
#define I915_PARAM_HAS_EXEC_CONSTANTS 14 #define I915_PARAM_HAS_EXEC_CONSTANTS 14
#define I915_PARAM_HAS_RELAXED_DELTA 15 #define I915_PARAM_HAS_RELAXED_DELTA 15
#define I915_PARAM_HAS_GEN7_SOL_RESET 16
typedef struct drm_i915_getparam { typedef struct drm_i915_getparam {
int param; int param;
@ -653,6 +658,9 @@ struct drm_i915_gem_execbuffer2 {
__u64 rsvd2; __u64 rsvd2;
}; };
/** Resets the SO write offset registers for transform feedback on gen7. */
#define I915_EXEC_GEN7_SOL_RESET (1<<8)
struct drm_i915_gem_pin { struct drm_i915_gem_pin {
/** Handle of the buffer to be pinned. */ /** Handle of the buffer to be pinned. */
__u32 handle; __u32 handle;
@ -844,4 +852,36 @@ struct drm_intel_overlay_attrs {
__u32 gamma5; __u32 gamma5;
}; };
/*
* Intel sprite handling
*
* Color keying works with a min/mask/max tuple. Both source and destination
* color keying is allowed.
*
* Source keying:
* Sprite pixels within the min & max values, masked against the color channels
* specified in the mask field, will be transparent. All other pixels will
* be displayed on top of the primary plane. For RGB surfaces, only the min
* and mask fields will be used; ranged compares are not allowed.
*
* Destination keying:
* Primary plane pixels that match the min value, masked against the color
* channels specified in the mask field, will be replaced by corresponding
* pixels from the sprite plane.
*
* Note that source & destination keying are exclusive; only one can be
* active on a given plane.
*/
#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */
#define I915_SET_COLORKEY_DESTINATION (1<<1)
#define I915_SET_COLORKEY_SOURCE (1<<2)
struct drm_intel_sprite_colorkey {
__u32 plane_id;
__u32 min_value;
__u32 channel_mask;
__u32 max_value;
__u32 flags;
};
#endif /* _I915_DRM_H_ */ #endif /* _I915_DRM_H_ */

View File

@ -53,7 +53,7 @@ int i915_panel_ignore_lid __read_mostly = 0;
unsigned int i915_powersave __read_mostly = 0; unsigned int i915_powersave __read_mostly = 0;
unsigned int i915_enable_rc6 __read_mostly = 0; unsigned int i915_enable_rc6 __read_mostly = -1;
unsigned int i915_enable_fbc __read_mostly = 0; unsigned int i915_enable_fbc __read_mostly = 0;
@ -66,7 +66,7 @@ int i915_vbt_sdvo_panel_type __read_mostly = -1;
#define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_VENDOR_ID_INTEL 0x8086
#define INTEL_VGA_DEVICE(id, info) { \ #define INTEL_VGA_DEVICE(id, info) { \
.class = PCI_CLASS_DISPLAY_VGA << 8, \ .class = PCI_BASE_CLASS_DISPLAY << 16, \
.class_mask = 0xff0000, \ .class_mask = 0xff0000, \
.vendor = 0x8086, \ .vendor = 0x8086, \
.device = id, \ .device = id, \
@ -277,7 +277,7 @@ void intel_detect_pch (struct drm_device *dev)
} }
} }
static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
{ {
int count; int count;
@ -293,6 +293,22 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
udelay(10); udelay(10);
} }
void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
{
int count;
count = 0;
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
udelay(10);
I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
POSTING_READ(FORCEWAKE_MT);
count = 0;
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
udelay(10);
}
/* /*
* Generally this is called implicitly by the register read function. However, * Generally this is called implicitly by the register read function. However,
* if some sequence requires the GT to not power down then this function should * if some sequence requires the GT to not power down then this function should
@ -301,28 +317,37 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
*/ */
void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
{ {
// WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); unsigned long irqflags;
/* Forcewake is atomic in case we get in here without the lock */ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) if (dev_priv->forcewake_count++ == 0)
__gen6_gt_force_wake_get(dev_priv); dev_priv->display.force_wake_get(dev_priv);
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
} }
static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE, 0); I915_WRITE_NOTRACE(FORCEWAKE, 0);
POSTING_READ(FORCEWAKE); POSTING_READ(FORCEWAKE);
} }
void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
{
I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
POSTING_READ(FORCEWAKE_MT);
}
/* /*
* see gen6_gt_force_wake_get() * see gen6_gt_force_wake_get()
*/ */
void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
{ {
// WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); unsigned long irqflags;
if (atomic_dec_and_test(&dev_priv->forcewake_count)) spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
__gen6_gt_force_wake_put(dev_priv); if (--dev_priv->forcewake_count == 0)
dev_priv->display.force_wake_put(dev_priv);
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
} }
void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
@ -441,3 +466,39 @@ err_g4:
} }
#define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
u##x val = 0; \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
unsigned long irqflags; \
spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
if (dev_priv->forcewake_count == 0) \
dev_priv->display.force_wake_get(dev_priv); \
val = read##y(dev_priv->regs + reg); \
if (dev_priv->forcewake_count == 0) \
dev_priv->display.force_wake_put(dev_priv); \
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
} else { \
val = read##y(dev_priv->regs + reg); \
} \
return val; \
}
__i915_read(8, b)
__i915_read(16, w)
__i915_read(32, l)
__i915_read(64, q)
#undef __i915_read
#define __i915_write(x, y) \
void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__gen6_gt_wait_for_fifo(dev_priv); \
} \
write##y(val, dev_priv->regs + reg); \
}
__i915_write(8, b)
__i915_write(16, w)
__i915_write(32, l)
__i915_write(64, q)
#undef __i915_write

View File

@ -105,6 +105,7 @@ struct opregion_header;
struct opregion_acpi; struct opregion_acpi;
struct opregion_swsci; struct opregion_swsci;
struct opregion_asle; struct opregion_asle;
struct drm_i915_private;
struct intel_opregion { struct intel_opregion {
struct opregion_header *header; struct opregion_header *header;
@ -124,6 +125,9 @@ struct drm_i915_master_private {
struct _drm_i915_sarea *sarea_priv; struct _drm_i915_sarea *sarea_priv;
}; };
#define I915_FENCE_REG_NONE -1 #define I915_FENCE_REG_NONE -1
#define I915_MAX_NUM_FENCES 16
/* 16 fences + sign bit for FENCE_REG_NONE */
#define I915_MAX_NUM_FENCE_BITS 5
struct drm_i915_fence_reg { struct drm_i915_fence_reg {
struct list_head lru_list; struct list_head lru_list;
@ -137,7 +141,6 @@ struct sdvo_device_mapping {
u8 slave_addr; u8 slave_addr;
u8 dvo_wiring; u8 dvo_wiring;
u8 i2c_pin; u8 i2c_pin;
u8 i2c_speed;
u8 ddc_pin; u8 ddc_pin;
}; };
@ -167,7 +170,7 @@ struct drm_i915_error_state {
u32 instdone1; u32 instdone1;
u32 seqno; u32 seqno;
u64 bbaddr; u64 bbaddr;
u64 fence[16]; u64 fence[I915_MAX_NUM_FENCES];
struct timeval time; struct timeval time;
struct drm_i915_error_object { struct drm_i915_error_object {
int page_count; int page_count;
@ -181,7 +184,7 @@ struct drm_i915_error_state {
u32 gtt_offset; u32 gtt_offset;
u32 read_domains; u32 read_domains;
u32 write_domain; u32 write_domain;
s32 fence_reg:5; s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
s32 pinned:2; s32 pinned:2;
u32 tiling:2; u32 tiling:2;
u32 dirty:1; u32 dirty:1;
@ -202,11 +205,15 @@ struct drm_i915_display_funcs {
int (*get_display_clock_speed)(struct drm_device *dev); int (*get_display_clock_speed)(struct drm_device *dev);
int (*get_fifo_size)(struct drm_device *dev, int plane); int (*get_fifo_size)(struct drm_device *dev, int plane);
void (*update_wm)(struct drm_device *dev); void (*update_wm)(struct drm_device *dev);
void (*update_sprite_wm)(struct drm_device *dev, int pipe,
uint32_t sprite_width, int pixel_size);
int (*crtc_mode_set)(struct drm_crtc *crtc, int (*crtc_mode_set)(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, struct drm_display_mode *adjusted_mode,
int x, int y, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
void (*write_eld)(struct drm_connector *connector,
struct drm_crtc *crtc);
void (*fdi_link_train)(struct drm_crtc *crtc); void (*fdi_link_train)(struct drm_crtc *crtc);
void (*init_clock_gating)(struct drm_device *dev); void (*init_clock_gating)(struct drm_device *dev);
void (*init_pch_clock_gating)(struct drm_device *dev); void (*init_pch_clock_gating)(struct drm_device *dev);
@ -215,6 +222,8 @@ struct drm_i915_display_funcs {
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
int x, int y); int x, int y);
void (*force_wake_get)(struct drm_i915_private *dev_priv);
void (*force_wake_put)(struct drm_i915_private *dev_priv);
/* clock updates for mode set */ /* clock updates for mode set */
/* cursor updates */ /* cursor updates */
/* render clock increase/decrease */ /* render clock increase/decrease */
@ -277,7 +286,13 @@ typedef struct drm_i915_private {
int relative_constants_mode; int relative_constants_mode;
void __iomem *regs; void __iomem *regs;
u32 gt_fifo_count; /** gt_fifo_count and the subsequent register write are synchronized
* with dev->struct_mutex. */
unsigned gt_fifo_count;
/** forcewake_count is protected by gt_lock */
unsigned forcewake_count;
/** gt_lock is also taken in irq contexts. */
spinlock_t gt_lock;
struct intel_gmbus { struct intel_gmbus {
struct i2c_adapter adapter; struct i2c_adapter adapter;
@ -328,6 +343,8 @@ typedef struct drm_i915_private {
struct timer_list hangcheck_timer; struct timer_list hangcheck_timer;
int hangcheck_count; int hangcheck_count;
uint32_t last_acthd; uint32_t last_acthd;
uint32_t last_acthd_bsd;
uint32_t last_acthd_blt;
uint32_t last_instdone; uint32_t last_instdone;
uint32_t last_instdone1; uint32_t last_instdone1;
@ -341,11 +358,11 @@ typedef struct drm_i915_private {
/* overlay */ /* overlay */
// struct intel_overlay *overlay; // struct intel_overlay *overlay;
bool sprite_scaling_enabled;
/* LVDS info */ /* LVDS info */
int backlight_level; /* restore backlight to this value */ int backlight_level; /* restore backlight to this value */
bool backlight_enabled; bool backlight_enabled;
struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
@ -355,6 +372,7 @@ typedef struct drm_i915_private {
unsigned int lvds_vbt:1; unsigned int lvds_vbt:1;
unsigned int int_crt_support:1; unsigned int int_crt_support:1;
unsigned int lvds_use_ssc:1; unsigned int lvds_use_ssc:1;
unsigned int display_clock_mode:1;
int lvds_ssc_freq; int lvds_ssc_freq;
struct { struct {
int rate; int rate;
@ -372,7 +390,7 @@ typedef struct drm_i915_private {
// struct notifier_block lid_notifier; // struct notifier_block lid_notifier;
int crt_ddc_pin; int crt_ddc_pin;
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@ -503,7 +521,7 @@ typedef struct drm_i915_private {
u8 saveAR[21]; u8 saveAR[21];
u8 saveDACMASK; u8 saveDACMASK;
u8 saveCR[37]; u8 saveCR[37];
uint64_t saveFENCE[16]; uint64_t saveFENCE[I915_MAX_NUM_FENCES];
u32 saveCURACNTR; u32 saveCURACNTR;
u32 saveCURAPOS; u32 saveCURAPOS;
u32 saveCURABASE; u32 saveCURABASE;
@ -670,10 +688,9 @@ typedef struct drm_i915_private {
unsigned int lvds_border_bits; unsigned int lvds_border_bits;
/* Panel fitter placement and size for Ironlake+ */ /* Panel fitter placement and size for Ironlake+ */
u32 pch_pf_pos, pch_pf_size; u32 pch_pf_pos, pch_pf_size;
int panel_t3, panel_t12;
struct drm_crtc *plane_to_crtc_mapping[2]; struct drm_crtc *plane_to_crtc_mapping[3];
struct drm_crtc *pipe_to_crtc_mapping[2]; struct drm_crtc *pipe_to_crtc_mapping[3];
// wait_queue_head_t pending_flip_queue; // wait_queue_head_t pending_flip_queue;
bool flip_pending_is_done; bool flip_pending_is_done;
@ -705,6 +722,7 @@ typedef struct drm_i915_private {
u64 last_count1; u64 last_count1;
unsigned long last_time1; unsigned long last_time1;
unsigned long chipset_power;
u64 last_count2; u64 last_count2;
struct timespec last_time2; struct timespec last_time2;
unsigned long gfx_power; unsigned long gfx_power;
@ -727,8 +745,6 @@ typedef struct drm_i915_private {
// struct drm_property *broadcast_rgb_property; // struct drm_property *broadcast_rgb_property;
// struct drm_property *force_audio_property; // struct drm_property *force_audio_property;
atomic_t forcewake_count;
} drm_i915_private_t; } drm_i915_private_t;
enum i915_cache_level { enum i915_cache_level {
@ -775,10 +791,8 @@ struct drm_i915_gem_object {
* Fence register bits (if any) for this object. Will be set * Fence register bits (if any) for this object. Will be set
* as needed when mapped into the GTT. * as needed when mapped into the GTT.
* Protected by dev->struct_mutex. * Protected by dev->struct_mutex.
*
* Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
*/ */
signed int fence_reg : 5; signed int fence_reg:I915_MAX_NUM_FENCE_BITS;
/** /**
* Advice: are the backing pages purgeable? * Advice: are the backing pages purgeable?
@ -915,7 +929,7 @@ struct drm_i915_gem_request {
struct drm_i915_file_private { struct drm_i915_file_private {
struct { struct {
// struct spinlock lock; spinlock_t lock;
struct list_head request_list; struct list_head request_list;
} mm; } mm;
}; };
@ -1159,6 +1173,9 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
return ring->outstanding_lazy_request = dev_priv->next_seqno; return ring->outstanding_lazy_request = dev_priv->next_seqno;
} }
int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *pipelined);
int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_reset(struct drm_device *dev); void i915_gem_reset(struct drm_device *dev);
@ -1255,12 +1272,10 @@ extern int intel_setup_gmbus(struct drm_device *dev);
extern void intel_teardown_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev);
extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
//extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) {
//{ return container_of(adapter, struct intel_gmbus, adapter)->force_bit;
// return container_of(adapter, struct intel_gmbus, adapter)->force_bit; }
//}
extern void intel_i2c_reset(struct drm_device *dev); extern void intel_i2c_reset(struct drm_device *dev);
/* intel_opregion.c */ /* intel_opregion.c */
@ -1296,11 +1311,17 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
extern bool intel_fbc_enabled(struct drm_device *dev); extern bool intel_fbc_enabled(struct drm_device *dev);
extern void intel_disable_fbc(struct drm_device *dev); extern void intel_disable_fbc(struct drm_device *dev);
extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
extern void ironlake_init_pch_refclk(struct drm_device *dev);
extern void ironlake_enable_rc6(struct drm_device *dev); extern void ironlake_enable_rc6(struct drm_device *dev);
extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void gen6_set_rps(struct drm_device *dev, u8 val);
extern void intel_detect_pch(struct drm_device *dev); extern void intel_detect_pch(struct drm_device *dev);
extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
/* overlay */ /* overlay */
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
@ -1349,18 +1370,7 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
((reg) != FORCEWAKE)) ((reg) != FORCEWAKE))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
u##x val = 0; \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
gen6_gt_force_wake_get(dev_priv); \
val = read##y(dev_priv->regs + reg); \
gen6_gt_force_wake_put(dev_priv); \
} else { \
val = read##y(dev_priv->regs + reg); \
} \
/* trace_i915_reg_rw(false, reg, val, sizeof(val)); */\
return val; \
}
__i915_read(8, b) __i915_read(8, b)
__i915_read(16, w) __i915_read(16, w)
@ -1369,13 +1379,8 @@ __i915_read(64, q)
#undef __i915_read #undef __i915_read
#define __i915_write(x, y) \ #define __i915_write(x, y) \
static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
/* trace_i915_reg_rw(true, reg, val, sizeof(val));*/ \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__gen6_gt_wait_for_fifo(dev_priv); \
} \
write##y(val, dev_priv->regs + reg); \
}
__i915_write(8, b) __i915_write(8, b)
__i915_write(16, w) __i915_write(16, w)
__i915_write(32, l) __i915_write(32, l)

View File

@ -246,6 +246,8 @@ i915_gem_create(struct drm_file *file,
u32 handle; u32 handle;
size = roundup(size, PAGE_SIZE); size = roundup(size, PAGE_SIZE);
if (size == 0)
return -EINVAL;
/* Allocate the new object */ /* Allocate the new object */
obj = i915_gem_alloc_object(dev, size); obj = i915_gem_alloc_object(dev, size);
@ -1557,13 +1559,6 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
@ -1593,7 +1588,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->base.write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->base.read_domains = I915_GEM_DOMAIN_CPU;
if (IS_GEN6(dev)) { if (IS_GEN6(dev) || IS_GEN7(dev)) {
/* On Gen6, we can have the GPU use the LLC (the CPU /* On Gen6, we can have the GPU use the LLC (the CPU
* cache) for about a 10% performance improvement * cache) for about a 10% performance improvement
* compared to uncached. Graphics requests other than * compared to uncached. Graphics requests other than
@ -1787,7 +1782,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->mm.gtt_list); INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
for (i = 0; i < I915_NUM_RINGS; i++) for (i = 0; i < I915_NUM_RINGS; i++)
init_ring_lists(&dev_priv->ring[i]); init_ring_lists(&dev_priv->ring[i]);
for (i = 0; i < 16; i++) for (i = 0; i < I915_MAX_NUM_FENCES; i++)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
// INIT_DELAYED_WORK(&dev_priv->mm.retire_work, // INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
// i915_gem_retire_work_handler); // i915_gem_retire_work_handler);

View File

@ -110,7 +110,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
if (INTEL_INFO(dev)->gen >= 5) { if (INTEL_INFO(dev)->gen >= 6) {
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
} else if (IS_GEN5(dev)) {
/* On Ironlake whatever DRAM config, GPU always do /* On Ironlake whatever DRAM config, GPU always do
* same swizzling setup. * same swizzling setup.
*/ */
@ -459,14 +462,9 @@ i915_gem_swizzle_page(struct page *page)
void void
i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int page_count = obj->base.size >> PAGE_SHIFT; int page_count = obj->base.size >> PAGE_SHIFT;
int i; int i;
if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
return;
if (obj->bit_17 == NULL) if (obj->bit_17 == NULL)
return; return;
@ -483,14 +481,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
void void
i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int page_count = obj->base.size >> PAGE_SHIFT; int page_count = obj->base.size >> PAGE_SHIFT;
int i; int i;
if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
return;
if (obj->bit_17 == NULL) { if (obj->bit_17 == NULL) {
obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
sizeof(long), GFP_KERNEL); sizeof(long), GFP_KERNEL);

View File

@ -194,6 +194,13 @@
#define MI_SEMAPHORE_UPDATE (1<<21) #define MI_SEMAPHORE_UPDATE (1<<21)
#define MI_SEMAPHORE_COMPARE (1<<20) #define MI_SEMAPHORE_COMPARE (1<<20)
#define MI_SEMAPHORE_REGISTER (1<<18) #define MI_SEMAPHORE_REGISTER (1<<18)
#define MI_SEMAPHORE_SYNC_RV (2<<16)
#define MI_SEMAPHORE_SYNC_RB (0<<16)
#define MI_SEMAPHORE_SYNC_VR (0<<16)
#define MI_SEMAPHORE_SYNC_VB (2<<16)
#define MI_SEMAPHORE_SYNC_BR (2<<16)
#define MI_SEMAPHORE_SYNC_BV (0<<16)
#define MI_SEMAPHORE_SYNC_INVALID (1<<0)
/* /*
* 3D instructions used by the kernel * 3D instructions used by the kernel
*/ */
@ -235,16 +242,22 @@
#define ASYNC_FLIP (1<<22) #define ASYNC_FLIP (1<<22)
#define DISPLAY_PLANE_A (0<<20) #define DISPLAY_PLANE_A (0<<20)
#define DISPLAY_PLANE_B (1<<20) #define DISPLAY_PLANE_B (1<<20)
#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2) #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
#define PIPE_CONTROL_CS_STALL (1<<20)
#define PIPE_CONTROL_QW_WRITE (1<<14) #define PIPE_CONTROL_QW_WRITE (1<<14)
#define PIPE_CONTROL_DEPTH_STALL (1<<13) #define PIPE_CONTROL_DEPTH_STALL (1<<13)
#define PIPE_CONTROL_WC_FLUSH (1<<12) #define PIPE_CONTROL_WRITE_FLUSH (1<<12)
#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */ #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */
#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */ #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */
#define PIPE_CONTROL_ISP_DIS (1<<9) #define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */
#define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9)
#define PIPE_CONTROL_NOTIFY (1<<8) #define PIPE_CONTROL_NOTIFY (1<<8)
#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4)
#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3)
#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2)
#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1)
#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0)
#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
#define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */
/* /*
@ -296,6 +309,12 @@
#define RING_CTL(base) ((base)+0x3c) #define RING_CTL(base) ((base)+0x3c)
#define RING_SYNC_0(base) ((base)+0x40) #define RING_SYNC_0(base) ((base)+0x40)
#define RING_SYNC_1(base) ((base)+0x44) #define RING_SYNC_1(base) ((base)+0x44)
#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE))
#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE))
#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE))
#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE))
#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE))
#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE))
#define RING_MAX_IDLE(base) ((base)+0x54) #define RING_MAX_IDLE(base) ((base)+0x54)
#define RING_HWS_PGA(base) ((base)+0x80) #define RING_HWS_PGA(base) ((base)+0x80)
#define RING_HWS_PGA_GEN6(base) ((base)+0x2080) #define RING_HWS_PGA_GEN6(base) ((base)+0x2080)
@ -423,6 +442,7 @@
#define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts #define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts
will not assert AGPBUSY# and will only will not assert AGPBUSY# and will only
be delivered when out of C3. */ be delivered when out of C3. */
#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */
#define ACTHD 0x020c8 #define ACTHD 0x020c8
#define FW_BLC 0x020d8 #define FW_BLC 0x020d8
#define FW_BLC2 0x020dc #define FW_BLC2 0x020dc
@ -1534,12 +1554,21 @@
*/ */
#define PP_READY (1 << 30) #define PP_READY (1 << 30)
#define PP_SEQUENCE_NONE (0 << 28) #define PP_SEQUENCE_NONE (0 << 28)
#define PP_SEQUENCE_ON (1 << 28) #define PP_SEQUENCE_POWER_UP (1 << 28)
#define PP_SEQUENCE_OFF (2 << 28) #define PP_SEQUENCE_POWER_DOWN (2 << 28)
#define PP_SEQUENCE_MASK 0x30000000 #define PP_SEQUENCE_MASK (3 << 28)
#define PP_SEQUENCE_SHIFT 28
#define PP_CYCLE_DELAY_ACTIVE (1 << 27) #define PP_CYCLE_DELAY_ACTIVE (1 << 27)
#define PP_SEQUENCE_STATE_ON_IDLE (1 << 3)
#define PP_SEQUENCE_STATE_MASK 0x0000000f #define PP_SEQUENCE_STATE_MASK 0x0000000f
#define PP_SEQUENCE_STATE_OFF_IDLE (0x0 << 0)
#define PP_SEQUENCE_STATE_OFF_S0_1 (0x1 << 0)
#define PP_SEQUENCE_STATE_OFF_S0_2 (0x2 << 0)
#define PP_SEQUENCE_STATE_OFF_S0_3 (0x3 << 0)
#define PP_SEQUENCE_STATE_ON_IDLE (0x8 << 0)
#define PP_SEQUENCE_STATE_ON_S1_0 (0x9 << 0)
#define PP_SEQUENCE_STATE_ON_S1_2 (0xa << 0)
#define PP_SEQUENCE_STATE_ON_S1_3 (0xb << 0)
#define PP_SEQUENCE_STATE_RESET (0xf << 0)
#define PP_CONTROL 0x61204 #define PP_CONTROL 0x61204
#define POWER_TARGET_ON (1 << 0) #define POWER_TARGET_ON (1 << 0)
#define PP_ON_DELAYS 0x61208 #define PP_ON_DELAYS 0x61208
@ -2293,6 +2322,7 @@
#define PIPECONF_PROGRESSIVE (0 << 21) #define PIPECONF_PROGRESSIVE (0 << 21)
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
#define PIPECONF_INTERLACE_MASK (7 << 21)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16) #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_BPP_MASK (0x000000e0) #define PIPECONF_BPP_MASK (0x000000e0)
#define PIPECONF_BPP_8 (0<<5) #define PIPECONF_BPP_8 (0<<5)
@ -2416,6 +2446,7 @@
#define WM0_PIPE_CURSOR_MASK (0x1f) #define WM0_PIPE_CURSOR_MASK (0x1f)
#define WM0_PIPEB_ILK 0x45104 #define WM0_PIPEB_ILK 0x45104
#define WM0_PIPEC_IVB 0x45200
#define WM1_LP_ILK 0x45108 #define WM1_LP_ILK 0x45108
#define WM1_LP_SR_EN (1<<31) #define WM1_LP_SR_EN (1<<31)
#define WM1_LP_LATENCY_SHIFT 24 #define WM1_LP_LATENCY_SHIFT 24
@ -2430,6 +2461,8 @@
#define WM3_LP_ILK 0x45110 #define WM3_LP_ILK 0x45110
#define WM3_LP_EN (1<<31) #define WM3_LP_EN (1<<31)
#define WM1S_LP_ILK 0x45120 #define WM1S_LP_ILK 0x45120
#define WM2S_LP_IVB 0x45124
#define WM3S_LP_IVB 0x45128
#define WM1S_LP_EN (1<<31) #define WM1S_LP_EN (1<<31)
/* Memory latency timer register */ /* Memory latency timer register */
@ -2554,10 +2587,18 @@
#define _CURBBASE 0x700c4 #define _CURBBASE 0x700c4
#define _CURBPOS 0x700c8 #define _CURBPOS 0x700c8
#define _CURBCNTR_IVB 0x71080
#define _CURBBASE_IVB 0x71084
#define _CURBPOS_IVB 0x71088
#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS) #define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB)
#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB)
#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB)
/* Display A control */ /* Display A control */
#define _DSPACNTR 0x70180 #define _DSPACNTR 0x70180
#define DISPLAY_PLANE_ENABLE (1<<31) #define DISPLAY_PLANE_ENABLE (1<<31)
@ -2638,6 +2679,140 @@
#define _DSPBSURF 0x7119C #define _DSPBSURF 0x7119C
#define _DSPBTILEOFF 0x711A4 #define _DSPBTILEOFF 0x711A4
/* Sprite A control */
#define _DVSACNTR 0x72180
#define DVS_ENABLE (1<<31)
#define DVS_GAMMA_ENABLE (1<<30)
#define DVS_PIXFORMAT_MASK (3<<25)
#define DVS_FORMAT_YUV422 (0<<25)
#define DVS_FORMAT_RGBX101010 (1<<25)
#define DVS_FORMAT_RGBX888 (2<<25)
#define DVS_FORMAT_RGBX161616 (3<<25)
#define DVS_SOURCE_KEY (1<<22)
#define DVS_RGB_ORDER_RGBX (1<<20)
#define DVS_YUV_BYTE_ORDER_MASK (3<<16)
#define DVS_YUV_ORDER_YUYV (0<<16)
#define DVS_YUV_ORDER_UYVY (1<<16)
#define DVS_YUV_ORDER_YVYU (2<<16)
#define DVS_YUV_ORDER_VYUY (3<<16)
#define DVS_DEST_KEY (1<<2)
#define DVS_TRICKLE_FEED_DISABLE (1<<14)
#define DVS_TILED (1<<10)
#define _DVSALINOFF 0x72184
#define _DVSASTRIDE 0x72188
#define _DVSAPOS 0x7218c
#define _DVSASIZE 0x72190
#define _DVSAKEYVAL 0x72194
#define _DVSAKEYMSK 0x72198
#define _DVSASURF 0x7219c
#define _DVSAKEYMAXVAL 0x721a0
#define _DVSATILEOFF 0x721a4
#define _DVSASURFLIVE 0x721ac
#define _DVSASCALE 0x72204
#define DVS_SCALE_ENABLE (1<<31)
#define DVS_FILTER_MASK (3<<29)
#define DVS_FILTER_MEDIUM (0<<29)
#define DVS_FILTER_ENHANCING (1<<29)
#define DVS_FILTER_SOFTENING (2<<29)
#define DVS_VERTICAL_OFFSET_HALF (1<<28) /* must be enabled below */
#define DVS_VERTICAL_OFFSET_ENABLE (1<<27)
#define _DVSAGAMC 0x72300
#define _DVSBCNTR 0x73180
#define _DVSBLINOFF 0x73184
#define _DVSBSTRIDE 0x73188
#define _DVSBPOS 0x7318c
#define _DVSBSIZE 0x73190
#define _DVSBKEYVAL 0x73194
#define _DVSBKEYMSK 0x73198
#define _DVSBSURF 0x7319c
#define _DVSBKEYMAXVAL 0x731a0
#define _DVSBTILEOFF 0x731a4
#define _DVSBSURFLIVE 0x731ac
#define _DVSBSCALE 0x73204
#define _DVSBGAMC 0x73300
#define DVSCNTR(pipe) _PIPE(pipe, _DVSACNTR, _DVSBCNTR)
#define DVSLINOFF(pipe) _PIPE(pipe, _DVSALINOFF, _DVSBLINOFF)
#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
#define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL)
#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
#define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
#define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
#define _SPRA_CTL 0x70280
#define SPRITE_ENABLE (1<<31)
#define SPRITE_GAMMA_ENABLE (1<<30)
#define SPRITE_PIXFORMAT_MASK (7<<25)
#define SPRITE_FORMAT_YUV422 (0<<25)
#define SPRITE_FORMAT_RGBX101010 (1<<25)
#define SPRITE_FORMAT_RGBX888 (2<<25)
#define SPRITE_FORMAT_RGBX161616 (3<<25)
#define SPRITE_FORMAT_YUV444 (4<<25)
#define SPRITE_FORMAT_XR_BGR101010 (5<<25) /* Extended range */
#define SPRITE_CSC_ENABLE (1<<24)
#define SPRITE_SOURCE_KEY (1<<22)
#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */
#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19)
#define SPRITE_YUV_CSC_FORMAT_BT709 (1<<18) /* 0 is BT601 */
#define SPRITE_YUV_BYTE_ORDER_MASK (3<<16)
#define SPRITE_YUV_ORDER_YUYV (0<<16)
#define SPRITE_YUV_ORDER_UYVY (1<<16)
#define SPRITE_YUV_ORDER_YVYU (2<<16)
#define SPRITE_YUV_ORDER_VYUY (3<<16)
#define SPRITE_TRICKLE_FEED_DISABLE (1<<14)
#define SPRITE_INT_GAMMA_ENABLE (1<<13)
#define SPRITE_TILED (1<<10)
#define SPRITE_DEST_KEY (1<<2)
#define _SPRA_LINOFF 0x70284
#define _SPRA_STRIDE 0x70288
#define _SPRA_POS 0x7028c
#define _SPRA_SIZE 0x70290
#define _SPRA_KEYVAL 0x70294
#define _SPRA_KEYMSK 0x70298
#define _SPRA_SURF 0x7029c
#define _SPRA_KEYMAX 0x702a0
#define _SPRA_TILEOFF 0x702a4
#define _SPRA_SCALE 0x70304
#define SPRITE_SCALE_ENABLE (1<<31)
#define SPRITE_FILTER_MASK (3<<29)
#define SPRITE_FILTER_MEDIUM (0<<29)
#define SPRITE_FILTER_ENHANCING (1<<29)
#define SPRITE_FILTER_SOFTENING (2<<29)
#define SPRITE_VERTICAL_OFFSET_HALF (1<<28) /* must be enabled below */
#define SPRITE_VERTICAL_OFFSET_ENABLE (1<<27)
#define _SPRA_GAMC 0x70400
#define _SPRB_CTL 0x71280
#define _SPRB_LINOFF 0x71284
#define _SPRB_STRIDE 0x71288
#define _SPRB_POS 0x7128c
#define _SPRB_SIZE 0x71290
#define _SPRB_KEYVAL 0x71294
#define _SPRB_KEYMSK 0x71298
#define _SPRB_SURF 0x7129c
#define _SPRB_KEYMAX 0x712a0
#define _SPRB_TILEOFF 0x712a4
#define _SPRB_SCALE 0x71304
#define _SPRB_GAMC 0x71400
#define SPRCTL(pipe) _PIPE(pipe, _SPRA_CTL, _SPRB_CTL)
#define SPRLINOFF(pipe) _PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF)
#define SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE)
#define SPRPOS(pipe) _PIPE(pipe, _SPRA_POS, _SPRB_POS)
#define SPRSIZE(pipe) _PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE)
#define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL)
#define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK)
#define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
#define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
#define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
#define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
#define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
/* VBIOS regs */ /* VBIOS regs */
#define VGACNTRL 0x71400 #define VGACNTRL 0x71400
# define VGA_DISP_DISABLE (1 << 31) # define VGA_DISP_DISABLE (1 << 31)
@ -2845,6 +3020,10 @@
#define ILK_DPFC_DIS1 (1<<8) #define ILK_DPFC_DIS1 (1<<8)
#define ILK_DPFC_DIS2 (1<<9) #define ILK_DPFC_DIS2 (1<<9)
#define IVB_CHICKEN3 0x4200c
# define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE (1 << 5)
# define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2)
#define DISP_ARB_CTL 0x45000 #define DISP_ARB_CTL 0x45000
#define DISP_TILE_SURFACE_SWIZZLING (1<<13) #define DISP_TILE_SURFACE_SWIZZLING (1<<13)
#define DISP_FBC_WM_DIS (1<<15) #define DISP_FBC_WM_DIS (1<<15)
@ -2903,12 +3082,13 @@
#define SDEIER 0xc400c #define SDEIER 0xc400c
/* digital port hotplug */ /* digital port hotplug */
#define PCH_PORT_HOTPLUG 0xc4030 #define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
#define PORTD_HOTPLUG_ENABLE (1 << 20) #define PORTD_HOTPLUG_ENABLE (1 << 20)
#define PORTD_PULSE_DURATION_2ms (0) #define PORTD_PULSE_DURATION_2ms (0)
#define PORTD_PULSE_DURATION_4_5ms (1 << 18) #define PORTD_PULSE_DURATION_4_5ms (1 << 18)
#define PORTD_PULSE_DURATION_6ms (2 << 18) #define PORTD_PULSE_DURATION_6ms (2 << 18)
#define PORTD_PULSE_DURATION_100ms (3 << 18) #define PORTD_PULSE_DURATION_100ms (3 << 18)
#define PORTD_PULSE_DURATION_MASK (3 << 18)
#define PORTD_HOTPLUG_NO_DETECT (0) #define PORTD_HOTPLUG_NO_DETECT (0)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17) #define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
@ -2917,6 +3097,7 @@
#define PORTC_PULSE_DURATION_4_5ms (1 << 10) #define PORTC_PULSE_DURATION_4_5ms (1 << 10)
#define PORTC_PULSE_DURATION_6ms (2 << 10) #define PORTC_PULSE_DURATION_6ms (2 << 10)
#define PORTC_PULSE_DURATION_100ms (3 << 10) #define PORTC_PULSE_DURATION_100ms (3 << 10)
#define PORTC_PULSE_DURATION_MASK (3 << 10)
#define PORTC_HOTPLUG_NO_DETECT (0) #define PORTC_HOTPLUG_NO_DETECT (0)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9) #define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
@ -2925,6 +3106,7 @@
#define PORTB_PULSE_DURATION_4_5ms (1 << 2) #define PORTB_PULSE_DURATION_4_5ms (1 << 2)
#define PORTB_PULSE_DURATION_6ms (2 << 2) #define PORTB_PULSE_DURATION_6ms (2 << 2)
#define PORTB_PULSE_DURATION_100ms (3 << 2) #define PORTB_PULSE_DURATION_100ms (3 << 2)
#define PORTB_PULSE_DURATION_MASK (3 << 2)
#define PORTB_HOTPLUG_NO_DETECT (0) #define PORTB_HOTPLUG_NO_DETECT (0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1) #define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
@ -2945,15 +3127,15 @@
#define _PCH_DPLL_A 0xc6014 #define _PCH_DPLL_A 0xc6014
#define _PCH_DPLL_B 0xc6018 #define _PCH_DPLL_B 0xc6018
#define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B) #define PCH_DPLL(pipe) (pipe == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
#define _PCH_FPA0 0xc6040 #define _PCH_FPA0 0xc6040
#define FP_CB_TUNE (0x3<<22) #define FP_CB_TUNE (0x3<<22)
#define _PCH_FPA1 0xc6044 #define _PCH_FPA1 0xc6044
#define _PCH_FPB0 0xc6048 #define _PCH_FPB0 0xc6048
#define _PCH_FPB1 0xc604c #define _PCH_FPB1 0xc604c
#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0) #define PCH_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0)
#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1) #define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1)
#define PCH_DPLL_TEST 0xc606c #define PCH_DPLL_TEST 0xc606c
@ -3167,6 +3349,7 @@
#define FDI_LINK_TRAIN_NONE_IVB (3<<8) #define FDI_LINK_TRAIN_NONE_IVB (3<<8)
/* both Tx and Rx */ /* both Tx and Rx */
#define FDI_COMPOSITE_SYNC (1<<11)
#define FDI_LINK_TRAIN_AUTO (1<<10) #define FDI_LINK_TRAIN_AUTO (1<<10)
#define FDI_SCRAMBLING_ENABLE (0<<7) #define FDI_SCRAMBLING_ENABLE (0<<7)
#define FDI_SCRAMBLING_DISABLE (1<<7) #define FDI_SCRAMBLING_DISABLE (1<<7)
@ -3262,10 +3445,10 @@
/* or SDVOB */ /* or SDVOB */
#define HDMIB 0xe1140 #define HDMIB 0xe1140
#define PORT_ENABLE (1 << 31) #define PORT_ENABLE (1 << 31)
#define TRANSCODER_A (0)
#define TRANSCODER_B (1 << 30)
#define TRANSCODER(pipe) ((pipe) << 30) #define TRANSCODER(pipe) ((pipe) << 30)
#define TRANSCODER_CPT(pipe) ((pipe) << 29)
#define TRANSCODER_MASK (1 << 30) #define TRANSCODER_MASK (1 << 30)
#define TRANSCODER_MASK_CPT (3 << 29)
#define COLOR_FORMAT_8bpc (0) #define COLOR_FORMAT_8bpc (0)
#define COLOR_FORMAT_12bpc (3 << 26) #define COLOR_FORMAT_12bpc (3 << 26)
#define SDVOB_HOTPLUG_ENABLE (1 << 23) #define SDVOB_HOTPLUG_ENABLE (1 << 23)
@ -3308,15 +3491,35 @@
#define PCH_PP_STATUS 0xc7200 #define PCH_PP_STATUS 0xc7200
#define PCH_PP_CONTROL 0xc7204 #define PCH_PP_CONTROL 0xc7204
#define PANEL_UNLOCK_REGS (0xabcd << 16) #define PANEL_UNLOCK_REGS (0xabcd << 16)
#define PANEL_UNLOCK_MASK (0xffff << 16)
#define EDP_FORCE_VDD (1 << 3) #define EDP_FORCE_VDD (1 << 3)
#define EDP_BLC_ENABLE (1 << 2) #define EDP_BLC_ENABLE (1 << 2)
#define PANEL_POWER_RESET (1 << 1) #define PANEL_POWER_RESET (1 << 1)
#define PANEL_POWER_OFF (0 << 0) #define PANEL_POWER_OFF (0 << 0)
#define PANEL_POWER_ON (1 << 0) #define PANEL_POWER_ON (1 << 0)
#define PCH_PP_ON_DELAYS 0xc7208 #define PCH_PP_ON_DELAYS 0xc7208
#define PANEL_PORT_SELECT_MASK (3 << 30)
#define PANEL_PORT_SELECT_LVDS (0 << 30)
#define PANEL_PORT_SELECT_DPA (1 << 30)
#define EDP_PANEL (1 << 30) #define EDP_PANEL (1 << 30)
#define PANEL_PORT_SELECT_DPC (2 << 30)
#define PANEL_PORT_SELECT_DPD (3 << 30)
#define PANEL_POWER_UP_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_UP_DELAY_SHIFT 16
#define PANEL_LIGHT_ON_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_ON_DELAY_SHIFT 0
#define PCH_PP_OFF_DELAYS 0xc720c #define PCH_PP_OFF_DELAYS 0xc720c
#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_DOWN_DELAY_SHIFT 16
#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_OFF_DELAY_SHIFT 0
#define PCH_PP_DIVISOR 0xc7210 #define PCH_PP_DIVISOR 0xc7210
#define PP_REFERENCE_DIVIDER_MASK (0xffffff00)
#define PP_REFERENCE_DIVIDER_SHIFT 8
#define PANEL_POWER_CYCLE_DELAY_MASK (0x1f)
#define PANEL_POWER_CYCLE_DELAY_SHIFT 0
#define PCH_DP_B 0xe4100 #define PCH_DP_B 0xe4100
#define PCH_DPB_AUX_CH_CTL 0xe4110 #define PCH_DPB_AUX_CH_CTL 0xe4110
@ -3386,12 +3589,38 @@
#define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22) #define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22)
#define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22) #define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22)
/* IVB */
#define EDP_LINK_TRAIN_400MV_0DB_IVB (0x24 <<22)
#define EDP_LINK_TRAIN_400MV_3_5DB_IVB (0x2a <<22)
#define EDP_LINK_TRAIN_400MV_6DB_IVB (0x2f <<22)
#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22)
#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22)
#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22)
#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22)
/* legacy values */
#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22)
#define EDP_LINK_TRAIN_1000MV_0DB_IVB (0x20 <<22)
#define EDP_LINK_TRAIN_500MV_3_5DB_IVB (0x02 <<22)
#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB (0x22 <<22)
#define EDP_LINK_TRAIN_1000MV_6DB_IVB (0x23 <<22)
#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22)
#define FORCEWAKE 0xA18C #define FORCEWAKE 0xA18C
#define FORCEWAKE_ACK 0x130090 #define FORCEWAKE_ACK 0x130090
#define FORCEWAKE_MT 0xa188 /* multi-threaded */
#define FORCEWAKE_MT_ACK 0x130040
#define ECOBUS 0xa180
#define FORCEWAKE_MT_ENABLE (1<<5)
#define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_FREE_ENTRIES 0x120008
#define GT_FIFO_NUM_RESERVED_ENTRIES 20 #define GT_FIFO_NUM_RESERVED_ENTRIES 20
#define GEN6_UCGCTL2 0x9404
# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12)
# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11)
#define GEN6_RPNSWREQ 0xA008 #define GEN6_RPNSWREQ 0xA008
#define GEN6_TURBO_DISABLE (1<<31) #define GEN6_TURBO_DISABLE (1<<31)
#define GEN6_FREQUENCY(x) ((x)<<25) #define GEN6_FREQUENCY(x) ((x)<<25)
@ -3413,7 +3642,11 @@
#define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT) #define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT)
#define GEN6_RP_CONTROL 0xA024 #define GEN6_RP_CONTROL 0xA024
#define GEN6_RP_MEDIA_TURBO (1<<11) #define GEN6_RP_MEDIA_TURBO (1<<11)
#define GEN6_RP_USE_NORMAL_FREQ (1<<9) #define GEN6_RP_MEDIA_MODE_MASK (3<<9)
#define GEN6_RP_MEDIA_HW_TURBO_MODE (3<<9)
#define GEN6_RP_MEDIA_HW_NORMAL_MODE (2<<9)
#define GEN6_RP_MEDIA_HW_MODE (1<<9)
#define GEN6_RP_MEDIA_SW_MODE (0<<9)
#define GEN6_RP_MEDIA_IS_GFX (1<<8) #define GEN6_RP_MEDIA_IS_GFX (1<<8)
#define GEN6_RP_ENABLE (1<<7) #define GEN6_RP_ENABLE (1<<7)
#define GEN6_RP_UP_IDLE_MIN (0x1<<3) #define GEN6_RP_UP_IDLE_MIN (0x1<<3)
@ -3470,4 +3703,43 @@
#define GEN6_PCODE_DATA 0x138128 #define GEN6_PCODE_DATA 0x138128
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
#define GEN6_GT_CORE_STATUS 0x138060
#define GEN6_CORE_CPD_STATE_MASK (7<<4)
#define GEN6_RCn_MASK 7
#define GEN6_RC0 0
#define GEN6_RC3 2
#define GEN6_RC6 3
#define GEN6_RC7 4
#define G4X_AUD_VID_DID 0x62020
#define INTEL_AUDIO_DEVCL 0x808629FB
#define INTEL_AUDIO_DEVBLC 0x80862801
#define INTEL_AUDIO_DEVCTG 0x80862802
#define G4X_AUD_CNTL_ST 0x620B4
#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
#define G4X_ELDV_DEVCTG (1 << 14)
#define G4X_ELD_ADDR (0xf << 5)
#define G4X_ELD_ACK (1 << 4)
#define G4X_HDMIW_HDMIEDID 0x6210C
#define IBX_HDMIW_HDMIEDID_A 0xE2050
#define IBX_AUD_CNTL_ST_A 0xE20B4
#define IBX_ELD_BUFFER_SIZE (0x1f << 10)
#define IBX_ELD_ADDRESS (0x1f << 5)
#define IBX_ELD_ACK (1 << 4)
#define IBX_AUD_CNTL_ST2 0xE20C0
#define IBX_ELD_VALIDB (1 << 0)
#define IBX_CP_READYB (1 << 1)
#define CPT_HDMIW_HDMIEDID_A 0xE5050
#define CPT_AUD_CNTL_ST_A 0xE50B4
#define CPT_AUD_CNTRL_ST2 0xE50C0
/* These are the 4 32-bit write offset registers for each stream
* output buffer. It determines the offset from the
* 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to.
*/
#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4)
#endif /* _I915_REG_H_ */ #endif /* _I915_REG_H_ */

View File

@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_private *dev_priv,
dev_priv->lvds_use_ssc = general->enable_ssc; dev_priv->lvds_use_ssc = general->enable_ssc;
dev_priv->lvds_ssc_freq = dev_priv->lvds_ssc_freq =
intel_bios_ssc_frequency(dev, general->ssc_freq); intel_bios_ssc_frequency(dev, general->ssc_freq);
dev_priv->display_clock_mode = general->display_clock_mode;
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
dev_priv->int_tv_support,
dev_priv->int_crt_support,
dev_priv->lvds_use_ssc,
dev_priv->lvds_ssc_freq,
dev_priv->display_clock_mode);
} }
} }
@ -396,15 +403,13 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->dvo_wiring = p_child->dvo_wiring;
p_mapping->ddc_pin = p_child->ddc_pin; p_mapping->ddc_pin = p_child->ddc_pin;
p_mapping->i2c_pin = p_child->i2c_pin; p_mapping->i2c_pin = p_child->i2c_pin;
p_mapping->i2c_speed = p_child->i2c_speed;
p_mapping->initialized = 1; p_mapping->initialized = 1;
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n", DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port, p_mapping->dvo_port,
p_mapping->slave_addr, p_mapping->slave_addr,
p_mapping->dvo_wiring, p_mapping->dvo_wiring,
p_mapping->ddc_pin, p_mapping->ddc_pin,
p_mapping->i2c_pin, p_mapping->i2c_pin);
p_mapping->i2c_speed);
} else { } else {
DRM_DEBUG_KMS("Maybe one SDVO port is shared by " DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n"); "two SDVO device.\n");
@ -610,7 +615,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
/* Default to using SSC */ /* Default to using SSC */
dev_priv->lvds_use_ssc = 1; dev_priv->lvds_use_ssc = 1;
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
/* eDP data */ /* eDP data */
dev_priv->edp.bpp = 18; dev_priv->edp.bpp = 18;
@ -639,7 +644,7 @@ intel_parse_bios(struct drm_device *dev)
if (dev_priv->opregion.vbt) { if (dev_priv->opregion.vbt) {
struct vbt_header *vbt = dev_priv->opregion.vbt; struct vbt_header *vbt = dev_priv->opregion.vbt;
if (memcmp(vbt->signature, "$VBT", 4) == 0) { if (memcmp(vbt->signature, "$VBT", 4) == 0) {
DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n", DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
vbt->signature); vbt->signature);
bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
} else } else

View File

@ -1,5 +1,5 @@
/* /*
* Copyright © 2006 Intel Corporation * Copyright © 2006 Intel Corporation
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -120,7 +120,9 @@ struct bdb_general_features {
u8 ssc_freq:1; u8 ssc_freq:1;
u8 enable_lfp_on_override:1; u8 enable_lfp_on_override:1;
u8 disable_ssc_ddt:1; u8 disable_ssc_ddt:1;
u8 rsvd8:3; /* finish byte */ u8 rsvd7:1;
u8 display_clock_mode:1;
u8 rsvd8:1; /* finish byte */
/* bits 3 */ /* bits 3 */
u8 disable_smooth_vision:1; u8 disable_smooth_vision:1;
@ -133,7 +135,10 @@ struct bdb_general_features {
/* bits 5 */ /* bits 5 */
u8 int_crt_support:1; u8 int_crt_support:1;
u8 int_tv_support:1; u8 int_tv_support:1;
u8 rsvd11:6; /* finish byte */ u8 int_efp_support:1;
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
u8 rsvd11:3; /* finish byte */
} __attribute__((packed)); } __attribute__((packed));
/* pre-915 */ /* pre-915 */
@ -197,8 +202,7 @@ struct bdb_general_features {
struct child_device_config { struct child_device_config {
u16 handle; u16 handle;
u16 device_type; u16 device_type;
u8 i2c_speed; u8 device_id[10]; /* ascii string */
u8 rsvd[9];
u16 addin_offset; u16 addin_offset;
u8 dvo_port; /* See Device_PORT_* above */ u8 dvo_port; /* See Device_PORT_* above */
u8 i2c_pin; u8 i2c_pin;
@ -446,11 +450,11 @@ struct bdb_driver_features {
#define EDP_VSWING_1_2V 3 #define EDP_VSWING_1_2V 3
struct edp_power_seq { struct edp_power_seq {
u16 t3; u16 t1_t3;
u16 t7; u16 t8;
u16 t9; u16 t9;
u16 t10; u16 t10;
u16 t12; u16 t11_t12;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct edp_link_params { struct edp_link_params {
@ -463,8 +467,12 @@ struct edp_link_params {
struct bdb_edp { struct bdb_edp {
struct edp_power_seq power_seqs[16]; struct edp_power_seq power_seqs[16];
u32 color_depth; u32 color_depth;
u32 sdrrs_msa_timing_delay;
struct edp_link_params link_params[16]; struct edp_link_params link_params[16];
u32 sdrrs_msa_timing_delay;
/* ith bit indicates enabled/disabled for (i+1)th panel */
u16 edp_s3d_feature;
u16 edp_t3_optimization;
} __attribute__ ((packed)); } __attribute__ ((packed));
void intel_setup_bios(struct drm_device *dev); void intel_setup_bios(struct drm_device *dev);

View File

@ -152,17 +152,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
adpa |= ADPA_VSYNC_ACTIVE_HIGH; adpa |= ADPA_VSYNC_ACTIVE_HIGH;
if (intel_crtc->pipe == 0) { /* For CPT allow 3 pipe config, for others just use A or B */
if (HAS_PCH_CPT(dev)) if (HAS_PCH_CPT(dev))
adpa |= PORT_TRANS_A_SEL_CPT; adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
else else if (intel_crtc->pipe == 0)
adpa |= ADPA_PIPE_A_SELECT; adpa |= ADPA_PIPE_A_SELECT;
} else {
if (HAS_PCH_CPT(dev))
adpa |= PORT_TRANS_B_SEL_CPT;
else else
adpa |= ADPA_PIPE_B_SELECT; adpa |= ADPA_PIPE_B_SELECT;
}
if (!HAS_PCH_SPLIT(dev)) if (!HAS_PCH_SPLIT(dev))
I915_WRITE(BCLRPAT(intel_crtc->pipe), 0); I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
#define __INTEL_DRV_H__ #define __INTEL_DRV_H__
#include <linux/i2c.h> #include <linux/i2c.h>
#include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
@ -111,6 +112,7 @@
/* drm_display_mode->private_flags */ /* drm_display_mode->private_flags */
#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
#define INTEL_MODE_DP_FORCE_6BPC (0x10)
static inline void static inline void
intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
@ -172,12 +174,37 @@ struct intel_crtc {
int16_t cursor_width, cursor_height; int16_t cursor_width, cursor_height;
bool cursor_visible; bool cursor_visible;
unsigned int bpp; unsigned int bpp;
bool no_pll; /* tertiary pipe for IVB */
bool use_pll_a;
};
struct intel_plane {
struct drm_plane base;
enum pipe pipe;
struct drm_i915_gem_object *obj;
bool primary_disabled;
int max_downscale;
u32 lut_r[1024], lut_g[1024], lut_b[1024];
void (*update_plane)(struct drm_plane *plane,
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t x, uint32_t y,
uint32_t src_w, uint32_t src_h);
void (*disable_plane)(struct drm_plane *plane);
int (*update_colorkey)(struct drm_plane *plane,
struct drm_intel_sprite_colorkey *key);
void (*get_colorkey)(struct drm_plane *plane,
struct drm_intel_sprite_colorkey *key);
}; };
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base) #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
#define to_intel_connector(x) container_of(x, struct intel_connector, base) #define to_intel_connector(x) container_of(x, struct intel_connector, base)
#define to_intel_encoder(x) container_of(x, struct intel_encoder, base) #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
#define to_intel_plane(x) container_of(x, struct intel_plane, base)
#define DIP_HEADER_SIZE 5 #define DIP_HEADER_SIZE 5
@ -185,7 +212,7 @@ struct intel_crtc {
#define DIP_VERSION_AVI 0x2 #define DIP_VERSION_AVI 0x2
#define DIP_LEN_AVI 13 #define DIP_LEN_AVI 13
#define DIP_TYPE_SPD 0x3 #define DIP_TYPE_SPD 0x83
#define DIP_VERSION_SPD 0x1 #define DIP_VERSION_SPD 0x1
#define DIP_LEN_SPD 25 #define DIP_LEN_SPD 25
#define DIP_SPD_UNKNOWN 0 #define DIP_SPD_UNKNOWN 0
@ -287,6 +314,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
extern bool intel_dpd_is_edp(struct drm_device *dev); extern bool intel_dpd_is_edp(struct drm_device *dev);
extern void intel_edp_link_config(struct intel_encoder *, int *, int *); extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
/* intel_panel.c */ /* intel_panel.c */
extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
@ -338,9 +366,6 @@ extern void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
struct drm_connector *connector, struct drm_connector *connector,
struct intel_load_detect_pipe *old); struct intel_load_detect_pipe *old);
extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
extern int intel_sdvo_supports_hotplug(struct drm_connector *connector);
extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable);
extern void intelfb_restore(void); extern void intelfb_restore(void);
extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno); u16 blue, int regno);
@ -360,7 +385,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
extern int intel_framebuffer_init(struct drm_device *dev, extern int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb, struct intel_framebuffer *ifb,
struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
extern int intel_fbdev_init(struct drm_device *dev); extern int intel_fbdev_init(struct drm_device *dev);
extern void intel_fbdev_fini(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev);
@ -380,5 +405,25 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
extern void intel_fb_output_poll_changed(struct drm_device *dev); extern void intel_fb_output_poll_changed(struct drm_device *dev);
extern void intel_fb_restore_mode(struct drm_device *dev); extern void intel_fb_restore_mode(struct drm_device *dev);
extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
bool state);
#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
extern void intel_init_clock_gating(struct drm_device *dev); extern void intel_init_clock_gating(struct drm_device *dev);
extern void intel_write_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode);
extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
/* For use by IVB LP watermark workaround in intel_sprite.c */
extern void sandybridge_update_wm(struct drm_device *dev);
extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
uint32_t sprite_width,
int pixel_size);
extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);
#endif /* __INTEL_DRV_H__ */ #endif /* __INTEL_DRV_H__ */

View File

@ -93,7 +93,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct fb_info *info; struct fb_info *info;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_mode_fb_cmd mode_cmd; struct drm_mode_fb_cmd2 mode_cmd;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct device *device = &dev->pdev->dev; struct device *device = &dev->pdev->dev;
int size, ret; int size, ret;
@ -105,11 +105,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
mode_cmd.width = sizes->surface_width; mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height; mode_cmd.height = sizes->surface_height;
mode_cmd.bpp = sizes->surface_bpp; mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); 8), 64);
mode_cmd.depth = sizes->surface_depth; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
size = mode_cmd.pitch * mode_cmd.height; size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE); size = ALIGN(size, PAGE_SIZE);
obj = i915_gem_alloc_object(dev, size); obj = i915_gem_alloc_object(dev, size);
if (!obj) { if (!obj) {
@ -186,7 +187,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
// memset(info->screen_base, 0, size); // memset(info->screen_base, 0, size);
drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
@ -206,6 +207,7 @@ out_unref:
out: out:
return ret; return ret;
} }
static int intel_fb_find_or_create_single(struct drm_fb_helper *helper, static int intel_fb_find_or_create_single(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes) struct drm_fb_helper_surface_size *sizes)
{ {

View File

@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame)
frame->checksum = 0; frame->checksum = 0;
frame->ecc = 0; frame->ecc = 0;
/* Header isn't part of the checksum */ for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
for (i = 5; i < frame->len; i++)
sum += data[i]; sum += data[i];
frame->checksum = 0x100 - sum; frame->checksum = 0x100 - sum;
@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct dip_infoframe *frame)
flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC; flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
break; break;
case DIP_TYPE_SPD: case DIP_TYPE_SPD:
flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC; flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
break; break;
default: default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
@ -165,9 +164,9 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,
flags = intel_infoframe_index(frame); flags = intel_infoframe_index(frame);
val &= ~VIDEO_DIP_SELECT_MASK; val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
I915_WRITE(reg, val | flags); I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
for (i = 0; i < len; i += 4) { for (i = 0; i < len; i += 4) {
I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
@ -245,16 +244,17 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
sdvox |= HDMI_MODE_SELECT; sdvox |= HDMI_MODE_SELECT;
if (intel_hdmi->has_audio) { if (intel_hdmi->has_audio) {
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
pipe_name(intel_crtc->pipe));
sdvox |= SDVO_AUDIO_ENABLE; sdvox |= SDVO_AUDIO_ENABLE;
sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC; sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
intel_write_eld(encoder, adjusted_mode);
} }
if (intel_crtc->pipe == 1) {
if (HAS_PCH_CPT(dev)) if (HAS_PCH_CPT(dev))
sdvox |= PORT_TRANS_B_SEL_CPT; sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
else else if (intel_crtc->pipe == 1)
sdvox |= SDVO_PIPE_B_SELECT; sdvox |= SDVO_PIPE_B_SELECT;
}
I915_WRITE(intel_hdmi->sdvox_reg, sdvox); I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
POSTING_READ(intel_hdmi->sdvox_reg); POSTING_READ(intel_hdmi->sdvox_reg);
@ -269,6 +269,10 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 temp; u32 temp;
u32 enable_bits = SDVO_ENABLE;
if (intel_hdmi->has_audio)
enable_bits |= SDVO_AUDIO_ENABLE;
temp = I915_READ(intel_hdmi->sdvox_reg); temp = I915_READ(intel_hdmi->sdvox_reg);
@ -281,9 +285,9 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
} }
if (mode != DRM_MODE_DPMS_ON) { if (mode != DRM_MODE_DPMS_ON) {
temp &= ~SDVO_ENABLE; temp &= ~enable_bits;
} else { } else {
temp |= SDVO_ENABLE; temp |= enable_bits;
} }
I915_WRITE(intel_hdmi->sdvox_reg, temp); I915_WRITE(intel_hdmi->sdvox_reg, temp);
@ -486,6 +490,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct intel_hdmi *intel_hdmi; struct intel_hdmi *intel_hdmi;
int i;
intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
if (!intel_hdmi) if (!intel_hdmi)
@ -511,7 +516,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
connector->polled = DRM_CONNECTOR_POLL_HPD; connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->interlace_allowed = 0; connector->interlace_allowed = 0;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (sdvox_reg == SDVOB) { if (sdvox_reg == SDVOB) {
@ -538,10 +543,14 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
intel_hdmi->sdvox_reg = sdvox_reg; intel_hdmi->sdvox_reg = sdvox_reg;
if (!HAS_PCH_SPLIT(dev)) if (!HAS_PCH_SPLIT(dev)) {
intel_hdmi->write_infoframe = i9xx_write_infoframe; intel_hdmi->write_infoframe = i9xx_write_infoframe;
else I915_WRITE(VIDEO_DIP_CTL, 0);
} else {
intel_hdmi->write_infoframe = ironlake_write_infoframe; intel_hdmi->write_infoframe = ironlake_write_infoframe;
for_each_pipe(i)
I915_WRITE(TVIDEO_DIP_CTL(i), 0);
}
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);

View File

@ -550,13 +550,7 @@ void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
{ {
struct intel_gmbus *bus = to_intel_gmbus(adapter); struct intel_gmbus *bus = to_intel_gmbus(adapter);
/* speed: bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed;
* 0x0 = 100 KHz
* 0x1 = 50 KHz
* 0x2 = 400 KHz
* 0x3 = 1000 Khz
*/
bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
} }
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)

View File

@ -709,6 +709,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "U800"), DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
}, },
}, },
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Clientron E830",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
},
},
{ {
.callback = intel_no_lvds_dmi_callback, .callback = intel_no_lvds_dmi_callback,
.ident = "Asus EeeBox PC EB1007", .ident = "Asus EeeBox PC EB1007",
@ -717,6 +725,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
}, },
}, },
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Asus AT5NM10T-I",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
},
},
{ } /* terminating entry */ { } /* terminating entry */
}; };
@ -890,9 +906,11 @@ bool intel_lvds_init(struct drm_device *dev)
intel_encoder->type = INTEL_OUTPUT_LVDS; intel_encoder->type = INTEL_OUTPUT_LVDS;
intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
if (HAS_PCH_SPLIT(dev))
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
else
intel_encoder->crtc_mask = (1 << 1); intel_encoder->crtc_mask = (1 << 1);
if (INTEL_INFO(dev)->gen >= 5)
intel_encoder->crtc_mask |= (1 << 0);
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB; connector->display_info.subpixel_order = SubPixelHorizontalRGB;

View File

@ -26,6 +26,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <drm/drm_edid.h>
#include "drmP.h" #include "drmP.h"
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drv.h" #include "i915_drv.h"
@ -74,6 +75,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
if (edid) { if (edid) {
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
connector->display_info.raw_edid = NULL; connector->display_info.raw_edid = NULL;
kfree(edid); kfree(edid);
} }

View File

@ -193,13 +193,10 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
max >>= 16; max >>= 16;
} else { } else {
if (IS_PINEVIEW(dev)) {
max >>= 17;
} else {
max >>= 16;
if (INTEL_INFO(dev)->gen < 4) if (INTEL_INFO(dev)->gen < 4)
max &= ~1; max >>= 17;
} else
max >>= 16;
if (is_backlight_combination_mode(dev)) if (is_backlight_combination_mode(dev))
max *= 0xff; max *= 0xff;
@ -218,13 +215,12 @@ u32 intel_panel_get_backlight(struct drm_device *dev)
val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
} else { } else {
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
if (IS_PINEVIEW(dev)) if (INTEL_INFO(dev)->gen < 4)
val >>= 1; val >>= 1;
if (is_backlight_combination_mode(dev)) { if (is_backlight_combination_mode(dev)) {
u8 lbpc; u8 lbpc;
val &= ~1;
pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
val *= lbpc; val *= lbpc;
} }
@ -241,7 +237,7 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
I915_WRITE(BLC_PWM_CPU_CTL, val | level); I915_WRITE(BLC_PWM_CPU_CTL, val | level);
} }
void intel_panel_set_backlight(struct drm_device *dev, u32 level) static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 tmp; u32 tmp;
@ -261,24 +257,27 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
} }
tmp = I915_READ(BLC_PWM_CTL); tmp = I915_READ(BLC_PWM_CTL);
if (IS_PINEVIEW(dev)) { if (INTEL_INFO(dev)->gen < 4)
tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
level <<= 1; level <<= 1;
} else
tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
I915_WRITE(BLC_PWM_CTL, tmp | level); I915_WRITE(BLC_PWM_CTL, tmp | level);
} }
void intel_panel_set_backlight(struct drm_device *dev, u32 level)
{
struct drm_i915_private *dev_priv = dev->dev_private;
dev_priv->backlight_level = level;
if (dev_priv->backlight_enabled)
intel_panel_actually_set_backlight(dev, level);
}
void intel_panel_disable_backlight(struct drm_device *dev) void intel_panel_disable_backlight(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
if (dev_priv->backlight_enabled) {
dev_priv->backlight_level = intel_panel_get_backlight(dev);
dev_priv->backlight_enabled = false; dev_priv->backlight_enabled = false;
} intel_panel_actually_set_backlight(dev, 0);
intel_panel_set_backlight(dev, 0);
} }
void intel_panel_enable_backlight(struct drm_device *dev) void intel_panel_enable_backlight(struct drm_device *dev)
@ -288,8 +287,8 @@ void intel_panel_enable_backlight(struct drm_device *dev)
if (dev_priv->backlight_level == 0) if (dev_priv->backlight_level == 0)
dev_priv->backlight_level = intel_panel_get_max_backlight(dev); dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
dev_priv->backlight_enabled = true; dev_priv->backlight_enabled = true;
intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
} }
static void intel_panel_init_backlight(struct drm_device *dev) static void intel_panel_init_backlight(struct drm_device *dev)
@ -336,7 +335,8 @@ static int intel_panel_update_status(struct backlight_device *bd)
static int intel_panel_get_brightness(struct backlight_device *bd) static int intel_panel_get_brightness(struct backlight_device *bd)
{ {
struct drm_device *dev = bl_get_data(bd); struct drm_device *dev = bl_get_data(bd);
return intel_panel_get_backlight(dev); struct drm_i915_private *dev_priv = dev->dev_private;
return dev_priv->backlight_level;
} }
static const struct backlight_ops intel_panel_bl_ops = { static const struct backlight_ops intel_panel_bl_ops = {

View File

@ -36,6 +36,16 @@
//#include "i915_trace.h" //#include "i915_trace.h"
#include "intel_drv.h" #include "intel_drv.h"
/*
* 965+ support PIPE_CONTROL commands, which provide finer grained control
* over cache flushing.
*/
struct pipe_control {
struct drm_i915_gem_object *obj;
volatile u32 *cpu_page;
u32 gtt_offset;
};
static inline int ring_space(struct intel_ring_buffer *ring) static inline int ring_space(struct intel_ring_buffer *ring)
{ {
int space = (ring->head & HEAD_ADDR) - (ring->tail + 8); int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
@ -125,6 +135,118 @@ render_ring_flush(struct intel_ring_buffer *ring,
return 0; return 0;
} }
/**
* Emits a PIPE_CONTROL with a non-zero post-sync operation, for
* implementing two workarounds on gen6. From section 1.4.7.1
* "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
*
* [DevSNB-C+{W/A}] Before any depth stall flush (including those
* produced by non-pipelined state commands), software needs to first
* send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
* 0.
*
* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
* =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
*
* And the workaround for these two requires this workaround first:
*
* [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
* BEFORE the pipe-control with a post-sync op and no write-cache
* flushes.
*
* And this last workaround is tricky because of the requirements on
* that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
* volume 2 part 1:
*
* "1 of the following must also be set:
* - Render Target Cache Flush Enable ([12] of DW1)
* - Depth Cache Flush Enable ([0] of DW1)
* - Stall at Pixel Scoreboard ([1] of DW1)
* - Depth Stall ([13] of DW1)
* - Post-Sync Operation ([13] of DW1)
* - Notify Enable ([8] of DW1)"
*
* The cache flushes require the workaround flush that triggered this
* one, so we can't use it. Depth stall would trigger the same.
* Post-sync nonzero is what triggered this second workaround, so we
* can't use that one either. Notify enable is IRQs, which aren't
* really our business. That leaves only stall at scoreboard.
*/
static int
intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring)
{
struct pipe_control *pc = ring->private;
u32 scratch_addr = pc->gtt_offset + 128;
int ret;
ret = intel_ring_begin(ring, 6);
if (ret)
return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
PIPE_CONTROL_STALL_AT_SCOREBOARD);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
intel_ring_emit(ring, 0); /* low dword */
intel_ring_emit(ring, 0); /* high dword */
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
ret = intel_ring_begin(ring, 6);
if (ret)
return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
intel_ring_emit(ring, 0);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
return 0;
}
static int
gen6_render_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate_domains, u32 flush_domains)
{
u32 flags = 0;
struct pipe_control *pc = ring->private;
u32 scratch_addr = pc->gtt_offset + 128;
int ret;
/* Force SNB workarounds for PIPE_CONTROL flushes */
intel_emit_post_sync_nonzero_flush(ring);
/* Just flush everything. Experiments have shown that reducing the
* number of bits based on the write domains has little performance
* impact.
*/
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
ret = intel_ring_begin(ring, 6);
if (ret)
return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, flags);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, 0); /* lower dword */
intel_ring_emit(ring, 0); /* uppwer dword */
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
return 0;
}
static void ring_write_tail(struct intel_ring_buffer *ring, static void ring_write_tail(struct intel_ring_buffer *ring,
u32 value) u32 value)
{ {
@ -205,16 +327,6 @@ static int init_ring_common(struct intel_ring_buffer *ring)
return 0; return 0;
} }
/*
* 965+ support PIPE_CONTROL commands, which provide finer grained control
* over cache flushing.
*/
struct pipe_control {
struct drm_i915_gem_object *obj;
volatile u32 *cpu_page;
u32 gtt_offset;
};
static int static int
init_pipe_control(struct intel_ring_buffer *ring) init_pipe_control(struct intel_ring_buffer *ring)
{ {
@ -295,13 +407,17 @@ static int init_render_ring(struct intel_ring_buffer *ring)
GFX_MODE_ENABLE(GFX_REPLAY_MODE)); GFX_MODE_ENABLE(GFX_REPLAY_MODE));
} }
if (INTEL_INFO(dev)->gen >= 6) { if (INTEL_INFO(dev)->gen >= 5) {
} else if (IS_GEN5(dev)) {
ret = init_pipe_control(ring); ret = init_pipe_control(ring);
if (ret) if (ret)
return ret; return ret;
} }
if (INTEL_INFO(dev)->gen >= 6) {
I915_WRITE(INSTPM,
INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
}
return ret; return ret;
} }
@ -314,83 +430,131 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
} }
static void static void
update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno) update_mboxes(struct intel_ring_buffer *ring,
u32 seqno,
u32 mmio_offset)
{ {
struct drm_device *dev = ring->dev; intel_ring_emit(ring, MI_SEMAPHORE_MBOX |
struct drm_i915_private *dev_priv = dev->dev_private; MI_SEMAPHORE_GLOBAL_GTT |
int id;
/*
* cs -> 1 = vcs, 0 = bcs
* vcs -> 1 = bcs, 0 = cs,
* bcs -> 1 = cs, 0 = vcs.
*/
id = ring - dev_priv->ring;
id += 2 - i;
id %= 3;
intel_ring_emit(ring,
MI_SEMAPHORE_MBOX |
MI_SEMAPHORE_REGISTER | MI_SEMAPHORE_REGISTER |
MI_SEMAPHORE_UPDATE); MI_SEMAPHORE_UPDATE);
intel_ring_emit(ring, seqno); intel_ring_emit(ring, seqno);
intel_ring_emit(ring, intel_ring_emit(ring, mmio_offset);
RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i);
} }
/**
* gen6_add_request - Update the semaphore mailbox registers
*
* @ring - ring that is adding a request
* @seqno - return seqno stuck into the ring
*
* Update the mailbox registers in the *other* rings with the current seqno.
* This acts like a signal in the canonical semaphore.
*/
static int static int
gen6_add_request(struct intel_ring_buffer *ring, gen6_add_request(struct intel_ring_buffer *ring,
u32 *result) u32 *seqno)
{ {
u32 seqno; u32 mbox1_reg;
u32 mbox2_reg;
int ret; int ret;
ret = intel_ring_begin(ring, 10); ret = intel_ring_begin(ring, 10);
if (ret) if (ret)
return ret; return ret;
seqno = i915_gem_get_seqno(ring->dev); mbox1_reg = ring->signal_mbox[0];
update_semaphore(ring, 0, seqno); mbox2_reg = ring->signal_mbox[1];
update_semaphore(ring, 1, seqno);
*seqno = i915_gem_get_seqno(ring->dev);
update_mboxes(ring, *seqno, mbox1_reg);
update_mboxes(ring, *seqno, mbox2_reg);
intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
intel_ring_emit(ring, seqno); intel_ring_emit(ring, *seqno);
intel_ring_emit(ring, MI_USER_INTERRUPT); intel_ring_emit(ring, MI_USER_INTERRUPT);
intel_ring_advance(ring); intel_ring_advance(ring);
*result = seqno;
return 0; return 0;
} }
int /**
intel_ring_sync(struct intel_ring_buffer *ring, * intel_ring_sync - sync the waiter to the signaller on seqno
struct intel_ring_buffer *to, *
* @waiter - ring that is waiting
* @signaller - ring which has, or will signal
* @seqno - seqno which the waiter will block on
*/
static int
intel_ring_sync(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
int ring,
u32 seqno) u32 seqno)
{ {
int ret; int ret;
u32 dw1 = MI_SEMAPHORE_MBOX |
MI_SEMAPHORE_COMPARE |
MI_SEMAPHORE_REGISTER;
ret = intel_ring_begin(ring, 4); ret = intel_ring_begin(waiter, 4);
if (ret) if (ret)
return ret; return ret;
intel_ring_emit(ring, intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
MI_SEMAPHORE_MBOX | intel_ring_emit(waiter, seqno);
MI_SEMAPHORE_REGISTER | intel_ring_emit(waiter, 0);
intel_ring_sync_index(ring, to) << 17 | intel_ring_emit(waiter, MI_NOOP);
MI_SEMAPHORE_COMPARE); intel_ring_advance(waiter);
intel_ring_emit(ring, seqno);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
return 0; return 0;
} }
/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
int
render_ring_sync_to(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
u32 seqno)
{
// WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID);
return intel_ring_sync(waiter,
signaller,
RCS,
seqno);
}
/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
int
gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
u32 seqno)
{
// WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID);
return intel_ring_sync(waiter,
signaller,
VCS,
seqno);
}
/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
int
gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
u32 seqno)
{
// WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID);
return intel_ring_sync(waiter,
signaller,
BCS,
seqno);
}
#define PIPE_CONTROL_FLUSH(ring__, addr__) \ #define PIPE_CONTROL_FLUSH(ring__, addr__) \
do { \ do { \
intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \ intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \
PIPE_CONTROL_DEPTH_STALL | 2); \ PIPE_CONTROL_DEPTH_STALL); \
intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \
intel_ring_emit(ring__, 0); \ intel_ring_emit(ring__, 0); \
intel_ring_emit(ring__, 0); \ intel_ring_emit(ring__, 0); \
@ -418,8 +582,9 @@ pc_render_add_request(struct intel_ring_buffer *ring,
if (ret) if (ret)
return ret; return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH); PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, seqno); intel_ring_emit(ring, seqno);
intel_ring_emit(ring, 0); intel_ring_emit(ring, 0);
@ -434,8 +599,9 @@ pc_render_add_request(struct intel_ring_buffer *ring,
PIPE_CONTROL_FLUSH(ring, scratch_addr); PIPE_CONTROL_FLUSH(ring, scratch_addr);
scratch_addr += 128; scratch_addr += 128;
PIPE_CONTROL_FLUSH(ring, scratch_addr); PIPE_CONTROL_FLUSH(ring, scratch_addr);
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH | PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
PIPE_CONTROL_NOTIFY); PIPE_CONTROL_NOTIFY);
intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, seqno); intel_ring_emit(ring, seqno);
@ -468,6 +634,19 @@ render_ring_add_request(struct intel_ring_buffer *ring,
return 0; return 0;
} }
static u32
gen6_ring_get_seqno(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
/* Workaround to force correct ordering between irq and seqno writes on
* ivb (and maybe also on snb) by reading from a CS register (like
* ACTHD) before reading the status page. */
if (IS_GEN7(dev))
intel_ring_get_active_head(ring);
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
}
static u32 static u32
ring_get_seqno(struct intel_ring_buffer *ring) ring_get_seqno(struct intel_ring_buffer *ring)
{ {
@ -513,7 +692,6 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
POSTING_READ(IMR); POSTING_READ(IMR);
} }
#if 0
static bool static bool
render_ring_get_irq(struct intel_ring_buffer *ring) render_ring_get_irq(struct intel_ring_buffer *ring)
{ {
@ -553,7 +731,6 @@ render_ring_put_irq(struct intel_ring_buffer *ring)
} }
spin_unlock(&ring->irq_lock); spin_unlock(&ring->irq_lock);
} }
#endif
void intel_ring_setup_status_page(struct intel_ring_buffer *ring) void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
{ {
@ -626,8 +803,6 @@ ring_add_request(struct intel_ring_buffer *ring,
return 0; return 0;
} }
#if 0
static bool static bool
gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
{ {
@ -637,6 +812,12 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
if (!dev->irq_enabled) if (!dev->irq_enabled)
return false; return false;
/* It looks like we need to prevent the gt from suspending while waiting
* for an notifiy irq, otherwise irqs seem to get lost on at least the
* blt/bsd rings on ivb. */
if (IS_GEN7(dev))
gen6_gt_force_wake_get(dev_priv);
spin_lock(&ring->irq_lock); spin_lock(&ring->irq_lock);
if (ring->irq_refcount++ == 0) { if (ring->irq_refcount++ == 0) {
ring->irq_mask &= ~rflag; ring->irq_mask &= ~rflag;
@ -661,6 +842,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
ironlake_disable_irq(dev_priv, gflag); ironlake_disable_irq(dev_priv, gflag);
} }
spin_unlock(&ring->irq_lock); spin_unlock(&ring->irq_lock);
if (IS_GEN7(dev))
gen6_gt_force_wake_put(dev_priv);
} }
static bool static bool
@ -698,7 +882,6 @@ bsd_ring_put_irq(struct intel_ring_buffer *ring)
} }
spin_unlock(&ring->irq_lock); spin_unlock(&ring->irq_lock);
} }
#endif
static int static int
ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length) ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
@ -828,7 +1011,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
INIT_LIST_HEAD(&ring->gpu_write_list); INIT_LIST_HEAD(&ring->gpu_write_list);
// init_waitqueue_head(&ring->irq_queue); // init_waitqueue_head(&ring->irq_queue);
// spin_lock_init(&ring->irq_lock); spin_lock_init(&ring->irq_lock);
ring->irq_mask = ~0; ring->irq_mask = ~0;
if (I915_NEED_GFX_HWS(dev)) { if (I915_NEED_GFX_HWS(dev)) {
@ -1038,11 +1221,16 @@ static const struct intel_ring_buffer render_ring = {
.write_tail = ring_write_tail, .write_tail = ring_write_tail,
.flush = render_ring_flush, .flush = render_ring_flush,
.add_request = render_ring_add_request, .add_request = render_ring_add_request,
// .get_seqno = ring_get_seqno, .get_seqno = ring_get_seqno,
// .irq_get = render_ring_get_irq, .irq_get = render_ring_get_irq,
// .irq_put = render_ring_put_irq, .irq_put = render_ring_put_irq,
.dispatch_execbuffer = render_ring_dispatch_execbuffer, .dispatch_execbuffer = render_ring_dispatch_execbuffer,
// .cleanup = render_ring_cleanup, // .cleanup = render_ring_cleanup,
.sync_to = render_ring_sync_to,
.semaphore_register = {MI_SEMAPHORE_SYNC_INVALID,
MI_SEMAPHORE_SYNC_RV,
MI_SEMAPHORE_SYNC_RB},
.signal_mbox = {GEN6_VRSYNC, GEN6_BRSYNC},
}; };
/* ring buffer for bit-stream decoder */ /* ring buffer for bit-stream decoder */
@ -1056,9 +1244,9 @@ static const struct intel_ring_buffer bsd_ring = {
.write_tail = ring_write_tail, .write_tail = ring_write_tail,
.flush = bsd_ring_flush, .flush = bsd_ring_flush,
.add_request = ring_add_request, .add_request = ring_add_request,
// .get_seqno = ring_get_seqno, .get_seqno = ring_get_seqno,
// .irq_get = bsd_ring_get_irq, .irq_get = bsd_ring_get_irq,
// .irq_put = bsd_ring_put_irq, .irq_put = bsd_ring_put_irq,
.dispatch_execbuffer = ring_dispatch_execbuffer, .dispatch_execbuffer = ring_dispatch_execbuffer,
}; };
@ -1124,8 +1312,6 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
return 0; return 0;
} }
#if 0
static bool static bool
gen6_render_ring_get_irq(struct intel_ring_buffer *ring) gen6_render_ring_get_irq(struct intel_ring_buffer *ring)
{ {
@ -1158,8 +1344,6 @@ gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
GEN6_BSD_USER_INTERRUPT); GEN6_BSD_USER_INTERRUPT);
} }
#endif
/* ring buffer for Video Codec for Gen6+ */ /* ring buffer for Video Codec for Gen6+ */
static const struct intel_ring_buffer gen6_bsd_ring = { static const struct intel_ring_buffer gen6_bsd_ring = {
.name = "gen6 bsd ring", .name = "gen6 bsd ring",
@ -1170,13 +1354,17 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
.write_tail = gen6_bsd_ring_write_tail, .write_tail = gen6_bsd_ring_write_tail,
.flush = gen6_ring_flush, .flush = gen6_ring_flush,
.add_request = gen6_add_request, .add_request = gen6_add_request,
// .get_seqno = ring_get_seqno, .get_seqno = gen6_ring_get_seqno,
// .irq_get = gen6_bsd_ring_get_irq, .irq_get = gen6_bsd_ring_get_irq,
// .irq_put = gen6_bsd_ring_put_irq, .irq_put = gen6_bsd_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer, .dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
.sync_to = gen6_bsd_ring_sync_to,
.semaphore_register = {MI_SEMAPHORE_SYNC_VR,
MI_SEMAPHORE_SYNC_INVALID,
MI_SEMAPHORE_SYNC_VB},
.signal_mbox = {GEN6_RVSYNC, GEN6_BVSYNC},
}; };
#if 0
/* Blitter support (SandyBridge+) */ /* Blitter support (SandyBridge+) */
static bool static bool
@ -1194,7 +1382,6 @@ blt_ring_put_irq(struct intel_ring_buffer *ring)
GT_BLT_USER_INTERRUPT, GT_BLT_USER_INTERRUPT,
GEN6_BLITTER_USER_INTERRUPT); GEN6_BLITTER_USER_INTERRUPT);
} }
#endif
/* Workaround for some stepping of SNB, /* Workaround for some stepping of SNB,
@ -1302,11 +1489,16 @@ static const struct intel_ring_buffer gen6_blt_ring = {
.write_tail = ring_write_tail, .write_tail = ring_write_tail,
.flush = blt_ring_flush, .flush = blt_ring_flush,
.add_request = gen6_add_request, .add_request = gen6_add_request,
// .get_seqno = ring_get_seqno, .get_seqno = gen6_ring_get_seqno,
// .irq_get = blt_ring_get_irq, .irq_get = blt_ring_get_irq,
// .irq_put = blt_ring_put_irq, .irq_put = blt_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer, .dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
// .cleanup = blt_ring_cleanup, // .cleanup = blt_ring_cleanup,
.sync_to = gen6_blt_ring_sync_to,
.semaphore_register = {MI_SEMAPHORE_SYNC_BR,
MI_SEMAPHORE_SYNC_BV,
MI_SEMAPHORE_SYNC_INVALID},
.signal_mbox = {GEN6_RBSYNC, GEN6_VBSYNC},
}; };
int intel_init_render_ring_buffer(struct drm_device *dev) int intel_init_render_ring_buffer(struct drm_device *dev)
@ -1317,11 +1509,13 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
*ring = render_ring; *ring = render_ring;
if (INTEL_INFO(dev)->gen >= 6) { if (INTEL_INFO(dev)->gen >= 6) {
ring->add_request = gen6_add_request; ring->add_request = gen6_add_request;
// ring->irq_get = gen6_render_ring_get_irq; ring->flush = gen6_render_ring_flush;
// ring->irq_put = gen6_render_ring_put_irq; ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq;
ring->get_seqno = gen6_ring_get_seqno;
} else if (IS_GEN5(dev)) { } else if (IS_GEN5(dev)) {
ring->add_request = pc_render_add_request; ring->add_request = pc_render_add_request;
// ring->get_seqno = pc_render_get_seqno; ring->get_seqno = pc_render_get_seqno;
} }
if (!I915_NEED_GFX_HWS(dev)) { if (!I915_NEED_GFX_HWS(dev)) {

View File

@ -75,7 +75,12 @@ struct intel_ring_buffer {
int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, int (*dispatch_execbuffer)(struct intel_ring_buffer *ring,
u32 offset, u32 length); u32 offset, u32 length);
void (*cleanup)(struct intel_ring_buffer *ring); void (*cleanup)(struct intel_ring_buffer *ring);
int (*sync_to)(struct intel_ring_buffer *ring,
struct intel_ring_buffer *to,
u32 seqno);
u32 semaphore_register[3]; /*our mbox written by others */
u32 signal_mbox[2]; /* mboxes this ring signals to */
/** /**
* List of objects currently involved in rendering from the * List of objects currently involved in rendering from the
* ringbuffer. * ringbuffer.
@ -180,9 +185,6 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring,
void intel_ring_advance(struct intel_ring_buffer *ring); void intel_ring_advance(struct intel_ring_buffer *ring);
u32 intel_ring_get_seqno(struct intel_ring_buffer *ring); u32 intel_ring_get_seqno(struct intel_ring_buffer *ring);
int intel_ring_sync(struct intel_ring_buffer *ring,
struct intel_ring_buffer *to,
u32 seqno);
int intel_init_render_ring_buffer(struct drm_device *dev); int intel_init_render_ring_buffer(struct drm_device *dev);
int intel_init_bsd_ring_buffer(struct drm_device *dev); int intel_init_bsd_ring_buffer(struct drm_device *dev);

View File

@ -58,6 +58,7 @@ unsigned int hweight16(unsigned int w)
#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK)
#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK)
#define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
static const char *tv_format_names[] = { static const char *tv_format_names[] = {
@ -101,6 +102,11 @@ struct intel_sdvo {
*/ */
uint16_t attached_output; uint16_t attached_output;
/*
* Hotplug activation bits for this device
*/
uint8_t hotplug_active[2];
/** /**
* This is used to select the color range of RBG outputs in HDMI mode. * This is used to select the color range of RBG outputs in HDMI mode.
* It is only valid when using TMDS encoding and 8 bit per color mode. * It is only valid when using TMDS encoding and 8 bit per color mode.
@ -1068,15 +1074,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
/* Set the SDVO control regs. */ /* Set the SDVO control regs. */
if (INTEL_INFO(dev)->gen >= 4) { if (INTEL_INFO(dev)->gen >= 4) {
sdvox = 0; /* The real mode polarity is set by the SDVO commands, using
* struct intel_sdvo_dtd. */
sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
if (intel_sdvo->is_hdmi) if (intel_sdvo->is_hdmi)
sdvox |= intel_sdvo->color_range; sdvox |= intel_sdvo->color_range;
if (INTEL_INFO(dev)->gen < 5) if (INTEL_INFO(dev)->gen < 5)
sdvox |= SDVO_BORDER_ENABLE; sdvox |= SDVO_BORDER_ENABLE;
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
} else { } else {
sdvox = I915_READ(intel_sdvo->sdvo_reg); sdvox = I915_READ(intel_sdvo->sdvo_reg);
switch (intel_sdvo->sdvo_reg) { switch (intel_sdvo->sdvo_reg) {
@ -1089,8 +1093,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
} }
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
} }
if (intel_crtc->pipe == 1)
sdvox |= SDVO_PIPE_B_SELECT; if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
sdvox |= TRANSCODER_CPT(intel_crtc->pipe);
else
sdvox |= TRANSCODER(intel_crtc->pipe);
if (intel_sdvo->has_hdmi_audio) if (intel_sdvo->has_hdmi_audio)
sdvox |= SDVO_AUDIO_ENABLE; sdvox |= SDVO_AUDIO_ENABLE;
@ -1217,81 +1225,26 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
return true; return true;
} }
/* No use! */ static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo)
#if 0
struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB)
{
struct drm_connector *connector = NULL;
struct intel_sdvo *iout = NULL;
struct intel_sdvo *sdvo;
/* find the sdvo connector */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
iout = to_intel_sdvo(connector);
if (iout->type != INTEL_OUTPUT_SDVO)
continue;
sdvo = iout->dev_priv;
if (sdvo->sdvo_reg == SDVOB && sdvoB)
return connector;
if (sdvo->sdvo_reg == SDVOC && !sdvoB)
return connector;
}
return NULL;
}
int intel_sdvo_supports_hotplug(struct drm_connector *connector)
{ {
u8 response[2]; u8 response[2];
u8 status;
struct intel_sdvo *intel_sdvo;
DRM_DEBUG_KMS("\n");
if (!connector)
return 0;
intel_sdvo = to_intel_sdvo(connector);
return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
&response, 2) && response[0]; &response, 2) && response[0];
} }
void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder)
{ {
u8 response[2]; struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
u8 status;
struct intel_sdvo *intel_sdvo = to_intel_sdvo(connector);
intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &intel_sdvo->hotplug_active, 2);
intel_sdvo_read_response(intel_sdvo, &response, 2);
if (on) {
intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
status = intel_sdvo_read_response(intel_sdvo, &response, 2);
intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
} else {
response[0] = 0;
response[1] = 0;
intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
} }
intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
intel_sdvo_read_response(intel_sdvo, &response, 2);
}
#endif
static bool static bool
intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
{ {
/* Is there more than one type of output? */ /* Is there more than one type of output? */
int caps = intel_sdvo->caps.output_flags & 0xf; return hweight16(intel_sdvo->caps.output_flags) > 1;
return caps & -caps;
} }
static struct edid * static struct edid *
@ -1312,7 +1265,7 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector)
} }
enum drm_connector_status enum drm_connector_status
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
{ {
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
enum drm_connector_status status; enum drm_connector_status status;
@ -1372,6 +1325,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
return status; return status;
} }
static bool
intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
struct edid *edid)
{
bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
bool connector_is_digital = !!IS_DIGITAL(sdvo);
DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n",
connector_is_digital, monitor_is_digital);
return connector_is_digital == monitor_is_digital;
}
static enum drm_connector_status static enum drm_connector_status
intel_sdvo_detect(struct drm_connector *connector, bool force) intel_sdvo_detect(struct drm_connector *connector, bool force)
{ {
@ -1407,7 +1372,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
if ((intel_sdvo_connector->output_flag & response) == 0) if ((intel_sdvo_connector->output_flag & response) == 0)
ret = connector_status_disconnected; ret = connector_status_disconnected;
else if (IS_TMDS(intel_sdvo_connector)) else if (IS_TMDS(intel_sdvo_connector))
ret = intel_sdvo_hdmi_sink_detect(connector); ret = intel_sdvo_tmds_sink_detect(connector);
else { else {
struct edid *edid; struct edid *edid;
@ -1416,10 +1381,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
if (edid == NULL) if (edid == NULL)
edid = intel_sdvo_get_analog_edid(connector); edid = intel_sdvo_get_analog_edid(connector);
if (edid != NULL) { if (edid != NULL) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) if (intel_sdvo_connector_matches_edid(intel_sdvo_connector,
ret = connector_status_disconnected; edid))
else
ret = connector_status_connected; ret = connector_status_connected;
else
ret = connector_status_disconnected;
connector->display_info.raw_edid = NULL; connector->display_info.raw_edid = NULL;
kfree(edid); kfree(edid);
} else } else
@ -1460,11 +1427,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
edid = intel_sdvo_get_analog_edid(connector); edid = intel_sdvo_get_analog_edid(connector);
if (edid != NULL) { if (edid != NULL) {
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); edid)) {
bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector);
if (connector_is_digital == monitor_is_digital) {
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid); drm_add_edid_modes(connector, edid);
} }
@ -1944,7 +1908,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
struct intel_sdvo *sdvo, u32 reg) struct intel_sdvo *sdvo, u32 reg)
{ {
struct sdvo_device_mapping *mapping; struct sdvo_device_mapping *mapping;
u8 pin, speed; u8 pin;
if (IS_SDVOB(reg)) if (IS_SDVOB(reg))
mapping = &dev_priv->sdvo_mappings[0]; mapping = &dev_priv->sdvo_mappings[0];
@ -1952,19 +1916,17 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
mapping = &dev_priv->sdvo_mappings[1]; mapping = &dev_priv->sdvo_mappings[1];
pin = GMBUS_PORT_DPB; pin = GMBUS_PORT_DPB;
speed = GMBUS_RATE_1MHZ >> 8; if (mapping->initialized)
if (mapping->initialized) {
pin = mapping->i2c_pin; pin = mapping->i2c_pin;
speed = mapping->i2c_speed;
}
if (pin < GMBUS_NUM_PORTS) { if (pin < GMBUS_NUM_PORTS) {
sdvo->i2c = &dev_priv->gmbus[pin].adapter; sdvo->i2c = &dev_priv->gmbus[pin].adapter;
intel_gmbus_set_speed(sdvo->i2c, speed); intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
intel_gmbus_force_bit(sdvo->i2c, true); intel_gmbus_force_bit(sdvo->i2c, true);
} else } else {
sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter; sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
} }
}
static bool static bool
intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device)
@ -2044,6 +2006,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
{ {
struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_encoder *encoder = &intel_sdvo->base.base;
struct drm_connector *connector; struct drm_connector *connector;
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector; struct intel_sdvo_connector *intel_sdvo_connector;
@ -2061,6 +2024,16 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
intel_connector = &intel_sdvo_connector->base; intel_connector = &intel_sdvo_connector->base;
connector = &intel_connector->base; connector = &intel_connector->base;
if (intel_sdvo_supports_hotplug(intel_sdvo) & (1 << device)) {
connector->polled = DRM_CONNECTOR_POLL_HPD;
intel_sdvo->hotplug_active[0] |= 1 << device;
/* Some SDVO devices have one-shot hotplug interrupts.
* Ensure that they get re-enabled when an interrupt happens.
*/
intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
intel_sdvo_enable_hotplug(intel_encoder);
}
else
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
encoder->encoder_type = DRM_MODE_ENCODER_TMDS; encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
connector->connector_type = DRM_MODE_CONNECTOR_DVID; connector->connector_type = DRM_MODE_CONNECTOR_DVID;
@ -2243,7 +2216,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
bytes[0], bytes[1]); bytes[0], bytes[1]);
return false; return false;
} }
intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1); intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
return true; return true;
} }
@ -2568,6 +2541,14 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
goto err; goto err;
/* Set up hotplug command - note paranoia about contents of reply.
* We assume that the hardware is in a sane state, and only touch
* the bits we think we understand.
*/
intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG,
&intel_sdvo->hotplug_active, 2);
intel_sdvo->hotplug_active[0] &= ~0x3;
if (intel_sdvo_output_setup(intel_sdvo, if (intel_sdvo_output_setup(intel_sdvo,
intel_sdvo->caps.output_flags) != true) { intel_sdvo->caps.output_flags) != true) {
DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",

View File

@ -1,5 +1,5 @@
/* /*
* Copyright © 2006-2007 Intel Corporation * Copyright © 2006-2007 Intel Corporation
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),

View File

@ -0,0 +1,664 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Jesse Barnes <jbarnes@virtuousgeek.org>
*
* New plane/sprite handling.
*
* The older chips had a separate interface for programming plane related
* registers; newer ones are much simpler and we can use the new DRM plane
* support.
*/
#include "drmP.h"
#include "drm_crtc.h"
#include "drm_fourcc.h"
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
static void
ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t x, uint32_t y,
uint32_t src_w, uint32_t src_h)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
u32 sprctl, sprscale = 0;
int pixel_size;
sprctl = I915_READ(SPRCTL(pipe));
/* Mask out pixel format bits in case we change it */
sprctl &= ~SPRITE_PIXFORMAT_MASK;
sprctl &= ~SPRITE_RGB_ORDER_RGBX;
sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
sprctl |= SPRITE_FORMAT_RGBX888;
pixel_size = 4;
break;
case DRM_FORMAT_XRGB8888:
sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
pixel_size = 4;
break;
case DRM_FORMAT_YUYV:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
pixel_size = 2;
break;
case DRM_FORMAT_YVYU:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
pixel_size = 2;
break;
case DRM_FORMAT_UYVY:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
pixel_size = 2;
break;
case DRM_FORMAT_VYUY:
sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
pixel_size = 2;
break;
default:
DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
sprctl |= DVS_FORMAT_RGBX888;
pixel_size = 4;
break;
}
if (obj->tiling_mode != I915_TILING_NONE)
sprctl |= SPRITE_TILED;
/* must disable */
sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
sprctl |= SPRITE_ENABLE;
sprctl |= SPRITE_DEST_KEY;
/* Sizes are 0 based */
src_w--;
src_h--;
crtc_w--;
crtc_h--;
intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
/*
* IVB workaround: must disable low power watermarks for at least
* one frame before enabling scaling. LP watermarks can be re-enabled
* when scaling is disabled.
*/
if (crtc_w != src_w || crtc_h != src_h) {
dev_priv->sprite_scaling_enabled = true;
sandybridge_update_wm(dev);
intel_wait_for_vblank(dev, pipe);
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
} else {
dev_priv->sprite_scaling_enabled = false;
/* potentially re-enable LP watermarks */
sandybridge_update_wm(dev);
}
I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
if (obj->tiling_mode != I915_TILING_NONE) {
I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
} else {
unsigned long offset;
offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
I915_WRITE(SPRLINOFF(pipe), offset);
}
I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
I915_WRITE(SPRSCALE(pipe), sprscale);
I915_WRITE(SPRCTL(pipe), sprctl);
I915_WRITE(SPRSURF(pipe), obj->gtt_offset);
POSTING_READ(SPRSURF(pipe));
}
static void
ivb_disable_plane(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
/* Can't leave the scaler enabled... */
I915_WRITE(SPRSCALE(pipe), 0);
/* Activate double buffered register update */
I915_WRITE(SPRSURF(pipe), 0);
POSTING_READ(SPRSURF(pipe));
}
static int
ivb_update_colorkey(struct drm_plane *plane,
struct drm_intel_sprite_colorkey *key)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane;
u32 sprctl;
int ret = 0;
intel_plane = to_intel_plane(plane);
I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
sprctl = I915_READ(SPRCTL(intel_plane->pipe));
sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
if (key->flags & I915_SET_COLORKEY_DESTINATION)
sprctl |= SPRITE_DEST_KEY;
else if (key->flags & I915_SET_COLORKEY_SOURCE)
sprctl |= SPRITE_SOURCE_KEY;
I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
POSTING_READ(SPRKEYMSK(intel_plane->pipe));
return ret;
}
static void
ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane;
u32 sprctl;
intel_plane = to_intel_plane(plane);
key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
key->flags = 0;
sprctl = I915_READ(SPRCTL(intel_plane->pipe));
if (sprctl & SPRITE_DEST_KEY)
key->flags = I915_SET_COLORKEY_DESTINATION;
else if (sprctl & SPRITE_SOURCE_KEY)
key->flags = I915_SET_COLORKEY_SOURCE;
else
key->flags = I915_SET_COLORKEY_NONE;
}
static void
snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t x, uint32_t y,
uint32_t src_w, uint32_t src_h)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe, pixel_size;
u32 dvscntr, dvsscale = 0;
dvscntr = I915_READ(DVSCNTR(pipe));
/* Mask out pixel format bits in case we change it */
dvscntr &= ~DVS_PIXFORMAT_MASK;
dvscntr &= ~DVS_RGB_ORDER_RGBX;
dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
switch (fb->pixel_format) {
case DRM_FORMAT_XBGR8888:
dvscntr |= DVS_FORMAT_RGBX888;
pixel_size = 4;
break;
case DRM_FORMAT_XRGB8888:
dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX;
pixel_size = 4;
break;
case DRM_FORMAT_YUYV:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
pixel_size = 2;
break;
case DRM_FORMAT_YVYU:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
pixel_size = 2;
break;
case DRM_FORMAT_UYVY:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
pixel_size = 2;
break;
case DRM_FORMAT_VYUY:
dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
pixel_size = 2;
break;
default:
DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
dvscntr |= DVS_FORMAT_RGBX888;
pixel_size = 4;
break;
}
if (obj->tiling_mode != I915_TILING_NONE)
dvscntr |= DVS_TILED;
/* must disable */
dvscntr |= DVS_TRICKLE_FEED_DISABLE;
dvscntr |= DVS_ENABLE;
/* Sizes are 0 based */
src_w--;
src_h--;
crtc_w--;
crtc_h--;
intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
if (crtc_w != src_w || crtc_h != src_h)
dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
if (obj->tiling_mode != I915_TILING_NONE) {
I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
} else {
unsigned long offset;
offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
I915_WRITE(DVSLINOFF(pipe), offset);
}
I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
I915_WRITE(DVSSCALE(pipe), dvsscale);
I915_WRITE(DVSCNTR(pipe), dvscntr);
I915_WRITE(DVSSURF(pipe), obj->gtt_offset);
POSTING_READ(DVSSURF(pipe));
}
static void
snb_disable_plane(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
/* Disable the scaler */
I915_WRITE(DVSSCALE(pipe), 0);
/* Flush double buffered register updates */
I915_WRITE(DVSSURF(pipe), 0);
POSTING_READ(DVSSURF(pipe));
}
static void
intel_enable_primary(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int reg = DSPCNTR(intel_crtc->plane);
I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
}
static void
intel_disable_primary(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int reg = DSPCNTR(intel_crtc->plane);
I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
}
static int
snb_update_colorkey(struct drm_plane *plane,
struct drm_intel_sprite_colorkey *key)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane;
u32 dvscntr;
int ret = 0;
intel_plane = to_intel_plane(plane);
I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
if (key->flags & I915_SET_COLORKEY_DESTINATION)
dvscntr |= DVS_DEST_KEY;
else if (key->flags & I915_SET_COLORKEY_SOURCE)
dvscntr |= DVS_SOURCE_KEY;
I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
POSTING_READ(DVSKEYMSK(intel_plane->pipe));
return ret;
}
static void
snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane;
u32 dvscntr;
intel_plane = to_intel_plane(plane);
key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
key->flags = 0;
dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
if (dvscntr & DVS_DEST_KEY)
key->flags = I915_SET_COLORKEY_DESTINATION;
else if (dvscntr & DVS_SOURCE_KEY)
key->flags = I915_SET_COLORKEY_SOURCE;
else
key->flags = I915_SET_COLORKEY_NONE;
}
static int
intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane = to_intel_plane(plane);
struct intel_framebuffer *intel_fb;
struct drm_i915_gem_object *obj, *old_obj;
int pipe = intel_plane->pipe;
int ret = 0;
int x = src_x >> 16, y = src_y >> 16;
int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
bool disable_primary = false;
intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;
old_obj = intel_plane->obj;
/* Pipe must be running... */
if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
return -EINVAL;
if (crtc_x >= primary_w || crtc_y >= primary_h)
return -EINVAL;
/* Don't modify another pipe's plane */
if (intel_plane->pipe != intel_crtc->pipe)
return -EINVAL;
/*
* Clamp the width & height into the visible area. Note we don't
* try to scale the source if part of the visible region is offscreen.
* The caller must handle that by adjusting source offset and size.
*/
if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
crtc_w += crtc_x;
crtc_x = 0;
}
if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
goto out;
if ((crtc_x + crtc_w) > primary_w)
crtc_w = primary_w - crtc_x;
if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
crtc_h += crtc_y;
crtc_y = 0;
}
if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
goto out;
if (crtc_y + crtc_h > primary_h)
crtc_h = primary_h - crtc_y;
if (!crtc_w || !crtc_h) /* Again, nothing to display */
goto out;
/*
* We can take a larger source and scale it down, but
* only so much... 16x is the max on SNB.
*/
if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
return -EINVAL;
/*
* If the sprite is completely covering the primary plane,
* we can disable the primary and save power.
*/
if ((crtc_x == 0) && (crtc_y == 0) &&
(crtc_w == primary_w) && (crtc_h == primary_h))
disable_primary = true;
mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
if (ret)
goto out_unlock;
intel_plane->obj = obj;
/*
* Be sure to re-enable the primary before the sprite is no longer
* covering it fully.
*/
if (!disable_primary && intel_plane->primary_disabled) {
intel_enable_primary(crtc);
intel_plane->primary_disabled = false;
}
intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
crtc_w, crtc_h, x, y, src_w, src_h);
if (disable_primary) {
intel_disable_primary(crtc);
intel_plane->primary_disabled = true;
}
/* Unpin old obj after new one is active to avoid ugliness */
if (old_obj) {
/*
* It's fairly common to simply update the position of
* an existing object. In that case, we don't need to
* wait for vblank to avoid ugliness, we only need to
* do the pin & ref bookkeeping.
*/
if (old_obj != obj) {
mutex_unlock(&dev->struct_mutex);
intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
mutex_lock(&dev->struct_mutex);
}
// i915_gem_object_unpin(old_obj);
}
out_unlock:
mutex_unlock(&dev->struct_mutex);
out:
return ret;
}
static int
intel_disable_plane(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
int ret = 0;
if (intel_plane->primary_disabled) {
intel_enable_primary(plane->crtc);
intel_plane->primary_disabled = false;
}
intel_plane->disable_plane(plane);
if (!intel_plane->obj)
goto out;
mutex_lock(&dev->struct_mutex);
// i915_gem_object_unpin(intel_plane->obj);
intel_plane->obj = NULL;
mutex_unlock(&dev->struct_mutex);
out:
return ret;
}
static void intel_destroy_plane(struct drm_plane *plane)
{
struct intel_plane *intel_plane = to_intel_plane(plane);
intel_disable_plane(plane);
drm_plane_cleanup(plane);
kfree(intel_plane);
}
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_intel_sprite_colorkey *set = data;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_object *obj;
struct drm_plane *plane;
struct intel_plane *intel_plane;
int ret = 0;
if (!dev_priv)
return -EINVAL;
/* Make sure we don't try to enable both src & dest simultaneously */
if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
return -EINVAL;
mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
if (!obj) {
ret = -EINVAL;
goto out_unlock;
}
plane = obj_to_plane(obj);
intel_plane = to_intel_plane(plane);
ret = intel_plane->update_colorkey(plane, set);
out_unlock:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_intel_sprite_colorkey *get = data;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_object *obj;
struct drm_plane *plane;
struct intel_plane *intel_plane;
int ret = 0;
if (!dev_priv)
return -EINVAL;
mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
if (!obj) {
ret = -EINVAL;
goto out_unlock;
}
plane = obj_to_plane(obj);
intel_plane = to_intel_plane(plane);
intel_plane->get_colorkey(plane, get);
out_unlock:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
static const struct drm_plane_funcs intel_plane_funcs = {
.update_plane = intel_update_plane,
.disable_plane = intel_disable_plane,
.destroy = intel_destroy_plane,
};
static uint32_t snb_plane_formats[] = {
DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_YUYV,
DRM_FORMAT_YVYU,
DRM_FORMAT_UYVY,
DRM_FORMAT_VYUY,
};
int
intel_plane_init(struct drm_device *dev, enum pipe pipe)
{
struct intel_plane *intel_plane;
unsigned long possible_crtcs;
int ret;
if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV;
intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
if (!intel_plane)
return -ENOMEM;
if (IS_GEN6(dev)) {
intel_plane->max_downscale = 16;
intel_plane->update_plane = snb_update_plane;
intel_plane->disable_plane = snb_disable_plane;
intel_plane->update_colorkey = snb_update_colorkey;
intel_plane->get_colorkey = snb_get_colorkey;
} else if (IS_GEN7(dev)) {
intel_plane->max_downscale = 2;
intel_plane->update_plane = ivb_update_plane;
intel_plane->disable_plane = ivb_disable_plane;
intel_plane->update_colorkey = ivb_update_colorkey;
intel_plane->get_colorkey = ivb_get_colorkey;
}
intel_plane->pipe = pipe;
possible_crtcs = (1 << pipe);
ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs, snb_plane_formats,
ARRAY_SIZE(snb_plane_formats), false);
if (ret)
kfree(intel_plane);
return ret;
}

View File

@ -191,48 +191,31 @@ int init_display_kms(struct drm_device *dev)
}; };
safe_sti(ifl); safe_sti(ifl);
{
#define XY_COLOR_BLT ((2<<29)|(0x50<<22)|(0x4)) #define XY_COLOR_BLT ((2<<29)|(0x50<<22)|(0x4))
#define BLT_WRITE_ALPHA (1<<21) #define BLT_WRITE_ALPHA (1<<21)
#define BLT_WRITE_RGB (1<<20) #define BLT_WRITE_RGB (1<<20)
#if 1
{
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct intel_ring_buffer *ring; struct intel_ring_buffer *ring;
u32_t br13, cmd, *b;
int n=0;
cmd = XY_COLOR_BLT | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
br13 = os_display->pitch;
br13 |= 0xF0 << 16;
br13 |= 3 << 24;
obj = i915_gem_alloc_object(dev, 4096); obj = i915_gem_alloc_object(dev, 4096);
i915_gem_object_pin(obj, 4096, true); i915_gem_object_pin(obj, 4096, true);
cmd_buffer = MapIoMem(obj->pages[0], 4096, PG_SW|PG_NOCACHE); cmd_buffer = MapIoMem(obj->pages[0], 4096, PG_SW|PG_NOCACHE);
cmd_offset = obj->gtt_offset; cmd_offset = obj->gtt_offset;
};
#endif
b = (u32_t*)cmd_buffer; int err;
b[n++] = cmd;
b[n++] = br13;
b[n++] = 0; // top, left
b[n++] = (128 << 16) | 128; // bottom, right
b[n++] = 0; // dst
b[n++] = 0x0000FF00;
b[n++] = MI_BATCH_BUFFER_END;
if( n & 1)
b[n++] = MI_NOOP;
// cmd_buffer = (u32_t)&b[n];
// i915_gem_object_set_to_gtt_domain(obj, false);
ring = &dev_priv->ring[BCS];
ring->dispatch_execbuffer(ring,cmd_offset, n*4);
err = init_bitmaps();
if( !err )
{
printf("Initialize bitmap manager\n");
}; };
LEAVE(); LEAVE();
@ -303,7 +286,11 @@ do_set:
fb->width = reqmode->width; fb->width = reqmode->width;
fb->height = reqmode->height; fb->height = reqmode->height;
fb->pitch = ALIGN(reqmode->width * 4, 64); fb->pitches[0] = ALIGN(reqmode->width * 4, 64);
fb->pitches[1] = ALIGN(reqmode->width * 4, 64);
fb->pitches[2] = ALIGN(reqmode->width * 4, 64);
fb->pitches[3] = ALIGN(reqmode->width * 4, 64);
fb->bits_per_pixel = 32; fb->bits_per_pixel = 32;
fb->depth == 24; fb->depth == 24;
@ -320,13 +307,13 @@ do_set:
{ {
os_display->width = fb->width; os_display->width = fb->width;
os_display->height = fb->height; os_display->height = fb->height;
os_display->pitch = fb->pitch; os_display->pitch = fb->pitches[0];
os_display->vrefresh = drm_mode_vrefresh(mode); os_display->vrefresh = drm_mode_vrefresh(mode);
sysSetScreen(fb->width, fb->height, fb->pitch); sysSetScreen(fb->width, fb->height, fb->pitches[0]);
dbgprintf("new mode %d x %d pitch %d\n", dbgprintf("new mode %d x %d pitch %d\n",
fb->width, fb->height, fb->pitch); fb->width, fb->height, fb->pitches[0]);
} }
else else
DRM_ERROR("failed to set mode %d_%d on crtc %p\n", DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
@ -406,6 +393,8 @@ int set_user_mode(videomode_t *mode)
void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor) void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor)
{ {
/* FIXME synchronization */
list_del(&cursor->list); list_del(&cursor->list);
// radeon_bo_unpin(cursor->robj); // radeon_bo_unpin(cursor->robj);
// KernelFree(cursor->data); // KernelFree(cursor->data);
@ -592,68 +581,36 @@ extern struct drm_device *main_device;
#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
int video_blit(uint64_t src_offset, int x, int y,
int w, int h, int pitch) typedef struct
{ {
int left;
drm_i915_private_t *dev_priv = main_device->dev_private; int top;
struct intel_ring_buffer *ring; int right;
int bottom;
u32_t br13, cmd, *b; }rect_t;
u32_t offset;
int n=0;
// if( cmd_buffer & 0xF80 )
// cmd_buffer&= 0xFFFFF000;
// b = (u32_t*)ALIGN(cmd_buffer,16);
// offset = cmd_offset + ((u32_t)b & 0xFFF);
b = cmd_buffer;
cmd = XY_SRC_COPY_BLT_CMD | BLT_WRITE_RGB;
br13 = os_display->pitch;
br13 |= 0xCC << 16;
br13 |= 3 << 24;
b[n++] = cmd;
b[n++] = br13;
b[n++] = (y << 16) | x;
b[n++] = ( (y+h) << 16) | (x+w); // bottom, right
b[n++] = 0; // dst_offset
b[n++] = 0; //src_top|src_left
b[n++] = pitch;
b[n++] = (u32_t)src_offset;
b[n++] = MI_BATCH_BUFFER_END;
if( n & 1)
b[n++] = MI_NOOP;
// i915_gem_object_set_to_gtt_domain(obj, false);
ring = &dev_priv->ring[BCS];
ring->dispatch_execbuffer(ring, cmd_offset, n*4);
intel_ring_begin(ring, 4);
// if (ret)
// return ret;
// cmd = MI_FLUSH_DW;
// if (invalidate & I915_GEM_GPU_DOMAINS)
// cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
intel_ring_emit(ring, MI_FLUSH_DW);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
fail: #include "clip.inc"
return -1;
}; void FASTCALL GetWindowRect(rect_t *rc)__asm__("GetWindowRect");
#define CURRENT_TASK (0x80003000)
static u32_t get_display_map()
{
u32_t addr;
addr = (u32_t)os_display;
addr+= sizeof(display_t); /* shoot me */
return *(u32_t*)addr;
}
#define XY_SRC_COPY_CHROMA_CMD ((2<<29)|(0x73<<22)|8)
#define ROP_COPY_SRC 0xCC
#define FORMAT8888 3
typedef int v4si __attribute__ ((vector_size (16)));
int blit_video(u32 hbitmap, int dst_x, int dst_y, int blit_video(u32 hbitmap, int dst_x, int dst_y,
@ -663,42 +620,188 @@ int blit_video(u32 hbitmap, int dst_x, int dst_y,
struct intel_ring_buffer *ring; struct intel_ring_buffer *ring;
bitmap_t *bitmap; bitmap_t *bitmap;
u32_t br13, cmd, *b; rect_t winrc;
u32_t offset; clip_t dst_clip;
clip_t src_clip;
u32_t width;
u32_t height;
u32_t br13, cmd, slot_mask, *b;
u32_t offset;
u8 slot;
int n=0; int n=0;
if(unlikely(hbitmap==0)) if(unlikely(hbitmap==0))
return -1; return -1;
bitmap = hman_get_data(&bm_man, hbitmap); bitmap = (bitmap_t*)hman_get_data(&bm_man, hbitmap);
if(unlikely(bitmap==NULL)) if(unlikely(bitmap==NULL))
return -1; return -1;
// if( cmd_buffer & 0xF80 )
// cmd_buffer&= 0xFFFFF000;
// b = (u32_t*)ALIGN(cmd_buffer,16); GetWindowRect(&winrc);
// offset = cmd_offset + ((u32_t)b & 0xFFF); dst_clip.xmin = 0;
dst_clip.ymin = 0;
dst_clip.xmax = winrc.right-winrc.left-1;
dst_clip.ymax = winrc.bottom -winrc.top -1;
b = cmd_buffer; src_clip.xmin = 0;
src_clip.ymin = 0;
src_clip.xmax = bitmap->width - 1;
src_clip.ymax = bitmap->height - 1;
width = w;
height = h;
if( blit_clip(&dst_clip, &dst_x, &dst_y,
&src_clip, &src_x, &src_y,
&width, &height) )
return 0;
dst_x+= winrc.left;
dst_y+= winrc.top;
slot = *((u8*)CURRENT_TASK);
slot_mask = (u32_t)slot<<24;
{
#if 0
static v4si write_mask = {0xFF000000, 0xFF000000,
0xFF000000, 0xFF000000};
u8* src_offset;
u8* dst_offset;
src_offset = (u8*)(src_y*bitmap->pitch + src_x*4);
src_offset += (u32)bitmap->uaddr;
dst_offset = (u8*)(dst_y*os_display->width + dst_x);
dst_offset+= get_display_map();
u32_t tmp_h = height;
__asm__ __volatile__ (
"movdqa %[write_mask], %%xmm7 \n"
"movd %[slot_mask], %%xmm6 \n"
"punpckldq %%xmm6, %%xmm6 \n"
"punpcklqdq %%xmm6, %%xmm6 \n"
:: [write_mask] "m" (write_mask),
[slot_mask] "g" (slot_mask)
:"xmm7", "xmm6");
while( tmp_h--)
{
u32_t tmp_w = width;
u8* tmp_src = src_offset;
u8* tmp_dst = dst_offset;
src_offset+= bitmap->pitch;
dst_offset+= os_display->width;
while( tmp_w >= 8 )
{
__asm__ __volatile__ (
"movq (%0), %%xmm0 \n"
"punpcklbw %%xmm0, %%xmm0 \n"
"movdqa %%xmm0, %%xmm1 \n"
"punpcklwd %%xmm0, %%xmm0 \n"
"punpckhwd %%xmm1, %%xmm1 \n"
"pcmpeqb %%xmm6, %%xmm0 \n"
"pcmpeqb %%xmm6, %%xmm1 \n"
"maskmovdqu %%xmm7, %%xmm0 \n"
"addl $16, %%edi \n"
"maskmovdqu %%xmm7, %%xmm1 \n"
:: "r" (tmp_dst), "D" (tmp_src)
:"xmm0", "xmm1");
__asm__ __volatile__ ("":::"edi");
tmp_w -= 8;
tmp_src += 32;
tmp_dst += 8;
};
if( tmp_w >= 4 )
{
__asm__ __volatile__ (
"movd (%0), %%xmm0 \n"
"punpcklbw %%xmm0, %%xmm0 \n"
"punpcklwd %%xmm0, %%xmm0 \n"
"pcmpeqb %%xmm6, %%xmm0 \n"
"maskmovdqu %%xmm7, %%xmm0 \n"
:: "r" (tmp_dst), "D" (tmp_src)
:"xmm0");
tmp_w -= 4;
tmp_src += 16;
tmp_dst += 4;
};
while( tmp_w--)
{
*(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00;
tmp_src+=4;
tmp_dst++;
};
};
#else
u8* src_offset;
u8* dst_offset;
src_offset = (u8*)(src_y*bitmap->pitch + src_x*4);
src_offset += (u32)bitmap->uaddr;
dst_offset = (u8*)(dst_y*os_display->width + dst_x);
dst_offset+= get_display_map();
u32_t tmp_h = height;
while( tmp_h--)
{
u32_t tmp_w = width;
u8* tmp_src = src_offset;
u8* tmp_dst = dst_offset;
src_offset+= bitmap->pitch;
dst_offset+= os_display->width;
while( tmp_w--)
{
*(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00;
tmp_src+=4;
tmp_dst++;
};
};
}
#endif
if((cmd_buffer & 0xFC0)==0xFC0)
cmd_buffer&= 0xFFFFF000;
b = (u32_t*)ALIGN(cmd_buffer,16);
offset = cmd_offset + ((u32_t)b & 0xFFF);
cmd = XY_SRC_COPY_CHROMA_CMD | BLT_WRITE_RGB | BLT_WRITE_ALPHA;
cmd |= 3 << 17;
cmd = XY_SRC_COPY_BLT_CMD | BLT_WRITE_RGB;
br13 = os_display->pitch; br13 = os_display->pitch;
br13 |= 0xCC << 16; br13|= ROP_COPY_SRC << 16;
br13 |= 3 << 24; br13|= FORMAT8888 << 24;
b[n++] = cmd; b[n++] = cmd;
b[n++] = br13; b[n++] = br13;
b[n++] = (dst_y << 16) | dst_x; b[n++] = (dst_y << 16) | dst_x; // left, top
b[n++] = ( (dst_y+h) << 16) | (dst_x+w); // bottom, right b[n++] = ((dst_y+height-1)<< 16)|(dst_x+width-1); // bottom, right
b[n++] = 0; // dst_offset b[n++] = 0; // destination
b[n++] = (src_y << 16) | src_x; b[n++] = (src_y << 16) | src_x; // source left & top
b[n++] = bitmap->pitch; // source pitch
b[n++] = bitmap->gaddr; // source
b[n++] = bitmap->pitch; b[n++] = 0; // Transparency Color Low
b[n++] = bitmap->gaddr; b[n++] = 0x00FFFFFF; // Transparency Color High
b[n++] = MI_BATCH_BUFFER_END; b[n++] = MI_BATCH_BUFFER_END;
if( n & 1) if( n & 1)
@ -706,7 +809,11 @@ int blit_video(u32 hbitmap, int dst_x, int dst_y,
// i915_gem_object_set_to_gtt_domain(obj, false); // i915_gem_object_set_to_gtt_domain(obj, false);
if (HAS_BLT(main_device))
ring = &dev_priv->ring[BCS]; ring = &dev_priv->ring[BCS];
else
ring = &dev_priv->ring[RCS];
ring->dispatch_execbuffer(ring, cmd_offset, n*4); ring->dispatch_execbuffer(ring, cmd_offset, n*4);
intel_ring_begin(ring, 4); intel_ring_begin(ring, 4);

View File

@ -12,14 +12,13 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <syscall.h> #include <syscall.h>
typedef struct bitmap bitmap_t; #include "bitmap.h"
void parse_cmdline(char *cmdline, char *log); void parse_cmdline(char *cmdline, char *log);
int _stdcall display_handler(ioctl_t *io); int _stdcall display_handler(ioctl_t *io);
int init_agp(void); int init_agp(void);
int create_video(int width, int height, u32_t *outp); int create_video(int width, int height, u32_t *outp);
int create_bitmap(bitmap_t **pbitmap, int width, int height);
int video_blit(uint64_t src_offset, int x, int y, int video_blit(uint64_t src_offset, int x, int y,
int w, int h, int pitch); int w, int h, int pitch);
@ -52,7 +51,7 @@ u32_t drvEntry(int action, char *cmdline)
return 0; return 0;
}; };
} }
dbgprintf("i915_early_preview second edition\n cmdline: %s\n", cmdline); dbgprintf("i915 blitter preview\n cmdline: %s\n", cmdline);
enum_pci_devices(); enum_pci_devices();
@ -78,9 +77,9 @@ u32_t drvEntry(int action, char *cmdline)
#define SRV_ENUM_MODES 1 #define SRV_ENUM_MODES 1
#define SRV_SET_MODE 2 #define SRV_SET_MODE 2
#define SRV_CREATE_VIDEO 9 #define SRV_CREATE_BITMAP 10
#define SRV_BLIT_VIDEO 10
#define SRV_CREATE_BITMAP 11 #define SRV_BLIT_VIDEO 20
#define check_input(size) \ #define check_input(size) \
if( unlikely((inp==NULL)||(io->inp_size != (size))) ) \ if( unlikely((inp==NULL)||(io->inp_size != (size))) ) \
@ -124,25 +123,18 @@ int _stdcall display_handler(ioctl_t *io)
retval = set_user_mode((videomode_t*)inp); retval = set_user_mode((videomode_t*)inp);
break; break;
case SRV_CREATE_VIDEO: case SRV_CREATE_BITMAP:
check_input(2); check_input(5);
check_output(4); retval = create_bitmap((struct ubitmap*)inp);
retval = create_video(inp[0], inp[1], outp);
break; break;
case SRV_BLIT_VIDEO: case SRV_BLIT_VIDEO:
video_blit( ((uint64_t*)inp)[0], inp[2], inp[3], blit_video( inp[0], inp[1], inp[2],
inp[4], inp[5], inp[6]); inp[3], inp[4], inp[5], inp[6]);
retval = 0; retval = 0;
break; break;
case SRV_CREATE_BITMAP:
check_input(8);
check_output(4);
retval = create_bitmap((bitmap_t**)outp, inp[0], inp[1]);
break;
}; };
return retval; return retval;