Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (31 commits) gma500: Fix suspend/resume functions drm/exynos: fixed pm feature for fimd module. MAINTAINERS: added maintainer entry for Exynos DRM Driver. drm/exynos: fixed build dependency for DRM_EXYNOS_FIMD drm/exynos: fix build dependency for DRM_EXYNOS_HDMI drm/exynos: use release_mem_region instead of release_resource agp: fix scratch page cleanup drm/i915: fixup forcewake spinlock fallout in drpc debugfs function drm/i915: debugfs: show semaphore registers also on gen7 drm/i915: allow userspace forcewake references also on gen7 drm/i915: Re-enable gen7 RC6 and GPU turbo after resume. drm/i915: Correct debugfs printout for RC1e. Revert "drm/i915: Work around gen7 BLT ring synchronization issues." drm/i915: rip out the HWSTAM missed irq workaround drm/i915: paper over missed irq issues with force wake voodoo drm/i915: Hold gt_lock across forcewake register reads drm/i915: Hold gt_lock during reset drm/i915: Move reset forcewake processing to gen6_do_reset drm/i915: protect force_wake_(get|put) with the gt_lock drm/i915: convert force_wake_get to func pointer in the gpu reset code ...
This commit is contained in:
commit
acb42a3b61
@ -2350,6 +2350,9 @@ F: include/drm/i915*
|
||||
|
||||
DRM DRIVERS FOR EXYNOS
|
||||
M: Inki Dae <inki.dae@samsung.com>
|
||||
M: Joonyoung Shim <jy0922.shim@samsung.com>
|
||||
M: Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/exynos
|
||||
|
@ -194,10 +194,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
|
||||
|
||||
err_out:
|
||||
if (bridge->driver->needs_scratch_page) {
|
||||
void *va = page_address(bridge->scratch_page_page);
|
||||
struct page *page = bridge->scratch_page_page;
|
||||
|
||||
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
|
||||
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
|
||||
bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
|
||||
bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
|
||||
}
|
||||
if (got_gatt)
|
||||
bridge->driver->free_gatt_table(bridge);
|
||||
@ -221,10 +221,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
|
||||
|
||||
if (bridge->driver->agp_destroy_page &&
|
||||
bridge->driver->needs_scratch_page) {
|
||||
void *va = page_address(bridge->scratch_page_page);
|
||||
struct page *page = bridge->scratch_page_page;
|
||||
|
||||
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
|
||||
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
|
||||
bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
|
||||
bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ config DRM_EXYNOS
|
||||
|
||||
config DRM_EXYNOS_FIMD
|
||||
tristate "Exynos DRM FIMD"
|
||||
depends on DRM_EXYNOS
|
||||
depends on DRM_EXYNOS && !FB_S3C
|
||||
default n
|
||||
help
|
||||
Choose this option if you want to use Exynos FIMD for DRM.
|
||||
@ -21,7 +21,7 @@ config DRM_EXYNOS_FIMD
|
||||
|
||||
config DRM_EXYNOS_HDMI
|
||||
tristate "Exynos DRM HDMI"
|
||||
depends on DRM_EXYNOS
|
||||
depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
|
||||
help
|
||||
Choose this option if you want to use Exynos HDMI for DRM.
|
||||
If M is selected, the module will be called exynos_drm_hdmi
|
||||
|
@ -158,6 +158,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (!ctx->suspended)
|
||||
pm_runtime_put_sync(subdrv_dev);
|
||||
break;
|
||||
default:
|
||||
@ -734,6 +735,46 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
}
|
||||
|
||||
static int fimd_power_on(struct fimd_context *ctx, bool enable)
|
||||
{
|
||||
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
|
||||
struct device *dev = subdrv->manager.dev;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (enable != false && enable != true)
|
||||
return -EINVAL;
|
||||
|
||||
if (enable) {
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(ctx->bus_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(ctx->lcd_clk);
|
||||
if (ret < 0) {
|
||||
clk_disable(ctx->bus_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->suspended = false;
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (test_and_clear_bit(0, &ctx->irq_flags))
|
||||
fimd_enable_vblank(dev);
|
||||
|
||||
fimd_apply(dev);
|
||||
} else {
|
||||
clk_disable(ctx->lcd_clk);
|
||||
clk_disable(ctx->bus_clk);
|
||||
|
||||
ctx->suspended = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit fimd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -911,39 +952,30 @@ out:
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int fimd_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
ret = pm_runtime_suspend(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* do not use pm_runtime_suspend(). if pm_runtime_suspend() is
|
||||
* called here, an error would be returned by that interface
|
||||
* because the usage_count of pm runtime is more than 1.
|
||||
*/
|
||||
return fimd_power_on(ctx, false);
|
||||
}
|
||||
|
||||
static int fimd_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
|
||||
ret = pm_runtime_resume(dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to resume runtime pm.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
ret = pm_runtime_set_active(dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to active runtime pm.\n");
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_suspend(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
/*
|
||||
* if entered to sleep when lcd panel was on, the usage_count
|
||||
* of pm runtime would still be 1 so in this case, fimd driver
|
||||
* should be on directly not drawing on pm runtime interface.
|
||||
*/
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return fimd_power_on(ctx, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -956,39 +988,16 @@ static int fimd_runtime_suspend(struct device *dev)
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
clk_disable(ctx->lcd_clk);
|
||||
clk_disable(ctx->bus_clk);
|
||||
|
||||
ctx->suspended = true;
|
||||
return 0;
|
||||
return fimd_power_on(ctx, false);
|
||||
}
|
||||
|
||||
static int fimd_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ret = clk_enable(ctx->bus_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(ctx->lcd_clk);
|
||||
if (ret < 0) {
|
||||
clk_disable(ctx->bus_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->suspended = false;
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (test_and_clear_bit(0, &ctx->irq_flags))
|
||||
fimd_enable_vblank(dev);
|
||||
|
||||
fimd_apply(dev);
|
||||
|
||||
return 0;
|
||||
return fimd_power_on(ctx, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1116,8 +1116,8 @@ err_ddc:
|
||||
err_iomap:
|
||||
iounmap(hdata->regs);
|
||||
err_req_region:
|
||||
release_resource(hdata->regs_res);
|
||||
kfree(hdata->regs_res);
|
||||
release_mem_region(hdata->regs_res->start,
|
||||
resource_size(hdata->regs_res));
|
||||
err_resource:
|
||||
hdmi_resources_cleanup(hdata);
|
||||
err_data:
|
||||
@ -1145,8 +1145,8 @@ static int __devexit hdmi_remove(struct platform_device *pdev)
|
||||
|
||||
iounmap(hdata->regs);
|
||||
|
||||
release_resource(hdata->regs_res);
|
||||
kfree(hdata->regs_res);
|
||||
release_mem_region(hdata->regs_res->start,
|
||||
resource_size(hdata->regs_res));
|
||||
|
||||
/* hdmiphy i2c driver */
|
||||
i2c_del_driver(&hdmiphy_driver);
|
||||
|
@ -113,12 +113,12 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
|
||||
void psbfb_suspend(struct drm_device *dev)
|
||||
{
|
||||
struct drm_framebuffer *fb = 0;
|
||||
struct psb_framebuffer *psbfb = to_psb_fb(fb);
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
console_lock();
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
|
||||
struct psb_framebuffer *psbfb = to_psb_fb(fb);
|
||||
struct fb_info *info = psbfb->fbdev;
|
||||
fb_set_suspend(info, 1);
|
||||
drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
|
||||
@ -129,12 +129,12 @@ void psbfb_suspend(struct drm_device *dev)
|
||||
|
||||
void psbfb_resume(struct drm_device *dev)
|
||||
{
|
||||
struct drm_framebuffer *fb = 0;
|
||||
struct psb_framebuffer *psbfb = to_psb_fb(fb);
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
console_lock();
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
|
||||
struct psb_framebuffer *psbfb = to_psb_fb(fb);
|
||||
struct fb_info *info = psbfb->fbdev;
|
||||
fb_set_suspend(info, 0);
|
||||
drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
|
||||
|
@ -121,11 +121,11 @@ static const char *cache_level_str(int type)
|
||||
static void
|
||||
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
|
||||
{
|
||||
seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s%s",
|
||||
seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s",
|
||||
&obj->base,
|
||||
get_pin_flag(obj),
|
||||
get_tiling_flag(obj),
|
||||
obj->base.size,
|
||||
obj->base.size / 1024,
|
||||
obj->base.read_domains,
|
||||
obj->base.write_domain,
|
||||
obj->last_rendering_seqno,
|
||||
@ -653,7 +653,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
|
||||
seq_printf(m, " Size : %08x\n", ring->size);
|
||||
seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring));
|
||||
seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring));
|
||||
if (IS_GEN6(dev)) {
|
||||
if (IS_GEN6(dev) || IS_GEN7(dev)) {
|
||||
seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring));
|
||||
seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring));
|
||||
}
|
||||
@ -1075,6 +1075,7 @@ static int gen6_drpc_info(struct seq_file *m)
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 rpmodectl1, gt_core_status, rcctl1;
|
||||
unsigned forcewake_count;
|
||||
int count=0, ret;
|
||||
|
||||
|
||||
@ -1082,9 +1083,13 @@ static int gen6_drpc_info(struct seq_file *m)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (atomic_read(&dev_priv->forcewake_count)) {
|
||||
seq_printf(m, "RC information inaccurate because userspace "
|
||||
"holds a reference \n");
|
||||
spin_lock_irq(&dev_priv->gt_lock);
|
||||
forcewake_count = dev_priv->forcewake_count;
|
||||
spin_unlock_irq(&dev_priv->gt_lock);
|
||||
|
||||
if (forcewake_count) {
|
||||
seq_printf(m, "RC information inaccurate because somebody "
|
||||
"holds a forcewake reference \n");
|
||||
} else {
|
||||
/* NB: we cannot use forcewake, else we read the wrong values */
|
||||
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
|
||||
@ -1106,7 +1111,7 @@ static int gen6_drpc_info(struct seq_file *m)
|
||||
seq_printf(m, "SW control enabled: %s\n",
|
||||
yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) ==
|
||||
GEN6_RP_MEDIA_SW_MODE));
|
||||
seq_printf(m, "RC6 Enabled: %s\n",
|
||||
seq_printf(m, "RC1e Enabled: %s\n",
|
||||
yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
|
||||
seq_printf(m, "RC6 Enabled: %s\n",
|
||||
yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
|
||||
@ -1398,9 +1403,13 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned forcewake_count;
|
||||
|
||||
seq_printf(m, "forcewake count = %d\n",
|
||||
atomic_read(&dev_priv->forcewake_count));
|
||||
spin_lock_irq(&dev_priv->gt_lock);
|
||||
forcewake_count = dev_priv->forcewake_count;
|
||||
spin_unlock_irq(&dev_priv->gt_lock);
|
||||
|
||||
seq_printf(m, "forcewake count = %u\n", forcewake_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1665,7 +1674,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if (!IS_GEN6(dev))
|
||||
if (INTEL_INFO(dev)->gen < 6)
|
||||
return 0;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
@ -1682,7 +1691,7 @@ int i915_forcewake_release(struct inode *inode, struct file *file)
|
||||
struct drm_device *dev = inode->i_private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!IS_GEN6(dev))
|
||||
if (INTEL_INFO(dev)->gen < 6)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
@ -2045,6 +2045,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
if (!IS_I945G(dev) && !IS_I945GM(dev))
|
||||
pci_enable_msi(dev->pdev);
|
||||
|
||||
spin_lock_init(&dev_priv->gt_lock);
|
||||
spin_lock_init(&dev_priv->irq_lock);
|
||||
spin_lock_init(&dev_priv->error_lock);
|
||||
spin_lock_init(&dev_priv->rps_lock);
|
||||
|
@ -368,11 +368,12 @@ void __gen6_gt_force_wake_mt_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 */
|
||||
if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
|
||||
spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
|
||||
if (dev_priv->forcewake_count++ == 0)
|
||||
dev_priv->display.force_wake_get(dev_priv);
|
||||
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
|
||||
}
|
||||
|
||||
void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
|
||||
@ -392,10 +393,12 @@ void __gen6_gt_force_wake_mt_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);
|
||||
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)
|
||||
@ -597,9 +600,36 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags)
|
||||
static int gen6_do_reset(struct drm_device *dev, u8 flags)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
unsigned long irqflags;
|
||||
|
||||
I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
|
||||
return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
|
||||
/* Hold gt_lock across reset to prevent any register access
|
||||
* with forcewake not set correctly
|
||||
*/
|
||||
spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
|
||||
|
||||
/* Reset the chip */
|
||||
|
||||
/* GEN6_GDRST is not in the gt power well, no need to check
|
||||
* for fifo space for the write or forcewake the chip for
|
||||
* the read
|
||||
*/
|
||||
I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
|
||||
|
||||
/* Spin waiting for the device to ack the reset request */
|
||||
ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
|
||||
|
||||
/* If reset with a user forcewake, try to restore, otherwise turn it off */
|
||||
if (dev_priv->forcewake_count)
|
||||
dev_priv->display.force_wake_get(dev_priv);
|
||||
else
|
||||
dev_priv->display.force_wake_put(dev_priv);
|
||||
|
||||
/* Restore fifo count */
|
||||
dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -643,9 +673,6 @@ int i915_reset(struct drm_device *dev, u8 flags)
|
||||
case 7:
|
||||
case 6:
|
||||
ret = gen6_do_reset(dev, flags);
|
||||
/* If reset with a user forcewake, try to restore */
|
||||
if (atomic_read(&dev_priv->forcewake_count))
|
||||
__gen6_gt_force_wake_get(dev_priv);
|
||||
break;
|
||||
case 5:
|
||||
ret = ironlake_do_reset(dev, flags);
|
||||
@ -927,9 +954,14 @@ MODULE_LICENSE("GPL and additional rights");
|
||||
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); \
|
||||
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); \
|
||||
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); \
|
||||
} else { \
|
||||
val = read##y(dev_priv->regs + reg); \
|
||||
} \
|
||||
|
@ -288,7 +288,13 @@ typedef struct drm_i915_private {
|
||||
int relative_constants_mode;
|
||||
|
||||
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. */
|
||||
struct spinlock gt_lock;
|
||||
|
||||
struct intel_gmbus {
|
||||
struct i2c_adapter adapter;
|
||||
@ -741,8 +747,6 @@ typedef struct drm_i915_private {
|
||||
|
||||
struct drm_property *broadcast_rgb_property;
|
||||
struct drm_property *force_audio_property;
|
||||
|
||||
atomic_t forcewake_count;
|
||||
} drm_i915_private_t;
|
||||
|
||||
enum i915_cache_level {
|
||||
|
@ -1751,7 +1751,8 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
|
||||
INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
|
||||
|
||||
I915_WRITE(HWSTAM, 0xeffe);
|
||||
if (IS_GEN6(dev) || IS_GEN7(dev)) {
|
||||
|
||||
if (IS_GEN6(dev)) {
|
||||
/* Workaround stalls observed on Sandy Bridge GPUs by
|
||||
* making the blitter command streamer generate a
|
||||
* write to the Hardware Status Page for
|
||||
|
@ -28,14 +28,19 @@
|
||||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 dpll_reg;
|
||||
|
||||
/* On IVB, 3rd pipe shares PLL with another one */
|
||||
if (pipe > 1)
|
||||
return false;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
|
||||
dpll_reg = PCH_DPLL(pipe);
|
||||
else
|
||||
dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
|
||||
|
||||
@ -822,7 +827,7 @@ int i915_save_state(struct drm_device *dev)
|
||||
|
||||
if (IS_IRONLAKE_M(dev))
|
||||
ironlake_disable_drps(dev);
|
||||
if (IS_GEN6(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 6)
|
||||
gen6_disable_rps(dev);
|
||||
|
||||
/* Cache mode state */
|
||||
@ -881,7 +886,7 @@ int i915_restore_state(struct drm_device *dev)
|
||||
intel_init_emon(dev);
|
||||
}
|
||||
|
||||
if (IS_GEN6(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
gen6_enable_rps(dev_priv);
|
||||
gen6_update_ring_freq(dev_priv);
|
||||
}
|
||||
|
@ -467,8 +467,12 @@ struct edp_link_params {
|
||||
struct bdb_edp {
|
||||
struct edp_power_seq power_seqs[16];
|
||||
u32 color_depth;
|
||||
u32 sdrrs_msa_timing_delay;
|
||||
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));
|
||||
|
||||
void intel_setup_bios(struct drm_device *dev);
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include "drmP.h"
|
||||
@ -540,6 +541,24 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
||||
.destroy = intel_encoder_destroy,
|
||||
};
|
||||
|
||||
static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id intel_no_crt[] = {
|
||||
{
|
||||
.callback = intel_no_crt_dmi_callback,
|
||||
.ident = "ACER ZGB",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
void intel_crt_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
@ -547,6 +566,10 @@ void intel_crt_init(struct drm_device *dev)
|
||||
struct intel_connector *intel_connector;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* Skip machines without VGA that falsely report hotplug events */
|
||||
if (dmi_check_system(intel_no_crt))
|
||||
return;
|
||||
|
||||
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
|
||||
if (!crt)
|
||||
return;
|
||||
|
@ -5808,12 +5808,15 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
||||
if (is_lvds) {
|
||||
temp = I915_READ(PCH_LVDS);
|
||||
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
|
||||
if (HAS_PCH_CPT(dev))
|
||||
if (HAS_PCH_CPT(dev)) {
|
||||
temp &= ~PORT_TRANS_SEL_MASK;
|
||||
temp |= PORT_TRANS_SEL_CPT(pipe);
|
||||
else if (pipe == 1)
|
||||
} else {
|
||||
if (pipe == 1)
|
||||
temp |= LVDS_PIPEB_SELECT;
|
||||
else
|
||||
temp &= ~LVDS_PIPEB_SELECT;
|
||||
}
|
||||
|
||||
/* set the corresponsding LVDS_BORDER bit */
|
||||
temp |= dev_priv->lvds_border_bits;
|
||||
@ -9025,12 +9028,9 @@ void intel_modeset_init(struct drm_device *dev)
|
||||
|
||||
for (i = 0; i < dev_priv->num_pipe; i++) {
|
||||
intel_crtc_init(dev, i);
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
ret = intel_plane_init(dev, i);
|
||||
if (ret)
|
||||
DRM_ERROR("plane %d init failed: %d\n",
|
||||
i, ret);
|
||||
}
|
||||
DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
|
||||
}
|
||||
|
||||
/* Just disable it once at startup */
|
||||
|
@ -707,6 +707,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
||||
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,
|
||||
.ident = "Asus EeeBox PC EB1007",
|
||||
|
@ -635,6 +635,19 @@ render_ring_add_request(struct intel_ring_buffer *ring,
|
||||
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
|
||||
ring_get_seqno(struct intel_ring_buffer *ring)
|
||||
{
|
||||
@ -791,17 +804,6 @@ ring_add_request(struct intel_ring_buffer *ring,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
gen7_blt_ring_get_irq(struct intel_ring_buffer *ring)
|
||||
{
|
||||
/* The BLT ring on IVB appears to have broken synchronization
|
||||
* between the seqno write and the interrupt, so that the
|
||||
* interrupt appears first. Returning false here makes
|
||||
* i915_wait_request() do a polling loop, instead.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
|
||||
{
|
||||
@ -811,6 +813,12 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
|
||||
if (!dev->irq_enabled)
|
||||
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);
|
||||
if (ring->irq_refcount++ == 0) {
|
||||
ring->irq_mask &= ~rflag;
|
||||
@ -835,6 +843,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
|
||||
ironlake_disable_irq(dev_priv, gflag);
|
||||
}
|
||||
spin_unlock(&ring->irq_lock);
|
||||
|
||||
if (IS_GEN7(dev))
|
||||
gen6_gt_force_wake_put(dev_priv);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1341,7 +1352,7 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
|
||||
.write_tail = gen6_bsd_ring_write_tail,
|
||||
.flush = gen6_ring_flush,
|
||||
.add_request = gen6_add_request,
|
||||
.get_seqno = ring_get_seqno,
|
||||
.get_seqno = gen6_ring_get_seqno,
|
||||
.irq_get = gen6_bsd_ring_get_irq,
|
||||
.irq_put = gen6_bsd_ring_put_irq,
|
||||
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
|
||||
@ -1476,7 +1487,7 @@ static const struct intel_ring_buffer gen6_blt_ring = {
|
||||
.write_tail = ring_write_tail,
|
||||
.flush = blt_ring_flush,
|
||||
.add_request = gen6_add_request,
|
||||
.get_seqno = ring_get_seqno,
|
||||
.get_seqno = gen6_ring_get_seqno,
|
||||
.irq_get = blt_ring_get_irq,
|
||||
.irq_put = blt_ring_put_irq,
|
||||
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
|
||||
@ -1499,6 +1510,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
|
||||
ring->flush = gen6_render_ring_flush;
|
||||
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)) {
|
||||
ring->add_request = pc_render_add_request;
|
||||
ring->get_seqno = pc_render_get_seqno;
|
||||
@ -1577,8 +1589,5 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
|
||||
|
||||
*ring = gen6_blt_ring;
|
||||
|
||||
if (IS_GEN7(dev))
|
||||
ring->irq_get = gen7_blt_ring_get_irq;
|
||||
|
||||
return intel_init_ring_buffer(dev, ring);
|
||||
}
|
||||
|
@ -1066,15 +1066,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
||||
|
||||
/* Set the SDVO control regs. */
|
||||
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)
|
||||
sdvox |= intel_sdvo->color_range;
|
||||
if (INTEL_INFO(dev)->gen < 5)
|
||||
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 {
|
||||
sdvox = I915_READ(intel_sdvo->sdvo_reg);
|
||||
switch (intel_sdvo->sdvo_reg) {
|
||||
|
@ -466,10 +466,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to pin object\n");
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
intel_plane->obj = obj;
|
||||
|
||||
@ -632,10 +630,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
|
||||
unsigned long possible_crtcs;
|
||||
int ret;
|
||||
|
||||
if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
|
||||
DRM_ERROR("new plane code only for SNB+\n");
|
||||
if (!(IS_GEN6(dev) || IS_GEN7(dev)))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
|
||||
if (!intel_plane)
|
||||
|
@ -417,7 +417,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "NTSC-M",
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.refresh = 59940,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
|
||||
@ -460,7 +460,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "NTSC-443",
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.refresh = 59940,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
|
||||
@ -502,7 +502,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "NTSC-J",
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.refresh = 59940,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
|
||||
@ -545,7 +545,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "PAL-M",
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.refresh = 59940,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
|
||||
@ -589,7 +589,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
|
||||
.name = "PAL-N",
|
||||
.clock = 108000,
|
||||
.refresh = 25000,
|
||||
.refresh = 50000,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
|
||||
@ -634,7 +634,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
|
||||
.name = "PAL",
|
||||
.clock = 108000,
|
||||
.refresh = 25000,
|
||||
.refresh = 50000,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
|
||||
@ -673,78 +673,6 @@ static const struct tv_mode tv_modes[] = {
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "480p@59.94Hz",
|
||||
.clock = 107520,
|
||||
.refresh = 59940,
|
||||
.oversample = TV_OVERSAMPLE_4X,
|
||||
.component_only = 1,
|
||||
|
||||
.hsync_end = 64, .hblank_end = 122,
|
||||
.hblank_start = 842, .htotal = 857,
|
||||
|
||||
.progressive = true, .trilevel_sync = false,
|
||||
|
||||
.vsync_start_f1 = 12, .vsync_start_f2 = 12,
|
||||
.vsync_len = 12,
|
||||
|
||||
.veq_ena = false,
|
||||
|
||||
.vi_end_f1 = 44, .vi_end_f2 = 44,
|
||||
.nbr_end = 479,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "480p@60Hz",
|
||||
.clock = 107520,
|
||||
.refresh = 60000,
|
||||
.oversample = TV_OVERSAMPLE_4X,
|
||||
.component_only = 1,
|
||||
|
||||
.hsync_end = 64, .hblank_end = 122,
|
||||
.hblank_start = 842, .htotal = 856,
|
||||
|
||||
.progressive = true, .trilevel_sync = false,
|
||||
|
||||
.vsync_start_f1 = 12, .vsync_start_f2 = 12,
|
||||
.vsync_len = 12,
|
||||
|
||||
.veq_ena = false,
|
||||
|
||||
.vi_end_f1 = 44, .vi_end_f2 = 44,
|
||||
.nbr_end = 479,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "576p",
|
||||
.clock = 107520,
|
||||
.refresh = 50000,
|
||||
.oversample = TV_OVERSAMPLE_4X,
|
||||
.component_only = 1,
|
||||
|
||||
.hsync_end = 64, .hblank_end = 139,
|
||||
.hblank_start = 859, .htotal = 863,
|
||||
|
||||
.progressive = true, .trilevel_sync = false,
|
||||
|
||||
.vsync_start_f1 = 10, .vsync_start_f2 = 10,
|
||||
.vsync_len = 10,
|
||||
|
||||
.veq_ena = false,
|
||||
|
||||
.vi_end_f1 = 48, .vi_end_f2 = 48,
|
||||
.nbr_end = 575,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "720p@60Hz",
|
||||
.clock = 148800,
|
||||
@ -769,30 +697,6 @@ static const struct tv_mode tv_modes[] = {
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "720p@59.94Hz",
|
||||
.clock = 148800,
|
||||
.refresh = 59940,
|
||||
.oversample = TV_OVERSAMPLE_2X,
|
||||
.component_only = 1,
|
||||
|
||||
.hsync_end = 80, .hblank_end = 300,
|
||||
.hblank_start = 1580, .htotal = 1651,
|
||||
|
||||
.progressive = true, .trilevel_sync = true,
|
||||
|
||||
.vsync_start_f1 = 10, .vsync_start_f2 = 10,
|
||||
.vsync_len = 10,
|
||||
|
||||
.veq_ena = false,
|
||||
|
||||
.vi_end_f1 = 29, .vi_end_f2 = 29,
|
||||
.nbr_end = 719,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "720p@50Hz",
|
||||
.clock = 148800,
|
||||
@ -821,7 +725,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "1080i@50Hz",
|
||||
.clock = 148800,
|
||||
.refresh = 25000,
|
||||
.refresh = 50000,
|
||||
.oversample = TV_OVERSAMPLE_2X,
|
||||
.component_only = 1,
|
||||
|
||||
@ -847,7 +751,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "1080i@60Hz",
|
||||
.clock = 148800,
|
||||
.refresh = 30000,
|
||||
.refresh = 60000,
|
||||
.oversample = TV_OVERSAMPLE_2X,
|
||||
.component_only = 1,
|
||||
|
||||
@ -863,32 +767,6 @@ static const struct tv_mode tv_modes[] = {
|
||||
.veq_start_f2 = 4, .veq_len = 10,
|
||||
|
||||
|
||||
.vi_end_f1 = 21, .vi_end_f2 = 22,
|
||||
.nbr_end = 539,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
.filter_table = filter_table,
|
||||
},
|
||||
{
|
||||
.name = "1080i@59.94Hz",
|
||||
.clock = 148800,
|
||||
.refresh = 29970,
|
||||
.oversample = TV_OVERSAMPLE_2X,
|
||||
.component_only = 1,
|
||||
|
||||
.hsync_end = 88, .hblank_end = 235,
|
||||
.hblank_start = 2155, .htotal = 2201,
|
||||
|
||||
.progressive = false, .trilevel_sync = true,
|
||||
|
||||
.vsync_start_f1 = 4, .vsync_start_f2 = 5,
|
||||
.vsync_len = 10,
|
||||
|
||||
.veq_ena = true, .veq_start_f1 = 4,
|
||||
.veq_start_f2 = 4, .veq_len = 10,
|
||||
|
||||
|
||||
.vi_end_f1 = 21, .vi_end_f2 = 22,
|
||||
.nbr_end = 539,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user