Commit 198ceac0 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel into drm-core-next

* 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel:
  drm/i915: add a LLC feature flag in device description
  drm/i915: kill i915_mem.c
  drm/i915: Use kcalloc instead of kzalloc to allocate array
  drm/i915/dp: Check for AUXCH error before checking for success
  drm/i915/dp: Use auxch precharge value of 5 everywhere
  drm/i915/dp: Tweak auxch clock divider for PCH
  drm/i915: Remove a comment about PCH from the non-PCH path
  drm/i915: Fix assert_pch_hdmi_disabled to mention HDMI (not DP)
  drm/i915: Implement plane-disabled assertion for PCH too
  drivers: i915: Fix BLC PWM register setup
  drm/i915: Check that plane/pipe is disabled before removing the fb
  drm/i915: fix typo in function name
  drm/i915: split out pll divider code
  drm/i915: split 9xx refclk & sdvo tv code out
  agp/intel: Add pci id for hostbridge from has/qemu
  drm/i915: there is no pipe CxSR on ironlake
  drm/i915: Only look for matching clocks for LVDS downclock
  drm/i915: Silence _DSM errors
parents 83b316fd 3d29b842
......@@ -850,6 +850,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
.subvendor = PCI_ANY_ID, \
.subdevice = PCI_ANY_ID, \
}
ID(PCI_DEVICE_ID_INTEL_82441), /* for HAS2 support */
ID(PCI_DEVICE_ID_INTEL_82443LX_0),
ID(PCI_DEVICE_ID_INTEL_82443BX_0),
ID(PCI_DEVICE_ID_INTEL_82443GX_0),
......
......@@ -37,6 +37,7 @@
#include "drm_core.h"
#include "linux/pci.h"
#include "linux/export.h"
/**
* Get the bus id.
......@@ -346,3 +347,4 @@ int drm_noop(struct drm_device *dev, void *data,
DRM_DEBUG("\n");
return 0;
}
EXPORT_SYMBOL(drm_noop);
......@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
ccflags-y := -Iinclude/drm
i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
i915-y := i915_drv.o i915_dma.o i915_irq.o \
i915_debugfs.o \
i915_suspend.o \
i915_gem.o \
......
......@@ -83,6 +83,7 @@ static int i915_capabilities(struct seq_file *m, void *data)
B(supports_tv);
B(has_bsd_ring);
B(has_blt_ring);
B(has_llc);
#undef B
return 0;
......
......@@ -784,6 +784,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_GEN7_SOL_RESET:
value = 1;
break;
case I915_PARAM_HAS_LLC:
value = HAS_LLC(dev);
break;
default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param);
......@@ -2247,18 +2250,12 @@ void i915_driver_lastclose(struct drm_device * dev)
i915_gem_lastclose(dev);
if (dev_priv->agp_heap)
i915_mem_takedown(&(dev_priv->agp_heap));
i915_dma_cleanup(dev);
}
void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
i915_gem_release(dev, file_priv);
if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_mem_release(dev, file_priv, dev_priv->agp_heap);
}
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
......@@ -2277,11 +2274,11 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_ALLOC, i915_mem_alloc, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_FREE, i915_mem_free, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
......
......@@ -198,7 +198,7 @@ static const struct intel_device_info intel_pineview_info = {
static const struct intel_device_info intel_ironlake_d_info = {
.gen = 5,
.need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
.need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
};
......@@ -214,6 +214,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
.need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.has_llc = 1,
};
static const struct intel_device_info intel_sandybridge_m_info = {
......@@ -222,6 +223,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
.has_fbc = 1,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.has_llc = 1,
};
static const struct intel_device_info intel_ivybridge_d_info = {
......@@ -229,6 +231,7 @@ static const struct intel_device_info intel_ivybridge_d_info = {
.need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.has_llc = 1,
};
static const struct intel_device_info intel_ivybridge_m_info = {
......@@ -237,6 +240,7 @@ static const struct intel_device_info intel_ivybridge_m_info = {
.has_fbc = 0, /* FBC is not enabled on Ivybridge mobile yet */
.has_bsd_ring = 1,
.has_blt_ring = 1,
.has_llc = 1,
};
static const struct pci_device_id pciidlist[] = { /* aka */
......@@ -633,7 +637,7 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags)
}
/**
* i965_reset - reset chip after a hang
* i915_reset - reset chip after a hang
* @dev: drm device to reset
* @flags: reset domains
*
......
......@@ -255,6 +255,7 @@ struct intel_device_info {
u8 supports_tv:1;
u8 has_bsd_ring:1;
u8 has_blt_ring:1;
u8 has_llc:1;
};
enum no_fbc_reason {
......@@ -335,7 +336,6 @@ typedef struct drm_i915_private {
int tex_lru_log_granularity;
int allow_batchbuffer;
struct mem_block *agp_heap;
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
int vblank_pipe;
int num_pipe;
......@@ -974,6 +974,7 @@ struct drm_i915_file_private {
#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring)
#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring)
#define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc)
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
......@@ -1079,18 +1080,6 @@ extern void i915_destroy_error_state(struct drm_device *dev);
#endif
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_mem_free(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_mem_init_heap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_mem_destroy_heap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(struct drm_device * dev,
struct drm_file *file_priv, struct mem_block *heap);
/* i915_gem.c */
int i915_gem_init_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
......
......@@ -3619,8 +3619,8 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
obj->base.write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU;
if (IS_GEN6(dev) || IS_GEN7(dev)) {
/* On Gen6, we can have the GPU use the LLC (the CPU
if (HAS_LLC(dev)) {
/* On some devices, we can have the GPU use the LLC (the CPU
* cache) for about a 10% performance improvement
* compared to uncached. Graphics requests other than
* display scanout are coherent with the CPU in
......
/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
*/
/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
*
*/
#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
/* This memory manager is integrated into the global/local lru
* mechanisms used by the clients. Specifically, it operates by
* setting the 'in_use' fields of the global LRU to indicate whether
* this region is privately allocated to a client.
*
* This does require the client to actually respect that field.
*
* Currently no effort is made to allocate 'private' memory in any
* clever way - the LRU information isn't used to determine which
* block to allocate, and the ring is drained prior to allocations --
* in other words allocation is expensive.
*/
static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv;
struct drm_tex_region *list;
unsigned shift, nr;
unsigned start;
unsigned end;
unsigned i;
int age;
shift = dev_priv->tex_lru_log_granularity;
nr = I915_NR_TEX_REGIONS;
start = p->start >> shift;
end = (p->start + p->size - 1) >> shift;
age = ++sarea_priv->texAge;
list = sarea_priv->texList;
/* Mark the regions with the new flag and update their age. Move
* them to head of list to preserve LRU semantics.
*/
for (i = start; i <= end; i++) {
list[i].in_use = in_use;
list[i].age = age;
/* remove_from_list(i)
*/
list[(unsigned)list[i].next].prev = list[i].prev;
list[(unsigned)list[i].prev].next = list[i].next;
/* insert_at_head(list, i)
*/
list[i].prev = nr;
list[i].next = list[nr].next;
list[(unsigned)list[nr].next].prev = i;
list[nr].next = i;
}
}
/* Very simple allocator for agp memory, working on a static range
* already mapped into each client's address space.
*/
static struct mem_block *split_block(struct mem_block *p, int start, int size,
struct drm_file *file_priv)
{
/* Maybe cut off the start of an existing block */
if (start > p->start) {
struct mem_block *newblock = kmalloc(sizeof(*newblock),
GFP_KERNEL);
if (!newblock)
goto out;
newblock->start = start;
newblock->size = p->size - (start - p->start);
newblock->file_priv = NULL;
newblock->next = p->next;
newblock->prev = p;
p->next->prev = newblock;
p->next = newblock;
p->size -= newblock->size;
p = newblock;
}
/* Maybe cut off the end of an existing block */
if (size < p->size) {
struct mem_block *newblock = kmalloc(sizeof(*newblock),
GFP_KERNEL);
if (!newblock)
goto out;
newblock->start = start + size;
newblock->size = p->size - size;
newblock->file_priv = NULL;
newblock->next = p->next;
newblock->prev = p;
p->next->prev = newblock;
p->next = newblock;
p->size = size;
}
out:
/* Our block is in the middle */
p->file_priv = file_priv;
return p;
}
static struct mem_block *alloc_block(struct mem_block *heap, int size,
int align2, struct drm_file *file_priv)
{
struct mem_block *p;
int mask = (1 << align2) - 1;
for (p = heap->next; p != heap; p = p->next) {
int start = (p->start + mask) & ~mask;
if (p->file_priv == NULL && start + size <= p->start + p->size)
return split_block(p, start, size, file_priv);
}
return NULL;
}
static struct mem_block *find_block(struct mem_block *heap, int start)
{
struct mem_block *p;
for (p = heap->next; p != heap; p = p->next)
if (p->start == start)
return p;
return NULL;
}
static void free_block(struct mem_block *p)
{
p->file_priv = NULL;
/* Assumes a single contiguous range. Needs a special file_priv in
* 'heap' to stop it being subsumed.
*/
if (p->next->file_priv == NULL) {
struct mem_block *q = p->next;
p->size += q->size;
p->next = q->next;
p->next->prev = p;
kfree(q);
}
if (p->prev->file_priv == NULL) {
struct mem_block *q = p->prev;
q->size += p->size;
q->next = p->next;
q->next->prev = q;
kfree(p);
}
}
/* Initialize. How to check for an uninitialized heap?
*/
static int init_heap(struct mem_block **heap, int start, int size)
{
struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
if (!blocks)
return -ENOMEM;
*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
if (!*heap) {
kfree(blocks);
return -ENOMEM;
}
blocks->start = start;
blocks->size = size;
blocks->file_priv = NULL;
blocks->next = blocks->prev = *heap;
memset(*heap, 0, sizeof(**heap));
(*heap)->file_priv = (struct drm_file *) -1;
(*heap)->next = (*heap)->prev = blocks;
return 0;
}
/* Free all blocks associated with the releasing file.
*/
void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv,
struct mem_block *heap)
{
struct mem_block *p;
if (!heap || !heap->next)
return;
for (p = heap->next; p != heap; p = p->next) {
if (p->file_priv == file_priv) {
p->file_priv = NULL;
mark_block(dev, p, 0);
}
}
/* Assumes a single contiguous range. Needs a special file_priv in
* 'heap' to stop it being subsumed.
*/
for (p = heap->next; p != heap; p = p->next) {
while (p->file_priv == NULL && p->next->file_priv == NULL) {
struct mem_block *q = p->next;
p->size += q->size;
p->next = q->next;
p->next->prev = p;
kfree(q);
}
}
}
/* Shutdown.
*/
void i915_mem_takedown(struct mem_block **heap)
{
struct mem_block *p;
if (!*heap)
return;
for (p = (*heap)->next; p != *heap;) {
struct mem_block *q = p;
p = p->next;
kfree(q);
}
kfree(*heap);
*heap = NULL;
}
static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
{
switch (region) {
case I915_MEM_REGION_AGP:
return &dev_priv->agp_heap;
default:
return NULL;
}
}
/* IOCTL HANDLERS */
int i915_mem_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_mem_alloc_t *alloc = data;
struct mem_block *block, **heap;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
heap = get_heap(dev_priv, alloc->region);
if (!heap || !*heap)
return -EFAULT;
/* Make things easier on ourselves: all allocations at least
* 4k aligned.
*/
if (alloc->alignment < 12)
alloc->alignment = 12;
block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
if (!block)
return -ENOMEM;
mark_block(dev, block, 1);
if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
sizeof(int))) {
DRM_ERROR("copy_to_user\n");
return -EFAULT;
}
return 0;
}
int i915_mem_free(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_mem_free_t *memfree = data;
struct mem_block *block, **heap;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
heap = get_heap(dev_priv, memfree->region);
if (!heap || !*heap)
return -EFAULT;
block = find_block(*heap, memfree->region_offset);
if (!block)
return -EFAULT;
if (block->file_priv != file_priv)
return -EPERM;
mark_block(dev, block, 0);
free_block(block);
return 0;
}
int i915_mem_init_heap(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_mem_init_heap_t *initheap = data;
struct mem_block **heap;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
heap = get_heap(dev_priv, initheap->region);
if (!heap)
return -EFAULT;
if (*heap) {
DRM_ERROR("heap already initialized?");
return -EFAULT;
}
return init_heap(heap, initheap->start, initheap->size);
}
int i915_mem_destroy_heap(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_mem_destroy_heap_t *destroyheap = data;
struct mem_block **heap;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
heap = get_heap(dev_priv, destroyheap->region);
if (!heap) {
DRM_ERROR("get_heap failed");
return -EFAULT;
}
if (!*heap) {
DRM_ERROR("heap not initialized?");
return -EFAULT;
}
i915_mem_takedown(heap);
return 0;
}
......@@ -208,7 +208,7 @@ static bool intel_dsm_pci_probe(struct pci_dev *pdev)
ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0);
if (ret < 0) {
DRM_ERROR("failed to get supported _DSM functions\n");
DRM_DEBUG_KMS("failed to get supported _DSM functions\n");
return false;
}
......
......@@ -572,7 +572,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
return;
}
dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
if (!dev_priv->child_dev) {
DRM_DEBUG_KMS("No memory space for child device\n");
return;
......
This diff is collapsed.
......@@ -362,7 +362,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
int recv_bytes;
uint32_t status;
uint32_t aux_clock_divider;
int try, precharge;
int try, precharge = 5;
intel_dp_check_edp(intel_dp);
/* The clock divider is based off the hrawclk,
......@@ -378,15 +378,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
else
aux_clock_divider = 225; /* eDP input clock at 450Mhz */
} else if (HAS_PCH_SPLIT(dev))
aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
aux_clock_divider = 63; /* IRL input clock fixed at 125Mhz */
else
aux_clock_divider = intel_hrawclk(dev) / 2;
if (IS_GEN6(dev))
precharge = 3;
else
precharge = 5;
/* Try to wait for any previous AUX channel activity */
for (try = 0; try < 3; try++) {
status = I915_READ(ch_ctl);
......@@ -431,6 +426,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR);
if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR))
continue;
if (status & DP_AUX_CH_CTL_DONE)
break;
}
......
......@@ -141,8 +141,8 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
dev_priv->saveBLC_PWM_CTL2 = val;
} else if (val == 0) {
I915_WRITE(BLC_PWM_PCH_CTL2,
dev_priv->saveBLC_PWM_CTL);
val = dev_priv->saveBLC_PWM_CTL;
dev_priv->saveBLC_PWM_CTL2);
val = dev_priv->saveBLC_PWM_CTL2;
}
} else {
val = I915_READ(BLC_PWM_CTL);
......
......@@ -296,6 +296,7 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_EXEC_CONSTANTS 14
#define I915_PARAM_HAS_RELAXED_DELTA 15
#define I915_PARAM_HAS_GEN7_SOL_RESET 16
#define I915_PARAM_HAS_LLC 17
typedef struct drm_i915_getparam {
int param;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment