Merge remote branch 'anholt/drm-intel-next' into drm-next-stage
* anholt/drm-intel-next: (103 commits) drm/i915: Use a dmi quirk to skip a broken SDVO TV output. drm/i915: enable/disable LVDS port at DPMS time drm/i915: check for multiple write domains in pin_and_relocate drm/i915: clean-up i915_gem_flush_gpu_write_domain drm/i915: reuse i915_gpu_idle helper drm/i915: ensure lru ordering of fence_list drm/i915: extract fence stealing code drm/i915: fixup active list locking in object_unbind drm/i915: reuse i915_gem_object_put_fence_reg for fence stealing code drm/i915: Add dependency on the intel agp module drm/i915: More s/IS_IRONLAKE/HAS_PCH_SPLIT for Sandybridge. drm/i915: Correct the Sandybridge chipset info structs. drm/i915: Disable the hangcheck reset on Sandybridge until we add support. drm/i915: Add a new mobile Sandybridge PCI ID. agp/intel: Add a new Sandybridge HB/IG PCI ID combo. drm/i915, agp/intel: Fix stolen memory size on Sandybridge drm/i915: Correct locking in the modesetting failure path, fixing a BUG_ON. drm/i915: Disable the surface tile swizzling on Sandybridge. agp/intel: Use a non-reserved value for the cache field of the PTEs. drm/i915: Fix sandybridge status page setup. ...
This commit is contained in:
commit
cf7934a2a0
|
@ -10,6 +10,9 @@
|
|||
#include <linux/agp_backend.h>
|
||||
#include "agp.h"
|
||||
|
||||
int intel_agp_enabled;
|
||||
EXPORT_SYMBOL(intel_agp_enabled);
|
||||
|
||||
/*
|
||||
* If we have Intel graphics, we're not going to have anything other than
|
||||
* an Intel IOMMU. So make the correct use of the PCI DMA API contingent
|
||||
|
@ -64,6 +67,10 @@
|
|||
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
|
||||
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
|
||||
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
|
||||
|
||||
/* cover 915 and 945 variants */
|
||||
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
|
||||
|
@ -98,7 +105,9 @@
|
|||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB)
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
||||
|
||||
extern int agp_memory_reserved;
|
||||
|
||||
|
@ -147,6 +156,25 @@ extern int agp_memory_reserved;
|
|||
#define INTEL_I7505_AGPCTRL 0x70
|
||||
#define INTEL_I7505_MCHCFG 0x50
|
||||
|
||||
#define SNB_GMCH_CTRL 0x50
|
||||
#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
|
||||
#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
|
||||
|
||||
static const struct aper_size_info_fixed intel_i810_sizes[] =
|
||||
{
|
||||
{64, 16384, 4},
|
||||
|
@ -293,6 +321,13 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
|
|||
off_t pg_start, int mask_type)
|
||||
{
|
||||
int i, j;
|
||||
u32 cache_bits = 0;
|
||||
|
||||
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
||||
{
|
||||
cache_bits = I830_PTE_SYSTEM_CACHED;
|
||||
}
|
||||
|
||||
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
||||
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
||||
|
@ -613,7 +648,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
|
|||
static void intel_i830_init_gtt_entries(void)
|
||||
{
|
||||
u16 gmch_ctrl;
|
||||
int gtt_entries;
|
||||
int gtt_entries = 0;
|
||||
u8 rdct;
|
||||
int local = 0;
|
||||
static const int ddt[4] = { 0, 16, 32, 64 };
|
||||
|
@ -705,6 +740,63 @@ static void intel_i830_init_gtt_entries(void)
|
|||
gtt_entries = 0;
|
||||
break;
|
||||
}
|
||||
} else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
|
||||
/*
|
||||
* SandyBridge has new memory control reg at 0x50.w
|
||||
*/
|
||||
u16 snb_gmch_ctl;
|
||||
pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
|
||||
switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
|
||||
case SNB_GMCH_GMS_STOLEN_32M:
|
||||
gtt_entries = MB(32) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_64M:
|
||||
gtt_entries = MB(64) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_96M:
|
||||
gtt_entries = MB(96) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_128M:
|
||||
gtt_entries = MB(128) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_160M:
|
||||
gtt_entries = MB(160) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_192M:
|
||||
gtt_entries = MB(192) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_224M:
|
||||
gtt_entries = MB(224) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_256M:
|
||||
gtt_entries = MB(256) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_288M:
|
||||
gtt_entries = MB(288) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_320M:
|
||||
gtt_entries = MB(320) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_352M:
|
||||
gtt_entries = MB(352) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_384M:
|
||||
gtt_entries = MB(384) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_416M:
|
||||
gtt_entries = MB(416) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_448M:
|
||||
gtt_entries = MB(448) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_480M:
|
||||
gtt_entries = MB(480) - KB(size);
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_512M:
|
||||
gtt_entries = MB(512) - KB(size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
|
||||
case I855_GMCH_GMS_STOLEN_1M:
|
||||
|
@ -1364,6 +1456,8 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
|
|||
case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
|
||||
case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
|
||||
case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
|
||||
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
|
||||
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
|
||||
*gtt_offset = *gtt_size = MB(2);
|
||||
break;
|
||||
default:
|
||||
|
@ -2345,9 +2439,9 @@ static const struct intel_driver_description {
|
|||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview",
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview",
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
|
||||
"GM45", NULL, &intel_i965_driver },
|
||||
|
@ -2362,13 +2456,17 @@ static const struct intel_driver_description {
|
|||
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
|
||||
"G41", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
|
||||
"Ironlake/D", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
||||
"Ironlake/M", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
||||
"Ironlake/MA", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
||||
"Ironlake/MC2", NULL, &intel_i965_driver },
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
|
||||
"Sandybridge", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
|
||||
"Sandybridge", NULL, &intel_i965_driver },
|
||||
{ 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -2378,7 +2476,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|||
struct agp_bridge_data *bridge;
|
||||
u8 cap_ptr = 0;
|
||||
struct resource *r;
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
|
||||
|
||||
|
@ -2470,7 +2568,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
pci_set_drvdata(pdev, bridge);
|
||||
return agp_add_bridge(bridge);
|
||||
err = agp_add_bridge(bridge);
|
||||
if (!err)
|
||||
intel_agp_enabled = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit agp_intel_remove(struct pci_dev *pdev)
|
||||
|
@ -2575,6 +2676,8 @@ static struct pci_device_id agp_intel_pci_table[] = {
|
|||
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
|
||||
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
ccflags-y := -Iinclude/drm
|
||||
|
||||
drm-y := drm_auth.o drm_bufs.o drm_cache.o \
|
||||
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
|
||||
drm_context.o drm_dma.o drm_drawable.o \
|
||||
drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
|
||||
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
|
||||
|
|
184
drivers/gpu/drm/drm_buffer.c
Normal file
184
drivers/gpu/drm/drm_buffer.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 Pauli Nieminen.
|
||||
* 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
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Multipart buffer for coping data which is larger than the page size.
|
||||
*
|
||||
* Authors:
|
||||
* Pauli Nieminen <suokkos-at-gmail-dot-com>
|
||||
*/
|
||||
|
||||
#include "drm_buffer.h"
|
||||
|
||||
/**
|
||||
* Allocate the drm buffer object.
|
||||
*
|
||||
* buf: Pointer to a pointer where the object is stored.
|
||||
* size: The number of bytes to allocate.
|
||||
*/
|
||||
int drm_buffer_alloc(struct drm_buffer **buf, int size)
|
||||
{
|
||||
int nr_pages = size / PAGE_SIZE + 1;
|
||||
int idx;
|
||||
|
||||
/* Allocating pointer table to end of structure makes drm_buffer
|
||||
* variable sized */
|
||||
*buf = kzalloc(sizeof(struct drm_buffer) + nr_pages*sizeof(char *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (*buf == NULL) {
|
||||
DRM_ERROR("Failed to allocate drm buffer object to hold"
|
||||
" %d bytes in %d pages.\n",
|
||||
size, nr_pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
(*buf)->size = size;
|
||||
|
||||
for (idx = 0; idx < nr_pages; ++idx) {
|
||||
|
||||
(*buf)->data[idx] =
|
||||
kmalloc(min(PAGE_SIZE, size - idx * PAGE_SIZE),
|
||||
GFP_KERNEL);
|
||||
|
||||
|
||||
if ((*buf)->data[idx] == NULL) {
|
||||
DRM_ERROR("Failed to allocate %dth page for drm"
|
||||
" buffer with %d bytes and %d pages.\n",
|
||||
idx + 1, size, nr_pages);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
|
||||
/* Only last element can be null pointer so check for it first. */
|
||||
if ((*buf)->data[idx])
|
||||
kfree((*buf)->data[idx]);
|
||||
|
||||
for (--idx; idx >= 0; --idx)
|
||||
kfree((*buf)->data[idx]);
|
||||
|
||||
kfree(*buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buffer_alloc);
|
||||
|
||||
/**
|
||||
* Copy the user data to the begin of the buffer and reset the processing
|
||||
* iterator.
|
||||
*
|
||||
* user_data: A pointer the data that is copied to the buffer.
|
||||
* size: The Number of bytes to copy.
|
||||
*/
|
||||
extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
|
||||
void __user *user_data, int size)
|
||||
{
|
||||
int nr_pages = size / PAGE_SIZE + 1;
|
||||
int idx;
|
||||
|
||||
if (size > buf->size) {
|
||||
DRM_ERROR("Requesting to copy %d bytes to a drm buffer with"
|
||||
" %d bytes space\n",
|
||||
size, buf->size);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < nr_pages; ++idx) {
|
||||
|
||||
if (DRM_COPY_FROM_USER(buf->data[idx],
|
||||
user_data + idx * PAGE_SIZE,
|
||||
min(PAGE_SIZE, size - idx * PAGE_SIZE))) {
|
||||
DRM_ERROR("Failed to copy user data (%p) to drm buffer"
|
||||
" (%p) %dth page.\n",
|
||||
user_data, buf, idx);
|
||||
return -EFAULT;
|
||||
|
||||
}
|
||||
}
|
||||
buf->iterator = 0;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buffer_copy_from_user);
|
||||
|
||||
/**
|
||||
* Free the drm buffer object
|
||||
*/
|
||||
void drm_buffer_free(struct drm_buffer *buf)
|
||||
{
|
||||
|
||||
if (buf != NULL) {
|
||||
|
||||
int nr_pages = buf->size / PAGE_SIZE + 1;
|
||||
int idx;
|
||||
for (idx = 0; idx < nr_pages; ++idx)
|
||||
kfree(buf->data[idx]);
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buffer_free);
|
||||
|
||||
/**
|
||||
* Read an object from buffer that may be split to multiple parts. If object
|
||||
* is not split function just returns the pointer to object in buffer. But in
|
||||
* case of split object data is copied to given stack object that is suplied
|
||||
* by caller.
|
||||
*
|
||||
* The processing location of the buffer is also advanced to the next byte
|
||||
* after the object.
|
||||
*
|
||||
* objsize: The size of the objet in bytes.
|
||||
* stack_obj: A pointer to a memory location where object can be copied.
|
||||
*/
|
||||
void *drm_buffer_read_object(struct drm_buffer *buf,
|
||||
int objsize, void *stack_obj)
|
||||
{
|
||||
int idx = drm_buffer_index(buf);
|
||||
int page = drm_buffer_page(buf);
|
||||
void *obj = 0;
|
||||
|
||||
if (idx + objsize <= PAGE_SIZE) {
|
||||
obj = &buf->data[page][idx];
|
||||
} else {
|
||||
/* The object is split which forces copy to temporary object.*/
|
||||
int beginsz = PAGE_SIZE - idx;
|
||||
memcpy(stack_obj, &buf->data[page][idx], beginsz);
|
||||
|
||||
memcpy(stack_obj + beginsz, &buf->data[page + 1][0],
|
||||
objsize - beginsz);
|
||||
|
||||
obj = stack_obj;
|
||||
}
|
||||
|
||||
drm_buffer_advance(buf, objsize);
|
||||
return obj;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buffer_read_object);
|
|
@ -60,8 +60,7 @@
|
|||
#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
|
||||
/* use +hsync +vsync for detailed mode */
|
||||
#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
|
||||
/* define the number of Extension EDID block */
|
||||
#define MAX_EDID_EXT_NUM 4
|
||||
|
||||
|
||||
#define LEVEL_DMT 0
|
||||
#define LEVEL_GTF 1
|
||||
|
@ -114,14 +113,14 @@ static const u8 edid_header[] = {
|
|||
};
|
||||
|
||||
/**
|
||||
* edid_is_valid - sanity check EDID data
|
||||
* drm_edid_is_valid - sanity check EDID data
|
||||
* @edid: EDID data
|
||||
*
|
||||
* Sanity check the EDID block by looking at the header, the version number
|
||||
* and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's
|
||||
* valid.
|
||||
*/
|
||||
static bool edid_is_valid(struct edid *edid)
|
||||
bool drm_edid_is_valid(struct edid *edid)
|
||||
{
|
||||
int i, score = 0;
|
||||
u8 csum = 0;
|
||||
|
@ -163,6 +162,7 @@ bad:
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_edid_is_valid);
|
||||
|
||||
/**
|
||||
* edid_vendor - match a string against EDID's obfuscated vendor field
|
||||
|
@ -1112,8 +1112,8 @@ static int add_detailed_info_eedid(struct drm_connector *connector,
|
|||
}
|
||||
|
||||
/* Chose real EDID extension number */
|
||||
edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
|
||||
MAX_EDID_EXT_NUM : edid->extensions;
|
||||
edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
|
||||
DRM_MAX_EDID_EXT_NUM : edid->extensions;
|
||||
|
||||
/* Find CEA extension */
|
||||
for (i = 0; i < edid_ext_num; i++) {
|
||||
|
@ -1195,7 +1195,7 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
|
|||
for (i = 0; i < 4; i++) {
|
||||
if (drm_do_probe_ddc_edid(adapter, buf, len))
|
||||
return -1;
|
||||
if (edid_is_valid((struct edid *)buf))
|
||||
if (drm_edid_is_valid((struct edid *)buf))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1220,7 +1220,7 @@ struct edid *drm_get_edid(struct drm_connector *connector,
|
|||
int ret;
|
||||
struct edid *edid;
|
||||
|
||||
edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
|
||||
edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
|
||||
GFP_KERNEL);
|
||||
if (edid == NULL) {
|
||||
dev_warn(&connector->dev->pdev->dev,
|
||||
|
@ -1238,14 +1238,14 @@ struct edid *drm_get_edid(struct drm_connector *connector,
|
|||
if (edid->extensions != 0) {
|
||||
int edid_ext_num = edid->extensions;
|
||||
|
||||
if (edid_ext_num > MAX_EDID_EXT_NUM) {
|
||||
if (edid_ext_num > DRM_MAX_EDID_EXT_NUM) {
|
||||
dev_warn(&connector->dev->pdev->dev,
|
||||
"The number of extension(%d) is "
|
||||
"over max (%d), actually read number (%d)\n",
|
||||
edid_ext_num, MAX_EDID_EXT_NUM,
|
||||
MAX_EDID_EXT_NUM);
|
||||
edid_ext_num, DRM_MAX_EDID_EXT_NUM,
|
||||
DRM_MAX_EDID_EXT_NUM);
|
||||
/* Reset EDID extension number to be read */
|
||||
edid_ext_num = MAX_EDID_EXT_NUM;
|
||||
edid_ext_num = DRM_MAX_EDID_EXT_NUM;
|
||||
}
|
||||
/* Read EDID including extensions too */
|
||||
ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
|
||||
|
@ -1288,8 +1288,8 @@ bool drm_detect_hdmi_monitor(struct edid *edid)
|
|||
goto end;
|
||||
|
||||
/* Chose real EDID extension number */
|
||||
edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
|
||||
MAX_EDID_EXT_NUM : edid->extensions;
|
||||
edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
|
||||
DRM_MAX_EDID_EXT_NUM : edid->extensions;
|
||||
|
||||
/* Find CEA extension */
|
||||
for (i = 0; i < edid_ext_num; i++) {
|
||||
|
@ -1346,7 +1346,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
|||
if (edid == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (!edid_is_valid(edid)) {
|
||||
if (!drm_edid_is_valid(edid)) {
|
||||
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
|
||||
drm_get_connector_name(connector));
|
||||
return 0;
|
||||
|
|
|
@ -162,7 +162,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (!IS_IRONLAKE(dev)) {
|
||||
if (!HAS_PCH_SPLIT(dev)) {
|
||||
seq_printf(m, "Interrupt enable: %08x\n",
|
||||
I915_READ(IER));
|
||||
seq_printf(m, "Interrupt identity: %08x\n",
|
||||
|
@ -350,6 +350,36 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *pin_flag(int pinned)
|
||||
{
|
||||
if (pinned > 0)
|
||||
return " P";
|
||||
else if (pinned < 0)
|
||||
return " p";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char *tiling_flag(int tiling)
|
||||
{
|
||||
switch (tiling) {
|
||||
default:
|
||||
case I915_TILING_NONE: return "";
|
||||
case I915_TILING_X: return " X";
|
||||
case I915_TILING_Y: return " Y";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *dirty_flag(int dirty)
|
||||
{
|
||||
return dirty ? " dirty" : "";
|
||||
}
|
||||
|
||||
static const char *purgeable_flag(int purgeable)
|
||||
{
|
||||
return purgeable ? " purgeable" : "";
|
||||
}
|
||||
|
||||
static int i915_error_state(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
|
@ -357,6 +387,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_error_state *error;
|
||||
unsigned long flags;
|
||||
int i, page, offset, elt;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->error_lock, flags);
|
||||
if (!dev_priv->first_error) {
|
||||
|
@ -368,6 +399,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|||
|
||||
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
||||
error->time.tv_usec);
|
||||
seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
||||
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
seq_printf(m, " PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
||||
seq_printf(m, " INSTPM: 0x%08x\n", error->instpm);
|
||||
|
@ -379,6 +411,59 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|||
seq_printf(m, " INSTPS: 0x%08x\n", error->instps);
|
||||
seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1);
|
||||
}
|
||||
seq_printf(m, "seqno: 0x%08x\n", error->seqno);
|
||||
|
||||
if (error->active_bo_count) {
|
||||
seq_printf(m, "Buffers [%d]:\n", error->active_bo_count);
|
||||
|
||||
for (i = 0; i < error->active_bo_count; i++) {
|
||||
seq_printf(m, " %08x %8zd %08x %08x %08x%s%s%s%s",
|
||||
error->active_bo[i].gtt_offset,
|
||||
error->active_bo[i].size,
|
||||
error->active_bo[i].read_domains,
|
||||
error->active_bo[i].write_domain,
|
||||
error->active_bo[i].seqno,
|
||||
pin_flag(error->active_bo[i].pinned),
|
||||
tiling_flag(error->active_bo[i].tiling),
|
||||
dirty_flag(error->active_bo[i].dirty),
|
||||
purgeable_flag(error->active_bo[i].purgeable));
|
||||
|
||||
if (error->active_bo[i].name)
|
||||
seq_printf(m, " (name: %d)", error->active_bo[i].name);
|
||||
if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE)
|
||||
seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg);
|
||||
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) {
|
||||
if (error->batchbuffer[i]) {
|
||||
struct drm_i915_error_object *obj = error->batchbuffer[i];
|
||||
|
||||
seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset);
|
||||
offset = 0;
|
||||
for (page = 0; page < obj->page_count; page++) {
|
||||
for (elt = 0; elt < PAGE_SIZE/4; elt++) {
|
||||
seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error->ringbuffer) {
|
||||
struct drm_i915_error_object *obj = error->ringbuffer;
|
||||
|
||||
seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset);
|
||||
offset = 0;
|
||||
for (page = 0; page < obj->page_count; page++) {
|
||||
for (elt = 0; elt < PAGE_SIZE/4; elt++) {
|
||||
seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
|
||||
|
@ -386,6 +471,165 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i915_rstdby_delays(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u16 crstanddelay = I915_READ16(CRSTANDVID);
|
||||
|
||||
seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u16 rgvswctl = I915_READ16(MEMSWCTL);
|
||||
|
||||
seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3);
|
||||
seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1);
|
||||
seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf,
|
||||
rgvswctl & 0x3f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_delayfreq_table(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 delayfreq;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
|
||||
seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int MAP_TO_MV(int map)
|
||||
{
|
||||
return 1250 - (map * 25);
|
||||
}
|
||||
|
||||
static int i915_inttoext_table(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 inttoext;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= 32; i++) {
|
||||
inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
|
||||
seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_drpc_info(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 rgvmodectl = I915_READ(MEMMODECTL);
|
||||
|
||||
seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
|
||||
"yes" : "no");
|
||||
seq_printf(m, "Boost freq: %d\n",
|
||||
(rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >>
|
||||
MEMMODE_BOOST_FREQ_SHIFT);
|
||||
seq_printf(m, "HW control enabled: %s\n",
|
||||
rgvmodectl & MEMMODE_HWIDLE_EN ? "yes" : "no");
|
||||
seq_printf(m, "SW control enabled: %s\n",
|
||||
rgvmodectl & MEMMODE_SWMODE_EN ? "yes" : "no");
|
||||
seq_printf(m, "Gated voltage change: %s\n",
|
||||
rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
|
||||
seq_printf(m, "Starting frequency: P%d\n",
|
||||
(rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
|
||||
seq_printf(m, "Max frequency: P%d\n",
|
||||
(rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
|
||||
seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_fbc_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_crtc *crtc;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
bool fbc_enabled = false;
|
||||
|
||||
if (!dev_priv->display.fbc_enabled) {
|
||||
seq_printf(m, "FBC unsupported on this chipset\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (!crtc->enabled)
|
||||
continue;
|
||||
if (dev_priv->display.fbc_enabled(crtc))
|
||||
fbc_enabled = true;
|
||||
}
|
||||
|
||||
if (fbc_enabled) {
|
||||
seq_printf(m, "FBC enabled\n");
|
||||
} else {
|
||||
seq_printf(m, "FBC disabled: ");
|
||||
switch (dev_priv->no_fbc_reason) {
|
||||
case FBC_STOLEN_TOO_SMALL:
|
||||
seq_printf(m, "not enough stolen memory");
|
||||
break;
|
||||
case FBC_UNSUPPORTED_MODE:
|
||||
seq_printf(m, "mode not supported");
|
||||
break;
|
||||
case FBC_MODE_TOO_LARGE:
|
||||
seq_printf(m, "mode too large");
|
||||
break;
|
||||
case FBC_BAD_PLANE:
|
||||
seq_printf(m, "FBC unsupported on plane");
|
||||
break;
|
||||
case FBC_NOT_TILED:
|
||||
seq_printf(m, "scanout buffer not tiled");
|
||||
break;
|
||||
default:
|
||||
seq_printf(m, "unknown reason");
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_sr_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
bool sr_enabled = false;
|
||||
|
||||
if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev))
|
||||
sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
|
||||
else if (IS_I915GM(dev))
|
||||
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
|
||||
else if (IS_PINEVIEW(dev))
|
||||
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
|
||||
|
||||
seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" :
|
||||
"disabled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_wedged_open(struct inode *inode,
|
||||
struct file *filp)
|
||||
|
@ -503,6 +747,13 @@ static struct drm_info_list i915_debugfs_list[] = {
|
|||
{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
|
||||
{"i915_batchbuffers", i915_batchbuffer_info, 0},
|
||||
{"i915_error_state", i915_error_state, 0},
|
||||
{"i915_rstdby_delays", i915_rstdby_delays, 0},
|
||||
{"i915_cur_delayinfo", i915_cur_delayinfo, 0},
|
||||
{"i915_delayfreq_table", i915_delayfreq_table, 0},
|
||||
{"i915_inttoext_table", i915_inttoext_table, 0},
|
||||
{"i915_drpc_info", i915_drpc_info, 0},
|
||||
{"i915_fbc_status", i915_fbc_status, 0},
|
||||
{"i915_sr_status", i915_sr_status, 0},
|
||||
};
|
||||
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "i915_drv.h"
|
||||
#include "i915_trace.h"
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pnp.h>
|
||||
|
||||
/* Really want an OS-independent resettable timer. Would like to have
|
||||
* this loop run for (eg) 3 sec, but have the timer reset every time
|
||||
|
@ -933,6 +935,120 @@ static int i915_get_bridge_dev(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MCHBAR_I915 0x44
|
||||
#define MCHBAR_I965 0x48
|
||||
#define MCHBAR_SIZE (4*4096)
|
||||
|
||||
#define DEVEN_REG 0x54
|
||||
#define DEVEN_MCHBAR_EN (1 << 28)
|
||||
|
||||
/* Allocate space for the MCH regs if needed, return nonzero on error */
|
||||
static int
|
||||
intel_alloc_mchbar_resource(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp_lo, temp_hi = 0;
|
||||
u64 mchbar_addr;
|
||||
int ret = 0;
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
|
||||
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
||||
|
||||
/* If ACPI doesn't have it, assume we need to allocate it ourselves */
|
||||
#ifdef CONFIG_PNP
|
||||
if (mchbar_addr &&
|
||||
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get some space for it */
|
||||
ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
|
||||
MCHBAR_SIZE, MCHBAR_SIZE,
|
||||
PCIBIOS_MIN_MEM,
|
||||
0, pcibios_align_resource,
|
||||
dev_priv->bridge_dev);
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
|
||||
dev_priv->mch_res.start = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
|
||||
upper_32_bits(dev_priv->mch_res.start));
|
||||
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg,
|
||||
lower_32_bits(dev_priv->mch_res.start));
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup MCHBAR if possible, return true if we should disable it again */
|
||||
static void
|
||||
intel_setup_mchbar(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
dev_priv->mchbar_need_disable = false;
|
||||
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
enabled = !!(temp & DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
enabled = temp & 1;
|
||||
}
|
||||
|
||||
/* If it's already enabled, don't have to do anything */
|
||||
if (enabled)
|
||||
return;
|
||||
|
||||
if (intel_alloc_mchbar_resource(dev))
|
||||
return;
|
||||
|
||||
dev_priv->mchbar_need_disable = true;
|
||||
|
||||
/* Space is allocated or reserved, so enable it. */
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
|
||||
temp | DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
intel_teardown_mchbar(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
|
||||
if (dev_priv->mchbar_need_disable) {
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
temp &= ~DEVEN_MCHBAR_EN;
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
temp &= ~1;
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_priv->mch_res.start)
|
||||
release_resource(&dev_priv->mch_res);
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_probe_agp - get AGP bootup configuration
|
||||
* @pdev: PCI device
|
||||
|
@ -978,59 +1094,123 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
|
|||
* Some of the preallocated space is taken by the GTT
|
||||
* and popup. GTT is 1K per MB of aperture size, and popup is 4K.
|
||||
*/
|
||||
if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev))
|
||||
if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev))
|
||||
overhead = 4096;
|
||||
else
|
||||
overhead = (*aperture_size / 1024) + 4096;
|
||||
|
||||
switch (tmp & INTEL_GMCH_GMS_MASK) {
|
||||
case INTEL_855_GMCH_GMS_DISABLED:
|
||||
DRM_ERROR("video memory is disabled\n");
|
||||
return -1;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_1M:
|
||||
stolen = 1 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_4M:
|
||||
stolen = 4 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_8M:
|
||||
stolen = 8 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_16M:
|
||||
stolen = 16 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_32M:
|
||||
stolen = 32 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_48M:
|
||||
stolen = 48 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_64M:
|
||||
stolen = 64 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_128M:
|
||||
stolen = 128 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_256M:
|
||||
stolen = 256 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_96M:
|
||||
stolen = 96 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_160M:
|
||||
stolen = 160 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_224M:
|
||||
stolen = 224 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_352M:
|
||||
stolen = 352 * 1024 * 1024;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
||||
tmp & INTEL_GMCH_GMS_MASK);
|
||||
return -1;
|
||||
if (IS_GEN6(dev)) {
|
||||
/* SNB has memory control reg at 0x50.w */
|
||||
pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &tmp);
|
||||
|
||||
switch (tmp & SNB_GMCH_GMS_STOLEN_MASK) {
|
||||
case INTEL_855_GMCH_GMS_DISABLED:
|
||||
DRM_ERROR("video memory is disabled\n");
|
||||
return -1;
|
||||
case SNB_GMCH_GMS_STOLEN_32M:
|
||||
stolen = 32 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_64M:
|
||||
stolen = 64 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_96M:
|
||||
stolen = 96 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_128M:
|
||||
stolen = 128 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_160M:
|
||||
stolen = 160 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_192M:
|
||||
stolen = 192 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_224M:
|
||||
stolen = 224 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_256M:
|
||||
stolen = 256 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_288M:
|
||||
stolen = 288 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_320M:
|
||||
stolen = 320 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_352M:
|
||||
stolen = 352 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_384M:
|
||||
stolen = 384 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_416M:
|
||||
stolen = 416 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_448M:
|
||||
stolen = 448 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_480M:
|
||||
stolen = 480 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_512M:
|
||||
stolen = 512 * 1024 * 1024;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
||||
tmp & SNB_GMCH_GMS_STOLEN_MASK);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch (tmp & INTEL_GMCH_GMS_MASK) {
|
||||
case INTEL_855_GMCH_GMS_DISABLED:
|
||||
DRM_ERROR("video memory is disabled\n");
|
||||
return -1;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_1M:
|
||||
stolen = 1 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_4M:
|
||||
stolen = 4 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_8M:
|
||||
stolen = 8 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_16M:
|
||||
stolen = 16 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_32M:
|
||||
stolen = 32 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_48M:
|
||||
stolen = 48 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_64M:
|
||||
stolen = 64 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_128M:
|
||||
stolen = 128 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_256M:
|
||||
stolen = 256 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_96M:
|
||||
stolen = 96 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_160M:
|
||||
stolen = 160 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_224M:
|
||||
stolen = 224 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_352M:
|
||||
stolen = 352 * 1024 * 1024;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
||||
tmp & INTEL_GMCH_GMS_MASK);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*preallocated_size = stolen - overhead;
|
||||
*start = overhead;
|
||||
|
||||
|
@ -1064,7 +1244,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
|
|||
int gtt_offset, gtt_size;
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
|
||||
if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
||||
gtt_offset = 2*1024*1024;
|
||||
gtt_size = 2*1024*1024;
|
||||
} else {
|
||||
|
@ -1133,6 +1313,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
|||
/* Leave 1M for line length buffer & misc. */
|
||||
compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
|
||||
if (!compressed_fb) {
|
||||
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
||||
i915_warn_stolen(dev);
|
||||
return;
|
||||
}
|
||||
|
@ -1140,6 +1321,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
|||
compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
|
||||
if (!compressed_fb) {
|
||||
i915_warn_stolen(dev);
|
||||
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1281,7 +1463,9 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|||
return 0;
|
||||
|
||||
destroy_ringbuffer:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_cleanup_ringbuffer(dev);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1445,11 +1629,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
dev->driver->get_vblank_counter = i915_get_vblank_counter;
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
|
||||
if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
||||
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
|
||||
dev->driver->get_vblank_counter = gm45_get_vblank_counter;
|
||||
}
|
||||
|
||||
/* Try to make sure MCHBAR is enabled before poking at it */
|
||||
intel_setup_mchbar(dev);
|
||||
|
||||
i915_gem_load(dev);
|
||||
|
||||
/* Init HWS */
|
||||
|
@ -1523,6 +1710,8 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
i915_destroy_error_state(dev);
|
||||
|
||||
destroy_workqueue(dev_priv->wq);
|
||||
del_timer_sync(&dev_priv->hangcheck_timer);
|
||||
|
||||
|
@ -1569,6 +1758,8 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
intel_cleanup_overlay(dev);
|
||||
}
|
||||
|
||||
intel_teardown_mchbar(dev);
|
||||
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
kfree(dev->dev_private);
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ unsigned int i915_lvds_downclock = 0;
|
|||
module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
|
||||
|
||||
static struct drm_driver driver;
|
||||
extern int intel_agp_enabled;
|
||||
|
||||
#define INTEL_VGA_DEVICE(id, info) { \
|
||||
.class = PCI_CLASS_DISPLAY_VGA << 8, \
|
||||
|
@ -136,6 +137,16 @@ const static struct intel_device_info intel_ironlake_m_info = {
|
|||
.has_hotplug = 1,
|
||||
};
|
||||
|
||||
const static struct intel_device_info intel_sandybridge_d_info = {
|
||||
.is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
|
||||
.has_hotplug = 1,
|
||||
};
|
||||
|
||||
const static struct intel_device_info intel_sandybridge_m_info = {
|
||||
.is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
|
||||
.has_hotplug = 1,
|
||||
};
|
||||
|
||||
const static struct pci_device_id pciidlist[] = {
|
||||
INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
|
||||
INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
|
||||
|
@ -167,6 +178,8 @@ const static struct pci_device_id pciidlist[] = {
|
|||
INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
|
||||
INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
|
||||
INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
|
||||
INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
|
||||
INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -546,6 +559,11 @@ static struct drm_driver driver = {
|
|||
|
||||
static int __init i915_init(void)
|
||||
{
|
||||
if (!intel_agp_enabled) {
|
||||
DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
driver.num_ioctls = i915_max_ioctl;
|
||||
|
||||
i915_gem_shrinker_init();
|
||||
|
@ -571,6 +589,11 @@ static int __init i915_init(void)
|
|||
driver.driver_features &= ~DRIVER_MODESET;
|
||||
#endif
|
||||
|
||||
if (!(driver.driver_features & DRIVER_MODESET)) {
|
||||
driver.suspend = i915_suspend;
|
||||
driver.resume = i915_resume;
|
||||
}
|
||||
|
||||
return drm_init(&driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,27 @@ struct drm_i915_error_state {
|
|||
u32 instps;
|
||||
u32 instdone1;
|
||||
u32 seqno;
|
||||
u64 bbaddr;
|
||||
struct timeval time;
|
||||
struct drm_i915_error_object {
|
||||
int page_count;
|
||||
u32 gtt_offset;
|
||||
u32 *pages[0];
|
||||
} *ringbuffer, *batchbuffer[2];
|
||||
struct drm_i915_error_buffer {
|
||||
size_t size;
|
||||
u32 name;
|
||||
u32 seqno;
|
||||
u32 gtt_offset;
|
||||
u32 read_domains;
|
||||
u32 write_domain;
|
||||
u32 fence_reg;
|
||||
s32 pinned:2;
|
||||
u32 tiling:2;
|
||||
u32 dirty:1;
|
||||
u32 purgeable:1;
|
||||
} *active_bo;
|
||||
u32 active_bo_count;
|
||||
};
|
||||
|
||||
struct drm_i915_display_funcs {
|
||||
|
@ -192,6 +212,14 @@ struct intel_device_info {
|
|||
u8 cursor_needs_physical : 1;
|
||||
};
|
||||
|
||||
enum no_fbc_reason {
|
||||
FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
|
||||
FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
|
||||
FBC_MODE_TOO_LARGE, /* mode too large for compression */
|
||||
FBC_BAD_PLANE, /* fbc not supported on plane */
|
||||
FBC_NOT_TILED, /* buffer not tiled */
|
||||
};
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
|
||||
|
@ -452,6 +480,7 @@ typedef struct drm_i915_private {
|
|||
u32 savePIPEB_DATA_N1;
|
||||
u32 savePIPEB_LINK_M1;
|
||||
u32 savePIPEB_LINK_N1;
|
||||
u32 saveMCHBAR_RENDER_STANDBY;
|
||||
|
||||
struct {
|
||||
struct drm_mm gtt_space;
|
||||
|
@ -590,6 +619,14 @@ typedef struct drm_i915_private {
|
|||
int child_dev_num;
|
||||
struct child_device_config *child_dev;
|
||||
struct drm_connector *int_lvds_connector;
|
||||
|
||||
bool mchbar_need_disable;
|
||||
|
||||
u8 cur_delay;
|
||||
u8 min_delay;
|
||||
u8 max_delay;
|
||||
|
||||
enum no_fbc_reason no_fbc_reason;
|
||||
} drm_i915_private_t;
|
||||
|
||||
/** driver private structure attached to each drm_gem_object */
|
||||
|
@ -761,6 +798,7 @@ extern int i965_reset(struct drm_device *dev, u8 flags);
|
|||
|
||||
/* i915_irq.c */
|
||||
void i915_hangcheck_elapsed(unsigned long data);
|
||||
void i915_destroy_error_state(struct drm_device *dev);
|
||||
extern int i915_irq_emit(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int i915_irq_wait(struct drm_device *dev, void *data,
|
||||
|
@ -897,7 +935,8 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
|
|||
void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
|
||||
bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
|
||||
int tiling_mode);
|
||||
bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj);
|
||||
bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
|
||||
int tiling_mode);
|
||||
|
||||
/* i915_gem_debug.c */
|
||||
void i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
||||
|
@ -1026,7 +1065,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define IS_845G(dev) ((dev)->pci_device == 0x2562)
|
||||
#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
|
||||
#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
|
||||
#define IS_I8XX(dev) (INTEL_INFO(dev)->is_i8xx)
|
||||
#define IS_GEN2(dev) (INTEL_INFO(dev)->is_i8xx)
|
||||
#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g)
|
||||
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
|
||||
#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
|
||||
|
@ -1045,8 +1084,29 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx)
|
||||
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
|
||||
|
||||
#define IS_GEN3(dev) (IS_I915G(dev) || \
|
||||
IS_I915GM(dev) || \
|
||||
IS_I945G(dev) || \
|
||||
IS_I945GM(dev) || \
|
||||
IS_G33(dev) || \
|
||||
IS_PINEVIEW(dev))
|
||||
#define IS_GEN4(dev) ((dev)->pci_device == 0x2972 || \
|
||||
(dev)->pci_device == 0x2982 || \
|
||||
(dev)->pci_device == 0x2992 || \
|
||||
(dev)->pci_device == 0x29A2 || \
|
||||
(dev)->pci_device == 0x2A02 || \
|
||||
(dev)->pci_device == 0x2A12 || \
|
||||
(dev)->pci_device == 0x2E02 || \
|
||||
(dev)->pci_device == 0x2E12 || \
|
||||
(dev)->pci_device == 0x2E22 || \
|
||||
(dev)->pci_device == 0x2E32 || \
|
||||
(dev)->pci_device == 0x2A42 || \
|
||||
(dev)->pci_device == 0x2E42)
|
||||
|
||||
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
|
||||
|
||||
#define IS_GEN6(dev) ((dev)->pci_device == 0x0102)
|
||||
|
||||
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
|
||||
* rows, which changed the alignment requirements and fence programming.
|
||||
*/
|
||||
|
@ -1067,6 +1127,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
|
||||
#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
|
||||
|
||||
#define HAS_PCH_SPLIT(dev) (IS_IRONLAKE(dev) || \
|
||||
IS_GEN6(dev))
|
||||
|
||||
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1558,6 +1558,38 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
|
|||
i915_verify_inactive(dev, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_gem_process_flushing_list(struct drm_device *dev,
|
||||
uint32_t flush_domains, uint32_t seqno)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv, *next;
|
||||
|
||||
list_for_each_entry_safe(obj_priv, next,
|
||||
&dev_priv->mm.gpu_write_list,
|
||||
gpu_write_list) {
|
||||
struct drm_gem_object *obj = obj_priv->obj;
|
||||
|
||||
if ((obj->write_domain & flush_domains) ==
|
||||
obj->write_domain) {
|
||||
uint32_t old_write_domain = obj->write_domain;
|
||||
|
||||
obj->write_domain = 0;
|
||||
list_del_init(&obj_priv->gpu_write_list);
|
||||
i915_gem_object_move_to_active(obj, seqno);
|
||||
|
||||
/* update the fence lru list */
|
||||
if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
|
||||
list_move_tail(&obj_priv->fence_list,
|
||||
&dev_priv->mm.fence_list);
|
||||
|
||||
trace_i915_gem_object_change_domain(obj,
|
||||
obj->read_domains,
|
||||
old_write_domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new sequence number, emitting a write of it to the status page
|
||||
* plus an interrupt, which will trigger i915_user_interrupt_handler.
|
||||
|
@ -1616,29 +1648,8 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
|
|||
/* Associate any objects on the flushing list matching the write
|
||||
* domain we're flushing with our flush.
|
||||
*/
|
||||
if (flush_domains != 0) {
|
||||
struct drm_i915_gem_object *obj_priv, *next;
|
||||
|
||||
list_for_each_entry_safe(obj_priv, next,
|
||||
&dev_priv->mm.gpu_write_list,
|
||||
gpu_write_list) {
|
||||
struct drm_gem_object *obj = obj_priv->obj;
|
||||
|
||||
if ((obj->write_domain & flush_domains) ==
|
||||
obj->write_domain) {
|
||||
uint32_t old_write_domain = obj->write_domain;
|
||||
|
||||
obj->write_domain = 0;
|
||||
list_del_init(&obj_priv->gpu_write_list);
|
||||
i915_gem_object_move_to_active(obj, seqno);
|
||||
|
||||
trace_i915_gem_object_change_domain(obj,
|
||||
obj->read_domains,
|
||||
old_write_domain);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (flush_domains != 0)
|
||||
i915_gem_process_flushing_list(dev, flush_domains, seqno);
|
||||
|
||||
if (!dev_priv->mm.suspended) {
|
||||
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
|
||||
|
@ -1818,7 +1829,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
|
|||
return -EIO;
|
||||
|
||||
if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ier = I915_READ(DEIER) | I915_READ(GTIER);
|
||||
else
|
||||
ier = I915_READ(IER);
|
||||
|
@ -1987,6 +1998,7 @@ int
|
|||
i915_gem_object_unbind(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -2042,8 +2054,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
|
|||
}
|
||||
|
||||
/* Remove ourselves from the LRU list if present. */
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
if (!list_empty(&obj_priv->list))
|
||||
list_del_init(&obj_priv->list);
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
|
||||
if (i915_gem_object_is_purgeable(obj_priv))
|
||||
i915_gem_object_truncate(obj);
|
||||
|
@ -2080,12 +2094,35 @@ i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
|
|||
return best ? best : first;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gpu_idle(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
bool lists_empty;
|
||||
uint32_t seqno;
|
||||
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
|
||||
list_empty(&dev_priv->mm.active_list);
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
|
||||
if (lists_empty)
|
||||
return 0;
|
||||
|
||||
/* Flush everything onto the inactive list. */
|
||||
i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
||||
seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
||||
if (seqno == 0)
|
||||
return -ENOMEM;
|
||||
|
||||
return i915_wait_request(dev, seqno);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gem_evict_everything(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
uint32_t seqno;
|
||||
bool lists_empty;
|
||||
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
|
@ -2098,12 +2135,7 @@ i915_gem_evict_everything(struct drm_device *dev)
|
|||
return -ENOSPC;
|
||||
|
||||
/* Flush everything (on to the inactive lists) and evict */
|
||||
i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
||||
seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
||||
if (seqno == 0)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = i915_wait_request(dev, seqno);
|
||||
ret = i915_gpu_idle(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -2261,6 +2293,28 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||
{
|
||||
struct drm_gem_object *obj = reg->obj;
|
||||
struct drm_device *dev = obj->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
int regnum = obj_priv->fence_reg;
|
||||
uint64_t val;
|
||||
|
||||
val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
|
||||
0xfffff000) << 32;
|
||||
val |= obj_priv->gtt_offset & 0xfffff000;
|
||||
val |= (uint64_t)((obj_priv->stride / 128) - 1) <<
|
||||
SANDYBRIDGE_FENCE_PITCH_SHIFT;
|
||||
|
||||
if (obj_priv->tiling_mode == I915_TILING_Y)
|
||||
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
|
||||
val |= I965_FENCE_REG_VALID;
|
||||
|
||||
I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val);
|
||||
}
|
||||
|
||||
static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||
{
|
||||
struct drm_gem_object *obj = reg->obj;
|
||||
|
@ -2357,6 +2411,58 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|||
I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
|
||||
}
|
||||
|
||||
static int i915_find_fence_reg(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_fence_reg *reg = NULL;
|
||||
struct drm_i915_gem_object *obj_priv = NULL;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_gem_object *obj = NULL;
|
||||
int i, avail, ret;
|
||||
|
||||
/* First try to find a free reg */
|
||||
avail = 0;
|
||||
for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
|
||||
reg = &dev_priv->fence_regs[i];
|
||||
if (!reg->obj)
|
||||
return i;
|
||||
|
||||
obj_priv = reg->obj->driver_private;
|
||||
if (!obj_priv->pin_count)
|
||||
avail++;
|
||||
}
|
||||
|
||||
if (avail == 0)
|
||||
return -ENOSPC;
|
||||
|
||||
/* None available, try to steal one or wait for a user to finish */
|
||||
i = I915_FENCE_REG_NONE;
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.fence_list,
|
||||
fence_list) {
|
||||
obj = obj_priv->obj;
|
||||
|
||||
if (obj_priv->pin_count)
|
||||
continue;
|
||||
|
||||
/* found one! */
|
||||
i = obj_priv->fence_reg;
|
||||
break;
|
||||
}
|
||||
|
||||
BUG_ON(i == I915_FENCE_REG_NONE);
|
||||
|
||||
/* We only have a reference on obj from the active list. put_fence_reg
|
||||
* might drop that one, causing a use-after-free in it. So hold a
|
||||
* private reference to obj like the other callers of put_fence_reg
|
||||
* (set_tiling ioctl) do. */
|
||||
drm_gem_object_reference(obj);
|
||||
ret = i915_gem_object_put_fence_reg(obj);
|
||||
drm_gem_object_unreference(obj);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_object_get_fence_reg - set up a fence reg for an object
|
||||
* @obj: object to map through a fence reg
|
||||
|
@ -2377,8 +2483,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
struct drm_i915_fence_reg *reg = NULL;
|
||||
struct drm_i915_gem_object *old_obj_priv = NULL;
|
||||
int i, ret, avail;
|
||||
int ret;
|
||||
|
||||
/* Just update our place in the LRU if our fence is getting used. */
|
||||
if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
|
||||
|
@ -2406,86 +2511,27 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
|
|||
break;
|
||||
}
|
||||
|
||||
/* First try to find a free reg */
|
||||
avail = 0;
|
||||
for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
|
||||
reg = &dev_priv->fence_regs[i];
|
||||
if (!reg->obj)
|
||||
break;
|
||||
ret = i915_find_fence_reg(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
old_obj_priv = reg->obj->driver_private;
|
||||
if (!old_obj_priv->pin_count)
|
||||
avail++;
|
||||
}
|
||||
|
||||
/* None available, try to steal one or wait for a user to finish */
|
||||
if (i == dev_priv->num_fence_regs) {
|
||||
struct drm_gem_object *old_obj = NULL;
|
||||
|
||||
if (avail == 0)
|
||||
return -ENOSPC;
|
||||
|
||||
list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
|
||||
fence_list) {
|
||||
old_obj = old_obj_priv->obj;
|
||||
|
||||
if (old_obj_priv->pin_count)
|
||||
continue;
|
||||
|
||||
/* Take a reference, as otherwise the wait_rendering
|
||||
* below may cause the object to get freed out from
|
||||
* under us.
|
||||
*/
|
||||
drm_gem_object_reference(old_obj);
|
||||
|
||||
/* i915 uses fences for GPU access to tiled buffers */
|
||||
if (IS_I965G(dev) || !old_obj_priv->active)
|
||||
break;
|
||||
|
||||
/* This brings the object to the head of the LRU if it
|
||||
* had been written to. The only way this should
|
||||
* result in us waiting longer than the expected
|
||||
* optimal amount of time is if there was a
|
||||
* fence-using buffer later that was read-only.
|
||||
*/
|
||||
i915_gem_object_flush_gpu_write_domain(old_obj);
|
||||
ret = i915_gem_object_wait_rendering(old_obj);
|
||||
if (ret != 0) {
|
||||
drm_gem_object_unreference(old_obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zap this virtual mapping so we can set up a fence again
|
||||
* for this object next time we need it.
|
||||
*/
|
||||
i915_gem_release_mmap(old_obj);
|
||||
|
||||
i = old_obj_priv->fence_reg;
|
||||
reg = &dev_priv->fence_regs[i];
|
||||
|
||||
old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
|
||||
list_del_init(&old_obj_priv->fence_list);
|
||||
|
||||
drm_gem_object_unreference(old_obj);
|
||||
}
|
||||
|
||||
obj_priv->fence_reg = i;
|
||||
obj_priv->fence_reg = ret;
|
||||
reg = &dev_priv->fence_regs[obj_priv->fence_reg];
|
||||
list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
|
||||
|
||||
reg->obj = obj;
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (IS_GEN6(dev))
|
||||
sandybridge_write_fence_reg(reg);
|
||||
else if (IS_I965G(dev))
|
||||
i965_write_fence_reg(reg);
|
||||
else if (IS_I9XX(dev))
|
||||
i915_write_fence_reg(reg);
|
||||
else
|
||||
i830_write_fence_reg(reg);
|
||||
|
||||
trace_i915_gem_object_get_fence(obj, i, obj_priv->tiling_mode);
|
||||
trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
|
||||
obj_priv->tiling_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2504,9 +2550,12 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (IS_GEN6(dev)) {
|
||||
I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 +
|
||||
(obj_priv->fence_reg * 8), 0);
|
||||
} else if (IS_I965G(dev)) {
|
||||
I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
|
||||
else {
|
||||
} else {
|
||||
uint32_t fence_reg;
|
||||
|
||||
if (obj_priv->fence_reg < 8)
|
||||
|
@ -2540,6 +2589,12 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
|
|||
if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
|
||||
return 0;
|
||||
|
||||
/* If we've changed tiling, GTT-mappings of the object
|
||||
* need to re-fault to ensure that the correct fence register
|
||||
* setup is in place.
|
||||
*/
|
||||
i915_gem_release_mmap(obj);
|
||||
|
||||
/* On the i915, GPU access to tiled buffers is via a fence,
|
||||
* therefore we must wait for any outstanding access to complete
|
||||
* before clearing the fence.
|
||||
|
@ -2548,12 +2603,12 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
|
|||
int ret;
|
||||
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
i915_gem_object_flush_gtt_write_domain(obj);
|
||||
ret = i915_gem_object_wait_rendering(obj);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
i915_gem_object_flush_gtt_write_domain(obj);
|
||||
i915_gem_clear_fence_reg (obj);
|
||||
|
||||
return 0;
|
||||
|
@ -2693,7 +2748,6 @@ static void
|
|||
i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
uint32_t seqno;
|
||||
uint32_t old_write_domain;
|
||||
|
||||
if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
|
||||
|
@ -2702,9 +2756,8 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
|||
/* Queue the GPU write cache flushing we need. */
|
||||
old_write_domain = obj->write_domain;
|
||||
i915_gem_flush(dev, 0, obj->write_domain);
|
||||
seqno = i915_add_request(dev, NULL, obj->write_domain);
|
||||
(void) i915_add_request(dev, NULL, obj->write_domain);
|
||||
BUG_ON(obj->write_domain);
|
||||
i915_gem_object_move_to_active(obj, seqno);
|
||||
|
||||
trace_i915_gem_object_change_domain(obj,
|
||||
obj->read_domains,
|
||||
|
@ -3243,7 +3296,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
|||
obj_priv->tiling_mode != I915_TILING_NONE;
|
||||
|
||||
/* Check fence reg constraints and rebind if necessary */
|
||||
if (need_fence && !i915_obj_fenceable(dev, obj))
|
||||
if (need_fence && !i915_gem_object_fence_offset_ok(obj,
|
||||
obj_priv->tiling_mode))
|
||||
i915_gem_object_unbind(obj);
|
||||
|
||||
/* Choose the GTT offset for our buffer and put it there. */
|
||||
|
@ -3313,6 +3367,16 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
|||
}
|
||||
|
||||
/* Validate that the target is in a valid r/w GPU domain */
|
||||
if (reloc->write_domain & (reloc->write_domain - 1)) {
|
||||
DRM_ERROR("reloc with multiple write domains: "
|
||||
"obj %p target %d offset %d "
|
||||
"read %08x write %08x",
|
||||
obj, reloc->target_handle,
|
||||
(int) reloc->offset,
|
||||
reloc->read_domains,
|
||||
reloc->write_domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
|
||||
reloc->read_domains & I915_GEM_DOMAIN_CPU) {
|
||||
DRM_ERROR("reloc with read/write CPU domains: "
|
||||
|
@ -4441,8 +4505,7 @@ int
|
|||
i915_gem_idle(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t seqno, cur_seqno, last_seqno;
|
||||
int stuck, ret;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
|
@ -4451,115 +4514,36 @@ i915_gem_idle(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Hack! Don't let anybody do execbuf while we don't control the chip.
|
||||
* We need to replace this with a semaphore, or something.
|
||||
*/
|
||||
dev_priv->mm.suspended = 1;
|
||||
del_timer(&dev_priv->hangcheck_timer);
|
||||
|
||||
/* Cancel the retire work handler, wait for it to finish if running
|
||||
*/
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
/* Flush the GPU along with all non-CPU write domains
|
||||
*/
|
||||
i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
||||
seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
||||
|
||||
if (seqno == 0) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_priv->mm.waiting_gem_seqno = seqno;
|
||||
last_seqno = 0;
|
||||
stuck = 0;
|
||||
for (;;) {
|
||||
cur_seqno = i915_get_gem_seqno(dev);
|
||||
if (i915_seqno_passed(cur_seqno, seqno))
|
||||
break;
|
||||
if (last_seqno == cur_seqno) {
|
||||
if (stuck++ > 100) {
|
||||
DRM_ERROR("hardware wedged\n");
|
||||
atomic_set(&dev_priv->mm.wedged, 1);
|
||||
DRM_WAKEUP(&dev_priv->irq_queue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
msleep(10);
|
||||
last_seqno = cur_seqno;
|
||||
}
|
||||
dev_priv->mm.waiting_gem_seqno = 0;
|
||||
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
if (!atomic_read(&dev_priv->mm.wedged)) {
|
||||
/* Active and flushing should now be empty as we've
|
||||
* waited for a sequence higher than any pending execbuffer
|
||||
*/
|
||||
WARN_ON(!list_empty(&dev_priv->mm.active_list));
|
||||
WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
|
||||
/* Request should now be empty as we've also waited
|
||||
* for the last request in the list
|
||||
*/
|
||||
WARN_ON(!list_empty(&dev_priv->mm.request_list));
|
||||
}
|
||||
|
||||
/* Empty the active and flushing lists to inactive. If there's
|
||||
* anything left at this point, it means that we're wedged and
|
||||
* nothing good's going to happen by leaving them there. So strip
|
||||
* the GPU domains and just stuff them onto inactive.
|
||||
*/
|
||||
while (!list_empty(&dev_priv->mm.active_list)) {
|
||||
struct drm_gem_object *obj;
|
||||
uint32_t old_write_domain;
|
||||
|
||||
obj = list_first_entry(&dev_priv->mm.active_list,
|
||||
struct drm_i915_gem_object,
|
||||
list)->obj;
|
||||
old_write_domain = obj->write_domain;
|
||||
obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||
i915_gem_object_move_to_inactive(obj);
|
||||
|
||||
trace_i915_gem_object_change_domain(obj,
|
||||
obj->read_domains,
|
||||
old_write_domain);
|
||||
}
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
|
||||
while (!list_empty(&dev_priv->mm.flushing_list)) {
|
||||
struct drm_gem_object *obj;
|
||||
uint32_t old_write_domain;
|
||||
|
||||
obj = list_first_entry(&dev_priv->mm.flushing_list,
|
||||
struct drm_i915_gem_object,
|
||||
list)->obj;
|
||||
old_write_domain = obj->write_domain;
|
||||
obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||
i915_gem_object_move_to_inactive(obj);
|
||||
|
||||
trace_i915_gem_object_change_domain(obj,
|
||||
obj->read_domains,
|
||||
old_write_domain);
|
||||
}
|
||||
|
||||
|
||||
/* Move all inactive buffers out of the GTT. */
|
||||
ret = i915_gem_evict_from_inactive_list(dev);
|
||||
WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
|
||||
ret = i915_gpu_idle(dev);
|
||||
if (ret) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Under UMS, be paranoid and evict. */
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = i915_gem_evict_from_inactive_list(dev);
|
||||
if (ret) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hack! Don't let anybody do execbuf while we don't control the chip.
|
||||
* We need to replace this with a semaphore, or something.
|
||||
* And not confound mm.suspended!
|
||||
*/
|
||||
dev_priv->mm.suspended = 1;
|
||||
del_timer(&dev_priv->hangcheck_timer);
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
i915_gem_cleanup_ringbuffer(dev);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
/* Cancel the retire work handler, which should be idle now. */
|
||||
cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4603,8 +4587,13 @@ i915_gem_init_hws(struct drm_device *dev)
|
|||
}
|
||||
dev_priv->hws_obj = obj;
|
||||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
||||
I915_READ(HWS_PGA); /* posting read */
|
||||
if (IS_GEN6(dev)) {
|
||||
I915_WRITE(HWS_PGA_GEN6, dev_priv->status_gfx_addr);
|
||||
I915_READ(HWS_PGA_GEN6); /* posting read */
|
||||
} else {
|
||||
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
||||
I915_READ(HWS_PGA); /* posting read */
|
||||
}
|
||||
DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
|
||||
|
||||
return 0;
|
||||
|
@ -4846,7 +4835,8 @@ i915_gem_load(struct drm_device *dev)
|
|||
spin_unlock(&shrink_list_lock);
|
||||
|
||||
/* Old X drivers will take 0-2 for front, back, depth buffers */
|
||||
dev_priv->fence_reg_start = 3;
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
dev_priv->fence_reg_start = 3;
|
||||
|
||||
if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
dev_priv->num_fence_regs = 16;
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pnp.h>
|
||||
#include "linux/string.h"
|
||||
#include "linux/bitops.h"
|
||||
#include "drmP.h"
|
||||
|
@ -83,120 +81,6 @@
|
|||
* to match what the GPU expects.
|
||||
*/
|
||||
|
||||
#define MCHBAR_I915 0x44
|
||||
#define MCHBAR_I965 0x48
|
||||
#define MCHBAR_SIZE (4*4096)
|
||||
|
||||
#define DEVEN_REG 0x54
|
||||
#define DEVEN_MCHBAR_EN (1 << 28)
|
||||
|
||||
/* Allocate space for the MCH regs if needed, return nonzero on error */
|
||||
static int
|
||||
intel_alloc_mchbar_resource(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp_lo, temp_hi = 0;
|
||||
u64 mchbar_addr;
|
||||
int ret = 0;
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
|
||||
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
||||
|
||||
/* If ACPI doesn't have it, assume we need to allocate it ourselves */
|
||||
#ifdef CONFIG_PNP
|
||||
if (mchbar_addr &&
|
||||
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get some space for it */
|
||||
ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
|
||||
MCHBAR_SIZE, MCHBAR_SIZE,
|
||||
PCIBIOS_MIN_MEM,
|
||||
0, pcibios_align_resource,
|
||||
dev_priv->bridge_dev);
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
|
||||
dev_priv->mch_res.start = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
|
||||
upper_32_bits(dev_priv->mch_res.start));
|
||||
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg,
|
||||
lower_32_bits(dev_priv->mch_res.start));
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup MCHBAR if possible, return true if we should disable it again */
|
||||
static bool
|
||||
intel_setup_mchbar(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
bool need_disable = false, enabled;
|
||||
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
enabled = !!(temp & DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
enabled = temp & 1;
|
||||
}
|
||||
|
||||
/* If it's already enabled, don't have to do anything */
|
||||
if (enabled)
|
||||
goto out;
|
||||
|
||||
if (intel_alloc_mchbar_resource(dev))
|
||||
goto out;
|
||||
|
||||
need_disable = true;
|
||||
|
||||
/* Space is allocated or reserved, so enable it. */
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
|
||||
temp | DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
|
||||
}
|
||||
out:
|
||||
return need_disable;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_teardown_mchbar(struct drm_device *dev, bool disable)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
|
||||
if (disable) {
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
temp &= ~DEVEN_MCHBAR_EN;
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
temp &= ~1;
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_priv->mch_res.start)
|
||||
release_resource(&dev_priv->mch_res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects bit 6 swizzling of address lookup between IGD access and CPU
|
||||
* access through main memory.
|
||||
|
@ -207,9 +91,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
bool need_disable;
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
||||
/* On Ironlake whatever DRAM config, GPU always do
|
||||
* same swizzling setup.
|
||||
*/
|
||||
|
@ -224,9 +107,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
} else if (IS_MOBILE(dev)) {
|
||||
uint32_t dcc;
|
||||
|
||||
/* Try to make sure MCHBAR is enabled before poking at it */
|
||||
need_disable = intel_setup_mchbar(dev);
|
||||
|
||||
/* On mobile 9xx chipsets, channel interleave by the CPU is
|
||||
* determined by DCC. For single-channel, neither the CPU
|
||||
* nor the GPU do swizzling. For dual channel interleaved,
|
||||
|
@ -266,8 +146,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
}
|
||||
|
||||
intel_teardown_mchbar(dev, need_disable);
|
||||
} else {
|
||||
/* The 965, G33, and newer, have a very flexible memory
|
||||
* configuration. It will enable dual-channel mode
|
||||
|
@ -302,39 +180,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether an object is currently fenceable. If not, it may need
|
||||
* to be unbound and have its pitch adjusted.
|
||||
*/
|
||||
bool
|
||||
i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
/* The 965 can have fences at any page boundary. */
|
||||
if (obj->size & 4095)
|
||||
return false;
|
||||
return true;
|
||||
} else if (IS_I9XX(dev)) {
|
||||
if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
|
||||
return false;
|
||||
} else {
|
||||
if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Power of two sized... */
|
||||
if (obj->size & (obj->size - 1))
|
||||
return false;
|
||||
|
||||
/* Objects must be size aligned as well */
|
||||
if (obj_priv->gtt_offset & (obj->size - 1))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check pitch constriants for all chips & tiling formats */
|
||||
bool
|
||||
i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
||||
|
@ -391,7 +236,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
@ -491,12 +336,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* If we've changed tiling, GTT-mappings of the object
|
||||
* need to re-fault to ensure that the correct fence register
|
||||
* setup is in place.
|
||||
*/
|
||||
i915_gem_release_mmap(obj);
|
||||
|
||||
obj_priv->tiling_mode = args->tiling_mode;
|
||||
obj_priv->stride = args->stride;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ void intel_enable_asle (struct drm_device *dev)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ironlake_enable_display_irq(dev_priv, DE_GSE);
|
||||
else
|
||||
i915_enable_pipestat(dev_priv, 1,
|
||||
|
@ -269,6 +269,57 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|||
drm_sysfs_hotplug_event(dev);
|
||||
}
|
||||
|
||||
static void i915_handle_rps_change(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 busy_up, busy_down, max_avg, min_avg;
|
||||
u16 rgvswctl;
|
||||
u8 new_delay = dev_priv->cur_delay;
|
||||
|
||||
I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG);
|
||||
busy_up = I915_READ(RCPREVBSYTUPAVG);
|
||||
busy_down = I915_READ(RCPREVBSYTDNAVG);
|
||||
max_avg = I915_READ(RCBMAXAVG);
|
||||
min_avg = I915_READ(RCBMINAVG);
|
||||
|
||||
/* Handle RCS change request from hw */
|
||||
if (busy_up > max_avg) {
|
||||
if (dev_priv->cur_delay != dev_priv->max_delay)
|
||||
new_delay = dev_priv->cur_delay - 1;
|
||||
if (new_delay < dev_priv->max_delay)
|
||||
new_delay = dev_priv->max_delay;
|
||||
} else if (busy_down < min_avg) {
|
||||
if (dev_priv->cur_delay != dev_priv->min_delay)
|
||||
new_delay = dev_priv->cur_delay + 1;
|
||||
if (new_delay > dev_priv->min_delay)
|
||||
new_delay = dev_priv->min_delay;
|
||||
}
|
||||
|
||||
DRM_DEBUG("rps change requested: %d -> %d\n",
|
||||
dev_priv->cur_delay, new_delay);
|
||||
|
||||
rgvswctl = I915_READ(MEMSWCTL);
|
||||
if (rgvswctl & MEMCTL_CMD_STS) {
|
||||
DRM_ERROR("gpu busy, RCS change rejected\n");
|
||||
return; /* still busy with another command */
|
||||
}
|
||||
|
||||
/* Program the new state */
|
||||
rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
|
||||
(new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
|
||||
I915_WRITE(MEMSWCTL, rgvswctl);
|
||||
POSTING_READ(MEMSWCTL);
|
||||
|
||||
rgvswctl |= MEMCTL_CMD_STS;
|
||||
I915_WRITE(MEMSWCTL, rgvswctl);
|
||||
|
||||
dev_priv->cur_delay = new_delay;
|
||||
|
||||
DRM_DEBUG("rps changed\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
@ -331,6 +382,11 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
|||
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
|
||||
}
|
||||
|
||||
if (de_iir & DE_PCU_EVENT) {
|
||||
I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS));
|
||||
i915_handle_rps_change(dev);
|
||||
}
|
||||
|
||||
/* should clear PCH hotplug event before clear CPU irq */
|
||||
I915_WRITE(SDEIIR, pch_iir);
|
||||
I915_WRITE(GTIIR, gt_iir);
|
||||
|
@ -376,6 +432,121 @@ static void i915_error_work_func(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
static struct drm_i915_error_object *
|
||||
i915_error_object_create(struct drm_device *dev,
|
||||
struct drm_gem_object *src)
|
||||
{
|
||||
struct drm_i915_error_object *dst;
|
||||
struct drm_i915_gem_object *src_priv;
|
||||
int page, page_count;
|
||||
|
||||
if (src == NULL)
|
||||
return NULL;
|
||||
|
||||
src_priv = src->driver_private;
|
||||
if (src_priv->pages == NULL)
|
||||
return NULL;
|
||||
|
||||
page_count = src->size / PAGE_SIZE;
|
||||
|
||||
dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
|
||||
if (dst == NULL)
|
||||
return NULL;
|
||||
|
||||
for (page = 0; page < page_count; page++) {
|
||||
void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
|
||||
if (d == NULL)
|
||||
goto unwind;
|
||||
s = kmap_atomic(src_priv->pages[page], KM_USER0);
|
||||
memcpy(d, s, PAGE_SIZE);
|
||||
kunmap_atomic(s, KM_USER0);
|
||||
dst->pages[page] = d;
|
||||
}
|
||||
dst->page_count = page_count;
|
||||
dst->gtt_offset = src_priv->gtt_offset;
|
||||
|
||||
return dst;
|
||||
|
||||
unwind:
|
||||
while (page--)
|
||||
kfree(dst->pages[page]);
|
||||
kfree(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
i915_error_object_free(struct drm_i915_error_object *obj)
|
||||
{
|
||||
int page;
|
||||
|
||||
if (obj == NULL)
|
||||
return;
|
||||
|
||||
for (page = 0; page < obj->page_count; page++)
|
||||
kfree(obj->pages[page]);
|
||||
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_error_state_free(struct drm_device *dev,
|
||||
struct drm_i915_error_state *error)
|
||||
{
|
||||
i915_error_object_free(error->batchbuffer[0]);
|
||||
i915_error_object_free(error->batchbuffer[1]);
|
||||
i915_error_object_free(error->ringbuffer);
|
||||
kfree(error->active_bo);
|
||||
kfree(error);
|
||||
}
|
||||
|
||||
static u32
|
||||
i915_get_bbaddr(struct drm_device *dev, u32 *ring)
|
||||
{
|
||||
u32 cmd;
|
||||
|
||||
if (IS_I830(dev) || IS_845G(dev))
|
||||
cmd = MI_BATCH_BUFFER;
|
||||
else if (IS_I965G(dev))
|
||||
cmd = (MI_BATCH_BUFFER_START | (2 << 6) |
|
||||
MI_BATCH_NON_SECURE_I965);
|
||||
else
|
||||
cmd = (MI_BATCH_BUFFER_START | (2 << 6));
|
||||
|
||||
return ring[0] == cmd ? ring[1] : 0;
|
||||
}
|
||||
|
||||
static u32
|
||||
i915_ringbuffer_last_batch(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 head, bbaddr;
|
||||
u32 *ring;
|
||||
|
||||
/* Locate the current position in the ringbuffer and walk back
|
||||
* to find the most recently dispatched batch buffer.
|
||||
*/
|
||||
bbaddr = 0;
|
||||
head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
|
||||
ring = (u32 *)(dev_priv->ring.virtual_start + head);
|
||||
|
||||
while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
|
||||
bbaddr = i915_get_bbaddr(dev, ring);
|
||||
if (bbaddr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bbaddr == 0) {
|
||||
ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size);
|
||||
while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
|
||||
bbaddr = i915_get_bbaddr(dev, ring);
|
||||
if (bbaddr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bbaddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_capture_error_state - capture an error record for later analysis
|
||||
* @dev: drm device
|
||||
|
@ -388,19 +559,26 @@ static void i915_error_work_func(struct work_struct *work)
|
|||
static void i915_capture_error_state(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
struct drm_i915_error_state *error;
|
||||
struct drm_gem_object *batchbuffer[2];
|
||||
unsigned long flags;
|
||||
u32 bbaddr;
|
||||
int count;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->error_lock, flags);
|
||||
if (dev_priv->first_error)
|
||||
goto out;
|
||||
error = dev_priv->first_error;
|
||||
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
|
||||
if (error)
|
||||
return;
|
||||
|
||||
error = kmalloc(sizeof(*error), GFP_ATOMIC);
|
||||
if (!error) {
|
||||
DRM_DEBUG_DRIVER("out ot memory, not capturing error state\n");
|
||||
goto out;
|
||||
DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
error->seqno = i915_get_gem_seqno(dev);
|
||||
error->eir = I915_READ(EIR);
|
||||
error->pgtbl_er = I915_READ(PGTBL_ER);
|
||||
error->pipeastat = I915_READ(PIPEASTAT);
|
||||
|
@ -411,6 +589,7 @@ static void i915_capture_error_state(struct drm_device *dev)
|
|||
error->ipehr = I915_READ(IPEHR);
|
||||
error->instdone = I915_READ(INSTDONE);
|
||||
error->acthd = I915_READ(ACTHD);
|
||||
error->bbaddr = 0;
|
||||
} else {
|
||||
error->ipeir = I915_READ(IPEIR_I965);
|
||||
error->ipehr = I915_READ(IPEHR_I965);
|
||||
|
@ -418,14 +597,101 @@ static void i915_capture_error_state(struct drm_device *dev)
|
|||
error->instps = I915_READ(INSTPS);
|
||||
error->instdone1 = I915_READ(INSTDONE1);
|
||||
error->acthd = I915_READ(ACTHD_I965);
|
||||
error->bbaddr = I915_READ64(BB_ADDR);
|
||||
}
|
||||
|
||||
bbaddr = i915_ringbuffer_last_batch(dev);
|
||||
|
||||
/* Grab the current batchbuffer, most likely to have crashed. */
|
||||
batchbuffer[0] = NULL;
|
||||
batchbuffer[1] = NULL;
|
||||
count = 0;
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
|
||||
struct drm_gem_object *obj = obj_priv->obj;
|
||||
|
||||
if (batchbuffer[0] == NULL &&
|
||||
bbaddr >= obj_priv->gtt_offset &&
|
||||
bbaddr < obj_priv->gtt_offset + obj->size)
|
||||
batchbuffer[0] = obj;
|
||||
|
||||
if (batchbuffer[1] == NULL &&
|
||||
error->acthd >= obj_priv->gtt_offset &&
|
||||
error->acthd < obj_priv->gtt_offset + obj->size &&
|
||||
batchbuffer[0] != obj)
|
||||
batchbuffer[1] = obj;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
/* We need to copy these to an anonymous buffer as the simplest
|
||||
* method to avoid being overwritten by userpace.
|
||||
*/
|
||||
error->batchbuffer[0] = i915_error_object_create(dev, batchbuffer[0]);
|
||||
error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
|
||||
|
||||
/* Record the ringbuffer */
|
||||
error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj);
|
||||
|
||||
/* Record buffers on the active list. */
|
||||
error->active_bo = NULL;
|
||||
error->active_bo_count = 0;
|
||||
|
||||
if (count)
|
||||
error->active_bo = kmalloc(sizeof(*error->active_bo)*count,
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (error->active_bo) {
|
||||
int i = 0;
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
|
||||
struct drm_gem_object *obj = obj_priv->obj;
|
||||
|
||||
error->active_bo[i].size = obj->size;
|
||||
error->active_bo[i].name = obj->name;
|
||||
error->active_bo[i].seqno = obj_priv->last_rendering_seqno;
|
||||
error->active_bo[i].gtt_offset = obj_priv->gtt_offset;
|
||||
error->active_bo[i].read_domains = obj->read_domains;
|
||||
error->active_bo[i].write_domain = obj->write_domain;
|
||||
error->active_bo[i].fence_reg = obj_priv->fence_reg;
|
||||
error->active_bo[i].pinned = 0;
|
||||
if (obj_priv->pin_count > 0)
|
||||
error->active_bo[i].pinned = 1;
|
||||
if (obj_priv->user_pin_count > 0)
|
||||
error->active_bo[i].pinned = -1;
|
||||
error->active_bo[i].tiling = obj_priv->tiling_mode;
|
||||
error->active_bo[i].dirty = obj_priv->dirty;
|
||||
error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED;
|
||||
|
||||
if (++i == count)
|
||||
break;
|
||||
}
|
||||
error->active_bo_count = i;
|
||||
}
|
||||
|
||||
do_gettimeofday(&error->time);
|
||||
|
||||
dev_priv->first_error = error;
|
||||
|
||||
out:
|
||||
spin_lock_irqsave(&dev_priv->error_lock, flags);
|
||||
if (dev_priv->first_error == NULL) {
|
||||
dev_priv->first_error = error;
|
||||
error = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
|
||||
|
||||
if (error)
|
||||
i915_error_state_free(dev, error);
|
||||
}
|
||||
|
||||
void i915_destroy_error_state(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_error_state *error;
|
||||
|
||||
spin_lock(&dev_priv->error_lock);
|
||||
error = dev_priv->first_error;
|
||||
dev_priv->first_error = NULL;
|
||||
spin_unlock(&dev_priv->error_lock);
|
||||
|
||||
if (error)
|
||||
i915_error_state_free(dev, error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -576,7 +842,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
atomic_inc(&dev_priv->irq_received);
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return ironlake_irq_handler(dev);
|
||||
|
||||
iir = I915_READ(IIR);
|
||||
|
@ -737,7 +1003,7 @@ void i915_user_irq_get(struct drm_device *dev)
|
|||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
|
||||
else
|
||||
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
|
||||
|
@ -753,7 +1019,7 @@ void i915_user_irq_put(struct drm_device *dev)
|
|||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
|
||||
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
|
||||
else
|
||||
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
|
||||
|
@ -861,7 +1127,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
|
|||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
|
||||
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
|
||||
else if (IS_I965G(dev))
|
||||
|
@ -883,7 +1149,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
|
|||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
|
||||
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
|
||||
else
|
||||
|
@ -897,7 +1163,7 @@ void i915_enable_interrupt (struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!IS_IRONLAKE(dev))
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
opregion_enable_asle(dev);
|
||||
dev_priv->irq_enabled = 1;
|
||||
}
|
||||
|
@ -973,7 +1239,11 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|||
struct drm_device *dev = (struct drm_device *)data;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t acthd;
|
||||
|
||||
|
||||
/* No reset support on this chip yet. */
|
||||
if (IS_GEN6(dev))
|
||||
return;
|
||||
|
||||
if (!IS_I965G(dev))
|
||||
acthd = I915_READ(ACTHD);
|
||||
else
|
||||
|
@ -1064,6 +1334,13 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
|
|||
I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
|
||||
(void) I915_READ(SDEIER);
|
||||
|
||||
if (IS_IRONLAKE_M(dev)) {
|
||||
/* Clear & enable PCU event interrupts */
|
||||
I915_WRITE(DEIIR, DE_PCU_EVENT);
|
||||
I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT);
|
||||
ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1076,7 +1353,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
|||
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
|
||||
INIT_WORK(&dev_priv->error_work, i915_error_work_func);
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
ironlake_irq_preinstall(dev);
|
||||
return;
|
||||
}
|
||||
|
@ -1108,7 +1385,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
|
|||
|
||||
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return ironlake_irq_postinstall(dev);
|
||||
|
||||
/* Unmask the interrupts that we always want on. */
|
||||
|
@ -1196,7 +1473,7 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
|
|||
|
||||
dev_priv->vblank_pipe = 0;
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
ironlake_irq_uninstall(dev);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,25 @@
|
|||
#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
|
||||
|
||||
#define SNB_GMCH_CTRL 0x50
|
||||
#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
|
||||
#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
|
||||
|
||||
/* PCI config space */
|
||||
|
||||
#define HPLLCC 0xc0 /* 855 only */
|
||||
|
@ -61,6 +80,7 @@
|
|||
#define GC_CLOCK_100_200 (1 << 0)
|
||||
#define GC_CLOCK_100_133 (2 << 0)
|
||||
#define GC_CLOCK_166_250 (3 << 0)
|
||||
#define GCFGC2 0xda
|
||||
#define GCFGC 0xf0 /* 915+ only */
|
||||
#define GC_LOW_FREQUENCY_ENABLE (1 << 7)
|
||||
#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
|
||||
|
@ -234,6 +254,9 @@
|
|||
#define I965_FENCE_REG_VALID (1<<0)
|
||||
#define I965_FENCE_MAX_PITCH_VAL 0x0400
|
||||
|
||||
#define FENCE_REG_SANDYBRIDGE_0 0x100000
|
||||
#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32
|
||||
|
||||
/*
|
||||
* Instruction and interrupt control regs
|
||||
*/
|
||||
|
@ -265,6 +288,7 @@
|
|||
#define INSTDONE1 0x0207c /* 965+ only */
|
||||
#define ACTHD_I965 0x02074
|
||||
#define HWS_PGA 0x02080
|
||||
#define HWS_PGA_GEN6 0x04080
|
||||
#define HWS_ADDRESS_MASK 0xfffff000
|
||||
#define HWS_START_ADDRESS_SHIFT 4
|
||||
#define PWRCTXA 0x2088 /* 965GM+ only */
|
||||
|
@ -282,7 +306,7 @@
|
|||
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
|
||||
#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
|
||||
#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
|
||||
#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14)
|
||||
#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) /* p-state */
|
||||
#define I915_HWB_OOM_INTERRUPT (1<<13)
|
||||
#define I915_SYNC_STATUS_INTERRUPT (1<<12)
|
||||
#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
|
||||
|
@ -306,11 +330,14 @@
|
|||
#define I915_ERROR_MEMORY_REFRESH (1<<1)
|
||||
#define I915_ERROR_INSTRUCTION (1<<0)
|
||||
#define INSTPM 0x020c0
|
||||
#define INSTPM_SELF_EN (1<<12) /* 915GM only */
|
||||
#define ACTHD 0x020c8
|
||||
#define FW_BLC 0x020d8
|
||||
#define FW_BLC2 0x020dc
|
||||
#define FW_BLC_SELF 0x020e0 /* 915+ only */
|
||||
#define FW_BLC_SELF_EN (1<<15)
|
||||
#define FW_BLC_SELF_EN_MASK (1<<31)
|
||||
#define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */
|
||||
#define FW_BLC_SELF_EN (1<<15) /* 945 only */
|
||||
#define MM_BURST_LENGTH 0x00700000
|
||||
#define MM_FIFO_WATERMARK 0x0001F000
|
||||
#define LM_BURST_LENGTH 0x00000700
|
||||
|
@ -324,6 +351,7 @@
|
|||
#define CM0_COLOR_EVICT_DISABLE (1<<3)
|
||||
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
|
||||
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
|
||||
#define BB_ADDR 0x02140 /* 8 bytes */
|
||||
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
|
||||
|
||||
|
||||
|
@ -784,10 +812,144 @@
|
|||
#define CLKCFG_MEM_800 (3 << 4)
|
||||
#define CLKCFG_MEM_MASK (7 << 4)
|
||||
|
||||
/** GM965 GM45 render standby register */
|
||||
#define MCHBAR_RENDER_STANDBY 0x111B8
|
||||
#define CRSTANDVID 0x11100
|
||||
#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
|
||||
#define PXVFREQ_PX_MASK 0x7f000000
|
||||
#define PXVFREQ_PX_SHIFT 24
|
||||
#define VIDFREQ_BASE 0x11110
|
||||
#define VIDFREQ1 0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */
|
||||
#define VIDFREQ2 0x11114
|
||||
#define VIDFREQ3 0x11118
|
||||
#define VIDFREQ4 0x1111c
|
||||
#define VIDFREQ_P0_MASK 0x1f000000
|
||||
#define VIDFREQ_P0_SHIFT 24
|
||||
#define VIDFREQ_P0_CSCLK_MASK 0x00f00000
|
||||
#define VIDFREQ_P0_CSCLK_SHIFT 20
|
||||
#define VIDFREQ_P0_CRCLK_MASK 0x000f0000
|
||||
#define VIDFREQ_P0_CRCLK_SHIFT 16
|
||||
#define VIDFREQ_P1_MASK 0x00001f00
|
||||
#define VIDFREQ_P1_SHIFT 8
|
||||
#define VIDFREQ_P1_CSCLK_MASK 0x000000f0
|
||||
#define VIDFREQ_P1_CSCLK_SHIFT 4
|
||||
#define VIDFREQ_P1_CRCLK_MASK 0x0000000f
|
||||
#define INTTOEXT_BASE_ILK 0x11300
|
||||
#define INTTOEXT_BASE 0x11120 /* INTTOEXT1-8 (0x1113c) */
|
||||
#define INTTOEXT_MAP3_SHIFT 24
|
||||
#define INTTOEXT_MAP3_MASK (0x1f << INTTOEXT_MAP3_SHIFT)
|
||||
#define INTTOEXT_MAP2_SHIFT 16
|
||||
#define INTTOEXT_MAP2_MASK (0x1f << INTTOEXT_MAP2_SHIFT)
|
||||
#define INTTOEXT_MAP1_SHIFT 8
|
||||
#define INTTOEXT_MAP1_MASK (0x1f << INTTOEXT_MAP1_SHIFT)
|
||||
#define INTTOEXT_MAP0_SHIFT 0
|
||||
#define INTTOEXT_MAP0_MASK (0x1f << INTTOEXT_MAP0_SHIFT)
|
||||
#define MEMSWCTL 0x11170 /* Ironlake only */
|
||||
#define MEMCTL_CMD_MASK 0xe000
|
||||
#define MEMCTL_CMD_SHIFT 13
|
||||
#define MEMCTL_CMD_RCLK_OFF 0
|
||||
#define MEMCTL_CMD_RCLK_ON 1
|
||||
#define MEMCTL_CMD_CHFREQ 2
|
||||
#define MEMCTL_CMD_CHVID 3
|
||||
#define MEMCTL_CMD_VMMOFF 4
|
||||
#define MEMCTL_CMD_VMMON 5
|
||||
#define MEMCTL_CMD_STS (1<<12) /* write 1 triggers command, clears
|
||||
when command complete */
|
||||
#define MEMCTL_FREQ_MASK 0x0f00 /* jitter, from 0-15 */
|
||||
#define MEMCTL_FREQ_SHIFT 8
|
||||
#define MEMCTL_SFCAVM (1<<7)
|
||||
#define MEMCTL_TGT_VID_MASK 0x007f
|
||||
#define MEMIHYST 0x1117c
|
||||
#define MEMINTREN 0x11180 /* 16 bits */
|
||||
#define MEMINT_RSEXIT_EN (1<<8)
|
||||
#define MEMINT_CX_SUPR_EN (1<<7)
|
||||
#define MEMINT_CONT_BUSY_EN (1<<6)
|
||||
#define MEMINT_AVG_BUSY_EN (1<<5)
|
||||
#define MEMINT_EVAL_CHG_EN (1<<4)
|
||||
#define MEMINT_MON_IDLE_EN (1<<3)
|
||||
#define MEMINT_UP_EVAL_EN (1<<2)
|
||||
#define MEMINT_DOWN_EVAL_EN (1<<1)
|
||||
#define MEMINT_SW_CMD_EN (1<<0)
|
||||
#define MEMINTRSTR 0x11182 /* 16 bits */
|
||||
#define MEM_RSEXIT_MASK 0xc000
|
||||
#define MEM_RSEXIT_SHIFT 14
|
||||
#define MEM_CONT_BUSY_MASK 0x3000
|
||||
#define MEM_CONT_BUSY_SHIFT 12
|
||||
#define MEM_AVG_BUSY_MASK 0x0c00
|
||||
#define MEM_AVG_BUSY_SHIFT 10
|
||||
#define MEM_EVAL_CHG_MASK 0x0300
|
||||
#define MEM_EVAL_BUSY_SHIFT 8
|
||||
#define MEM_MON_IDLE_MASK 0x00c0
|
||||
#define MEM_MON_IDLE_SHIFT 6
|
||||
#define MEM_UP_EVAL_MASK 0x0030
|
||||
#define MEM_UP_EVAL_SHIFT 4
|
||||
#define MEM_DOWN_EVAL_MASK 0x000c
|
||||
#define MEM_DOWN_EVAL_SHIFT 2
|
||||
#define MEM_SW_CMD_MASK 0x0003
|
||||
#define MEM_INT_STEER_GFX 0
|
||||
#define MEM_INT_STEER_CMR 1
|
||||
#define MEM_INT_STEER_SMI 2
|
||||
#define MEM_INT_STEER_SCI 3
|
||||
#define MEMINTRSTS 0x11184
|
||||
#define MEMINT_RSEXIT (1<<7)
|
||||
#define MEMINT_CONT_BUSY (1<<6)
|
||||
#define MEMINT_AVG_BUSY (1<<5)
|
||||
#define MEMINT_EVAL_CHG (1<<4)
|
||||
#define MEMINT_MON_IDLE (1<<3)
|
||||
#define MEMINT_UP_EVAL (1<<2)
|
||||
#define MEMINT_DOWN_EVAL (1<<1)
|
||||
#define MEMINT_SW_CMD (1<<0)
|
||||
#define MEMMODECTL 0x11190
|
||||
#define MEMMODE_BOOST_EN (1<<31)
|
||||
#define MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */
|
||||
#define MEMMODE_BOOST_FREQ_SHIFT 24
|
||||
#define MEMMODE_IDLE_MODE_MASK 0x00030000
|
||||
#define MEMMODE_IDLE_MODE_SHIFT 16
|
||||
#define MEMMODE_IDLE_MODE_EVAL 0
|
||||
#define MEMMODE_IDLE_MODE_CONT 1
|
||||
#define MEMMODE_HWIDLE_EN (1<<15)
|
||||
#define MEMMODE_SWMODE_EN (1<<14)
|
||||
#define MEMMODE_RCLK_GATE (1<<13)
|
||||
#define MEMMODE_HW_UPDATE (1<<12)
|
||||
#define MEMMODE_FSTART_MASK 0x00000f00 /* starting jitter, 0-15 */
|
||||
#define MEMMODE_FSTART_SHIFT 8
|
||||
#define MEMMODE_FMAX_MASK 0x000000f0 /* max jitter, 0-15 */
|
||||
#define MEMMODE_FMAX_SHIFT 4
|
||||
#define MEMMODE_FMIN_MASK 0x0000000f /* min jitter, 0-15 */
|
||||
#define RCBMAXAVG 0x1119c
|
||||
#define MEMSWCTL2 0x1119e /* Cantiga only */
|
||||
#define SWMEMCMD_RENDER_OFF (0 << 13)
|
||||
#define SWMEMCMD_RENDER_ON (1 << 13)
|
||||
#define SWMEMCMD_SWFREQ (2 << 13)
|
||||
#define SWMEMCMD_TARVID (3 << 13)
|
||||
#define SWMEMCMD_VRM_OFF (4 << 13)
|
||||
#define SWMEMCMD_VRM_ON (5 << 13)
|
||||
#define CMDSTS (1<<12)
|
||||
#define SFCAVM (1<<11)
|
||||
#define SWFREQ_MASK 0x0380 /* P0-7 */
|
||||
#define SWFREQ_SHIFT 7
|
||||
#define TARVID_MASK 0x001f
|
||||
#define MEMSTAT_CTG 0x111a0
|
||||
#define RCBMINAVG 0x111a0
|
||||
#define RCUPEI 0x111b0
|
||||
#define RCDNEI 0x111b4
|
||||
#define MCHBAR_RENDER_STANDBY 0x111b8
|
||||
#define RCX_SW_EXIT (1<<23)
|
||||
#define RSX_STATUS_MASK 0x00700000
|
||||
#define VIDCTL 0x111c0
|
||||
#define VIDSTS 0x111c8
|
||||
#define VIDSTART 0x111cc /* 8 bits */
|
||||
#define MEMSTAT_ILK 0x111f8
|
||||
#define MEMSTAT_VID_MASK 0x7f00
|
||||
#define MEMSTAT_VID_SHIFT 8
|
||||
#define MEMSTAT_PSTATE_MASK 0x00f8
|
||||
#define MEMSTAT_PSTATE_SHIFT 3
|
||||
#define MEMSTAT_MON_ACTV (1<<2)
|
||||
#define MEMSTAT_SRC_CTL_MASK 0x0003
|
||||
#define MEMSTAT_SRC_CTL_CORE 0
|
||||
#define MEMSTAT_SRC_CTL_TRB 1
|
||||
#define MEMSTAT_SRC_CTL_THM 2
|
||||
#define MEMSTAT_SRC_CTL_STDBY 3
|
||||
#define RCPREVBSYTUPAVG 0x113b8
|
||||
#define RCPREVBSYTDNAVG 0x113bc
|
||||
#define PEG_BAND_GAP_DATA 0x14d68
|
||||
|
||||
/*
|
||||
|
|
|
@ -682,6 +682,8 @@ void i915_restore_display(struct drm_device *dev)
|
|||
I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
|
||||
I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
|
||||
I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
|
||||
I915_WRITE(MCHBAR_RENDER_STANDBY,
|
||||
dev_priv->saveMCHBAR_RENDER_STANDBY);
|
||||
} else {
|
||||
I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
|
||||
I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
|
||||
|
@ -745,11 +747,16 @@ int i915_save_state(struct drm_device *dev)
|
|||
dev_priv->saveGTIMR = I915_READ(GTIMR);
|
||||
dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
|
||||
dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
|
||||
dev_priv->saveMCHBAR_RENDER_STANDBY =
|
||||
I915_READ(MCHBAR_RENDER_STANDBY);
|
||||
} else {
|
||||
dev_priv->saveIER = I915_READ(IER);
|
||||
dev_priv->saveIMR = I915_READ(IMR);
|
||||
}
|
||||
|
||||
if (IS_IRONLAKE_M(dev))
|
||||
ironlake_disable_drps(dev);
|
||||
|
||||
/* Cache mode state */
|
||||
dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
|
||||
|
||||
|
@ -820,6 +827,9 @@ int i915_restore_state(struct drm_device *dev)
|
|||
/* Clock gating state */
|
||||
intel_init_clock_gating(dev);
|
||||
|
||||
if (IS_IRONLAKE_M(dev))
|
||||
ironlake_enable_drps(dev);
|
||||
|
||||
/* Cache mode state */
|
||||
I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
|
||||
|
||||
|
|
|
@ -247,6 +247,7 @@ static void
|
|||
parse_general_features(struct drm_i915_private *dev_priv,
|
||||
struct bdb_header *bdb)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct bdb_general_features *general;
|
||||
|
||||
/* Set sensible defaults in case we can't find the general block */
|
||||
|
@ -263,7 +264,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
|||
if (IS_I85X(dev_priv->dev))
|
||||
dev_priv->lvds_ssc_freq =
|
||||
general->ssc_freq ? 66 : 48;
|
||||
else if (IS_IRONLAKE(dev_priv->dev))
|
||||
else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev))
|
||||
dev_priv->lvds_ssc_freq =
|
||||
general->ssc_freq ? 100 : 120;
|
||||
else
|
||||
|
|
|
@ -39,7 +39,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 temp, reg;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = PCH_ADPA;
|
||||
else
|
||||
reg = ADPA;
|
||||
|
@ -113,7 +113,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|||
else
|
||||
dpll_md_reg = DPLL_B_MD;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
adpa_reg = PCH_ADPA;
|
||||
else
|
||||
adpa_reg = ADPA;
|
||||
|
@ -122,7 +122,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|||
* Disable separate mode multiplier used when cloning SDVO to CRT
|
||||
* XXX this needs to be adjusted when we really are cloning
|
||||
*/
|
||||
if (IS_I965G(dev) && !IS_IRONLAKE(dev)) {
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
||||
dpll_md = I915_READ(dpll_md_reg);
|
||||
I915_WRITE(dpll_md_reg,
|
||||
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
|
@ -136,11 +136,11 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|||
|
||||
if (intel_crtc->pipe == 0) {
|
||||
adpa |= ADPA_PIPE_A_SELECT;
|
||||
if (!IS_IRONLAKE(dev))
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
I915_WRITE(BCLRPAT_A, 0);
|
||||
} else {
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
if (!IS_IRONLAKE(dev))
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
I915_WRITE(BCLRPAT_B, 0);
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
|||
u32 hotplug_en;
|
||||
int i, tries = 0;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return intel_ironlake_crt_detect_hotplug(connector);
|
||||
|
||||
/*
|
||||
|
@ -524,7 +524,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
&intel_output->enc);
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
i2c_reg = PCH_GPIOA;
|
||||
else {
|
||||
i2c_reg = GPIOA;
|
||||
|
|
|
@ -232,7 +232,7 @@ struct intel_limit {
|
|||
#define G4X_P2_DISPLAY_PORT_FAST 10
|
||||
#define G4X_P2_DISPLAY_PORT_LIMIT 0
|
||||
|
||||
/* Ironlake */
|
||||
/* Ironlake / Sandybridge */
|
||||
/* as we calculate clock using (register_value + 2) for
|
||||
N/M1/M2, so here the range value for them is (actual_value-2).
|
||||
*/
|
||||
|
@ -690,7 +690,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
|
|||
struct drm_device *dev = crtc->dev;
|
||||
const intel_limit_t *limit;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
limit = intel_ironlake_limit(crtc);
|
||||
else if (IS_G4X(dev)) {
|
||||
limit = intel_g4x_limit(crtc);
|
||||
|
@ -886,7 +886,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
||||
int lvds_reg;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
lvds_reg = PCH_LVDS;
|
||||
else
|
||||
lvds_reg = LVDS;
|
||||
|
@ -1188,25 +1188,30 @@ static void intel_update_fbc(struct drm_crtc *crtc,
|
|||
if (intel_fb->obj->size > dev_priv->cfb_size) {
|
||||
DRM_DEBUG_KMS("framebuffer too large, disabling "
|
||||
"compression\n");
|
||||
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
||||
goto out_disable;
|
||||
}
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
|
||||
(mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
|
||||
DRM_DEBUG_KMS("mode incompatible with compression, "
|
||||
"disabling\n");
|
||||
dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
|
||||
goto out_disable;
|
||||
}
|
||||
if ((mode->hdisplay > 2048) ||
|
||||
(mode->vdisplay > 1536)) {
|
||||
DRM_DEBUG_KMS("mode too large for compression, disabling\n");
|
||||
dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
|
||||
goto out_disable;
|
||||
}
|
||||
if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) {
|
||||
DRM_DEBUG_KMS("plane not 0, disabling compression\n");
|
||||
dev_priv->no_fbc_reason = FBC_BAD_PLANE;
|
||||
goto out_disable;
|
||||
}
|
||||
if (obj_priv->tiling_mode != I915_TILING_X) {
|
||||
DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
|
||||
dev_priv->no_fbc_reason = FBC_NOT_TILED;
|
||||
goto out_disable;
|
||||
}
|
||||
|
||||
|
@ -1366,7 +1371,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
dspcntr &= ~DISPPLANE_TILED;
|
||||
}
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
/* must disable */
|
||||
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
||||
|
||||
|
@ -1427,7 +1432,7 @@ static void i915_disable_vga (struct drm_device *dev)
|
|||
u8 sr1;
|
||||
u32 vga_reg;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
vga_reg = CPU_VGACNTRL;
|
||||
else
|
||||
vga_reg = VGACNTRL;
|
||||
|
@ -2111,7 +2116,7 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
|
|||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
/* FDI link clock is fixed at 2.7G */
|
||||
if (mode->clock * 3 > 27000 * 4)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
@ -2757,11 +2762,22 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
|
|||
srwm = total_size - sr_entries;
|
||||
if (srwm < 0)
|
||||
srwm = 1;
|
||||
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
|
||||
|
||||
if (IS_I945G(dev) || IS_I945GM(dev))
|
||||
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
|
||||
else if (IS_I915GM(dev)) {
|
||||
/* 915M has a smaller SRWM field */
|
||||
I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
|
||||
I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
|
||||
}
|
||||
} else {
|
||||
/* Turn off self refresh if both pipes are enabled */
|
||||
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
|
||||
& ~FW_BLC_SELF_EN);
|
||||
if (IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
|
||||
& ~FW_BLC_SELF_EN);
|
||||
} else if (IS_I915GM(dev)) {
|
||||
I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
|
||||
|
@ -2967,7 +2983,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
refclk / 1000);
|
||||
} else if (IS_I9XX(dev)) {
|
||||
refclk = 96000;
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
refclk = 120000; /* 120Mhz refclk */
|
||||
} else {
|
||||
refclk = 48000;
|
||||
|
@ -3025,7 +3041,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
/* FDI link */
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
int lane, link_bw, bpp;
|
||||
/* eDP doesn't require FDI link, so just set DP M/N
|
||||
according to current link config */
|
||||
|
@ -3102,7 +3118,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
* PCH B stepping, previous chipset stepping should be
|
||||
* ignoring this setting.
|
||||
*/
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
temp = I915_READ(PCH_DREF_CONTROL);
|
||||
/* Always enable nonspread source */
|
||||
temp &= ~DREF_NONSPREAD_SOURCE_MASK;
|
||||
|
@ -3149,7 +3165,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
reduced_clock.m2;
|
||||
}
|
||||
|
||||
if (!IS_IRONLAKE(dev))
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
dpll = DPLL_VGA_MODE_DIS;
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
|
@ -3162,7 +3178,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
||||
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
|
||||
else if (IS_IRONLAKE(dev))
|
||||
else if (HAS_PCH_SPLIT(dev))
|
||||
dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
|
||||
}
|
||||
if (is_dp)
|
||||
|
@ -3174,7 +3190,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
else {
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
||||
/* also FPA1 */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
||||
if (IS_G4X(dev) && has_reduced_clock)
|
||||
dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
||||
|
@ -3193,7 +3209,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
|
||||
break;
|
||||
}
|
||||
if (IS_I965G(dev) && !IS_IRONLAKE(dev))
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
|
||||
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
|
||||
} else {
|
||||
if (is_lvds) {
|
||||
|
@ -3227,7 +3243,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
|
||||
/* Ironlake's plane is forced to pipe, bit 24 is to
|
||||
enable color space conversion */
|
||||
if (!IS_IRONLAKE(dev)) {
|
||||
if (!HAS_PCH_SPLIT(dev)) {
|
||||
if (pipe == 0)
|
||||
dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
|
||||
else
|
||||
|
@ -3254,14 +3270,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
|
||||
|
||||
/* Disable the panel fitter if it was on our pipe */
|
||||
if (!IS_IRONLAKE(dev) && intel_panel_fitter_pipe(dev) == pipe)
|
||||
if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
|
||||
I915_WRITE(PFIT_CONTROL, 0);
|
||||
|
||||
DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
|
||||
/* assign to Ironlake registers */
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
fp_reg = pch_fp_reg;
|
||||
dpll_reg = pch_dpll_reg;
|
||||
}
|
||||
|
@ -3282,7 +3298,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
if (is_lvds) {
|
||||
u32 lvds;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
lvds_reg = PCH_LVDS;
|
||||
|
||||
lvds = I915_READ(lvds_reg);
|
||||
|
@ -3304,12 +3320,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
/* set the dithering flag */
|
||||
if (IS_I965G(dev)) {
|
||||
if (dev_priv->lvds_dither) {
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
pipeconf |= PIPE_ENABLE_DITHER;
|
||||
else
|
||||
lvds |= LVDS_ENABLE_DITHER;
|
||||
} else {
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
pipeconf &= ~PIPE_ENABLE_DITHER;
|
||||
else
|
||||
lvds &= ~LVDS_ENABLE_DITHER;
|
||||
|
@ -3328,7 +3344,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
/* Wait for the clocks to stabilize. */
|
||||
udelay(150);
|
||||
|
||||
if (IS_I965G(dev) && !IS_IRONLAKE(dev)) {
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
||||
if (is_sdvo) {
|
||||
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
||||
I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
|
||||
|
@ -3375,14 +3391,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
/* pipesrc and dspsize control the size that is scaled from, which should
|
||||
* always be the user's requested size.
|
||||
*/
|
||||
if (!IS_IRONLAKE(dev)) {
|
||||
if (!HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
|
||||
(mode->hdisplay - 1));
|
||||
I915_WRITE(dsppos_reg, 0);
|
||||
}
|
||||
I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
|
||||
I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
|
||||
I915_WRITE(link_m1_reg, m_n.link_m);
|
||||
|
@ -3438,7 +3454,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|||
return;
|
||||
|
||||
/* use legacy palette for Ironlake */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
|
||||
LGC_PALETTE_B;
|
||||
|
||||
|
@ -3921,7 +3937,7 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)
|
|||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll = I915_READ(dpll_reg);
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return;
|
||||
|
||||
if (!dev_priv->lvds_downclock_avail)
|
||||
|
@ -3960,7 +3976,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
|
|||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll = I915_READ(dpll_reg);
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return;
|
||||
|
||||
if (!dev_priv->lvds_downclock_avail)
|
||||
|
@ -4010,6 +4026,11 @@ static void intel_idle_update(struct work_struct *work)
|
|||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
|
||||
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
/* Skip inactive CRTCs */
|
||||
if (!crtc->fb)
|
||||
|
@ -4043,9 +4064,17 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
|
|||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return;
|
||||
|
||||
if (!dev_priv->busy)
|
||||
if (!dev_priv->busy) {
|
||||
if (IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
u32 fw_blc_self;
|
||||
|
||||
DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
|
||||
fw_blc_self = I915_READ(FW_BLC_SELF);
|
||||
fw_blc_self &= ~FW_BLC_SELF_EN;
|
||||
I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
|
||||
}
|
||||
dev_priv->busy = true;
|
||||
else
|
||||
} else
|
||||
mod_timer(&dev_priv->idle_timer, jiffies +
|
||||
msecs_to_jiffies(GPU_IDLE_TIMEOUT));
|
||||
|
||||
|
@ -4057,6 +4086,14 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
|
|||
intel_fb = to_intel_framebuffer(crtc->fb);
|
||||
if (intel_fb->obj == obj) {
|
||||
if (!intel_crtc->busy) {
|
||||
if (IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
u32 fw_blc_self;
|
||||
|
||||
DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
|
||||
fw_blc_self = I915_READ(FW_BLC_SELF);
|
||||
fw_blc_self &= ~FW_BLC_SELF_EN;
|
||||
I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
|
||||
}
|
||||
/* Non-busy -> busy, upclock */
|
||||
intel_increase_pllclock(crtc, true);
|
||||
intel_crtc->busy = true;
|
||||
|
@ -4381,7 +4418,7 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||
if (IS_MOBILE(dev) && !IS_I830(dev))
|
||||
intel_lvds_init(dev);
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
int found;
|
||||
|
||||
if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
|
||||
|
@ -4450,7 +4487,7 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||
DRM_DEBUG_KMS("probing DP_D\n");
|
||||
intel_dp_init(dev, DP_D);
|
||||
}
|
||||
} else if (IS_I8XX(dev))
|
||||
} else if (IS_GEN2(dev))
|
||||
intel_dvo_init(dev);
|
||||
|
||||
if (SUPPORTS_TV(dev))
|
||||
|
@ -4586,6 +4623,91 @@ err_unref:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void ironlake_enable_drps(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl;
|
||||
u8 fmax, fmin, fstart, vstart;
|
||||
int i = 0;
|
||||
|
||||
/* 100ms RC evaluation intervals */
|
||||
I915_WRITE(RCUPEI, 100000);
|
||||
I915_WRITE(RCDNEI, 100000);
|
||||
|
||||
/* Set max/min thresholds to 90ms and 80ms respectively */
|
||||
I915_WRITE(RCBMAXAVG, 90000);
|
||||
I915_WRITE(RCBMINAVG, 80000);
|
||||
|
||||
I915_WRITE(MEMIHYST, 1);
|
||||
|
||||
/* Set up min, max, and cur for interrupt handling */
|
||||
fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT;
|
||||
fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
|
||||
fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
|
||||
MEMMODE_FSTART_SHIFT;
|
||||
vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
|
||||
PXVFREQ_PX_SHIFT;
|
||||
|
||||
dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */
|
||||
dev_priv->min_delay = fmin;
|
||||
dev_priv->cur_delay = fstart;
|
||||
|
||||
I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
|
||||
|
||||
/*
|
||||
* Interrupts will be enabled in ironlake_irq_postinstall
|
||||
*/
|
||||
|
||||
I915_WRITE(VIDSTART, vstart);
|
||||
POSTING_READ(VIDSTART);
|
||||
|
||||
rgvmodectl |= MEMMODE_SWMODE_EN;
|
||||
I915_WRITE(MEMMODECTL, rgvmodectl);
|
||||
|
||||
while (I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) {
|
||||
if (i++ > 100) {
|
||||
DRM_ERROR("stuck trying to change perf mode\n");
|
||||
break;
|
||||
}
|
||||
msleep(1);
|
||||
}
|
||||
msleep(1);
|
||||
|
||||
rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
|
||||
(fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
|
||||
I915_WRITE(MEMSWCTL, rgvswctl);
|
||||
POSTING_READ(MEMSWCTL);
|
||||
|
||||
rgvswctl |= MEMCTL_CMD_STS;
|
||||
I915_WRITE(MEMSWCTL, rgvswctl);
|
||||
}
|
||||
|
||||
void ironlake_disable_drps(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 rgvswctl;
|
||||
u8 fstart;
|
||||
|
||||
/* Ack interrupts, disable EFC interrupt */
|
||||
I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
|
||||
I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG);
|
||||
I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT);
|
||||
I915_WRITE(DEIIR, DE_PCU_EVENT);
|
||||
I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
|
||||
|
||||
/* Go back to the starting frequency */
|
||||
fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >>
|
||||
MEMMODE_FSTART_SHIFT;
|
||||
rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
|
||||
(fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
|
||||
I915_WRITE(MEMSWCTL, rgvswctl);
|
||||
msleep(1);
|
||||
rgvswctl |= MEMCTL_CMD_STS;
|
||||
I915_WRITE(MEMSWCTL, rgvswctl);
|
||||
msleep(1);
|
||||
|
||||
}
|
||||
|
||||
void intel_init_clock_gating(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
@ -4594,7 +4716,7 @@ void intel_init_clock_gating(struct drm_device *dev)
|
|||
* Disable clock gating reported to work incorrectly according to the
|
||||
* specs, but enable as much else as we can.
|
||||
*/
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
return;
|
||||
} else if (IS_G4X(dev)) {
|
||||
uint32_t dspclk_gate;
|
||||
|
@ -4667,7 +4789,7 @@ static void intel_init_display(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* We always want a DPMS function */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
dev_priv->display.dpms = ironlake_crtc_dpms;
|
||||
else
|
||||
dev_priv->display.dpms = i9xx_crtc_dpms;
|
||||
|
@ -4710,7 +4832,7 @@ static void intel_init_display(struct drm_device *dev)
|
|||
i830_get_display_clock_speed;
|
||||
|
||||
/* For FIFO watermark updates */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
dev_priv->display.update_wm = NULL;
|
||||
else if (IS_G4X(dev))
|
||||
dev_priv->display.update_wm = g4x_update_wm;
|
||||
|
@ -4769,11 +4891,6 @@ void intel_modeset_init(struct drm_device *dev)
|
|||
DRM_DEBUG_KMS("%d display pipe%s available.\n",
|
||||
num_pipe, num_pipe > 1 ? "s" : "");
|
||||
|
||||
if (IS_I85X(dev))
|
||||
pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
|
||||
else if (IS_I9XX(dev) || IS_G4X(dev))
|
||||
pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
|
||||
|
||||
for (i = 0; i < num_pipe; i++) {
|
||||
intel_crtc_init(dev, i);
|
||||
}
|
||||
|
@ -4782,6 +4899,9 @@ void intel_modeset_init(struct drm_device *dev)
|
|||
|
||||
intel_init_clock_gating(dev);
|
||||
|
||||
if (IS_IRONLAKE_M(dev))
|
||||
ironlake_enable_drps(dev);
|
||||
|
||||
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
|
||||
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
|
||||
(unsigned long)dev);
|
||||
|
@ -4829,6 +4949,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|||
drm_gem_object_unreference(dev_priv->pwrctx);
|
||||
}
|
||||
|
||||
if (IS_IRONLAKE_M(dev))
|
||||
ironlake_disable_drps(dev);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
|
|
@ -231,7 +231,7 @@ intel_dp_aux_ch(struct intel_output *intel_output,
|
|||
*/
|
||||
if (IS_eDP(intel_output))
|
||||
aux_clock_divider = 225; /* eDP input clock at 450Mhz */
|
||||
else if (IS_IRONLAKE(dev))
|
||||
else if (HAS_PCH_SPLIT(dev))
|
||||
aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
|
||||
else
|
||||
aux_clock_divider = intel_hrawclk(dev) / 2;
|
||||
|
@ -584,7 +584,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|||
intel_dp_compute_m_n(3, lane_count,
|
||||
mode->clock, adjusted_mode->clock, &m_n);
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
if (intel_crtc->pipe == 0) {
|
||||
I915_WRITE(TRANSA_DATA_M1,
|
||||
((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
|
||||
|
@ -1176,7 +1176,7 @@ intel_dp_detect(struct drm_connector *connector)
|
|||
|
||||
dp_priv->has_audio = false;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return ironlake_dp_detect(connector);
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
|
|
|
@ -209,6 +209,8 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
|||
extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
|
||||
u16 *blue, int regno);
|
||||
extern void intel_init_clock_gating(struct drm_device *dev);
|
||||
extern void ironlake_enable_drps(struct drm_device *dev);
|
||||
extern void ironlake_disable_drps(struct drm_device *dev);
|
||||
|
||||
extern int intel_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd *mode_cmd,
|
||||
|
|
|
@ -82,7 +82,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
|||
/* HW workaround, need to toggle enable bit off and on for 12bpc, but
|
||||
* we do this anyway which shows more stable in testing.
|
||||
*/
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
|
||||
POSTING_READ(hdmi_priv->sdvox_reg);
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
|||
/* HW workaround, need to write this twice for issue that may result
|
||||
* in first write getting masked.
|
||||
*/
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(hdmi_priv->sdvox_reg, temp);
|
||||
POSTING_READ(hdmi_priv->sdvox_reg);
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ intel_i2c_reset_gmbus(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(PCH_GMBUS0, 0);
|
||||
} else {
|
||||
I915_WRITE(GMBUS0, 0);
|
||||
|
|
|
@ -56,7 +56,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 blc_pwm_ctl, reg;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = BLC_PWM_CPU_CTL;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
@ -74,7 +74,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = BLC_PWM_PCH_CTL2;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
@ -89,17 +89,22 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
|||
static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_status, ctl_reg, status_reg;
|
||||
u32 pp_status, ctl_reg, status_reg, lvds_reg;
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
ctl_reg = PCH_PP_CONTROL;
|
||||
status_reg = PCH_PP_STATUS;
|
||||
lvds_reg = PCH_LVDS;
|
||||
} else {
|
||||
ctl_reg = PP_CONTROL;
|
||||
status_reg = PP_STATUS;
|
||||
lvds_reg = LVDS;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
|
||||
POSTING_READ(lvds_reg);
|
||||
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
|
||||
POWER_TARGET_ON);
|
||||
do {
|
||||
|
@ -115,6 +120,9 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
|||
do {
|
||||
pp_status = I915_READ(status_reg);
|
||||
} while (pp_status & PP_ON);
|
||||
|
||||
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
|
||||
POSTING_READ(lvds_reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,7 +145,7 @@ static void intel_lvds_save(struct drm_connector *connector)
|
|||
u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
|
||||
u32 pwm_ctl_reg;
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
pp_on_reg = PCH_PP_ON_DELAYS;
|
||||
pp_off_reg = PCH_PP_OFF_DELAYS;
|
||||
pp_ctl_reg = PCH_PP_CONTROL;
|
||||
|
@ -174,7 +182,7 @@ static void intel_lvds_restore(struct drm_connector *connector)
|
|||
u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
|
||||
u32 pwm_ctl_reg;
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
pp_on_reg = PCH_PP_ON_DELAYS;
|
||||
pp_off_reg = PCH_PP_OFF_DELAYS;
|
||||
pp_ctl_reg = PCH_PP_CONTROL;
|
||||
|
@ -297,7 +305,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
}
|
||||
|
||||
/* full screen scale for now */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
goto out;
|
||||
|
||||
/* 965+ wants fuzzy fitting */
|
||||
|
@ -327,7 +335,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
* to register description and PRM.
|
||||
* Change the value here to see the borders for debugging
|
||||
*/
|
||||
if (!IS_IRONLAKE(dev)) {
|
||||
if (!HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(BCLRPAT_A, 0);
|
||||
I915_WRITE(BCLRPAT_B, 0);
|
||||
}
|
||||
|
@ -548,7 +556,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = BLC_PWM_CPU_CTL;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
@ -587,7 +595,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
|||
* settings.
|
||||
*/
|
||||
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -655,8 +663,15 @@ static const struct dmi_system_id bad_lid_status[] = {
|
|||
*/
|
||||
static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
enum drm_connector_status status = connector_status_connected;
|
||||
|
||||
/* ACPI lid methods were generally unreliable in this generation, so
|
||||
* don't even bother.
|
||||
*/
|
||||
if (IS_GEN2(dev))
|
||||
return connector_status_connected;
|
||||
|
||||
if (!dmi_check_system(bad_lid_status) && !acpi_lid_open())
|
||||
status = connector_status_disconnected;
|
||||
|
||||
|
@ -1020,7 +1035,7 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
|
||||
return;
|
||||
if (dev_priv->edp_support) {
|
||||
|
@ -1123,7 +1138,7 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
*/
|
||||
|
||||
/* Ironlake: FIXME if still fail, not try pipe mode now */
|
||||
if (IS_IRONLAKE(dev))
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
goto failed;
|
||||
|
||||
lvds = I915_READ(LVDS);
|
||||
|
@ -1144,7 +1159,7 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
goto failed;
|
||||
|
||||
out:
|
||||
if (IS_IRONLAKE(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
u32 pwm;
|
||||
/* make sure PWM is enabled */
|
||||
pwm = I915_READ(BLC_PWM_CPU_CTL2);
|
||||
|
|
|
@ -172,7 +172,7 @@ struct overlay_registers {
|
|||
#define OFC_UPDATE 0x1
|
||||
|
||||
#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
|
||||
#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev))
|
||||
#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
|
||||
|
||||
|
||||
static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
|
||||
|
@ -199,16 +199,11 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
|
|||
|
||||
static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
|
||||
{
|
||||
struct drm_device *dev = overlay->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (OVERLAY_NONPHYSICAL(overlay->dev))
|
||||
io_mapping_unmap_atomic(overlay->virt_addr);
|
||||
|
||||
overlay->virt_addr = NULL;
|
||||
|
||||
I915_READ(OVADD); /* flush wc cashes */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -225,9 +220,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
|
|||
overlay->active = 1;
|
||||
overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(MI_FLUSH);
|
||||
OUT_RING(MI_NOOP);
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
|
||||
OUT_RING(overlay->flip_addr | OFC_UPDATE);
|
||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
@ -267,9 +260,7 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
|
|||
if (tmp & (1 << 17))
|
||||
DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_FLUSH);
|
||||
OUT_RING(MI_NOOP);
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
|
||||
OUT_RING(flip_addr);
|
||||
ADVANCE_LP_RING();
|
||||
|
@ -338,9 +329,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|||
/* wait for overlay to go idle */
|
||||
overlay->hw_wedged = SWITCH_OFF_STAGE_1;
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(MI_FLUSH);
|
||||
OUT_RING(MI_NOOP);
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
|
||||
OUT_RING(flip_addr);
|
||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
@ -358,9 +347,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|||
/* turn overlay off */
|
||||
overlay->hw_wedged = SWITCH_OFF_STAGE_2;
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(MI_FLUSH);
|
||||
OUT_RING(MI_NOOP);
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
OUT_RING(flip_addr);
|
||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
@ -435,9 +422,7 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
|
|||
|
||||
overlay->hw_wedged = SWITCH_OFF_STAGE_2;
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(MI_FLUSH);
|
||||
OUT_RING(MI_NOOP);
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
OUT_RING(flip_addr);
|
||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_sdvo_regs.h"
|
||||
#include <linux/dmi.h>
|
||||
|
||||
static char *tv_format_names[] = {
|
||||
"NTSC_M" , "NTSC_J" , "NTSC_443",
|
||||
|
@ -2283,6 +2284,25 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
|
|||
return 0x72;
|
||||
}
|
||||
|
||||
static int intel_sdvo_bad_tv_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
DRM_DEBUG_KMS("Ignoring bad SDVO TV connector for %s\n", id->ident);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dmi_system_id intel_sdvo_bad_tv[] = {
|
||||
{
|
||||
.callback = intel_sdvo_bad_tv_callback,
|
||||
.ident = "IntelG45/ICH10R/DME1737",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "IBM CORPORATION"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "4800784"),
|
||||
},
|
||||
},
|
||||
|
||||
{ } /* terminating entry */
|
||||
};
|
||||
|
||||
static bool
|
||||
intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
|
||||
{
|
||||
|
@ -2323,7 +2343,8 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
|
|||
(1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
||||
(1 << INTEL_ANALOG_CLONE_BIT);
|
||||
}
|
||||
} else if (flags & SDVO_OUTPUT_SVID0) {
|
||||
} else if ((flags & SDVO_OUTPUT_SVID0) &&
|
||||
!dmi_check_system(intel_sdvo_bad_tv)) {
|
||||
|
||||
sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
|
||||
encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
|
||||
|
|
|
@ -30,6 +30,9 @@ $(obj)/r420_reg_safe.h: $(src)/reg_srcs/r420 $(obj)/mkregtable
|
|||
$(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
|
||||
|
||||
$(obj)/r200.o: $(obj)/r200_reg_safe.h
|
||||
|
@ -42,6 +45,8 @@ $(obj)/r420.o: $(obj)/r420_reg_safe.h
|
|||
|
||||
$(obj)/rs600.o: $(obj)/rs600_reg_safe.h
|
||||
|
||||
$(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
|
||||
|
||||
radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
|
||||
radeon_irq.o r300_cmdbuf.o r600_cp.o
|
||||
# add KMS driver
|
||||
|
@ -54,7 +59,8 @@ radeon-y += radeon_device.o radeon_kms.o \
|
|||
radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
|
||||
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
|
||||
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
|
||||
r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o
|
||||
r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
|
||||
evergreen.o
|
||||
|
||||
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -245,21 +245,25 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
atombios_enable_crtc(crtc, 1);
|
||||
atombios_enable_crtc(crtc, ATOM_ENABLE);
|
||||
if (ASIC_IS_DCE3(rdev))
|
||||
atombios_enable_crtc_memreq(crtc, 1);
|
||||
atombios_blank_crtc(crtc, 0);
|
||||
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
|
||||
atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
|
||||
atombios_blank_crtc(crtc, ATOM_DISABLE);
|
||||
/* XXX re-enable when interrupt support is added */
|
||||
if (!ASIC_IS_DCE4(rdev))
|
||||
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
|
||||
radeon_crtc_load_lut(crtc);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
|
||||
atombios_blank_crtc(crtc, 1);
|
||||
/* XXX re-enable when interrupt support is added */
|
||||
if (!ASIC_IS_DCE4(rdev))
|
||||
drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
|
||||
atombios_blank_crtc(crtc, ATOM_ENABLE);
|
||||
if (ASIC_IS_DCE3(rdev))
|
||||
atombios_enable_crtc_memreq(crtc, 0);
|
||||
atombios_enable_crtc(crtc, 0);
|
||||
atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
|
||||
atombios_enable_crtc(crtc, ATOM_DISABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -349,6 +353,11 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
|
|||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
union atom_enable_ss {
|
||||
ENABLE_LVDS_SS_PARAMETERS legacy;
|
||||
ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;
|
||||
};
|
||||
|
||||
static void atombios_set_ss(struct drm_crtc *crtc, int enable)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
|
@ -358,11 +367,14 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
|
|||
struct radeon_encoder *radeon_encoder = NULL;
|
||||
struct radeon_encoder_atom_dig *dig = NULL;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
|
||||
ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args;
|
||||
ENABLE_LVDS_SS_PARAMETERS legacy_args;
|
||||
union atom_enable_ss args;
|
||||
uint16_t percentage = 0;
|
||||
uint8_t type = 0, step = 0, delay = 0, range = 0;
|
||||
|
||||
/* XXX add ss support for DCE4 */
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
return;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
@ -386,29 +398,28 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
|
|||
if (!radeon_encoder)
|
||||
return;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
|
||||
args.ucSpreadSpectrumType = type;
|
||||
args.ucSpreadSpectrumStep = step;
|
||||
args.ucSpreadSpectrumDelay = delay;
|
||||
args.ucSpreadSpectrumRange = range;
|
||||
args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
|
||||
args.ucEnable = enable;
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
args.v1.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
|
||||
args.v1.ucSpreadSpectrumType = type;
|
||||
args.v1.ucSpreadSpectrumStep = step;
|
||||
args.v1.ucSpreadSpectrumDelay = delay;
|
||||
args.v1.ucSpreadSpectrumRange = range;
|
||||
args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
|
||||
args.v1.ucEnable = enable;
|
||||
} else {
|
||||
memset(&legacy_args, 0, sizeof(legacy_args));
|
||||
legacy_args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
|
||||
legacy_args.ucSpreadSpectrumType = type;
|
||||
legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
|
||||
legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
|
||||
legacy_args.ucEnable = enable;
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args);
|
||||
args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
|
||||
args.legacy.ucSpreadSpectrumType = type;
|
||||
args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
|
||||
args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
|
||||
args.legacy.ucEnable = enable;
|
||||
}
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
union adjust_pixel_clock {
|
||||
ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
|
||||
ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
|
||||
};
|
||||
|
||||
static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
||||
|
@ -420,10 +431,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
|||
struct drm_encoder *encoder = NULL;
|
||||
struct radeon_encoder *radeon_encoder = NULL;
|
||||
u32 adjusted_clock = mode->clock;
|
||||
int encoder_mode = 0;
|
||||
|
||||
/* reset the pll flags */
|
||||
pll->flags = 0;
|
||||
|
||||
/* select the PLL algo */
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (radeon_new_pll == 0)
|
||||
pll->algo = PLL_ALGO_LEGACY;
|
||||
else
|
||||
pll->algo = PLL_ALGO_NEW;
|
||||
} else {
|
||||
if (radeon_new_pll == 1)
|
||||
pll->algo = PLL_ALGO_NEW;
|
||||
else
|
||||
pll->algo = PLL_ALGO_LEGACY;
|
||||
}
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if ((rdev->family == CHIP_RS600) ||
|
||||
(rdev->family == CHIP_RS690) ||
|
||||
|
@ -448,10 +473,16 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
|||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
encoder_mode = atombios_get_encoder_mode(encoder);
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
|
||||
if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
|
||||
adjusted_clock = mode->clock * 2;
|
||||
/* LVDS PLL quirks */
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
pll->algo = dig->pll_algo;
|
||||
}
|
||||
} else {
|
||||
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
|
||||
pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
|
@ -468,14 +499,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
|||
*/
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
union adjust_pixel_clock args;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
u8 frev, crev;
|
||||
int index;
|
||||
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return adjusted_clock;
|
||||
dig = radeon_encoder->enc_priv;
|
||||
|
||||
index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
|
||||
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
|
||||
&crev);
|
||||
|
@ -489,12 +515,51 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
|||
case 2:
|
||||
args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
args.v1.ucTransmitterID = radeon_encoder->encoder_id;
|
||||
args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
|
||||
args.v1.ucEncodeMode = encoder_mode;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args);
|
||||
adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
|
||||
break;
|
||||
case 3:
|
||||
args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
|
||||
args.v3.sInput.ucEncodeMode = encoder_mode;
|
||||
args.v3.sInput.ucDispPllConfig = 0;
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
|
||||
if (encoder_mode == ATOM_ENCODER_MODE_DP)
|
||||
args.v3.sInput.ucDispPllConfig |=
|
||||
DISPPLL_CONFIG_COHERENT_MODE;
|
||||
else {
|
||||
if (dig->coherent_mode)
|
||||
args.v3.sInput.ucDispPllConfig |=
|
||||
DISPPLL_CONFIG_COHERENT_MODE;
|
||||
if (mode->clock > 165000)
|
||||
args.v3.sInput.ucDispPllConfig |=
|
||||
DISPPLL_CONFIG_DUAL_LINK;
|
||||
}
|
||||
} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
/* may want to enable SS on DP/eDP eventually */
|
||||
args.v3.sInput.ucDispPllConfig |=
|
||||
DISPPLL_CONFIG_SS_ENABLE;
|
||||
if (mode->clock > 165000)
|
||||
args.v3.sInput.ucDispPllConfig |=
|
||||
DISPPLL_CONFIG_DUAL_LINK;
|
||||
}
|
||||
atom_execute_table(rdev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args);
|
||||
adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
|
||||
if (args.v3.sOutput.ucRefDiv) {
|
||||
pll->flags |= RADEON_PLL_USE_REF_DIV;
|
||||
pll->reference_div = args.v3.sOutput.ucRefDiv;
|
||||
}
|
||||
if (args.v3.sOutput.ucPostDiv) {
|
||||
pll->flags |= RADEON_PLL_USE_POST_DIV;
|
||||
pll->post_div = args.v3.sOutput.ucPostDiv;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
|
||||
return adjusted_clock;
|
||||
|
@ -513,9 +578,47 @@ union set_pixel_clock {
|
|||
PIXEL_CLOCK_PARAMETERS v1;
|
||||
PIXEL_CLOCK_PARAMETERS_V2 v2;
|
||||
PIXEL_CLOCK_PARAMETERS_V3 v3;
|
||||
PIXEL_CLOCK_PARAMETERS_V5 v5;
|
||||
};
|
||||
|
||||
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
u8 frev, crev;
|
||||
int index;
|
||||
union set_pixel_clock args;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
|
||||
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
|
||||
&crev);
|
||||
|
||||
switch (frev) {
|
||||
case 1:
|
||||
switch (crev) {
|
||||
case 5:
|
||||
/* if the default dcpll clock is specified,
|
||||
* SetPixelClock provides the dividers
|
||||
*/
|
||||
args.v5.ucCRTC = ATOM_CRTC_INVALID;
|
||||
args.v5.usPixelClock = rdev->clock.default_dispclk;
|
||||
args.v5.ucPpll = ATOM_DCPLL;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
|
||||
return;
|
||||
}
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -529,12 +632,14 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
|
||||
struct radeon_pll *pll;
|
||||
u32 adjusted_clock;
|
||||
int encoder_mode = 0;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
encoder_mode = atombios_get_encoder_mode(encoder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -542,26 +647,24 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
if (!radeon_encoder)
|
||||
return;
|
||||
|
||||
if (radeon_crtc->crtc_id == 0)
|
||||
switch (radeon_crtc->pll_id) {
|
||||
case ATOM_PPLL1:
|
||||
pll = &rdev->clock.p1pll;
|
||||
else
|
||||
break;
|
||||
case ATOM_PPLL2:
|
||||
pll = &rdev->clock.p2pll;
|
||||
break;
|
||||
case ATOM_DCPLL:
|
||||
case ATOM_PPLL_INVALID:
|
||||
pll = &rdev->clock.dcpll;
|
||||
break;
|
||||
}
|
||||
|
||||
/* adjust pixel clock as needed */
|
||||
adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (radeon_new_pll)
|
||||
radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
|
||||
&fb_div, &frac_fb_div,
|
||||
&ref_div, &post_div);
|
||||
else
|
||||
radeon_compute_pll(pll, adjusted_clock, &pll_clock,
|
||||
&fb_div, &frac_fb_div,
|
||||
&ref_div, &post_div);
|
||||
} else
|
||||
radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
|
||||
&ref_div, &post_div);
|
||||
radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
|
||||
&ref_div, &post_div);
|
||||
|
||||
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
|
||||
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
|
||||
|
@ -576,8 +679,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
args.v1.usFbDiv = cpu_to_le16(fb_div);
|
||||
args.v1.ucFracFbDiv = frac_fb_div;
|
||||
args.v1.ucPostDiv = post_div;
|
||||
args.v1.ucPpll =
|
||||
radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
|
||||
args.v1.ucPpll = radeon_crtc->pll_id;
|
||||
args.v1.ucCRTC = radeon_crtc->crtc_id;
|
||||
args.v1.ucRefDivSrc = 1;
|
||||
break;
|
||||
|
@ -587,8 +689,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
args.v2.usFbDiv = cpu_to_le16(fb_div);
|
||||
args.v2.ucFracFbDiv = frac_fb_div;
|
||||
args.v2.ucPostDiv = post_div;
|
||||
args.v2.ucPpll =
|
||||
radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
|
||||
args.v2.ucPpll = radeon_crtc->pll_id;
|
||||
args.v2.ucCRTC = radeon_crtc->crtc_id;
|
||||
args.v2.ucRefDivSrc = 1;
|
||||
break;
|
||||
|
@ -598,12 +699,22 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
args.v3.usFbDiv = cpu_to_le16(fb_div);
|
||||
args.v3.ucFracFbDiv = frac_fb_div;
|
||||
args.v3.ucPostDiv = post_div;
|
||||
args.v3.ucPpll =
|
||||
radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
|
||||
args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
|
||||
args.v3.ucPpll = radeon_crtc->pll_id;
|
||||
args.v3.ucMiscInfo = (radeon_crtc->pll_id << 2);
|
||||
args.v3.ucTransmitterId = radeon_encoder->encoder_id;
|
||||
args.v3.ucEncoderMode =
|
||||
atombios_get_encoder_mode(encoder);
|
||||
args.v3.ucEncoderMode = encoder_mode;
|
||||
break;
|
||||
case 5:
|
||||
args.v5.ucCRTC = radeon_crtc->crtc_id;
|
||||
args.v5.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
args.v5.ucRefDiv = ref_div;
|
||||
args.v5.usFbDiv = cpu_to_le16(fb_div);
|
||||
args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
|
||||
args.v5.ucPostDiv = post_div;
|
||||
args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
|
||||
args.v5.ucTransmitterID = radeon_encoder->encoder_id;
|
||||
args.v5.ucEncoderMode = encoder_mode;
|
||||
args.v5.ucPpll = radeon_crtc->pll_id;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
|
||||
|
@ -618,6 +729,140 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_framebuffer *radeon_fb;
|
||||
struct drm_gem_object *obj;
|
||||
struct radeon_bo *rbo;
|
||||
uint64_t fb_location;
|
||||
uint32_t fb_format, fb_pitch_pixels, tiling_flags;
|
||||
int r;
|
||||
|
||||
/* no fb bound */
|
||||
if (!crtc->fb) {
|
||||
DRM_DEBUG("No FB bound\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
radeon_fb = to_radeon_framebuffer(crtc->fb);
|
||||
|
||||
/* Pin framebuffer & get tilling informations */
|
||||
obj = radeon_fb->obj;
|
||||
rbo = obj->driver_private;
|
||||
r = radeon_bo_reserve(rbo, false);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
|
||||
if (unlikely(r != 0)) {
|
||||
radeon_bo_unreserve(rbo);
|
||||
return -EINVAL;
|
||||
}
|
||||
radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
|
||||
radeon_bo_unreserve(rbo);
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |
|
||||
EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));
|
||||
break;
|
||||
case 15:
|
||||
fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
|
||||
EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));
|
||||
break;
|
||||
case 16:
|
||||
fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
|
||||
EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
|
||||
EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported screen depth %d\n",
|
||||
crtc->fb->bits_per_pixel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (radeon_crtc->crtc_id) {
|
||||
case 0:
|
||||
WREG32(AVIVO_D1VGA_CONTROL, 0);
|
||||
break;
|
||||
case 1:
|
||||
WREG32(AVIVO_D2VGA_CONTROL, 0);
|
||||
break;
|
||||
case 2:
|
||||
WREG32(EVERGREEN_D3VGA_CONTROL, 0);
|
||||
break;
|
||||
case 3:
|
||||
WREG32(EVERGREEN_D4VGA_CONTROL, 0);
|
||||
break;
|
||||
case 4:
|
||||
WREG32(EVERGREEN_D5VGA_CONTROL, 0);
|
||||
break;
|
||||
case 5:
|
||||
WREG32(EVERGREEN_D6VGA_CONTROL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
|
||||
upper_32_bits(fb_location));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
|
||||
upper_32_bits(fb_location));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
|
||||
(u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
|
||||
(u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
|
||||
WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
|
||||
|
||||
WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
|
||||
WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
|
||||
|
||||
fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
|
||||
WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
|
||||
WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
|
||||
|
||||
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
|
||||
crtc->mode.vdisplay);
|
||||
x &= ~3;
|
||||
y &= ~1;
|
||||
WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
|
||||
(x << 16) | y);
|
||||
WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
|
||||
(crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
|
||||
|
||||
if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
|
||||
WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
|
||||
EVERGREEN_INTERLEAVE_EN);
|
||||
else
|
||||
WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
|
||||
|
||||
if (old_fb && old_fb != crtc->fb) {
|
||||
radeon_fb = to_radeon_framebuffer(old_fb);
|
||||
rbo = radeon_fb->obj->driver_private;
|
||||
r = radeon_bo_reserve(rbo, false);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
radeon_bo_unpin(rbo);
|
||||
radeon_bo_unreserve(rbo);
|
||||
}
|
||||
|
||||
/* Bytes per pixel may have changed */
|
||||
radeon_bandwidth_update(rdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
|
@ -755,7 +1000,9 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
return evergreen_crtc_set_base(crtc, x, y, old_fb);
|
||||
else if (ASIC_IS_AVIVO(rdev))
|
||||
return avivo_crtc_set_base(crtc, x, y, old_fb);
|
||||
else
|
||||
return radeon_crtc_set_base(crtc, x, y, old_fb);
|
||||
|
@ -785,6 +1032,46 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
|
|||
}
|
||||
}
|
||||
|
||||
static int radeon_atom_pick_pll(struct drm_crtc *crtc)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_encoder *test_encoder;
|
||||
struct drm_crtc *test_crtc;
|
||||
uint32_t pll_in_use = 0;
|
||||
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
/* if crtc is driving DP and we have an ext clock, use that */
|
||||
list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (test_encoder->crtc && (test_encoder->crtc == crtc)) {
|
||||
if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) {
|
||||
if (rdev->clock.dp_extclk)
|
||||
return ATOM_PPLL_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise, pick one of the plls */
|
||||
list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct radeon_crtc *radeon_test_crtc;
|
||||
|
||||
if (crtc == test_crtc)
|
||||
continue;
|
||||
|
||||
radeon_test_crtc = to_radeon_crtc(test_crtc);
|
||||
if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) &&
|
||||
(radeon_test_crtc->pll_id <= ATOM_PPLL2))
|
||||
pll_in_use |= (1 << radeon_test_crtc->pll_id);
|
||||
}
|
||||
if (!(pll_in_use & 1))
|
||||
return ATOM_PPLL1;
|
||||
return ATOM_PPLL2;
|
||||
} else
|
||||
return radeon_crtc->crtc_id;
|
||||
|
||||
}
|
||||
|
||||
int atombios_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode,
|
||||
|
@ -796,19 +1083,27 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
|
|||
|
||||
/* TODO color tiling */
|
||||
|
||||
/* pick pll */
|
||||
radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);
|
||||
|
||||
atombios_set_ss(crtc, 0);
|
||||
/* always set DCPLL */
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
atombios_crtc_set_dcpll(crtc);
|
||||
atombios_crtc_set_pll(crtc, adjusted_mode);
|
||||
atombios_set_ss(crtc, 1);
|
||||
atombios_crtc_set_timing(crtc, adjusted_mode);
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
atombios_crtc_set_base(crtc, x, y, old_fb);
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
|
||||
else if (ASIC_IS_AVIVO(rdev))
|
||||
atombios_crtc_set_timing(crtc, adjusted_mode);
|
||||
else {
|
||||
atombios_crtc_set_timing(crtc, adjusted_mode);
|
||||
if (radeon_crtc->crtc_id == 0)
|
||||
atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
|
||||
atombios_crtc_set_base(crtc, x, y, old_fb);
|
||||
radeon_legacy_atom_fixup(crtc);
|
||||
}
|
||||
atombios_crtc_set_base(crtc, x, y, old_fb);
|
||||
atombios_overscan_setup(crtc, mode, adjusted_mode);
|
||||
atombios_scaler_setup(crtc);
|
||||
return 0;
|
||||
|
@ -825,14 +1120,14 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
|
|||
|
||||
static void atombios_crtc_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
atombios_lock_crtc(crtc, 1);
|
||||
atombios_lock_crtc(crtc, ATOM_ENABLE);
|
||||
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
static void atombios_crtc_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
atombios_lock_crtc(crtc, 0);
|
||||
atombios_lock_crtc(crtc, ATOM_DISABLE);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
|
||||
|
@ -848,8 +1143,37 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
|
|||
void radeon_atombios_init_crtc(struct drm_device *dev,
|
||||
struct radeon_crtc *radeon_crtc)
|
||||
{
|
||||
if (radeon_crtc->crtc_id == 1)
|
||||
radeon_crtc->crtc_offset =
|
||||
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
switch (radeon_crtc->crtc_id) {
|
||||
case 0:
|
||||
default:
|
||||
radeon_crtc->crtc_offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
|
||||
break;
|
||||
case 1:
|
||||
radeon_crtc->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
|
||||
break;
|
||||
case 2:
|
||||
radeon_crtc->crtc_offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
|
||||
break;
|
||||
case 3:
|
||||
radeon_crtc->crtc_offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
|
||||
break;
|
||||
case 4:
|
||||
radeon_crtc->crtc_offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
|
||||
break;
|
||||
case 5:
|
||||
radeon_crtc->crtc_offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (radeon_crtc->crtc_id == 1)
|
||||
radeon_crtc->crtc_offset =
|
||||
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
|
||||
else
|
||||
radeon_crtc->crtc_offset = 0;
|
||||
}
|
||||
radeon_crtc->pll_id = -1;
|
||||
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
|
||||
}
|
||||
|
|
|
@ -321,6 +321,10 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
|
|||
train_set[lane] = v | p;
|
||||
}
|
||||
|
||||
union aux_channel_transaction {
|
||||
PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
|
||||
PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
|
||||
};
|
||||
|
||||
/* radeon aux chan functions */
|
||||
bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
|
||||
|
@ -329,7 +333,7 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
|
|||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args;
|
||||
union aux_channel_transaction args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
|
||||
unsigned char *base;
|
||||
int retry_count = 0;
|
||||
|
@ -341,31 +345,33 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
|
|||
retry:
|
||||
memcpy(base, req_bytes, num_bytes);
|
||||
|
||||
args.lpAuxRequest = 0;
|
||||
args.lpDataOut = 16;
|
||||
args.ucDataOutLen = 0;
|
||||
args.ucChannelID = chan->rec.i2c_id;
|
||||
args.ucDelay = delay / 10;
|
||||
args.v1.lpAuxRequest = 0;
|
||||
args.v1.lpDataOut = 16;
|
||||
args.v1.ucDataOutLen = 0;
|
||||
args.v1.ucChannelID = chan->rec.i2c_id;
|
||||
args.v1.ucDelay = delay / 10;
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
args.v2.ucHPD_ID = chan->rec.hpd_id;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
if (args.ucReplyStatus && !args.ucDataOutLen) {
|
||||
if (args.ucReplyStatus == 0x20 && retry_count++ < 10)
|
||||
if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) {
|
||||
if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10)
|
||||
goto retry;
|
||||
DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n",
|
||||
req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],
|
||||
chan->rec.i2c_id, args.ucReplyStatus, retry_count);
|
||||
chan->rec.i2c_id, args.v1.ucReplyStatus, retry_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.ucDataOutLen && read_byte && read_buf_len) {
|
||||
if (read_buf_len < args.ucDataOutLen) {
|
||||
if (args.v1.ucDataOutLen && read_byte && read_buf_len) {
|
||||
if (read_buf_len < args.v1.ucDataOutLen) {
|
||||
DRM_ERROR("Buffer to small for return answer %d %d\n",
|
||||
read_buf_len, args.ucDataOutLen);
|
||||
read_buf_len, args.v1.ucDataOutLen);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
int len = min(read_buf_len, args.ucDataOutLen);
|
||||
int len = min(read_buf_len, args.v1.ucDataOutLen);
|
||||
memcpy(read_byte, base + 16, len);
|
||||
}
|
||||
}
|
||||
|
@ -626,12 +632,19 @@ void dp_link_train(struct drm_encoder *encoder,
|
|||
dp_set_link_bw_lanes(radeon_connector, link_configuration);
|
||||
/* disable downspread on the sink */
|
||||
dp_set_downspread(radeon_connector, 0);
|
||||
/* start training on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
/* set training pattern 1 on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
/* start training on the source */
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
|
||||
/* set training pattern 1 on the source */
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1);
|
||||
} else {
|
||||
/* start training on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
/* set training pattern 1 on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
}
|
||||
|
||||
/* set initial vs/emph */
|
||||
memset(train_set, 0, 4);
|
||||
|
@ -691,8 +704,11 @@ void dp_link_train(struct drm_encoder *encoder,
|
|||
/* set training pattern 2 on the sink */
|
||||
dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2);
|
||||
/* set training pattern 2 on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
||||
dig_connector->dp_clock, enc_id, 1);
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2);
|
||||
else
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
||||
dig_connector->dp_clock, enc_id, 1);
|
||||
|
||||
/* channel equalization loop */
|
||||
tries = 0;
|
||||
|
@ -729,7 +745,11 @@ void dp_link_train(struct drm_encoder *encoder,
|
|||
>> DP_TRAIN_PRE_EMPHASIS_SHIFT);
|
||||
|
||||
/* disable the training pattern on the sink */
|
||||
dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
|
||||
else
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
|
||||
#define D1CRTC_CONTROL 0x6080
|
||||
#define CRTC_EN (1 << 0)
|
||||
#define D1CRTC_STATUS 0x609c
|
||||
#define D1CRTC_UPDATE_LOCK 0x60E8
|
||||
#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110
|
||||
#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118
|
||||
|
||||
#define D2CRTC_CONTROL 0x6880
|
||||
#define D2CRTC_STATUS 0x689c
|
||||
#define D2CRTC_UPDATE_LOCK 0x68E8
|
||||
#define D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910
|
||||
#define D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918
|
||||
|
|
767
drivers/gpu/drm/radeon/evergreen.c
Normal file
767
drivers/gpu/drm/radeon/evergreen.c
Normal file
|
@ -0,0 +1,767 @@
|
|||
/*
|
||||
* Copyright 2010 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Alex Deucher
|
||||
*/
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "drmP.h"
|
||||
#include "radeon.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "rv770d.h"
|
||||
#include "atom.h"
|
||||
#include "avivod.h"
|
||||
#include "evergreen_reg.h"
|
||||
|
||||
static void evergreen_gpu_init(struct radeon_device *rdev);
|
||||
void evergreen_fini(struct radeon_device *rdev);
|
||||
|
||||
bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
|
||||
{
|
||||
bool connected = false;
|
||||
/* XXX */
|
||||
return connected;
|
||||
}
|
||||
|
||||
void evergreen_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
void evergreen_hpd_init(struct radeon_device *rdev)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
|
||||
void evergreen_bandwidth_update(struct radeon_device *rdev)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
void evergreen_hpd_fini(struct radeon_device *rdev)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
static int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned i;
|
||||
u32 tmp;
|
||||
|
||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||
/* read MC_STATUS */
|
||||
tmp = RREG32(SRBM_STATUS) & 0x1F00;
|
||||
if (!tmp)
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* GART
|
||||
*/
|
||||
int evergreen_pcie_gart_enable(struct radeon_device *rdev)
|
||||
{
|
||||
u32 tmp;
|
||||
int r, i;
|
||||
|
||||
if (rdev->gart.table.vram.robj == NULL) {
|
||||
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = radeon_gart_table_vram_pin(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
radeon_gart_restore(rdev);
|
||||
/* Setup L2 cache */
|
||||
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
|
||||
ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
|
||||
EFFECTIVE_L2_QUEUE_SIZE(7));
|
||||
WREG32(VM_L2_CNTL2, 0);
|
||||
WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
|
||||
/* Setup TLB control */
|
||||
tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
|
||||
SYSTEM_ACCESS_MODE_NOT_IN_SYS |
|
||||
SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
|
||||
EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
|
||||
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
|
||||
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
|
||||
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
|
||||
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
|
||||
WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
|
||||
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
|
||||
WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
|
||||
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
|
||||
WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
|
||||
(u32)(rdev->dummy_page.addr >> 12));
|
||||
for (i = 1; i < 7; i++)
|
||||
WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
|
||||
|
||||
r600_pcie_gart_tlb_flush(rdev);
|
||||
rdev->gart.ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void evergreen_pcie_gart_disable(struct radeon_device *rdev)
|
||||
{
|
||||
u32 tmp;
|
||||
int i, r;
|
||||
|
||||
/* Disable all tables */
|
||||
for (i = 0; i < 7; i++)
|
||||
WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
|
||||
|
||||
/* Setup L2 cache */
|
||||
WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING |
|
||||
EFFECTIVE_L2_QUEUE_SIZE(7));
|
||||
WREG32(VM_L2_CNTL2, 0);
|
||||
WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
|
||||
/* Setup TLB control */
|
||||
tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
|
||||
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
|
||||
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
|
||||
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
|
||||
if (rdev->gart.table.vram.robj) {
|
||||
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
|
||||
if (likely(r == 0)) {
|
||||
radeon_bo_kunmap(rdev->gart.table.vram.robj);
|
||||
radeon_bo_unpin(rdev->gart.table.vram.robj);
|
||||
radeon_bo_unreserve(rdev->gart.table.vram.robj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void evergreen_pcie_gart_fini(struct radeon_device *rdev)
|
||||
{
|
||||
evergreen_pcie_gart_disable(rdev);
|
||||
radeon_gart_table_vram_free(rdev);
|
||||
radeon_gart_fini(rdev);
|
||||
}
|
||||
|
||||
|
||||
void evergreen_agp_enable(struct radeon_device *rdev)
|
||||
{
|
||||
u32 tmp;
|
||||
int i;
|
||||
|
||||
/* Setup L2 cache */
|
||||
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
|
||||
ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
|
||||
EFFECTIVE_L2_QUEUE_SIZE(7));
|
||||
WREG32(VM_L2_CNTL2, 0);
|
||||
WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
|
||||
/* Setup TLB control */
|
||||
tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
|
||||
SYSTEM_ACCESS_MODE_NOT_IN_SYS |
|
||||
SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
|
||||
EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
|
||||
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
|
||||
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
|
||||
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
|
||||
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
|
||||
for (i = 0; i < 7; i++)
|
||||
WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
|
||||
}
|
||||
|
||||
static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
|
||||
{
|
||||
save->vga_control[0] = RREG32(D1VGA_CONTROL);
|
||||
save->vga_control[1] = RREG32(D2VGA_CONTROL);
|
||||
save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
|
||||
save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
|
||||
save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
|
||||
save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
|
||||
save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
|
||||
save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
|
||||
save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
|
||||
save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
|
||||
save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
|
||||
save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
|
||||
save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
|
||||
save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
|
||||
|
||||
/* Stop all video */
|
||||
WREG32(VGA_RENDER_CONTROL, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
|
||||
|
||||
WREG32(D1VGA_CONTROL, 0);
|
||||
WREG32(D2VGA_CONTROL, 0);
|
||||
WREG32(EVERGREEN_D3VGA_CONTROL, 0);
|
||||
WREG32(EVERGREEN_D4VGA_CONTROL, 0);
|
||||
WREG32(EVERGREEN_D5VGA_CONTROL, 0);
|
||||
WREG32(EVERGREEN_D6VGA_CONTROL, 0);
|
||||
}
|
||||
|
||||
static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
|
||||
{
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
|
||||
upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
|
||||
(u32)rdev->mc.vram_start);
|
||||
|
||||
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
|
||||
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
|
||||
/* Unlock host access */
|
||||
WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
|
||||
mdelay(1);
|
||||
/* Restore video state */
|
||||
WREG32(D1VGA_CONTROL, save->vga_control[0]);
|
||||
WREG32(D2VGA_CONTROL, save->vga_control[1]);
|
||||
WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
|
||||
WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
|
||||
WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
|
||||
WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
|
||||
WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
|
||||
}
|
||||
|
||||
static void evergreen_mc_program(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_mc_save save;
|
||||
u32 tmp;
|
||||
int i, j;
|
||||
|
||||
/* Initialize HDP */
|
||||
for (i = 0, j = 0; i < 32; i++, j += 0x18) {
|
||||
WREG32((0x2c14 + j), 0x00000000);
|
||||
WREG32((0x2c18 + j), 0x00000000);
|
||||
WREG32((0x2c1c + j), 0x00000000);
|
||||
WREG32((0x2c20 + j), 0x00000000);
|
||||
WREG32((0x2c24 + j), 0x00000000);
|
||||
}
|
||||
WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
|
||||
|
||||
evergreen_mc_stop(rdev, &save);
|
||||
if (evergreen_mc_wait_for_idle(rdev)) {
|
||||
dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
|
||||
}
|
||||
/* Lockout access through VGA aperture*/
|
||||
WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
|
||||
/* Update configuration */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
if (rdev->mc.vram_start < rdev->mc.gtt_start) {
|
||||
/* VRAM before AGP */
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
rdev->mc.vram_start >> 12);
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
|
||||
rdev->mc.gtt_end >> 12);
|
||||
} else {
|
||||
/* VRAM after AGP */
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
rdev->mc.gtt_start >> 12);
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
|
||||
rdev->mc.vram_end >> 12);
|
||||
}
|
||||
} else {
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
rdev->mc.vram_start >> 12);
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
|
||||
rdev->mc.vram_end >> 12);
|
||||
}
|
||||
WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
|
||||
tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
|
||||
tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
|
||||
WREG32(MC_VM_FB_LOCATION, tmp);
|
||||
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
|
||||
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
|
||||
WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
|
||||
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
|
||||
WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
|
||||
} else {
|
||||
WREG32(MC_VM_AGP_BASE, 0);
|
||||
WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
|
||||
WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
|
||||
}
|
||||
if (evergreen_mc_wait_for_idle(rdev)) {
|
||||
dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
|
||||
}
|
||||
evergreen_mc_resume(rdev, &save);
|
||||
/* we need to own VRAM, so turn off the VGA renderer here
|
||||
* to stop it overwriting our objects */
|
||||
rv515_vga_render_disable(rdev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* CP.
|
||||
*/
|
||||
static void evergreen_cp_stop(struct radeon_device *rdev)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
|
||||
static int evergreen_cp_load_microcode(struct radeon_device *rdev)
|
||||
{
|
||||
/* XXX */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Core functions
|
||||
*/
|
||||
static u32 evergreen_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
||||
u32 num_backends,
|
||||
u32 backend_disable_mask)
|
||||
{
|
||||
u32 backend_map = 0;
|
||||
|
||||
return backend_map;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void evergreen_gpu_init(struct radeon_device *rdev)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
int evergreen_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
fixed20_12 a;
|
||||
u32 tmp;
|
||||
int chansize, numchan;
|
||||
|
||||
/* Get VRAM informations */
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
tmp = RREG32(MC_ARB_RAMCFG);
|
||||
if (tmp & CHANSIZE_OVERRIDE) {
|
||||
chansize = 16;
|
||||
} else if (tmp & CHANSIZE_MASK) {
|
||||
chansize = 64;
|
||||
} else {
|
||||
chansize = 32;
|
||||
}
|
||||
tmp = RREG32(MC_SHARED_CHMAP);
|
||||
switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
|
||||
case 0:
|
||||
default:
|
||||
numchan = 1;
|
||||
break;
|
||||
case 1:
|
||||
numchan = 2;
|
||||
break;
|
||||
case 2:
|
||||
numchan = 4;
|
||||
break;
|
||||
case 3:
|
||||
numchan = 8;
|
||||
break;
|
||||
}
|
||||
rdev->mc.vram_width = numchan * chansize;
|
||||
/* Could aper size report 0 ? */
|
||||
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
|
||||
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
|
||||
/* Setup GPU memory space */
|
||||
/* size in MB on evergreen */
|
||||
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
|
||||
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
|
||||
rdev->mc.visible_vram_size = rdev->mc.aper_size;
|
||||
/* FIXME remove this once we support unmappable VRAM */
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
|
||||
rdev->mc.mc_vram_size = rdev->mc.aper_size;
|
||||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
}
|
||||
r600_vram_gtt_location(rdev, &rdev->mc);
|
||||
/* FIXME: we should enforce default clock in case GPU is not in
|
||||
* default setup
|
||||
*/
|
||||
a.full = rfixed_const(100);
|
||||
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
|
||||
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int evergreen_gpu_reset(struct radeon_device *rdev)
|
||||
{
|
||||
/* FIXME: implement for evergreen */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int evergreen_startup(struct radeon_device *rdev)
|
||||
{
|
||||
#if 0
|
||||
int r;
|
||||
|
||||
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
|
||||
r = r600_init_microcode(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to load firmware!\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
evergreen_mc_program(rdev);
|
||||
#if 0
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
evergreem_agp_enable(rdev);
|
||||
} else {
|
||||
r = evergreen_pcie_gart_enable(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
evergreen_gpu_init(rdev);
|
||||
#if 0
|
||||
if (!rdev->r600_blit.shader_obj) {
|
||||
r = r600_blit_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failed blitter (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
|
||||
&rdev->r600_blit.shader_gpu_addr);
|
||||
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to pin blit object %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Enable IRQ */
|
||||
r = r600_irq_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: IH init failed (%d).\n", r);
|
||||
radeon_irq_kms_fini(rdev);
|
||||
return r;
|
||||
}
|
||||
r600_irq_set(rdev);
|
||||
|
||||
r = radeon_ring_init(rdev, rdev->cp.ring_size);
|
||||
if (r)
|
||||
return r;
|
||||
r = evergreen_cp_load_microcode(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
r = r600_cp_resume(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* write back buffer are not vital so don't worry about failure */
|
||||
r600_wb_enable(rdev);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int evergreen_resume(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
|
||||
* posting will perform necessary task to bring back GPU into good
|
||||
* shape.
|
||||
*/
|
||||
/* post card */
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
/* Initialize clocks */
|
||||
r = radeon_clocks_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = evergreen_startup(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("r600 startup failed on resume\n");
|
||||
return r;
|
||||
}
|
||||
#if 0
|
||||
r = r600_ib_test(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failled testing IB (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int evergreen_suspend(struct radeon_device *rdev)
|
||||
{
|
||||
#if 0
|
||||
int r;
|
||||
|
||||
/* FIXME: we should wait for ring to be empty */
|
||||
r700_cp_stop(rdev);
|
||||
rdev->cp.ready = false;
|
||||
r600_wb_disable(rdev);
|
||||
evergreen_pcie_gart_disable(rdev);
|
||||
/* unpin shaders bo */
|
||||
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
|
||||
if (likely(r == 0)) {
|
||||
radeon_bo_unpin(rdev->r600_blit.shader_obj);
|
||||
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool evergreen_card_posted(struct radeon_device *rdev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* first check CRTCs */
|
||||
reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
|
||||
if (reg & EVERGREEN_CRTC_MASTER_EN)
|
||||
return true;
|
||||
|
||||
/* then check MEM_SIZE, in case the crtcs are off */
|
||||
if (RREG32(CONFIG_MEMSIZE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Plan is to move initialization in that function and use
|
||||
* helper function so that radeon_device_init pretty much
|
||||
* do nothing more than calling asic specific function. This
|
||||
* should also allow to remove a bunch of callback function
|
||||
* like vram_info.
|
||||
*/
|
||||
int evergreen_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = radeon_dummy_page_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* This don't do much */
|
||||
r = radeon_gem_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* Read BIOS */
|
||||
if (!radeon_get_bios(rdev)) {
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Must be an ATOMBIOS */
|
||||
if (!rdev->is_atom_bios) {
|
||||
dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = radeon_atombios_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* Post card if necessary */
|
||||
if (!evergreen_card_posted(rdev)) {
|
||||
if (!rdev->bios) {
|
||||
dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DRM_INFO("GPU not posted. posting now...\n");
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
}
|
||||
/* Initialize scratch registers */
|
||||
r600_scratch_init(rdev);
|
||||
/* Initialize surface registers */
|
||||
radeon_surface_init(rdev);
|
||||
/* Initialize clocks */
|
||||
radeon_get_clock_info(rdev->ddev);
|
||||
r = radeon_clocks_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r)
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
/* initialize memory controller */
|
||||
r = evergreen_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* Memory manager */
|
||||
r = radeon_bo_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
#if 0
|
||||
r = radeon_irq_kms_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
rdev->cp.ring_obj = NULL;
|
||||
r600_ring_init(rdev, 1024 * 1024);
|
||||
|
||||
rdev->ih.ring_obj = NULL;
|
||||
r600_ih_ring_init(rdev, 64 * 1024);
|
||||
|
||||
r = r600_pcie_gart_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
#endif
|
||||
rdev->accel_working = false;
|
||||
r = evergreen_startup(rdev);
|
||||
if (r) {
|
||||
evergreen_suspend(rdev);
|
||||
/*r600_wb_fini(rdev);*/
|
||||
/*radeon_ring_fini(rdev);*/
|
||||
/*evergreen_pcie_gart_fini(rdev);*/
|
||||
rdev->accel_working = false;
|
||||
}
|
||||
if (rdev->accel_working) {
|
||||
r = radeon_ib_pool_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
|
||||
rdev->accel_working = false;
|
||||
}
|
||||
r = r600_ib_test(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failed testing IB (%d).\n", r);
|
||||
rdev->accel_working = false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void evergreen_fini(struct radeon_device *rdev)
|
||||
{
|
||||
evergreen_suspend(rdev);
|
||||
#if 0
|
||||
r600_blit_fini(rdev);
|
||||
r600_irq_fini(rdev);
|
||||
radeon_irq_kms_fini(rdev);
|
||||
radeon_ring_fini(rdev);
|
||||
r600_wb_fini(rdev);
|
||||
evergreen_pcie_gart_fini(rdev);
|
||||
#endif
|
||||
radeon_gem_fini(rdev);
|
||||
radeon_fence_driver_fini(rdev);
|
||||
radeon_clocks_fini(rdev);
|
||||
radeon_agp_fini(rdev);
|
||||
radeon_bo_fini(rdev);
|
||||
radeon_atombios_fini(rdev);
|
||||
kfree(rdev->bios);
|
||||
rdev->bios = NULL;
|
||||
radeon_dummy_page_fini(rdev);
|
||||
}
|
176
drivers/gpu/drm/radeon/evergreen_reg.h
Normal file
176
drivers/gpu/drm/radeon/evergreen_reg.h
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright 2010 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Alex Deucher
|
||||
*/
|
||||
#ifndef __EVERGREEN_REG_H__
|
||||
#define __EVERGREEN_REG_H__
|
||||
|
||||
/* evergreen */
|
||||
#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310
|
||||
#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324
|
||||
#define EVERGREEN_D3VGA_CONTROL 0x3e0
|
||||
#define EVERGREEN_D4VGA_CONTROL 0x3e4
|
||||
#define EVERGREEN_D5VGA_CONTROL 0x3e8
|
||||
#define EVERGREEN_D6VGA_CONTROL 0x3ec
|
||||
|
||||
#define EVERGREEN_P1PLL_SS_CNTL 0x414
|
||||
#define EVERGREEN_P2PLL_SS_CNTL 0x454
|
||||
# define EVERGREEN_PxPLL_SS_EN (1 << 12)
|
||||
/* GRPH blocks at 0x6800, 0x7400, 0x10000, 0x10c00, 0x11800, 0x12400 */
|
||||
#define EVERGREEN_GRPH_ENABLE 0x6800
|
||||
#define EVERGREEN_GRPH_CONTROL 0x6804
|
||||
# define EVERGREEN_GRPH_DEPTH(x) (((x) & 0x3) << 0)
|
||||
# define EVERGREEN_GRPH_DEPTH_8BPP 0
|
||||
# define EVERGREEN_GRPH_DEPTH_16BPP 1
|
||||
# define EVERGREEN_GRPH_DEPTH_32BPP 2
|
||||
# define EVERGREEN_GRPH_FORMAT(x) (((x) & 0x7) << 8)
|
||||
/* 8 BPP */
|
||||
# define EVERGREEN_GRPH_FORMAT_INDEXED 0
|
||||
/* 16 BPP */
|
||||
# define EVERGREEN_GRPH_FORMAT_ARGB1555 0
|
||||
# define EVERGREEN_GRPH_FORMAT_ARGB565 1
|
||||
# define EVERGREEN_GRPH_FORMAT_ARGB4444 2
|
||||
# define EVERGREEN_GRPH_FORMAT_AI88 3
|
||||
# define EVERGREEN_GRPH_FORMAT_MONO16 4
|
||||
# define EVERGREEN_GRPH_FORMAT_BGRA5551 5
|
||||
/* 32 BPP */
|
||||
# define EVERGREEN_GRPH_FORMAT_ARGB8888 0
|
||||
# define EVERGREEN_GRPH_FORMAT_ARGB2101010 1
|
||||
# define EVERGREEN_GRPH_FORMAT_32BPP_DIG 2
|
||||
# define EVERGREEN_GRPH_FORMAT_8B_ARGB2101010 3
|
||||
# define EVERGREEN_GRPH_FORMAT_BGRA1010102 4
|
||||
# define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102 5
|
||||
# define EVERGREEN_GRPH_FORMAT_RGB111110 6
|
||||
# define EVERGREEN_GRPH_FORMAT_BGR101111 7
|
||||
#define EVERGREEN_GRPH_SWAP_CONTROL 0x680c
|
||||
# define EVERGREEN_GRPH_ENDIAN_SWAP(x) (((x) & 0x3) << 0)
|
||||
# define EVERGREEN_GRPH_ENDIAN_NONE 0
|
||||
# define EVERGREEN_GRPH_ENDIAN_8IN16 1
|
||||
# define EVERGREEN_GRPH_ENDIAN_8IN32 2
|
||||
# define EVERGREEN_GRPH_ENDIAN_8IN64 3
|
||||
# define EVERGREEN_GRPH_RED_CROSSBAR(x) (((x) & 0x3) << 4)
|
||||
# define EVERGREEN_GRPH_RED_SEL_R 0
|
||||
# define EVERGREEN_GRPH_RED_SEL_G 1
|
||||
# define EVERGREEN_GRPH_RED_SEL_B 2
|
||||
# define EVERGREEN_GRPH_RED_SEL_A 3
|
||||
# define EVERGREEN_GRPH_GREEN_CROSSBAR(x) (((x) & 0x3) << 6)
|
||||
# define EVERGREEN_GRPH_GREEN_SEL_G 0
|
||||
# define EVERGREEN_GRPH_GREEN_SEL_B 1
|
||||
# define EVERGREEN_GRPH_GREEN_SEL_A 2
|
||||
# define EVERGREEN_GRPH_GREEN_SEL_R 3
|
||||
# define EVERGREEN_GRPH_BLUE_CROSSBAR(x) (((x) & 0x3) << 8)
|
||||
# define EVERGREEN_GRPH_BLUE_SEL_B 0
|
||||
# define EVERGREEN_GRPH_BLUE_SEL_A 1
|
||||
# define EVERGREEN_GRPH_BLUE_SEL_R 2
|
||||
# define EVERGREEN_GRPH_BLUE_SEL_G 3
|
||||
# define EVERGREEN_GRPH_ALPHA_CROSSBAR(x) (((x) & 0x3) << 10)
|
||||
# define EVERGREEN_GRPH_ALPHA_SEL_A 0
|
||||
# define EVERGREEN_GRPH_ALPHA_SEL_R 1
|
||||
# define EVERGREEN_GRPH_ALPHA_SEL_G 2
|
||||
# define EVERGREEN_GRPH_ALPHA_SEL_B 3
|
||||
#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS 0x6810
|
||||
#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS 0x6814
|
||||
# define EVERGREEN_GRPH_DFQ_ENABLE (1 << 0)
|
||||
# define EVERGREEN_GRPH_SURFACE_ADDRESS_MASK 0xffffff00
|
||||
#define EVERGREEN_GRPH_PITCH 0x6818
|
||||
#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x681c
|
||||
#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x6820
|
||||
#define EVERGREEN_GRPH_SURFACE_OFFSET_X 0x6824
|
||||
#define EVERGREEN_GRPH_SURFACE_OFFSET_Y 0x6828
|
||||
#define EVERGREEN_GRPH_X_START 0x682c
|
||||
#define EVERGREEN_GRPH_Y_START 0x6830
|
||||
#define EVERGREEN_GRPH_X_END 0x6834
|
||||
#define EVERGREEN_GRPH_Y_END 0x6838
|
||||
|
||||
/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */
|
||||
#define EVERGREEN_CUR_CONTROL 0x6998
|
||||
# define EVERGREEN_CURSOR_EN (1 << 0)
|
||||
# define EVERGREEN_CURSOR_MODE(x) (((x) & 0x3) << 8)
|
||||
# define EVERGREEN_CURSOR_MONO 0
|
||||
# define EVERGREEN_CURSOR_24_1 1
|
||||
# define EVERGREEN_CURSOR_24_8_PRE_MULT 2
|
||||
# define EVERGREEN_CURSOR_24_8_UNPRE_MULT 3
|
||||
# define EVERGREEN_CURSOR_2X_MAGNIFY (1 << 16)
|
||||
# define EVERGREEN_CURSOR_FORCE_MC_ON (1 << 20)
|
||||
# define EVERGREEN_CURSOR_URGENT_CONTROL(x) (((x) & 0x7) << 24)
|
||||
# define EVERGREEN_CURSOR_URGENT_ALWAYS 0
|
||||
# define EVERGREEN_CURSOR_URGENT_1_8 1
|
||||
# define EVERGREEN_CURSOR_URGENT_1_4 2
|
||||
# define EVERGREEN_CURSOR_URGENT_3_8 3
|
||||
# define EVERGREEN_CURSOR_URGENT_1_2 4
|
||||
#define EVERGREEN_CUR_SURFACE_ADDRESS 0x699c
|
||||
# define EVERGREEN_CUR_SURFACE_ADDRESS_MASK 0xfffff000
|
||||
#define EVERGREEN_CUR_SIZE 0x69a0
|
||||
#define EVERGREEN_CUR_SURFACE_ADDRESS_HIGH 0x69a4
|
||||
#define EVERGREEN_CUR_POSITION 0x69a8
|
||||
#define EVERGREEN_CUR_HOT_SPOT 0x69ac
|
||||
#define EVERGREEN_CUR_COLOR1 0x69b0
|
||||
#define EVERGREEN_CUR_COLOR2 0x69b4
|
||||
#define EVERGREEN_CUR_UPDATE 0x69b8
|
||||
# define EVERGREEN_CURSOR_UPDATE_PENDING (1 << 0)
|
||||
# define EVERGREEN_CURSOR_UPDATE_TAKEN (1 << 1)
|
||||
# define EVERGREEN_CURSOR_UPDATE_LOCK (1 << 16)
|
||||
# define EVERGREEN_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24)
|
||||
|
||||
/* LUT blocks at 0x69e0, 0x75e0, 0x101e0, 0x10de0, 0x119e0, 0x125e0 */
|
||||
#define EVERGREEN_DC_LUT_RW_MODE 0x69e0
|
||||
#define EVERGREEN_DC_LUT_RW_INDEX 0x69e4
|
||||
#define EVERGREEN_DC_LUT_SEQ_COLOR 0x69e8
|
||||
#define EVERGREEN_DC_LUT_PWL_DATA 0x69ec
|
||||
#define EVERGREEN_DC_LUT_30_COLOR 0x69f0
|
||||
#define EVERGREEN_DC_LUT_VGA_ACCESS_ENABLE 0x69f4
|
||||
#define EVERGREEN_DC_LUT_WRITE_EN_MASK 0x69f8
|
||||
#define EVERGREEN_DC_LUT_AUTOFILL 0x69fc
|
||||
#define EVERGREEN_DC_LUT_CONTROL 0x6a00
|
||||
#define EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE 0x6a04
|
||||
#define EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN 0x6a08
|
||||
#define EVERGREEN_DC_LUT_BLACK_OFFSET_RED 0x6a0c
|
||||
#define EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE 0x6a10
|
||||
#define EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN 0x6a14
|
||||
#define EVERGREEN_DC_LUT_WHITE_OFFSET_RED 0x6a18
|
||||
|
||||
#define EVERGREEN_DATA_FORMAT 0x6b00
|
||||
# define EVERGREEN_INTERLEAVE_EN (1 << 0)
|
||||
#define EVERGREEN_DESKTOP_HEIGHT 0x6b04
|
||||
|
||||
#define EVERGREEN_VIEWPORT_START 0x6d70
|
||||
#define EVERGREEN_VIEWPORT_SIZE 0x6d74
|
||||
|
||||
/* display controller offsets used for crtc/cur/lut/grph/viewport/etc. */
|
||||
#define EVERGREEN_CRTC0_REGISTER_OFFSET (0x6df0 - 0x6df0)
|
||||
#define EVERGREEN_CRTC1_REGISTER_OFFSET (0x79f0 - 0x6df0)
|
||||
#define EVERGREEN_CRTC2_REGISTER_OFFSET (0x105f0 - 0x6df0)
|
||||
#define EVERGREEN_CRTC3_REGISTER_OFFSET (0x111f0 - 0x6df0)
|
||||
#define EVERGREEN_CRTC4_REGISTER_OFFSET (0x11df0 - 0x6df0)
|
||||
#define EVERGREEN_CRTC5_REGISTER_OFFSET (0x129f0 - 0x6df0)
|
||||
|
||||
/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */
|
||||
#define EVERGREEN_CRTC_CONTROL 0x6e70
|
||||
# define EVERGREEN_CRTC_MASTER_EN (1 << 0)
|
||||
#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4
|
||||
|
||||
#define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0
|
||||
#define EVERGREEN_DC_GPIO_HPD_A 0x64b4
|
||||
#define EVERGREEN_DC_GPIO_HPD_EN 0x64b8
|
||||
#define EVERGREEN_DC_GPIO_HPD_Y 0x64bc
|
||||
|
||||
#endif
|
|
@ -197,13 +197,13 @@ int r100_pci_gart_enable(struct radeon_device *rdev)
|
|||
{
|
||||
uint32_t tmp;
|
||||
|
||||
radeon_gart_restore(rdev);
|
||||
/* discard memory request outside of configured range */
|
||||
tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
|
||||
WREG32(RADEON_AIC_CNTL, tmp);
|
||||
/* set address range for PCI address translate */
|
||||
WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location);
|
||||
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
|
||||
WREG32(RADEON_AIC_HI_ADDR, tmp);
|
||||
WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_start);
|
||||
WREG32(RADEON_AIC_HI_ADDR, rdev->mc.gtt_end);
|
||||
/* set PCI GART page-table base address */
|
||||
WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr);
|
||||
tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
|
||||
|
@ -312,9 +312,11 @@ int r100_irq_process(struct radeon_device *rdev)
|
|||
/* Vertical blank interrupts */
|
||||
if (status & RADEON_CRTC_VBLANK_STAT) {
|
||||
drm_handle_vblank(rdev->ddev, 0);
|
||||
wake_up(&rdev->irq.vblank_queue);
|
||||
}
|
||||
if (status & RADEON_CRTC2_VBLANK_STAT) {
|
||||
drm_handle_vblank(rdev->ddev, 1);
|
||||
wake_up(&rdev->irq.vblank_queue);
|
||||
}
|
||||
if (status & RADEON_FP_DETECT_STAT) {
|
||||
queue_hotplug = true;
|
||||
|
@ -366,8 +368,8 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
|
|||
radeon_ring_write(rdev, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));
|
||||
radeon_ring_write(rdev, RADEON_RB3D_ZC_FLUSH_ALL);
|
||||
/* Wait until IDLE & CLEAN */
|
||||
radeon_ring_write(rdev, PACKET0(0x1720, 0));
|
||||
radeon_ring_write(rdev, (1 << 16) | (1 << 17));
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||
radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
|
||||
radeon_ring_write(rdev, rdev->config.r100.hdp_cntl |
|
||||
RADEON_HDP_READ_BUFFER_INVALIDATE);
|
||||
|
@ -1701,7 +1703,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev)
|
|||
}
|
||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||
tmp = RREG32(RADEON_RBBM_STATUS);
|
||||
if (!(tmp & (1 << 31))) {
|
||||
if (!(tmp & RADEON_RBBM_ACTIVE)) {
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
|
@ -1716,8 +1718,8 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
|
|||
|
||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||
/* read MC_STATUS */
|
||||
tmp = RREG32(0x0150);
|
||||
if (tmp & (1 << 2)) {
|
||||
tmp = RREG32(RADEON_MC_STATUS);
|
||||
if (tmp & RADEON_MC_IDLE) {
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
|
@ -1790,7 +1792,7 @@ int r100_gpu_reset(struct radeon_device *rdev)
|
|||
}
|
||||
/* Check if GPU is idle */
|
||||
status = RREG32(RADEON_RBBM_STATUS);
|
||||
if (status & (1 << 31)) {
|
||||
if (status & RADEON_RBBM_ACTIVE) {
|
||||
DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1800,6 +1802,9 @@ int r100_gpu_reset(struct radeon_device *rdev)
|
|||
|
||||
void r100_set_common_regs(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
bool force_dac2 = false;
|
||||
|
||||
/* set these so they don't interfere with anything */
|
||||
WREG32(RADEON_OV0_SCALE_CNTL, 0);
|
||||
WREG32(RADEON_SUBPIC_CNTL, 0);
|
||||
|
@ -1808,6 +1813,68 @@ void r100_set_common_regs(struct radeon_device *rdev)
|
|||
WREG32(RADEON_DVI_I2C_CNTL_1, 0);
|
||||
WREG32(RADEON_CAP0_TRIG_CNTL, 0);
|
||||
WREG32(RADEON_CAP1_TRIG_CNTL, 0);
|
||||
|
||||
/* always set up dac2 on rn50 and some rv100 as lots
|
||||
* of servers seem to wire it up to a VGA port but
|
||||
* don't report it in the bios connector
|
||||
* table.
|
||||
*/
|
||||
switch (dev->pdev->device) {
|
||||
/* RN50 */
|
||||
case 0x515e:
|
||||
case 0x5969:
|
||||
force_dac2 = true;
|
||||
break;
|
||||
/* RV100*/
|
||||
case 0x5159:
|
||||
case 0x515a:
|
||||
/* DELL triple head servers */
|
||||
if ((dev->pdev->subsystem_vendor == 0x1028 /* DELL */) &&
|
||||
((dev->pdev->subsystem_device == 0x016c) ||
|
||||
(dev->pdev->subsystem_device == 0x016d) ||
|
||||
(dev->pdev->subsystem_device == 0x016e) ||
|
||||
(dev->pdev->subsystem_device == 0x016f) ||
|
||||
(dev->pdev->subsystem_device == 0x0170) ||
|
||||
(dev->pdev->subsystem_device == 0x017d) ||
|
||||
(dev->pdev->subsystem_device == 0x017e) ||
|
||||
(dev->pdev->subsystem_device == 0x0183) ||
|
||||
(dev->pdev->subsystem_device == 0x018a) ||
|
||||
(dev->pdev->subsystem_device == 0x019a)))
|
||||
force_dac2 = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (force_dac2) {
|
||||
u32 disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
|
||||
u32 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
u32 dac2_cntl = RREG32(RADEON_DAC_CNTL2);
|
||||
|
||||
/* For CRT on DAC2, don't turn it on if BIOS didn't
|
||||
enable it, even it's detected.
|
||||
*/
|
||||
|
||||
/* force it to crtc0 */
|
||||
dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
|
||||
dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
|
||||
disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
|
||||
|
||||
/* set up the TV DAC */
|
||||
tv_dac_cntl &= ~(RADEON_TV_DAC_PEDESTAL |
|
||||
RADEON_TV_DAC_STD_MASK |
|
||||
RADEON_TV_DAC_RDACPD |
|
||||
RADEON_TV_DAC_GDACPD |
|
||||
RADEON_TV_DAC_BDACPD |
|
||||
RADEON_TV_DAC_BGADJ_MASK |
|
||||
RADEON_TV_DAC_DACADJ_MASK);
|
||||
tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
|
||||
RADEON_TV_DAC_NHOLD |
|
||||
RADEON_TV_DAC_STD_PS2 |
|
||||
(0x58 << 16));
|
||||
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1889,17 +1956,20 @@ static u32 r100_get_accessible_vram(struct radeon_device *rdev)
|
|||
void r100_vram_init_sizes(struct radeon_device *rdev)
|
||||
{
|
||||
u64 config_aper_size;
|
||||
u32 accessible;
|
||||
|
||||
/* work out accessible VRAM */
|
||||
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
|
||||
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
|
||||
rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev);
|
||||
/* FIXME we don't use the second aperture yet when we could use it */
|
||||
if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.visible_vram_size = rdev->mc.aper_size;
|
||||
config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
|
||||
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
uint32_t tom;
|
||||
/* read NB_TOM to get the amount of ram stolen for the GPU */
|
||||
tom = RREG32(RADEON_NB_TOM);
|
||||
rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
|
||||
/* for IGPs we need to keep VRAM where it was put by the BIOS */
|
||||
rdev->mc.vram_location = (tom & 0xffff) << 16;
|
||||
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
|
||||
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
|
||||
} else {
|
||||
|
@ -1911,30 +1981,19 @@ void r100_vram_init_sizes(struct radeon_device *rdev)
|
|||
rdev->mc.real_vram_size = 8192 * 1024;
|
||||
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
|
||||
}
|
||||
/* let driver place VRAM */
|
||||
rdev->mc.vram_location = 0xFFFFFFFFUL;
|
||||
/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM -
|
||||
* Novell bug 204882 + along with lots of ubuntu ones */
|
||||
/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM -
|
||||
* Novell bug 204882 + along with lots of ubuntu ones
|
||||
*/
|
||||
if (config_aper_size > rdev->mc.real_vram_size)
|
||||
rdev->mc.mc_vram_size = config_aper_size;
|
||||
else
|
||||
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
|
||||
}
|
||||
|
||||
/* work out accessible VRAM */
|
||||
accessible = r100_get_accessible_vram(rdev);
|
||||
|
||||
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
|
||||
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
|
||||
|
||||
if (accessible > rdev->mc.aper_size)
|
||||
accessible = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
|
||||
/* FIXME remove this once we support unmappable VRAM */
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
|
||||
rdev->mc.mc_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
}
|
||||
}
|
||||
|
||||
void r100_vga_set_state(struct radeon_device *rdev, bool state)
|
||||
|
@ -1951,11 +2010,18 @@ void r100_vga_set_state(struct radeon_device *rdev, bool state)
|
|||
WREG32(RADEON_CONFIG_CNTL, temp);
|
||||
}
|
||||
|
||||
void r100_vram_info(struct radeon_device *rdev)
|
||||
void r100_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
r100_vram_get_type(rdev);
|
||||
u64 base;
|
||||
|
||||
r100_vram_get_type(rdev);
|
||||
r100_vram_init_sizes(rdev);
|
||||
base = rdev->mc.aper_base;
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
if (!(rdev->flags & RADEON_IS_AGP))
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3226,10 +3292,9 @@ void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save)
|
|||
void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save)
|
||||
{
|
||||
/* Update base address for crtc */
|
||||
WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location);
|
||||
WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_start);
|
||||
if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
|
||||
WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR,
|
||||
rdev->mc.vram_location);
|
||||
WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, rdev->mc.vram_start);
|
||||
}
|
||||
/* Restore CRTC registers */
|
||||
WREG8(R_0003C2_GENMO_WT, save->GENMO_WT);
|
||||
|
@ -3390,32 +3455,6 @@ void r100_fini(struct radeon_device *rdev)
|
|||
rdev->bios = NULL;
|
||||
}
|
||||
|
||||
int r100_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
u32 tmp;
|
||||
|
||||
/* Setup GPU memory space */
|
||||
rdev->mc.vram_location = 0xFFFFFFFFUL;
|
||||
rdev->mc.gtt_location = 0xFFFFFFFFUL;
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
|
||||
rdev->mc.vram_location = tmp << 16;
|
||||
}
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
} else {
|
||||
rdev->mc.gtt_location = rdev->mc.agp_base;
|
||||
}
|
||||
}
|
||||
r = radeon_mc_setup(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r100_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
@ -3458,12 +3497,15 @@ int r100_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
r100_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = r100_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
}
|
||||
/* initialize VRAM */
|
||||
r100_mc_init(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
|
||||
#include "r100d.h"
|
||||
#include "r200_reg_safe.h"
|
||||
|
||||
#include "r100_track.h"
|
||||
|
@ -79,6 +80,51 @@ static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
|
|||
return vtx_size;
|
||||
}
|
||||
|
||||
int r200_copy_dma(struct radeon_device *rdev,
|
||||
uint64_t src_offset,
|
||||
uint64_t dst_offset,
|
||||
unsigned num_pages,
|
||||
struct radeon_fence *fence)
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t cur_size;
|
||||
int i, num_loops;
|
||||
int r = 0;
|
||||
|
||||
/* radeon pitch is /64 */
|
||||
size = num_pages << PAGE_SHIFT;
|
||||
num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
|
||||
r = radeon_ring_lock(rdev, num_loops * 4 + 64);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: moving bo (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
/* Must wait for 2D idle & clean before DMA or hangs might happen */
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||
radeon_ring_write(rdev, (1 << 16));
|
||||
for (i = 0; i < num_loops; i++) {
|
||||
cur_size = size;
|
||||
if (cur_size > 0x1FFFFF) {
|
||||
cur_size = 0x1FFFFF;
|
||||
}
|
||||
size -= cur_size;
|
||||
radeon_ring_write(rdev, PACKET0(0x720, 2));
|
||||
radeon_ring_write(rdev, src_offset);
|
||||
radeon_ring_write(rdev, dst_offset);
|
||||
radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30));
|
||||
src_offset += cur_size;
|
||||
dst_offset += cur_size;
|
||||
}
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||
radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
|
||||
if (fence) {
|
||||
r = radeon_fence_emit(rdev, fence);
|
||||
}
|
||||
radeon_ring_unlock_commit(rdev);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
|
||||
{
|
||||
int vtx_size, i, tex_size;
|
||||
|
|
|
@ -117,18 +117,19 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
|
|||
r = radeon_gart_table_vram_pin(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
radeon_gart_restore(rdev);
|
||||
/* discard memory request outside of configured range */
|
||||
tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location);
|
||||
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - RADEON_GPU_PAGE_SIZE;
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start);
|
||||
tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK;
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
|
||||
table_addr = rdev->gart.table_addr;
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr);
|
||||
/* FIXME: setup default page */
|
||||
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location);
|
||||
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start);
|
||||
WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
|
||||
/* Clear error */
|
||||
WREG32_PCIE(0x18, 0);
|
||||
|
@ -174,18 +175,20 @@ void r300_fence_ring_emit(struct radeon_device *rdev,
|
|||
/* Who ever call radeon_fence_emit should call ring_lock and ask
|
||||
* for enough space (today caller are ib schedule and buffer move) */
|
||||
/* Write SC register so SC & US assert idle */
|
||||
radeon_ring_write(rdev, PACKET0(0x43E0, 0));
|
||||
radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_TL, 0));
|
||||
radeon_ring_write(rdev, 0);
|
||||
radeon_ring_write(rdev, PACKET0(0x43E4, 0));
|
||||
radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_BR, 0));
|
||||
radeon_ring_write(rdev, 0);
|
||||
/* Flush 3D cache */
|
||||
radeon_ring_write(rdev, PACKET0(0x4E4C, 0));
|
||||
radeon_ring_write(rdev, (2 << 0));
|
||||
radeon_ring_write(rdev, PACKET0(0x4F18, 0));
|
||||
radeon_ring_write(rdev, (1 << 0));
|
||||
radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||
radeon_ring_write(rdev, R300_RB3D_DC_FLUSH);
|
||||
radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
|
||||
radeon_ring_write(rdev, R300_ZC_FLUSH);
|
||||
/* Wait until IDLE & CLEAN */
|
||||
radeon_ring_write(rdev, PACKET0(0x1720, 0));
|
||||
radeon_ring_write(rdev, (1 << 17) | (1 << 16) | (1 << 9));
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||
radeon_ring_write(rdev, (RADEON_WAIT_3D_IDLECLEAN |
|
||||
RADEON_WAIT_2D_IDLECLEAN |
|
||||
RADEON_WAIT_DMA_GUI_IDLE));
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
|
||||
radeon_ring_write(rdev, rdev->config.r300.hdp_cntl |
|
||||
RADEON_HDP_READ_BUFFER_INVALIDATE);
|
||||
|
@ -198,50 +201,6 @@ void r300_fence_ring_emit(struct radeon_device *rdev,
|
|||
radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
|
||||
}
|
||||
|
||||
int r300_copy_dma(struct radeon_device *rdev,
|
||||
uint64_t src_offset,
|
||||
uint64_t dst_offset,
|
||||
unsigned num_pages,
|
||||
struct radeon_fence *fence)
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t cur_size;
|
||||
int i, num_loops;
|
||||
int r = 0;
|
||||
|
||||
/* radeon pitch is /64 */
|
||||
size = num_pages << PAGE_SHIFT;
|
||||
num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
|
||||
r = radeon_ring_lock(rdev, num_loops * 4 + 64);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: moving bo (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
/* Must wait for 2D idle & clean before DMA or hangs might happen */
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 ));
|
||||
radeon_ring_write(rdev, (1 << 16));
|
||||
for (i = 0; i < num_loops; i++) {
|
||||
cur_size = size;
|
||||
if (cur_size > 0x1FFFFF) {
|
||||
cur_size = 0x1FFFFF;
|
||||
}
|
||||
size -= cur_size;
|
||||
radeon_ring_write(rdev, PACKET0(0x720, 2));
|
||||
radeon_ring_write(rdev, src_offset);
|
||||
radeon_ring_write(rdev, dst_offset);
|
||||
radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30));
|
||||
src_offset += cur_size;
|
||||
dst_offset += cur_size;
|
||||
}
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||
radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
|
||||
if (fence) {
|
||||
r = radeon_fence_emit(rdev, fence);
|
||||
}
|
||||
radeon_ring_unlock_commit(rdev);
|
||||
return r;
|
||||
}
|
||||
|
||||
void r300_ring_start(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned gb_tile_config;
|
||||
|
@ -281,8 +240,8 @@ void r300_ring_start(struct radeon_device *rdev)
|
|||
radeon_ring_write(rdev,
|
||||
RADEON_WAIT_2D_IDLECLEAN |
|
||||
RADEON_WAIT_3D_IDLECLEAN);
|
||||
radeon_ring_write(rdev, PACKET0(0x170C, 0));
|
||||
radeon_ring_write(rdev, 1 << 31);
|
||||
radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0));
|
||||
radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG);
|
||||
radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0));
|
||||
radeon_ring_write(rdev, 0);
|
||||
radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0));
|
||||
|
@ -349,8 +308,8 @@ int r300_mc_wait_for_idle(struct radeon_device *rdev)
|
|||
|
||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||
/* read MC_STATUS */
|
||||
tmp = RREG32(0x0150);
|
||||
if (tmp & (1 << 4)) {
|
||||
tmp = RREG32(RADEON_MC_STATUS);
|
||||
if (tmp & R300_MC_IDLE) {
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
|
@ -395,8 +354,8 @@ void r300_gpu_init(struct radeon_device *rdev)
|
|||
"programming pipes. Bad things might happen.\n");
|
||||
}
|
||||
|
||||
tmp = RREG32(0x170C);
|
||||
WREG32(0x170C, tmp | (1 << 31));
|
||||
tmp = RREG32(R300_DST_PIPE_CONFIG);
|
||||
WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG);
|
||||
|
||||
WREG32(R300_RB2D_DSTCACHE_MODE,
|
||||
R300_DC_AUTOFLUSH_ENABLE |
|
||||
|
@ -437,8 +396,8 @@ int r300_ga_reset(struct radeon_device *rdev)
|
|||
/* GA still busy soft reset it */
|
||||
WREG32(0x429C, 0x200);
|
||||
WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
|
||||
WREG32(0x43E0, 0);
|
||||
WREG32(0x43E4, 0);
|
||||
WREG32(R300_RE_SCISSORS_TL, 0);
|
||||
WREG32(R300_RE_SCISSORS_BR, 0);
|
||||
WREG32(0x24AC, 0);
|
||||
}
|
||||
/* Wait to prevent race in RBBM_STATUS */
|
||||
|
@ -488,7 +447,7 @@ int r300_gpu_reset(struct radeon_device *rdev)
|
|||
}
|
||||
/* Check if GPU is idle */
|
||||
status = RREG32(RADEON_RBBM_STATUS);
|
||||
if (status & (1 << 31)) {
|
||||
if (status & RADEON_RBBM_ACTIVE) {
|
||||
DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
@ -500,13 +459,13 @@ int r300_gpu_reset(struct radeon_device *rdev)
|
|||
/*
|
||||
* r300,r350,rv350,rv380 VRAM info
|
||||
*/
|
||||
void r300_vram_info(struct radeon_device *rdev)
|
||||
void r300_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
u64 base;
|
||||
u32 tmp;
|
||||
|
||||
/* DDR for all card after R300 & IGP */
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
|
||||
tmp = RREG32(RADEON_MEM_CNTL);
|
||||
tmp &= R300_MEM_NUM_CHANNELS_MASK;
|
||||
switch (tmp) {
|
||||
|
@ -515,8 +474,13 @@ void r300_vram_info(struct radeon_device *rdev)
|
|||
case 2: rdev->mc.vram_width = 256; break;
|
||||
default: rdev->mc.vram_width = 128; break;
|
||||
}
|
||||
|
||||
r100_vram_init_sizes(rdev);
|
||||
base = rdev->mc.aper_base;
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
if (!(rdev->flags & RADEON_IS_AGP))
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
}
|
||||
|
||||
void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
|
||||
|
@ -578,6 +542,40 @@ void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
|
|||
|
||||
}
|
||||
|
||||
int rv370_get_pcie_lanes(struct radeon_device *rdev)
|
||||
{
|
||||
u32 link_width_cntl;
|
||||
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
return 0;
|
||||
|
||||
if (!(rdev->flags & RADEON_IS_PCIE))
|
||||
return 0;
|
||||
|
||||
/* FIXME wait for idle */
|
||||
|
||||
if (rdev->family < CHIP_R600)
|
||||
link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
|
||||
else
|
||||
link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
|
||||
|
||||
switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
|
||||
case RADEON_PCIE_LC_LINK_WIDTH_X0:
|
||||
return 0;
|
||||
case RADEON_PCIE_LC_LINK_WIDTH_X1:
|
||||
return 1;
|
||||
case RADEON_PCIE_LC_LINK_WIDTH_X2:
|
||||
return 2;
|
||||
case RADEON_PCIE_LC_LINK_WIDTH_X4:
|
||||
return 4;
|
||||
case RADEON_PCIE_LC_LINK_WIDTH_X8:
|
||||
return 8;
|
||||
case RADEON_PCIE_LC_LINK_WIDTH_X16:
|
||||
default:
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data)
|
||||
{
|
||||
|
@ -707,6 +705,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
tile_flags |= R300_TXO_MACRO_TILE;
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
|
||||
tile_flags |= R300_TXO_MICRO_TILE;
|
||||
else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
|
||||
tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
|
||||
|
||||
tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
|
||||
tmp |= tile_flags;
|
||||
|
@ -757,6 +757,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
tile_flags |= R300_COLOR_TILE_ENABLE;
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
|
||||
tile_flags |= R300_COLOR_MICROTILE_ENABLE;
|
||||
else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
|
||||
tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
|
||||
|
||||
tmp = idx_value & ~(0x7 << 16);
|
||||
tmp |= tile_flags;
|
||||
|
@ -828,7 +830,9 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
|
||||
tile_flags |= R300_DEPTHMACROTILE_ENABLE;
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
|
||||
tile_flags |= R300_DEPTHMICROTILE_TILED;;
|
||||
tile_flags |= R300_DEPTHMICROTILE_TILED;
|
||||
else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
|
||||
tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
|
||||
|
||||
tmp = idx_value & ~(0x7 << 16);
|
||||
tmp |= tile_flags;
|
||||
|
@ -1387,12 +1391,15 @@ int r300_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
r300_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = r420_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
}
|
||||
/* initialize memory controller */
|
||||
r300_mc_init(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
#include "r300_reg.h"
|
||||
|
@ -299,46 +300,42 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
|
|||
int reg;
|
||||
int sz;
|
||||
int i;
|
||||
int values[64];
|
||||
u32 *value;
|
||||
RING_LOCALS;
|
||||
|
||||
sz = header.packet0.count;
|
||||
reg = (header.packet0.reghi << 8) | header.packet0.reglo;
|
||||
|
||||
if ((sz > 64) || (sz < 0)) {
|
||||
DRM_ERROR
|
||||
("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
|
||||
reg, sz);
|
||||
DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
|
||||
reg, sz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
values[i] = ((int *)cmdbuf->buf)[i];
|
||||
switch (r300_reg_flags[(reg >> 2) + i]) {
|
||||
case MARK_SAFE:
|
||||
break;
|
||||
case MARK_CHECK_OFFSET:
|
||||
if (!radeon_check_offset(dev_priv, (u32) values[i])) {
|
||||
DRM_ERROR
|
||||
("Offset failed range check (reg=%04x sz=%d)\n",
|
||||
reg, sz);
|
||||
value = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
|
||||
if (!radeon_check_offset(dev_priv, *value)) {
|
||||
DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n",
|
||||
reg, sz);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Register %04x failed check as flag=%02x\n",
|
||||
reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
|
||||
reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_RING(1 + sz);
|
||||
OUT_RING(CP_PACKET0(reg, sz - 1));
|
||||
OUT_RING_TABLE(values, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * 4;
|
||||
cmdbuf->bufsz -= sz * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -362,7 +359,7 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
|
|||
if (!sz)
|
||||
return 0;
|
||||
|
||||
if (sz * 4 > cmdbuf->bufsz)
|
||||
if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
|
||||
return -EINVAL;
|
||||
|
||||
if (reg + sz * 4 >= 0x10000) {
|
||||
|
@ -380,12 +377,9 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
|
|||
|
||||
BEGIN_RING(1 + sz);
|
||||
OUT_RING(CP_PACKET0(reg, sz - 1));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * 4;
|
||||
cmdbuf->bufsz -= sz * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -407,7 +401,7 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
|
|||
|
||||
if (!sz)
|
||||
return 0;
|
||||
if (sz * 16 > cmdbuf->bufsz)
|
||||
if (sz * 16 > drm_buffer_unprocessed(cmdbuf->buffer))
|
||||
return -EINVAL;
|
||||
|
||||
/* VAP is very sensitive so we purge cache before we program it
|
||||
|
@ -426,7 +420,7 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
|
|||
BEGIN_RING(3 + sz * 4);
|
||||
OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
|
||||
OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * 4);
|
||||
ADVANCE_RING();
|
||||
|
||||
BEGIN_RING(2);
|
||||
|
@ -434,9 +428,6 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
|
|||
OUT_RING(0);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * 16;
|
||||
cmdbuf->bufsz -= sz * 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -449,14 +440,14 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
|
|||
{
|
||||
RING_LOCALS;
|
||||
|
||||
if (8 * 4 > cmdbuf->bufsz)
|
||||
if (8 * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
|
||||
return -EINVAL;
|
||||
|
||||
BEGIN_RING(10);
|
||||
OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
|
||||
OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
|
||||
(1 << R300_PRIM_NUM_VERTICES_SHIFT));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, 8);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, 8);
|
||||
ADVANCE_RING();
|
||||
|
||||
BEGIN_RING(4);
|
||||
|
@ -468,9 +459,6 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
|
|||
/* set flush flag */
|
||||
dev_priv->track_flush |= RADEON_FLUSH_EMITED;
|
||||
|
||||
cmdbuf->buf += 8 * 4;
|
||||
cmdbuf->bufsz -= 8 * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -480,28 +468,29 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
|
|||
{
|
||||
int count, i, k;
|
||||
#define MAX_ARRAY_PACKET 64
|
||||
u32 payload[MAX_ARRAY_PACKET];
|
||||
u32 *data;
|
||||
u32 narrays;
|
||||
RING_LOCALS;
|
||||
|
||||
count = (header >> 16) & 0x3fff;
|
||||
count = (header & RADEON_CP_PACKET_COUNT_MASK) >> 16;
|
||||
|
||||
if ((count + 1) > MAX_ARRAY_PACKET) {
|
||||
DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
|
||||
count);
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(payload, 0, MAX_ARRAY_PACKET * 4);
|
||||
memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
|
||||
|
||||
/* carefully check packet contents */
|
||||
|
||||
narrays = payload[0];
|
||||
/* We have already read the header so advance the buffer. */
|
||||
drm_buffer_advance(cmdbuf->buffer, 4);
|
||||
|
||||
narrays = *(u32 *)drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
k = 0;
|
||||
i = 1;
|
||||
while ((k < narrays) && (i < (count + 1))) {
|
||||
i++; /* skip attribute field */
|
||||
if (!radeon_check_offset(dev_priv, payload[i])) {
|
||||
data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
|
||||
if (!radeon_check_offset(dev_priv, *data)) {
|
||||
DRM_ERROR
|
||||
("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
|
||||
k, i);
|
||||
|
@ -512,7 +501,8 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
|
|||
if (k == narrays)
|
||||
break;
|
||||
/* have one more to process, they come in pairs */
|
||||
if (!radeon_check_offset(dev_priv, payload[i])) {
|
||||
data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
|
||||
if (!radeon_check_offset(dev_priv, *data)) {
|
||||
DRM_ERROR
|
||||
("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
|
||||
k, i);
|
||||
|
@ -533,30 +523,30 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
|
|||
|
||||
BEGIN_RING(count + 2);
|
||||
OUT_RING(header);
|
||||
OUT_RING_TABLE(payload, count + 1);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 1);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count + 2) * 4;
|
||||
cmdbuf->bufsz -= (count + 2) * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
u32 *cmd = (u32 *) cmdbuf->buf;
|
||||
u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
int count, ret;
|
||||
RING_LOCALS;
|
||||
|
||||
count=(cmd[0]>>16) & 0x3fff;
|
||||
|
||||
if (cmd[0] & 0x8000) {
|
||||
count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
|
||||
|
||||
if (*cmd & 0x8000) {
|
||||
u32 offset;
|
||||
|
||||
if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
||||
u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
if (*cmd1 & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
||||
| RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
offset = cmd[2] << 10;
|
||||
|
||||
u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
|
||||
offset = *cmd2 << 10;
|
||||
ret = !radeon_check_offset(dev_priv, offset);
|
||||
if (ret) {
|
||||
DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
|
||||
|
@ -564,9 +554,10 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
|
|||
}
|
||||
}
|
||||
|
||||
if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
|
||||
(cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
offset = cmd[3] << 10;
|
||||
if ((*cmd1 & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
|
||||
(*cmd1 & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
|
||||
offset = *cmd3 << 10;
|
||||
ret = !radeon_check_offset(dev_priv, offset);
|
||||
if (ret) {
|
||||
DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
|
||||
|
@ -577,28 +568,25 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
|
|||
}
|
||||
|
||||
BEGIN_RING(count+2);
|
||||
OUT_RING(cmd[0]);
|
||||
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count+2)*4;
|
||||
cmdbuf->bufsz -= (count+2)*4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
u32 *cmd;
|
||||
u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
int count;
|
||||
int expected_count;
|
||||
RING_LOCALS;
|
||||
|
||||
cmd = (u32 *) cmdbuf->buf;
|
||||
count = (cmd[0]>>16) & 0x3fff;
|
||||
expected_count = cmd[1] >> 16;
|
||||
if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
|
||||
count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
|
||||
|
||||
expected_count = *cmd1 >> 16;
|
||||
if (!(*cmd1 & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
|
||||
expected_count = (expected_count+1)/2;
|
||||
|
||||
if (count && count != expected_count) {
|
||||
|
@ -608,55 +596,53 @@ static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
|
|||
}
|
||||
|
||||
BEGIN_RING(count+2);
|
||||
OUT_RING(cmd[0]);
|
||||
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count+2)*4;
|
||||
cmdbuf->bufsz -= (count+2)*4;
|
||||
|
||||
if (!count) {
|
||||
drm_r300_cmd_header_t header;
|
||||
drm_r300_cmd_header_t stack_header, *header;
|
||||
u32 *cmd1, *cmd2, *cmd3;
|
||||
|
||||
if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
|
||||
if (drm_buffer_unprocessed(cmdbuf->buffer)
|
||||
< 4*4 + sizeof(stack_header)) {
|
||||
DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
header.u = *(unsigned int *)cmdbuf->buf;
|
||||
header = drm_buffer_read_object(cmdbuf->buffer,
|
||||
sizeof(stack_header), &stack_header);
|
||||
|
||||
cmdbuf->buf += sizeof(header);
|
||||
cmdbuf->bufsz -= sizeof(header);
|
||||
cmd = (u32 *) cmdbuf->buf;
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
|
||||
cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
|
||||
|
||||
if (header.header.cmd_type != R300_CMD_PACKET3 ||
|
||||
header.packet3.packet != R300_CMD_PACKET3_RAW ||
|
||||
cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
|
||||
if (header->header.cmd_type != R300_CMD_PACKET3 ||
|
||||
header->packet3.packet != R300_CMD_PACKET3_RAW ||
|
||||
*cmd != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
|
||||
DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((cmd[1] & 0x8000ffff) != 0x80000810) {
|
||||
DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
|
||||
if ((*cmd1 & 0x8000ffff) != 0x80000810) {
|
||||
DRM_ERROR("Invalid indx_buffer reg address %08X\n",
|
||||
*cmd1);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!radeon_check_offset(dev_priv, cmd[2])) {
|
||||
DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
|
||||
if (!radeon_check_offset(dev_priv, *cmd2)) {
|
||||
DRM_ERROR("Invalid indx_buffer offset is %08X\n",
|
||||
*cmd2);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (cmd[3] != expected_count) {
|
||||
if (*cmd3 != expected_count) {
|
||||
DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
|
||||
cmd[3], expected_count);
|
||||
*cmd3, expected_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BEGIN_RING(4);
|
||||
OUT_RING(cmd[0]);
|
||||
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, 4);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += 4*4;
|
||||
cmdbuf->bufsz -= 4*4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -665,39 +651,39 @@ static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
|
|||
static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
u32 header;
|
||||
u32 *header;
|
||||
int count;
|
||||
RING_LOCALS;
|
||||
|
||||
if (4 > cmdbuf->bufsz)
|
||||
if (4 > drm_buffer_unprocessed(cmdbuf->buffer))
|
||||
return -EINVAL;
|
||||
|
||||
/* Fixme !! This simply emits a packet without much checking.
|
||||
We need to be smarter. */
|
||||
|
||||
/* obtain first word - actual packet3 header */
|
||||
header = *(u32 *) cmdbuf->buf;
|
||||
header = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
|
||||
/* Is it packet 3 ? */
|
||||
if ((header >> 30) != 0x3) {
|
||||
DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
|
||||
if ((*header >> 30) != 0x3) {
|
||||
DRM_ERROR("Not a packet3 header (0x%08x)\n", *header);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
count = (header >> 16) & 0x3fff;
|
||||
count = (*header >> 16) & 0x3fff;
|
||||
|
||||
/* Check again now that we know how much data to expect */
|
||||
if ((count + 2) * 4 > cmdbuf->bufsz) {
|
||||
if ((count + 2) * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) {
|
||||
DRM_ERROR
|
||||
("Expected packet3 of length %d but have only %d bytes left\n",
|
||||
(count + 2) * 4, cmdbuf->bufsz);
|
||||
(count + 2) * 4, drm_buffer_unprocessed(cmdbuf->buffer));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Is it a packet type we know about ? */
|
||||
switch (header & 0xff00) {
|
||||
switch (*header & 0xff00) {
|
||||
case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
|
||||
return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
|
||||
return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, *header);
|
||||
|
||||
case RADEON_CNTL_BITBLT_MULTI:
|
||||
return r300_emit_bitblt_multi(dev_priv, cmdbuf);
|
||||
|
@ -723,18 +709,14 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
|
|||
/* these packets are safe */
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
|
||||
DRM_ERROR("Unknown packet3 header (0x%08x)\n", *header);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BEGIN_RING(count + 2);
|
||||
OUT_RING(header);
|
||||
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count + 2) * 4;
|
||||
cmdbuf->bufsz -= (count + 2) * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -748,8 +730,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
|
|||
{
|
||||
int n;
|
||||
int ret;
|
||||
char *orig_buf = cmdbuf->buf;
|
||||
int orig_bufsz = cmdbuf->bufsz;
|
||||
int orig_iter = cmdbuf->buffer->iterator;
|
||||
|
||||
/* This is a do-while-loop so that we run the interior at least once,
|
||||
* even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
|
||||
|
@ -761,8 +742,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmdbuf->buf = orig_buf;
|
||||
cmdbuf->bufsz = orig_bufsz;
|
||||
cmdbuf->buffer->iterator = orig_iter;
|
||||
}
|
||||
|
||||
switch (header.packet3.packet) {
|
||||
|
@ -785,9 +765,9 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
|
|||
break;
|
||||
|
||||
default:
|
||||
DRM_ERROR("bad packet3 type %i at %p\n",
|
||||
DRM_ERROR("bad packet3 type %i at byte %d\n",
|
||||
header.packet3.packet,
|
||||
cmdbuf->buf - sizeof(header));
|
||||
cmdbuf->buffer->iterator - sizeof(header));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -923,12 +903,13 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
|
|||
drm_r300_cmd_header_t header)
|
||||
{
|
||||
u32 *ref_age_base;
|
||||
u32 i, buf_idx, h_pending;
|
||||
u64 ptr_addr;
|
||||
u32 i, *buf_idx, h_pending;
|
||||
u64 *ptr_addr;
|
||||
u64 stack_ptr_addr;
|
||||
RING_LOCALS;
|
||||
|
||||
if (cmdbuf->bufsz <
|
||||
(sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
|
||||
if (drm_buffer_unprocessed(cmdbuf->buffer) <
|
||||
(sizeof(u64) + header.scratch.n_bufs * sizeof(*buf_idx))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -938,36 +919,35 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
|
|||
|
||||
dev_priv->scratch_ages[header.scratch.reg]++;
|
||||
|
||||
ptr_addr = get_unaligned((u64 *)cmdbuf->buf);
|
||||
ref_age_base = (u32 *)(unsigned long)ptr_addr;
|
||||
|
||||
cmdbuf->buf += sizeof(u64);
|
||||
cmdbuf->bufsz -= sizeof(u64);
|
||||
ptr_addr = drm_buffer_read_object(cmdbuf->buffer,
|
||||
sizeof(stack_ptr_addr), &stack_ptr_addr);
|
||||
ref_age_base = (u32 *)(unsigned long)*ptr_addr;
|
||||
|
||||
for (i=0; i < header.scratch.n_bufs; i++) {
|
||||
buf_idx = *(u32 *)cmdbuf->buf;
|
||||
buf_idx *= 2; /* 8 bytes per buf */
|
||||
buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
*buf_idx *= 2; /* 8 bytes per buf */
|
||||
|
||||
if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
|
||||
if (DRM_COPY_TO_USER(ref_age_base + *buf_idx,
|
||||
&dev_priv->scratch_ages[header.scratch.reg],
|
||||
sizeof(u32)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
|
||||
if (DRM_COPY_FROM_USER(&h_pending,
|
||||
ref_age_base + *buf_idx + 1,
|
||||
sizeof(u32)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (h_pending == 0) {
|
||||
if (h_pending == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
h_pending--;
|
||||
|
||||
if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
|
||||
if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1,
|
||||
&h_pending,
|
||||
sizeof(u32)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmdbuf->buf += sizeof(buf_idx);
|
||||
cmdbuf->bufsz -= sizeof(buf_idx);
|
||||
drm_buffer_advance(cmdbuf->buffer, sizeof(*buf_idx));
|
||||
}
|
||||
|
||||
BEGIN_RING(2);
|
||||
|
@ -1009,19 +989,16 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
|
|||
DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
|
||||
if (!sz)
|
||||
return 0;
|
||||
if (sz * stride * 4 > cmdbuf->bufsz)
|
||||
if (sz * stride * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
|
||||
return -EINVAL;
|
||||
|
||||
BEGIN_RING(3 + sz * stride);
|
||||
OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
|
||||
OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * stride);
|
||||
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * stride * 4;
|
||||
cmdbuf->bufsz -= sz * stride * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1053,19 +1030,18 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
|
||||
while (drm_buffer_unprocessed(cmdbuf->buffer)
|
||||
>= sizeof(drm_r300_cmd_header_t)) {
|
||||
int idx;
|
||||
drm_r300_cmd_header_t header;
|
||||
drm_r300_cmd_header_t *header, stack_header;
|
||||
|
||||
header.u = *(unsigned int *)cmdbuf->buf;
|
||||
header = drm_buffer_read_object(cmdbuf->buffer,
|
||||
sizeof(stack_header), &stack_header);
|
||||
|
||||
cmdbuf->buf += sizeof(header);
|
||||
cmdbuf->bufsz -= sizeof(header);
|
||||
|
||||
switch (header.header.cmd_type) {
|
||||
switch (header->header.cmd_type) {
|
||||
case R300_CMD_PACKET0:
|
||||
DRM_DEBUG("R300_CMD_PACKET0\n");
|
||||
ret = r300_emit_packet0(dev_priv, cmdbuf, header);
|
||||
ret = r300_emit_packet0(dev_priv, cmdbuf, *header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_packet0 failed\n");
|
||||
goto cleanup;
|
||||
|
@ -1074,7 +1050,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
|
||||
case R300_CMD_VPU:
|
||||
DRM_DEBUG("R300_CMD_VPU\n");
|
||||
ret = r300_emit_vpu(dev_priv, cmdbuf, header);
|
||||
ret = r300_emit_vpu(dev_priv, cmdbuf, *header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_vpu failed\n");
|
||||
goto cleanup;
|
||||
|
@ -1083,7 +1059,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
|
||||
case R300_CMD_PACKET3:
|
||||
DRM_DEBUG("R300_CMD_PACKET3\n");
|
||||
ret = r300_emit_packet3(dev_priv, cmdbuf, header);
|
||||
ret = r300_emit_packet3(dev_priv, cmdbuf, *header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_packet3 failed\n");
|
||||
goto cleanup;
|
||||
|
@ -1117,8 +1093,8 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
int i;
|
||||
RING_LOCALS;
|
||||
|
||||
BEGIN_RING(header.delay.count);
|
||||
for (i = 0; i < header.delay.count; i++)
|
||||
BEGIN_RING(header->delay.count);
|
||||
for (i = 0; i < header->delay.count; i++)
|
||||
OUT_RING(RADEON_CP_PACKET2);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
@ -1126,7 +1102,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
|
||||
case R300_CMD_DMA_DISCARD:
|
||||
DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
|
||||
idx = header.dma.buf_idx;
|
||||
idx = header->dma.buf_idx;
|
||||
if (idx < 0 || idx >= dma->buf_count) {
|
||||
DRM_ERROR("buffer index %d (of %d max)\n",
|
||||
idx, dma->buf_count - 1);
|
||||
|
@ -1149,12 +1125,12 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
|
||||
case R300_CMD_WAIT:
|
||||
DRM_DEBUG("R300_CMD_WAIT\n");
|
||||
r300_cmd_wait(dev_priv, header);
|
||||
r300_cmd_wait(dev_priv, *header);
|
||||
break;
|
||||
|
||||
case R300_CMD_SCRATCH:
|
||||
DRM_DEBUG("R300_CMD_SCRATCH\n");
|
||||
ret = r300_scratch(dev_priv, cmdbuf, header);
|
||||
ret = r300_scratch(dev_priv, cmdbuf, *header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_scratch failed\n");
|
||||
goto cleanup;
|
||||
|
@ -1168,16 +1144,16 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||
goto cleanup;
|
||||
}
|
||||
DRM_DEBUG("R300_CMD_R500FP\n");
|
||||
ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
|
||||
ret = r300_emit_r500fp(dev_priv, cmdbuf, *header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_r500fp failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("bad cmd_type %i at %p\n",
|
||||
header.header.cmd_type,
|
||||
cmdbuf->buf - sizeof(header));
|
||||
DRM_ERROR("bad cmd_type %i at byte %d\n",
|
||||
header->header.cmd_type,
|
||||
cmdbuf->buffer->iterator - sizeof(*header));
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
|
@ -952,6 +952,7 @@
|
|||
# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
|
||||
# define R300_TXO_MACRO_TILE (1 << 2)
|
||||
# define R300_TXO_MICRO_TILE (1 << 3)
|
||||
# define R300_TXO_MICRO_TILE_SQUARE (2 << 3)
|
||||
# define R300_TXO_OFFSET_MASK 0xffffffe0
|
||||
# define R300_TXO_OFFSET_SHIFT 5
|
||||
/* END: Guess from R200 */
|
||||
|
@ -1360,6 +1361,7 @@
|
|||
# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
|
||||
# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
|
||||
# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
|
||||
# define R300_COLOR_MICROTILE_SQUARE_ENABLE (2 << 17)
|
||||
# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
|
||||
# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
|
||||
# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
|
||||
|
|
|
@ -40,28 +40,6 @@ static void r420_set_reg_safe(struct radeon_device *rdev)
|
|||
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm);
|
||||
}
|
||||
|
||||
int r420_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* Setup GPU memory space */
|
||||
rdev->mc.vram_location = 0xFFFFFFFFUL;
|
||||
rdev->mc.gtt_location = 0xFFFFFFFFUL;
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
} else {
|
||||
rdev->mc.gtt_location = rdev->mc.agp_base;
|
||||
}
|
||||
}
|
||||
r = radeon_mc_setup(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r420_pipes_init(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned tmp;
|
||||
|
@ -69,7 +47,8 @@ void r420_pipes_init(struct radeon_device *rdev)
|
|||
unsigned num_pipes;
|
||||
|
||||
/* GA_ENHANCE workaround TCL deadlock issue */
|
||||
WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
|
||||
WREG32(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL |
|
||||
(1 << 2) | (1 << 3));
|
||||
/* add idle wait as per freedesktop.org bug 24041 */
|
||||
if (r100_gui_wait_for_idle(rdev)) {
|
||||
printk(KERN_WARNING "Failed to wait GUI idle while "
|
||||
|
@ -97,17 +76,17 @@ void r420_pipes_init(struct radeon_device *rdev)
|
|||
tmp = (7 << 1);
|
||||
break;
|
||||
}
|
||||
WREG32(0x42C8, (1 << num_pipes) - 1);
|
||||
WREG32(R500_SU_REG_DEST, (1 << num_pipes) - 1);
|
||||
/* Sub pixel 1/12 so we can have 4K rendering according to doc */
|
||||
tmp |= (1 << 4) | (1 << 0);
|
||||
WREG32(0x4018, tmp);
|
||||
tmp |= R300_TILE_SIZE_16 | R300_ENABLE_TILING;
|
||||
WREG32(R300_GB_TILE_CONFIG, tmp);
|
||||
if (r100_gui_wait_for_idle(rdev)) {
|
||||
printk(KERN_WARNING "Failed to wait GUI idle while "
|
||||
"programming pipes. Bad things might happen.\n");
|
||||
}
|
||||
|
||||
tmp = RREG32(0x170C);
|
||||
WREG32(0x170C, tmp | (1 << 31));
|
||||
tmp = RREG32(R300_DST_PIPE_CONFIG);
|
||||
WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG);
|
||||
|
||||
WREG32(R300_RB2D_DSTCACHE_MODE,
|
||||
RREG32(R300_RB2D_DSTCACHE_MODE) |
|
||||
|
@ -348,13 +327,15 @@ int r420_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
r300_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = r420_mc_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
}
|
||||
/* initialize memory controller */
|
||||
r300_mc_init(rdev);
|
||||
r420_debugfs(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
|
|
|
@ -717,54 +717,62 @@
|
|||
#define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988
|
||||
|
||||
#define AVIVO_DC_GPIO_HPD_A 0x7e94
|
||||
|
||||
#define AVIVO_GPIO_0 0x7e30
|
||||
#define AVIVO_GPIO_1 0x7e40
|
||||
#define AVIVO_GPIO_2 0x7e50
|
||||
#define AVIVO_GPIO_3 0x7e60
|
||||
|
||||
#define AVIVO_DC_GPIO_HPD_Y 0x7e9c
|
||||
|
||||
#define AVIVO_I2C_STATUS 0x7d30
|
||||
# define AVIVO_I2C_STATUS_DONE (1 << 0)
|
||||
# define AVIVO_I2C_STATUS_NACK (1 << 1)
|
||||
# define AVIVO_I2C_STATUS_HALT (1 << 2)
|
||||
# define AVIVO_I2C_STATUS_GO (1 << 3)
|
||||
# define AVIVO_I2C_STATUS_MASK 0x7
|
||||
/* If radeon_mm_i2c is to be believed, this is HALT, NACK, and maybe
|
||||
* DONE? */
|
||||
# define AVIVO_I2C_STATUS_CMD_RESET 0x7
|
||||
# define AVIVO_I2C_STATUS_CMD_WAIT (1 << 3)
|
||||
#define AVIVO_I2C_STOP 0x7d34
|
||||
#define AVIVO_I2C_START_CNTL 0x7d38
|
||||
# define AVIVO_I2C_START (1 << 8)
|
||||
# define AVIVO_I2C_CONNECTOR0 (0 << 16)
|
||||
# define AVIVO_I2C_CONNECTOR1 (1 << 16)
|
||||
#define R520_I2C_START (1<<0)
|
||||
#define R520_I2C_STOP (1<<1)
|
||||
#define R520_I2C_RX (1<<2)
|
||||
#define R520_I2C_EN (1<<8)
|
||||
#define R520_I2C_DDC1 (0<<16)
|
||||
#define R520_I2C_DDC2 (1<<16)
|
||||
#define R520_I2C_DDC3 (2<<16)
|
||||
#define R520_I2C_DDC_MASK (3<<16)
|
||||
#define AVIVO_I2C_CONTROL2 0x7d3c
|
||||
# define AVIVO_I2C_7D3C_SIZE_SHIFT 8
|
||||
# define AVIVO_I2C_7D3C_SIZE_MASK (0xf << 8)
|
||||
#define AVIVO_I2C_CONTROL3 0x7d40
|
||||
/* Reading is done 4 bytes at a time: read the bottom 8 bits from
|
||||
* 7d44, four times in a row.
|
||||
* Writing is a little more complex. First write DATA with
|
||||
* 0xnnnnnnzz, then 0xnnnnnnyy, where nnnnnn is some non-deterministic
|
||||
* magic number, zz is, I think, the slave address, and yy is the byte
|
||||
* you want to write. */
|
||||
#define AVIVO_I2C_DATA 0x7d44
|
||||
#define R520_I2C_ADDR_COUNT_MASK (0x7)
|
||||
#define R520_I2C_DATA_COUNT_SHIFT (8)
|
||||
#define R520_I2C_DATA_COUNT_MASK (0xF00)
|
||||
#define AVIVO_I2C_CNTL 0x7d50
|
||||
# define AVIVO_I2C_EN (1 << 0)
|
||||
# define AVIVO_I2C_RESET (1 << 8)
|
||||
#define AVIVO_DC_I2C_STATUS1 0x7d30
|
||||
# define AVIVO_DC_I2C_DONE (1 << 0)
|
||||
# define AVIVO_DC_I2C_NACK (1 << 1)
|
||||
# define AVIVO_DC_I2C_HALT (1 << 2)
|
||||
# define AVIVO_DC_I2C_GO (1 << 3)
|
||||
#define AVIVO_DC_I2C_RESET 0x7d34
|
||||
# define AVIVO_DC_I2C_SOFT_RESET (1 << 0)
|
||||
# define AVIVO_DC_I2C_ABORT (1 << 8)
|
||||
#define AVIVO_DC_I2C_CONTROL1 0x7d38
|
||||
# define AVIVO_DC_I2C_START (1 << 0)
|
||||
# define AVIVO_DC_I2C_STOP (1 << 1)
|
||||
# define AVIVO_DC_I2C_RECEIVE (1 << 2)
|
||||
# define AVIVO_DC_I2C_EN (1 << 8)
|
||||
# define AVIVO_DC_I2C_PIN_SELECT(x) ((x) << 16)
|
||||
# define AVIVO_SEL_DDC1 0
|
||||
# define AVIVO_SEL_DDC2 1
|
||||
# define AVIVO_SEL_DDC3 2
|
||||
#define AVIVO_DC_I2C_CONTROL2 0x7d3c
|
||||
# define AVIVO_DC_I2C_ADDR_COUNT(x) ((x) << 0)
|
||||
# define AVIVO_DC_I2C_DATA_COUNT(x) ((x) << 8)
|
||||
#define AVIVO_DC_I2C_CONTROL3 0x7d40
|
||||
# define AVIVO_DC_I2C_DATA_DRIVE_EN (1 << 0)
|
||||
# define AVIVO_DC_I2C_DATA_DRIVE_SEL (1 << 1)
|
||||
# define AVIVO_DC_I2C_CLK_DRIVE_EN (1 << 7)
|
||||
# define AVIVO_DC_I2C_RD_INTRA_BYTE_DELAY(x) ((x) << 8)
|
||||
# define AVIVO_DC_I2C_WR_INTRA_BYTE_DELAY(x) ((x) << 16)
|
||||
# define AVIVO_DC_I2C_TIME_LIMIT(x) ((x) << 24)
|
||||
#define AVIVO_DC_I2C_DATA 0x7d44
|
||||
#define AVIVO_DC_I2C_INTERRUPT_CONTROL 0x7d48
|
||||
# define AVIVO_DC_I2C_INTERRUPT_STATUS (1 << 0)
|
||||
# define AVIVO_DC_I2C_INTERRUPT_AK (1 << 8)
|
||||
# define AVIVO_DC_I2C_INTERRUPT_ENABLE (1 << 16)
|
||||
#define AVIVO_DC_I2C_ARBITRATION 0x7d50
|
||||
# define AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C (1 << 0)
|
||||
# define AVIVO_DC_I2C_SW_CAN_USE_I2C (1 << 1)
|
||||
# define AVIVO_DC_I2C_SW_DONE_USING_I2C (1 << 8)
|
||||
# define AVIVO_DC_I2C_HW_NEEDS_I2C (1 << 9)
|
||||
# define AVIVO_DC_I2C_ABORT_HDCP_I2C (1 << 16)
|
||||
# define AVIVO_DC_I2C_HW_USING_I2C (1 << 17)
|
||||
|
||||
#define AVIVO_DC_GPIO_DDC1_MASK 0x7e40
|
||||
#define AVIVO_DC_GPIO_DDC1_A 0x7e44
|
||||
#define AVIVO_DC_GPIO_DDC1_EN 0x7e48
|
||||
#define AVIVO_DC_GPIO_DDC1_Y 0x7e4c
|
||||
|
||||
#define AVIVO_DC_GPIO_DDC2_MASK 0x7e50
|
||||
#define AVIVO_DC_GPIO_DDC2_A 0x7e54
|
||||
#define AVIVO_DC_GPIO_DDC2_EN 0x7e58
|
||||
#define AVIVO_DC_GPIO_DDC2_Y 0x7e5c
|
||||
|
||||
#define AVIVO_DC_GPIO_DDC3_MASK 0x7e60
|
||||
#define AVIVO_DC_GPIO_DDC3_A 0x7e64
|
||||
#define AVIVO_DC_GPIO_DDC3_EN 0x7e68
|
||||
#define AVIVO_DC_GPIO_DDC3_Y 0x7e6c
|
||||
|
||||
#define AVIVO_DISP_INTERRUPT_STATUS 0x7edc
|
||||
# define AVIVO_D1_VBLANK_INTERRUPT (1 << 4)
|
||||
|
|
|
@ -119,13 +119,15 @@ static void r520_vram_get_type(struct radeon_device *rdev)
|
|||
rdev->mc.vram_width *= 2;
|
||||
}
|
||||
|
||||
void r520_vram_info(struct radeon_device *rdev)
|
||||
void r520_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
fixed20_12 a;
|
||||
|
||||
r520_vram_get_type(rdev);
|
||||
|
||||
r100_vram_init_sizes(rdev);
|
||||
radeon_vram_location(rdev, &rdev->mc, 0);
|
||||
if (!(rdev->flags & RADEON_IS_AGP))
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
/* FIXME: we should enforce default clock in case GPU is not in
|
||||
* default setup
|
||||
*/
|
||||
|
@ -267,12 +269,15 @@ int r520_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
r520_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = r420_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
}
|
||||
/* initialize memory controller */
|
||||
r520_mc_init(rdev);
|
||||
rv515_debugfs(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
|
|
|
@ -353,23 +353,14 @@ void r600_hpd_fini(struct radeon_device *rdev)
|
|||
/*
|
||||
* R600 PCIE GART
|
||||
*/
|
||||
int r600_gart_clear_page(struct radeon_device *rdev, int i)
|
||||
{
|
||||
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
|
||||
u64 pte;
|
||||
|
||||
if (i < 0 || i > rdev->gart.num_gpu_pages)
|
||||
return -EINVAL;
|
||||
pte = 0;
|
||||
writeq(pte, ((void __iomem *)ptr) + (i * 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned i;
|
||||
u32 tmp;
|
||||
|
||||
/* flush hdp cache so updates hit vram */
|
||||
WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
|
||||
|
||||
WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12);
|
||||
WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12);
|
||||
WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
|
||||
|
@ -416,6 +407,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
|
|||
r = radeon_gart_table_vram_pin(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
radeon_gart_restore(rdev);
|
||||
|
||||
/* Setup L2 cache */
|
||||
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
|
||||
|
@ -619,6 +611,68 @@ static void r600_mc_program(struct radeon_device *rdev)
|
|||
rv515_vga_render_disable(rdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_vram_gtt_location - try to find VRAM & GTT location
|
||||
* @rdev: radeon device structure holding all necessary informations
|
||||
* @mc: memory controller structure holding memory informations
|
||||
*
|
||||
* Function will place try to place VRAM at same place as in CPU (PCI)
|
||||
* address space as some GPU seems to have issue when we reprogram at
|
||||
* different address space.
|
||||
*
|
||||
* If there is not enough space to fit the unvisible VRAM after the
|
||||
* aperture then we limit the VRAM size to the aperture.
|
||||
*
|
||||
* If we are using AGP then place VRAM adjacent to AGP aperture are we need
|
||||
* them to be in one from GPU point of view so that we can program GPU to
|
||||
* catch access outside them (weird GPU policy see ??).
|
||||
*
|
||||
* This function will never fails, worst case are limiting VRAM or GTT.
|
||||
*
|
||||
* Note: GTT start, end, size should be initialized before calling this
|
||||
* function on AGP platform.
|
||||
*/
|
||||
void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
|
||||
{
|
||||
u64 size_bf, size_af;
|
||||
|
||||
if (mc->mc_vram_size > 0xE0000000) {
|
||||
/* leave room for at least 512M GTT */
|
||||
dev_warn(rdev->dev, "limiting VRAM\n");
|
||||
mc->real_vram_size = 0xE0000000;
|
||||
mc->mc_vram_size = 0xE0000000;
|
||||
}
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
size_bf = mc->gtt_start;
|
||||
size_af = 0xFFFFFFFF - mc->gtt_end + 1;
|
||||
if (size_bf > size_af) {
|
||||
if (mc->mc_vram_size > size_bf) {
|
||||
dev_warn(rdev->dev, "limiting VRAM\n");
|
||||
mc->real_vram_size = size_bf;
|
||||
mc->mc_vram_size = size_bf;
|
||||
}
|
||||
mc->vram_start = mc->gtt_start - mc->mc_vram_size;
|
||||
} else {
|
||||
if (mc->mc_vram_size > size_af) {
|
||||
dev_warn(rdev->dev, "limiting VRAM\n");
|
||||
mc->real_vram_size = size_af;
|
||||
mc->mc_vram_size = size_af;
|
||||
}
|
||||
mc->vram_start = mc->gtt_end;
|
||||
}
|
||||
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
|
||||
dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
|
||||
mc->mc_vram_size >> 20, mc->vram_start,
|
||||
mc->vram_end, mc->real_vram_size >> 20);
|
||||
} else {
|
||||
u64 base = 0;
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
radeon_gtt_location(rdev, mc);
|
||||
}
|
||||
}
|
||||
|
||||
int r600_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
fixed20_12 a;
|
||||
|
@ -658,75 +712,21 @@ int r600_mc_init(struct radeon_device *rdev)
|
|||
/* Setup GPU memory space */
|
||||
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
|
||||
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
|
||||
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.visible_vram_size = rdev->mc.aper_size;
|
||||
/* FIXME remove this once we support unmappable VRAM */
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
|
||||
rdev->mc.mc_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
/* gtt_size is setup by radeon_agp_init */
|
||||
rdev->mc.gtt_location = rdev->mc.agp_base;
|
||||
tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
|
||||
/* Try to put vram before or after AGP because we
|
||||
* we want SYSTEM_APERTURE to cover both VRAM and
|
||||
* AGP so that GPU can catch out of VRAM/AGP access
|
||||
*/
|
||||
if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
|
||||
/* Enough place before */
|
||||
rdev->mc.vram_location = rdev->mc.gtt_location -
|
||||
rdev->mc.mc_vram_size;
|
||||
} else if (tmp > rdev->mc.mc_vram_size) {
|
||||
/* Enough place after */
|
||||
rdev->mc.vram_location = rdev->mc.gtt_location +
|
||||
rdev->mc.gtt_size;
|
||||
} else {
|
||||
/* Try to setup VRAM then AGP might not
|
||||
* not work on some card
|
||||
*/
|
||||
rdev->mc.vram_location = 0x00000000UL;
|
||||
rdev->mc.gtt_location = rdev->mc.mc_vram_size;
|
||||
}
|
||||
} else {
|
||||
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
|
||||
rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) &
|
||||
0xFFFF) << 24;
|
||||
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
|
||||
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
|
||||
/* Enough place after vram */
|
||||
rdev->mc.gtt_location = tmp;
|
||||
} else if (rdev->mc.vram_location >= rdev->mc.gtt_size) {
|
||||
/* Enough place before vram */
|
||||
rdev->mc.gtt_location = 0;
|
||||
} else {
|
||||
/* Not enough place after or before shrink
|
||||
* gart size
|
||||
*/
|
||||
if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) {
|
||||
rdev->mc.gtt_location = 0;
|
||||
rdev->mc.gtt_size = rdev->mc.vram_location;
|
||||
} else {
|
||||
rdev->mc.gtt_location = tmp;
|
||||
rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp;
|
||||
}
|
||||
}
|
||||
rdev->mc.gtt_location = rdev->mc.mc_vram_size;
|
||||
}
|
||||
rdev->mc.vram_start = rdev->mc.vram_location;
|
||||
rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
|
||||
rdev->mc.gtt_start = rdev->mc.gtt_location;
|
||||
rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
|
||||
r600_vram_gtt_location(rdev, &rdev->mc);
|
||||
/* FIXME: we should enforce default clock in case GPU is not in
|
||||
* default setup
|
||||
*/
|
||||
a.full = rfixed_const(100);
|
||||
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
|
||||
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
|
||||
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -981,6 +981,9 @@ void r600_gpu_init(struct radeon_device *rdev)
|
|||
{
|
||||
u32 tiling_config;
|
||||
u32 ramcfg;
|
||||
u32 backend_map;
|
||||
u32 cc_rb_backend_disable;
|
||||
u32 cc_gc_shader_pipe_config;
|
||||
u32 tmp;
|
||||
int i, j;
|
||||
u32 sq_config;
|
||||
|
@ -1090,8 +1093,11 @@ void r600_gpu_init(struct radeon_device *rdev)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes;
|
||||
rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
|
||||
tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
|
||||
tiling_config |= GROUP_SIZE(0);
|
||||
rdev->config.r600.tiling_group_size = 256;
|
||||
tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
|
||||
if (tmp > 3) {
|
||||
tiling_config |= ROW_TILING(3);
|
||||
|
@ -1101,24 +1107,33 @@ void r600_gpu_init(struct radeon_device *rdev)
|
|||
tiling_config |= SAMPLE_SPLIT(tmp);
|
||||
}
|
||||
tiling_config |= BANK_SWAPS(1);
|
||||
tmp = r600_get_tile_pipe_to_backend_map(rdev->config.r600.max_tile_pipes,
|
||||
rdev->config.r600.max_backends,
|
||||
(0xff << rdev->config.r600.max_backends) & 0xff);
|
||||
tiling_config |= BACKEND_MAP(tmp);
|
||||
|
||||
cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
|
||||
cc_rb_backend_disable |=
|
||||
BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << rdev->config.r600.max_backends) & R6XX_MAX_BACKENDS_MASK);
|
||||
|
||||
cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
|
||||
cc_gc_shader_pipe_config |=
|
||||
INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << rdev->config.r600.max_pipes) & R6XX_MAX_PIPES_MASK);
|
||||
cc_gc_shader_pipe_config |=
|
||||
INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << rdev->config.r600.max_simds) & R6XX_MAX_SIMDS_MASK);
|
||||
|
||||
backend_map = r600_get_tile_pipe_to_backend_map(rdev->config.r600.max_tile_pipes,
|
||||
(R6XX_MAX_BACKENDS -
|
||||
r600_count_pipe_bits((cc_rb_backend_disable &
|
||||
R6XX_MAX_BACKENDS_MASK) >> 16)),
|
||||
(cc_rb_backend_disable >> 16));
|
||||
|
||||
tiling_config |= BACKEND_MAP(backend_map);
|
||||
WREG32(GB_TILING_CONFIG, tiling_config);
|
||||
WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff);
|
||||
WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff);
|
||||
|
||||
tmp = BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << rdev->config.r600.max_backends) & R6XX_MAX_BACKENDS_MASK);
|
||||
WREG32(CC_RB_BACKEND_DISABLE, tmp);
|
||||
|
||||
/* Setup pipes */
|
||||
tmp = INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << rdev->config.r600.max_pipes) & R6XX_MAX_PIPES_MASK);
|
||||
tmp |= INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << rdev->config.r600.max_simds) & R6XX_MAX_SIMDS_MASK);
|
||||
WREG32(CC_GC_SHADER_PIPE_CONFIG, tmp);
|
||||
WREG32(GC_USER_SHADER_PIPE_CONFIG, tmp);
|
||||
WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
|
||||
tmp = R6XX_MAX_BACKENDS - r600_count_pipe_bits(tmp & INACTIVE_QD_PIPES_MASK);
|
||||
tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
|
||||
WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK);
|
||||
WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK);
|
||||
|
||||
|
@ -1783,12 +1798,17 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
|
|||
struct radeon_fence *fence)
|
||||
{
|
||||
/* Also consider EVENT_WRITE_EOP. it handles the interrupts + timestamps + events */
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
|
||||
radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* wait for 3D idle clean */
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
|
||||
radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit);
|
||||
/* Emit fence sequence & fire IRQ */
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
|
||||
radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
|
||||
radeon_ring_write(rdev, fence->seq);
|
||||
radeon_ring_write(rdev, PACKET0(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
|
||||
radeon_ring_write(rdev, 1);
|
||||
/* CP_INTERRUPT packet 3 no longer exists, use packet 0 */
|
||||
radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));
|
||||
radeon_ring_write(rdev, RB_INT_STAT);
|
||||
|
@ -2745,6 +2765,7 @@ restart_ih:
|
|||
case 0: /* D1 vblank */
|
||||
if (disp_int & LB_D1_VBLANK_INTERRUPT) {
|
||||
drm_handle_vblank(rdev->ddev, 0);
|
||||
wake_up(&rdev->irq.vblank_queue);
|
||||
disp_int &= ~LB_D1_VBLANK_INTERRUPT;
|
||||
DRM_DEBUG("IH: D1 vblank\n");
|
||||
}
|
||||
|
@ -2765,6 +2786,7 @@ restart_ih:
|
|||
case 0: /* D2 vblank */
|
||||
if (disp_int & LB_D2_VBLANK_INTERRUPT) {
|
||||
drm_handle_vblank(rdev->ddev, 1);
|
||||
wake_up(&rdev->irq.vblank_queue);
|
||||
disp_int &= ~LB_D2_VBLANK_INTERRUPT;
|
||||
DRM_DEBUG("IH: D2 vblank\n");
|
||||
}
|
||||
|
|
|
@ -146,6 +146,15 @@ static void r600_audio_update_hdmi(unsigned long param)
|
|||
jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on/off audio engine
|
||||
*/
|
||||
static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable)
|
||||
{
|
||||
DRM_INFO("%s audio support", enable ? "Enabling" : "Disabling");
|
||||
WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize the audio vars and register the update timer
|
||||
*/
|
||||
|
@ -154,8 +163,7 @@ int r600_audio_init(struct radeon_device *rdev)
|
|||
if (!r600_audio_chipset_supported(rdev))
|
||||
return 0;
|
||||
|
||||
DRM_INFO("%s audio support", radeon_audio ? "Enabling" : "Disabling");
|
||||
WREG32_P(R600_AUDIO_ENABLE, radeon_audio ? 0x81000000 : 0x0, ~0x81000000);
|
||||
r600_audio_engine_enable(rdev, radeon_audio);
|
||||
|
||||
rdev->audio_channels = -1;
|
||||
rdev->audio_rate = -1;
|
||||
|
@ -263,4 +271,6 @@ void r600_audio_fini(struct radeon_device *rdev)
|
|||
|
||||
del_timer(&rdev->audio_timer);
|
||||
WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000);
|
||||
|
||||
r600_audio_engine_enable(rdev, false);
|
||||
}
|
||||
|
|
|
@ -403,8 +403,6 @@ set_default_state(struct radeon_device *rdev)
|
|||
radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
|
||||
radeon_ring_write(rdev, dwords);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
|
||||
radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* SQ config */
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 6));
|
||||
radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
|
@ -578,9 +576,9 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
|
|||
ring_size = num_loops * dwords_per_loop;
|
||||
/* set default + shaders */
|
||||
ring_size += 40; /* shaders + def state */
|
||||
ring_size += 7; /* fence emit for VB IB */
|
||||
ring_size += 10; /* fence emit for VB IB */
|
||||
ring_size += 5; /* done copy */
|
||||
ring_size += 7; /* fence emit for done copy */
|
||||
ring_size += 10; /* fence emit for done copy */
|
||||
r = radeon_ring_lock(rdev, ring_size);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -594,13 +592,6 @@ void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
|
|||
{
|
||||
int r;
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
|
||||
radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* wait for 3D idle clean */
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
|
||||
radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit);
|
||||
|
||||
if (rdev->r600_blit.vb_ib)
|
||||
r600_vb_ib_put(rdev);
|
||||
|
||||
|
|
|
@ -9,11 +9,6 @@ const u32 r6xx_default_state[] =
|
|||
0xc0012800,
|
||||
0x80000000,
|
||||
0x80000000,
|
||||
0xc0004600,
|
||||
0x00000016,
|
||||
0xc0016800,
|
||||
0x00000010,
|
||||
0x00028000,
|
||||
0xc0016800,
|
||||
0x00000010,
|
||||
0x00008000,
|
||||
|
@ -531,11 +526,6 @@ const u32 r7xx_default_state[] =
|
|||
0xc0012800,
|
||||
0x80000000,
|
||||
0x80000000,
|
||||
0xc0004600,
|
||||
0x00000016,
|
||||
0xc0016800,
|
||||
0x00000010,
|
||||
0x00028000,
|
||||
0xc0016800,
|
||||
0x00000010,
|
||||
0x00008000,
|
||||
|
|
|
@ -734,8 +734,8 @@ static void r600_gfx_init(struct drm_device *dev,
|
|||
u32 hdp_host_path_cntl;
|
||||
u32 backend_map;
|
||||
u32 gb_tiling_config = 0;
|
||||
u32 cc_rb_backend_disable = 0;
|
||||
u32 cc_gc_shader_pipe_config = 0;
|
||||
u32 cc_rb_backend_disable;
|
||||
u32 cc_gc_shader_pipe_config;
|
||||
u32 ramcfg;
|
||||
|
||||
/* setup chip specs */
|
||||
|
@ -857,29 +857,44 @@ static void r600_gfx_init(struct drm_device *dev,
|
|||
|
||||
gb_tiling_config |= R600_BANK_SWAPS(1);
|
||||
|
||||
backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
|
||||
dev_priv->r600_max_backends,
|
||||
(0xff << dev_priv->r600_max_backends) & 0xff);
|
||||
gb_tiling_config |= R600_BACKEND_MAP(backend_map);
|
||||
cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000;
|
||||
cc_rb_backend_disable |=
|
||||
R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
|
||||
|
||||
cc_gc_shader_pipe_config =
|
||||
cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
|
||||
cc_gc_shader_pipe_config |=
|
||||
R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK);
|
||||
cc_gc_shader_pipe_config |=
|
||||
R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK);
|
||||
|
||||
cc_rb_backend_disable =
|
||||
R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
|
||||
backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
|
||||
(R6XX_MAX_BACKENDS -
|
||||
r600_count_pipe_bits((cc_rb_backend_disable &
|
||||
R6XX_MAX_BACKENDS_MASK) >> 16)),
|
||||
(cc_rb_backend_disable >> 16));
|
||||
gb_tiling_config |= R600_BACKEND_MAP(backend_map);
|
||||
|
||||
RADEON_WRITE(R600_GB_TILING_CONFIG, gb_tiling_config);
|
||||
RADEON_WRITE(R600_DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
|
||||
RADEON_WRITE(R600_HDP_TILING_CONFIG, (gb_tiling_config & 0xffff));
|
||||
if (gb_tiling_config & 0xc0) {
|
||||
dev_priv->r600_group_size = 512;
|
||||
} else {
|
||||
dev_priv->r600_group_size = 256;
|
||||
}
|
||||
dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7);
|
||||
if (gb_tiling_config & 0x30) {
|
||||
dev_priv->r600_nbanks = 8;
|
||||
} else {
|
||||
dev_priv->r600_nbanks = 4;
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
|
||||
num_qd_pipes =
|
||||
R6XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
|
||||
R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
|
||||
RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
|
||||
RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
|
||||
|
||||
|
@ -1151,7 +1166,8 @@ static void r600_gfx_init(struct drm_device *dev,
|
|||
|
||||
}
|
||||
|
||||
static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
||||
static u32 r700_get_tile_pipe_to_backend_map(drm_radeon_private_t *dev_priv,
|
||||
u32 num_tile_pipes,
|
||||
u32 num_backends,
|
||||
u32 backend_disable_mask)
|
||||
{
|
||||
|
@ -1162,6 +1178,7 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
u32 swizzle_pipe[R7XX_MAX_PIPES];
|
||||
u32 cur_backend;
|
||||
u32 i;
|
||||
bool force_no_swizzle;
|
||||
|
||||
if (num_tile_pipes > R7XX_MAX_PIPES)
|
||||
num_tile_pipes = R7XX_MAX_PIPES;
|
||||
|
@ -1191,6 +1208,18 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
if (enabled_backends_count != num_backends)
|
||||
num_backends = enabled_backends_count;
|
||||
|
||||
switch (dev_priv->flags & RADEON_FAMILY_MASK) {
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
force_no_swizzle = false;
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
default:
|
||||
force_no_swizzle = true;
|
||||
break;
|
||||
}
|
||||
|
||||
memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
|
||||
switch (num_tile_pipes) {
|
||||
case 1:
|
||||
|
@ -1201,49 +1230,100 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
swizzle_pipe[1] = 1;
|
||||
break;
|
||||
case 3:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 1;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 3;
|
||||
swizzle_pipe[3] = 1;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 3;
|
||||
swizzle_pipe[3] = 1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 1;
|
||||
swizzle_pipe[4] = 3;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 1;
|
||||
swizzle_pipe[4] = 3;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 5;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
swizzle_pipe[5] = 5;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 5;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 5;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
swizzle_pipe[5] = 5;
|
||||
swizzle_pipe[6] = 6;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 5;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 7;
|
||||
swizzle_pipe[7] = 5;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
swizzle_pipe[5] = 5;
|
||||
swizzle_pipe[6] = 6;
|
||||
swizzle_pipe[7] = 7;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 7;
|
||||
swizzle_pipe[7] = 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1264,8 +1344,10 @@ static void r700_gfx_init(struct drm_device *dev,
|
|||
drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
int i, j, num_qd_pipes;
|
||||
u32 ta_aux_cntl;
|
||||
u32 sx_debug_1;
|
||||
u32 smx_dc_ctl0;
|
||||
u32 db_debug3;
|
||||
u32 num_gs_verts_per_thread;
|
||||
u32 vgt_gs_per_es;
|
||||
u32 gs_prim_buffer_depth = 0;
|
||||
|
@ -1276,8 +1358,8 @@ static void r700_gfx_init(struct drm_device *dev,
|
|||
u32 sq_dyn_gpr_size_simd_ab_0;
|
||||
u32 backend_map;
|
||||
u32 gb_tiling_config = 0;
|
||||
u32 cc_rb_backend_disable = 0;
|
||||
u32 cc_gc_shader_pipe_config = 0;
|
||||
u32 cc_rb_backend_disable;
|
||||
u32 cc_gc_shader_pipe_config;
|
||||
u32 mc_arb_ramcfg;
|
||||
u32 db_debug4;
|
||||
|
||||
|
@ -1428,38 +1510,51 @@ static void r700_gfx_init(struct drm_device *dev,
|
|||
|
||||
gb_tiling_config |= R600_BANK_SWAPS(1);
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)
|
||||
backend_map = 0x28;
|
||||
else
|
||||
backend_map = r700_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
|
||||
dev_priv->r600_max_backends,
|
||||
(0xff << dev_priv->r600_max_backends) & 0xff);
|
||||
gb_tiling_config |= R600_BACKEND_MAP(backend_map);
|
||||
cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000;
|
||||
cc_rb_backend_disable |=
|
||||
R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
|
||||
|
||||
cc_gc_shader_pipe_config =
|
||||
cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
|
||||
cc_gc_shader_pipe_config |=
|
||||
R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK);
|
||||
cc_gc_shader_pipe_config |=
|
||||
R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK);
|
||||
|
||||
cc_rb_backend_disable =
|
||||
R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)
|
||||
backend_map = 0x28;
|
||||
else
|
||||
backend_map = r700_get_tile_pipe_to_backend_map(dev_priv,
|
||||
dev_priv->r600_max_tile_pipes,
|
||||
(R7XX_MAX_BACKENDS -
|
||||
r600_count_pipe_bits((cc_rb_backend_disable &
|
||||
R7XX_MAX_BACKENDS_MASK) >> 16)),
|
||||
(cc_rb_backend_disable >> 16));
|
||||
gb_tiling_config |= R600_BACKEND_MAP(backend_map);
|
||||
|
||||
RADEON_WRITE(R600_GB_TILING_CONFIG, gb_tiling_config);
|
||||
RADEON_WRITE(R600_DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
|
||||
RADEON_WRITE(R600_HDP_TILING_CONFIG, (gb_tiling_config & 0xffff));
|
||||
if (gb_tiling_config & 0xc0) {
|
||||
dev_priv->r600_group_size = 512;
|
||||
} else {
|
||||
dev_priv->r600_group_size = 256;
|
||||
}
|
||||
dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7);
|
||||
if (gb_tiling_config & 0x30) {
|
||||
dev_priv->r600_nbanks = 8;
|
||||
} else {
|
||||
dev_priv->r600_nbanks = 4;
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
|
||||
RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0);
|
||||
RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0);
|
||||
RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0);
|
||||
RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0);
|
||||
|
||||
num_qd_pipes =
|
||||
R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
|
||||
R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
|
||||
RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
|
||||
RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
|
||||
|
||||
|
@ -1469,10 +1564,8 @@ static void r700_gfx_init(struct drm_device *dev,
|
|||
|
||||
RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30));
|
||||
|
||||
RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
|
||||
R600_SYNC_GRADIENT |
|
||||
R600_SYNC_WALKER |
|
||||
R600_SYNC_ALIGNER));
|
||||
ta_aux_cntl = RADEON_READ(R600_TA_CNTL_AUX);
|
||||
RADEON_WRITE(R600_TA_CNTL_AUX, ta_aux_cntl | R600_DISABLE_CUBE_ANISO);
|
||||
|
||||
sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1);
|
||||
sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS;
|
||||
|
@ -1483,14 +1576,28 @@ static void r700_gfx_init(struct drm_device *dev,
|
|||
smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1);
|
||||
RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0);
|
||||
|
||||
RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
|
||||
R700_GS_FLUSH_CTL(4) |
|
||||
R700_ACK_FLUSH_CTL(3) |
|
||||
R700_SYNC_FLUSH_CTL));
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV740)
|
||||
RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
|
||||
R700_GS_FLUSH_CTL(4) |
|
||||
R700_ACK_FLUSH_CTL(3) |
|
||||
R700_SYNC_FLUSH_CTL));
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
|
||||
RADEON_WRITE(R700_DB_DEBUG3, R700_DB_CLK_OFF_DELAY(0x1f));
|
||||
else {
|
||||
db_debug3 = RADEON_READ(R700_DB_DEBUG3);
|
||||
db_debug3 &= ~R700_DB_CLK_OFF_DELAY(0x1f);
|
||||
switch (dev_priv->flags & RADEON_FAMILY_MASK) {
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV740:
|
||||
db_debug3 |= R700_DB_CLK_OFF_DELAY(0x1f);
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV730:
|
||||
default:
|
||||
db_debug3 |= R700_DB_CLK_OFF_DELAY(2);
|
||||
break;
|
||||
}
|
||||
RADEON_WRITE(R700_DB_DEBUG3, db_debug3);
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV770) {
|
||||
db_debug4 = RADEON_READ(RV700_DB_DEBUG4);
|
||||
db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER;
|
||||
RADEON_WRITE(RV700_DB_DEBUG4, db_debug4);
|
||||
|
@ -1519,10 +1626,10 @@ static void r700_gfx_init(struct drm_device *dev,
|
|||
R600_ALU_UPDATE_FIFO_HIWATER(0x8));
|
||||
switch (dev_priv->flags & RADEON_FAMILY_MASK) {
|
||||
case CHIP_RV770:
|
||||
sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
|
||||
break;
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
|
||||
break;
|
||||
case CHIP_RV740:
|
||||
default:
|
||||
sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
|
||||
|
@ -2529,3 +2636,12 @@ out:
|
|||
mutex_unlock(&dev_priv->cs_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size)
|
||||
{
|
||||
struct drm_radeon_private *dev_priv = dev->dev_private;
|
||||
|
||||
*npipes = dev_priv->r600_npipes;
|
||||
*nbanks = dev_priv->r600_nbanks;
|
||||
*group_size = dev_priv->r600_group_size;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "drmP.h"
|
||||
#include "radeon.h"
|
||||
#include "r600d.h"
|
||||
#include "r600_reg_safe.h"
|
||||
|
||||
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc);
|
||||
|
@ -35,11 +36,313 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
|||
struct radeon_cs_reloc **cs_reloc);
|
||||
typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
|
||||
static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
|
||||
extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
|
||||
|
||||
|
||||
struct r600_cs_track {
|
||||
u32 cb_color0_base_last;
|
||||
/* configuration we miror so that we use same code btw kms/ums */
|
||||
u32 group_size;
|
||||
u32 nbanks;
|
||||
u32 npipes;
|
||||
/* value we track */
|
||||
u32 nsamples;
|
||||
u32 cb_color_base_last[8];
|
||||
struct radeon_bo *cb_color_bo[8];
|
||||
u32 cb_color_bo_offset[8];
|
||||
struct radeon_bo *cb_color_frag_bo[8];
|
||||
struct radeon_bo *cb_color_tile_bo[8];
|
||||
u32 cb_color_info[8];
|
||||
u32 cb_color_size_idx[8];
|
||||
u32 cb_target_mask;
|
||||
u32 cb_shader_mask;
|
||||
u32 cb_color_size[8];
|
||||
u32 vgt_strmout_en;
|
||||
u32 vgt_strmout_buffer_en;
|
||||
u32 db_depth_control;
|
||||
u32 db_depth_info;
|
||||
u32 db_depth_size_idx;
|
||||
u32 db_depth_view;
|
||||
u32 db_depth_size;
|
||||
u32 db_offset;
|
||||
struct radeon_bo *db_bo;
|
||||
};
|
||||
|
||||
static inline int r600_bpe_from_format(u32 *bpe, u32 format)
|
||||
{
|
||||
switch (format) {
|
||||
case V_038004_COLOR_8:
|
||||
case V_038004_COLOR_4_4:
|
||||
case V_038004_COLOR_3_3_2:
|
||||
case V_038004_FMT_1:
|
||||
*bpe = 1;
|
||||
break;
|
||||
case V_038004_COLOR_16:
|
||||
case V_038004_COLOR_16_FLOAT:
|
||||
case V_038004_COLOR_8_8:
|
||||
case V_038004_COLOR_5_6_5:
|
||||
case V_038004_COLOR_6_5_5:
|
||||
case V_038004_COLOR_1_5_5_5:
|
||||
case V_038004_COLOR_4_4_4_4:
|
||||
case V_038004_COLOR_5_5_5_1:
|
||||
*bpe = 2;
|
||||
break;
|
||||
case V_038004_FMT_8_8_8:
|
||||
*bpe = 3;
|
||||
break;
|
||||
case V_038004_COLOR_32:
|
||||
case V_038004_COLOR_32_FLOAT:
|
||||
case V_038004_COLOR_16_16:
|
||||
case V_038004_COLOR_16_16_FLOAT:
|
||||
case V_038004_COLOR_8_24:
|
||||
case V_038004_COLOR_8_24_FLOAT:
|
||||
case V_038004_COLOR_24_8:
|
||||
case V_038004_COLOR_24_8_FLOAT:
|
||||
case V_038004_COLOR_10_11_11:
|
||||
case V_038004_COLOR_10_11_11_FLOAT:
|
||||
case V_038004_COLOR_11_11_10:
|
||||
case V_038004_COLOR_11_11_10_FLOAT:
|
||||
case V_038004_COLOR_2_10_10_10:
|
||||
case V_038004_COLOR_8_8_8_8:
|
||||
case V_038004_COLOR_10_10_10_2:
|
||||
case V_038004_FMT_5_9_9_9_SHAREDEXP:
|
||||
case V_038004_FMT_32_AS_8:
|
||||
case V_038004_FMT_32_AS_8_8:
|
||||
*bpe = 4;
|
||||
break;
|
||||
case V_038004_COLOR_X24_8_32_FLOAT:
|
||||
case V_038004_COLOR_32_32:
|
||||
case V_038004_COLOR_32_32_FLOAT:
|
||||
case V_038004_COLOR_16_16_16_16:
|
||||
case V_038004_COLOR_16_16_16_16_FLOAT:
|
||||
*bpe = 8;
|
||||
break;
|
||||
case V_038004_FMT_16_16_16:
|
||||
case V_038004_FMT_16_16_16_FLOAT:
|
||||
*bpe = 6;
|
||||
break;
|
||||
case V_038004_FMT_32_32_32:
|
||||
case V_038004_FMT_32_32_32_FLOAT:
|
||||
*bpe = 12;
|
||||
break;
|
||||
case V_038004_COLOR_32_32_32_32:
|
||||
case V_038004_COLOR_32_32_32_32_FLOAT:
|
||||
*bpe = 16;
|
||||
break;
|
||||
case V_038004_FMT_GB_GR:
|
||||
case V_038004_FMT_BG_RG:
|
||||
case V_038004_COLOR_INVALID:
|
||||
*bpe = 16;
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void r600_cs_track_init(struct r600_cs_track *track)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
track->cb_color_base_last[i] = 0;
|
||||
track->cb_color_size[i] = 0;
|
||||
track->cb_color_size_idx[i] = 0;
|
||||
track->cb_color_info[i] = 0;
|
||||
track->cb_color_bo[i] = NULL;
|
||||
track->cb_color_bo_offset[i] = 0xFFFFFFFF;
|
||||
}
|
||||
track->cb_target_mask = 0xFFFFFFFF;
|
||||
track->cb_shader_mask = 0xFFFFFFFF;
|
||||
track->db_bo = NULL;
|
||||
/* assume the biggest format and that htile is enabled */
|
||||
track->db_depth_info = 7 | (1 << 25);
|
||||
track->db_depth_view = 0xFFFFC000;
|
||||
track->db_depth_size = 0xFFFFFFFF;
|
||||
track->db_depth_size_idx = 0;
|
||||
track->db_depth_control = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
|
||||
{
|
||||
struct r600_cs_track *track = p->track;
|
||||
u32 bpe = 0, pitch, slice_tile_max, size, tmp, height;
|
||||
volatile u32 *ib = p->ib->ptr;
|
||||
|
||||
if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
|
||||
dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
size = radeon_bo_size(track->cb_color_bo[i]);
|
||||
if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
|
||||
dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
|
||||
__func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
|
||||
i, track->cb_color_info[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) << 3;
|
||||
slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
|
||||
if (!pitch) {
|
||||
dev_warn(p->dev, "%s:%d cb pitch (%d) for %d invalid (0x%08X)\n",
|
||||
__func__, __LINE__, pitch, i, track->cb_color_size[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
height = size / (pitch * bpe);
|
||||
if (height > 8192)
|
||||
height = 8192;
|
||||
switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) {
|
||||
case V_0280A0_ARRAY_LINEAR_GENERAL:
|
||||
case V_0280A0_ARRAY_LINEAR_ALIGNED:
|
||||
if (pitch & 0x3f) {
|
||||
dev_warn(p->dev, "%s:%d cb pitch (%d x %d = %d) invalid\n",
|
||||
__func__, __LINE__, pitch, bpe, pitch * bpe);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((pitch * bpe) & (track->group_size - 1)) {
|
||||
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||
__func__, __LINE__, pitch);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case V_0280A0_ARRAY_1D_TILED_THIN1:
|
||||
if ((pitch * 8 * bpe * track->nsamples) & (track->group_size - 1)) {
|
||||
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||
__func__, __LINE__, pitch);
|
||||
return -EINVAL;
|
||||
}
|
||||
height &= ~0x7;
|
||||
if (!height)
|
||||
height = 8;
|
||||
break;
|
||||
case V_0280A0_ARRAY_2D_TILED_THIN1:
|
||||
if (pitch & ((8 * track->nbanks) - 1)) {
|
||||
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||
__func__, __LINE__, pitch);
|
||||
return -EINVAL;
|
||||
}
|
||||
tmp = pitch * 8 * bpe * track->nsamples;
|
||||
tmp = tmp / track->nbanks;
|
||||
if (tmp & (track->group_size - 1)) {
|
||||
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
|
||||
__func__, __LINE__, pitch);
|
||||
return -EINVAL;
|
||||
}
|
||||
height &= ~((16 * track->npipes) - 1);
|
||||
if (!height)
|
||||
height = 16 * track->npipes;
|
||||
break;
|
||||
default:
|
||||
dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
|
||||
G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
|
||||
track->cb_color_info[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* check offset */
|
||||
tmp = height * pitch;
|
||||
if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
|
||||
dev_warn(p->dev, "%s offset[%d] %d to big\n", __func__, i, track->cb_color_bo_offset[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* limit max tile */
|
||||
tmp = (height * pitch) >> 6;
|
||||
if (tmp < slice_tile_max)
|
||||
slice_tile_max = tmp;
|
||||
tmp = S_028060_PITCH_TILE_MAX((pitch >> 3) - 1) |
|
||||
S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
|
||||
ib[track->cb_color_size_idx[i]] = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r600_cs_track_check(struct radeon_cs_parser *p)
|
||||
{
|
||||
struct r600_cs_track *track = p->track;
|
||||
u32 tmp;
|
||||
int r, i;
|
||||
volatile u32 *ib = p->ib->ptr;
|
||||
|
||||
/* on legacy kernel we don't perform advanced check */
|
||||
if (p->rdev == NULL)
|
||||
return 0;
|
||||
/* we don't support out buffer yet */
|
||||
if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
|
||||
dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* check that we have a cb for each enabled target, we don't check
|
||||
* shader_mask because it seems mesa isn't always setting it :(
|
||||
*/
|
||||
tmp = track->cb_target_mask;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((tmp >> (i * 4)) & 0xF) {
|
||||
/* at least one component is enabled */
|
||||
if (track->cb_color_bo[i] == NULL) {
|
||||
dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
|
||||
__func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* perform rewrite of CB_COLOR[0-7]_SIZE */
|
||||
r = r600_cs_track_validate_cb(p, i);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* Check depth buffer */
|
||||
if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
|
||||
G_028800_Z_ENABLE(track->db_depth_control)) {
|
||||
u32 nviews, bpe, ntiles;
|
||||
if (track->db_bo == NULL) {
|
||||
dev_warn(p->dev, "z/stencil with no depth buffer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
|
||||
dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (G_028010_FORMAT(track->db_depth_info)) {
|
||||
case V_028010_DEPTH_16:
|
||||
bpe = 2;
|
||||
break;
|
||||
case V_028010_DEPTH_X8_24:
|
||||
case V_028010_DEPTH_8_24:
|
||||
case V_028010_DEPTH_X8_24_FLOAT:
|
||||
case V_028010_DEPTH_8_24_FLOAT:
|
||||
case V_028010_DEPTH_32_FLOAT:
|
||||
bpe = 4;
|
||||
break;
|
||||
case V_028010_DEPTH_X24_8_32_FLOAT:
|
||||
bpe = 8;
|
||||
break;
|
||||
default:
|
||||
dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
|
||||
if (!track->db_depth_size_idx) {
|
||||
dev_warn(p->dev, "z/stencil buffer size not set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n");
|
||||
tmp = radeon_bo_size(track->db_bo) - track->db_offset;
|
||||
tmp = (tmp / bpe) >> 6;
|
||||
if (!tmp) {
|
||||
dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
|
||||
track->db_depth_size, bpe, track->db_offset,
|
||||
radeon_bo_size(track->db_bo));
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
|
||||
} else {
|
||||
ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
|
||||
nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
|
||||
tmp = ntiles * bpe * 64 * nviews;
|
||||
if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
|
||||
dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %d have %ld)\n",
|
||||
track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
|
||||
radeon_bo_size(track->db_bo));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_cs_packet_parse() - parse cp packet and point ib index to next packet
|
||||
* @parser: parser structure holding parsing context.
|
||||
|
@ -359,6 +662,334 @@ static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_cs_check_reg() - check if register is authorized or not
|
||||
* @parser: parser structure holding parsing context
|
||||
* @reg: register we are testing
|
||||
* @idx: index into the cs buffer
|
||||
*
|
||||
* This function will test against r600_reg_safe_bm and return 0
|
||||
* if register is safe. If register is not flag as safe this function
|
||||
* will test it against a list of register needind special handling.
|
||||
*/
|
||||
static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
|
||||
{
|
||||
struct r600_cs_track *track = (struct r600_cs_track *)p->track;
|
||||
struct radeon_cs_reloc *reloc;
|
||||
u32 last_reg = ARRAY_SIZE(r600_reg_safe_bm);
|
||||
u32 m, i, tmp, *ib;
|
||||
int r;
|
||||
|
||||
i = (reg >> 7);
|
||||
if (i > last_reg) {
|
||||
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
m = 1 << ((reg >> 2) & 31);
|
||||
if (!(r600_reg_safe_bm[i] & m))
|
||||
return 0;
|
||||
ib = p->ib->ptr;
|
||||
switch (reg) {
|
||||
/* force following reg to 0 in an attemp to disable out buffer
|
||||
* which will need us to better understand how it works to perform
|
||||
* security check on it (Jerome)
|
||||
*/
|
||||
case R_0288A8_SQ_ESGS_RING_ITEMSIZE:
|
||||
case R_008C44_SQ_ESGS_RING_SIZE:
|
||||
case R_0288B0_SQ_ESTMP_RING_ITEMSIZE:
|
||||
case R_008C54_SQ_ESTMP_RING_SIZE:
|
||||
case R_0288C0_SQ_FBUF_RING_ITEMSIZE:
|
||||
case R_008C74_SQ_FBUF_RING_SIZE:
|
||||
case R_0288B4_SQ_GSTMP_RING_ITEMSIZE:
|
||||
case R_008C5C_SQ_GSTMP_RING_SIZE:
|
||||
case R_0288AC_SQ_GSVS_RING_ITEMSIZE:
|
||||
case R_008C4C_SQ_GSVS_RING_SIZE:
|
||||
case R_0288BC_SQ_PSTMP_RING_ITEMSIZE:
|
||||
case R_008C6C_SQ_PSTMP_RING_SIZE:
|
||||
case R_0288C4_SQ_REDUC_RING_ITEMSIZE:
|
||||
case R_008C7C_SQ_REDUC_RING_SIZE:
|
||||
case R_0288B8_SQ_VSTMP_RING_ITEMSIZE:
|
||||
case R_008C64_SQ_VSTMP_RING_SIZE:
|
||||
case R_0288C8_SQ_GS_VERT_ITEMSIZE:
|
||||
/* get value to populate the IB don't remove */
|
||||
tmp =radeon_get_ib_value(p, idx);
|
||||
ib[idx] = 0;
|
||||
break;
|
||||
case R_028800_DB_DEPTH_CONTROL:
|
||||
track->db_depth_control = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028010_DB_DEPTH_INFO:
|
||||
track->db_depth_info = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028004_DB_DEPTH_VIEW:
|
||||
track->db_depth_view = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028000_DB_DEPTH_SIZE:
|
||||
track->db_depth_size = radeon_get_ib_value(p, idx);
|
||||
track->db_depth_size_idx = idx;
|
||||
break;
|
||||
case R_028AB0_VGT_STRMOUT_EN:
|
||||
track->vgt_strmout_en = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028B20_VGT_STRMOUT_BUFFER_EN:
|
||||
track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028238_CB_TARGET_MASK:
|
||||
track->cb_target_mask = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_02823C_CB_SHADER_MASK:
|
||||
track->cb_shader_mask = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028C04_PA_SC_AA_CONFIG:
|
||||
tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
|
||||
track->nsamples = 1 << tmp;
|
||||
break;
|
||||
case R_0280A0_CB_COLOR0_INFO:
|
||||
case R_0280A4_CB_COLOR1_INFO:
|
||||
case R_0280A8_CB_COLOR2_INFO:
|
||||
case R_0280AC_CB_COLOR3_INFO:
|
||||
case R_0280B0_CB_COLOR4_INFO:
|
||||
case R_0280B4_CB_COLOR5_INFO:
|
||||
case R_0280B8_CB_COLOR6_INFO:
|
||||
case R_0280BC_CB_COLOR7_INFO:
|
||||
tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
|
||||
track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
|
||||
break;
|
||||
case R_028060_CB_COLOR0_SIZE:
|
||||
case R_028064_CB_COLOR1_SIZE:
|
||||
case R_028068_CB_COLOR2_SIZE:
|
||||
case R_02806C_CB_COLOR3_SIZE:
|
||||
case R_028070_CB_COLOR4_SIZE:
|
||||
case R_028074_CB_COLOR5_SIZE:
|
||||
case R_028078_CB_COLOR6_SIZE:
|
||||
case R_02807C_CB_COLOR7_SIZE:
|
||||
tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
|
||||
track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
|
||||
track->cb_color_size_idx[tmp] = idx;
|
||||
break;
|
||||
/* This register were added late, there is userspace
|
||||
* which does provide relocation for those but set
|
||||
* 0 offset. In order to avoid breaking old userspace
|
||||
* we detect this and set address to point to last
|
||||
* CB_COLOR0_BASE, note that if userspace doesn't set
|
||||
* CB_COLOR0_BASE before this register we will report
|
||||
* error. Old userspace always set CB_COLOR0_BASE
|
||||
* before any of this.
|
||||
*/
|
||||
case R_0280E0_CB_COLOR0_FRAG:
|
||||
case R_0280E4_CB_COLOR1_FRAG:
|
||||
case R_0280E8_CB_COLOR2_FRAG:
|
||||
case R_0280EC_CB_COLOR3_FRAG:
|
||||
case R_0280F0_CB_COLOR4_FRAG:
|
||||
case R_0280F4_CB_COLOR5_FRAG:
|
||||
case R_0280F8_CB_COLOR6_FRAG:
|
||||
case R_0280FC_CB_COLOR7_FRAG:
|
||||
tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
|
||||
if (!r600_cs_packet_next_is_pkt3_nop(p)) {
|
||||
if (!track->cb_color_base_last[tmp]) {
|
||||
dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx] = track->cb_color_base_last[tmp];
|
||||
printk_once(KERN_WARNING "You have old & broken userspace "
|
||||
"please consider updating mesa & xf86-video-ati\n");
|
||||
track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
|
||||
} else {
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
track->cb_color_frag_bo[tmp] = reloc->robj;
|
||||
}
|
||||
break;
|
||||
case R_0280C0_CB_COLOR0_TILE:
|
||||
case R_0280C4_CB_COLOR1_TILE:
|
||||
case R_0280C8_CB_COLOR2_TILE:
|
||||
case R_0280CC_CB_COLOR3_TILE:
|
||||
case R_0280D0_CB_COLOR4_TILE:
|
||||
case R_0280D4_CB_COLOR5_TILE:
|
||||
case R_0280D8_CB_COLOR6_TILE:
|
||||
case R_0280DC_CB_COLOR7_TILE:
|
||||
tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
|
||||
if (!r600_cs_packet_next_is_pkt3_nop(p)) {
|
||||
if (!track->cb_color_base_last[tmp]) {
|
||||
dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx] = track->cb_color_base_last[tmp];
|
||||
printk_once(KERN_WARNING "You have old & broken userspace "
|
||||
"please consider updating mesa & xf86-video-ati\n");
|
||||
track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
|
||||
} else {
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
track->cb_color_tile_bo[tmp] = reloc->robj;
|
||||
}
|
||||
break;
|
||||
case CB_COLOR0_BASE:
|
||||
case CB_COLOR1_BASE:
|
||||
case CB_COLOR2_BASE:
|
||||
case CB_COLOR3_BASE:
|
||||
case CB_COLOR4_BASE:
|
||||
case CB_COLOR5_BASE:
|
||||
case CB_COLOR6_BASE:
|
||||
case CB_COLOR7_BASE:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
dev_warn(p->dev, "bad SET_CONTEXT_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
tmp = (reg - CB_COLOR0_BASE) / 4;
|
||||
track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
|
||||
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
track->cb_color_base_last[tmp] = ib[idx];
|
||||
track->cb_color_bo[tmp] = reloc->robj;
|
||||
break;
|
||||
case DB_DEPTH_BASE:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
dev_warn(p->dev, "bad SET_CONTEXT_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
track->db_offset = radeon_get_ib_value(p, idx);
|
||||
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
track->db_bo = reloc->robj;
|
||||
break;
|
||||
case DB_HTILE_DATA_BASE:
|
||||
case SQ_PGM_START_FS:
|
||||
case SQ_PGM_START_ES:
|
||||
case SQ_PGM_START_VS:
|
||||
case SQ_PGM_START_GS:
|
||||
case SQ_PGM_START_PS:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
dev_warn(p->dev, "bad SET_CONTEXT_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
break;
|
||||
default:
|
||||
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned minify(unsigned size, unsigned levels)
|
||||
{
|
||||
size = size >> levels;
|
||||
if (size < 1)
|
||||
size = 1;
|
||||
return size;
|
||||
}
|
||||
|
||||
static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels,
|
||||
unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
|
||||
unsigned *l0_size, unsigned *mipmap_size)
|
||||
{
|
||||
unsigned offset, i, level, face;
|
||||
unsigned width, height, depth, rowstride, size;
|
||||
|
||||
w0 = minify(w0, 0);
|
||||
h0 = minify(h0, 0);
|
||||
d0 = minify(d0, 0);
|
||||
for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
|
||||
width = minify(w0, i);
|
||||
height = minify(h0, i);
|
||||
depth = minify(d0, i);
|
||||
for(face = 0; face < nfaces; face++) {
|
||||
rowstride = ((width * bpe) + 255) & ~255;
|
||||
size = height * rowstride * depth;
|
||||
offset += size;
|
||||
offset = (offset + 0x1f) & ~0x1f;
|
||||
}
|
||||
}
|
||||
*l0_size = (((w0 * bpe) + 255) & ~255) * h0 * d0;
|
||||
*mipmap_size = offset;
|
||||
if (!blevel)
|
||||
*mipmap_size -= *l0_size;
|
||||
if (!nlevels)
|
||||
*mipmap_size = *l0_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_check_texture_resource() - check if register is authorized or not
|
||||
* @p: parser structure holding parsing context
|
||||
* @idx: index into the cs buffer
|
||||
* @texture: texture's bo structure
|
||||
* @mipmap: mipmap's bo structure
|
||||
*
|
||||
* This function will check that the resource has valid field and that
|
||||
* the texture and mipmap bo object are big enough to cover this resource.
|
||||
*/
|
||||
static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
|
||||
struct radeon_bo *texture,
|
||||
struct radeon_bo *mipmap)
|
||||
{
|
||||
u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
|
||||
u32 word0, word1, l0_size, mipmap_size;
|
||||
|
||||
/* on legacy kernel we don't perform advanced check */
|
||||
if (p->rdev == NULL)
|
||||
return 0;
|
||||
word0 = radeon_get_ib_value(p, idx + 0);
|
||||
word1 = radeon_get_ib_value(p, idx + 1);
|
||||
w0 = G_038000_TEX_WIDTH(word0) + 1;
|
||||
h0 = G_038004_TEX_HEIGHT(word1) + 1;
|
||||
d0 = G_038004_TEX_DEPTH(word1);
|
||||
nfaces = 1;
|
||||
switch (G_038000_DIM(word0)) {
|
||||
case V_038000_SQ_TEX_DIM_1D:
|
||||
case V_038000_SQ_TEX_DIM_2D:
|
||||
case V_038000_SQ_TEX_DIM_3D:
|
||||
break;
|
||||
case V_038000_SQ_TEX_DIM_CUBEMAP:
|
||||
nfaces = 6;
|
||||
break;
|
||||
case V_038000_SQ_TEX_DIM_1D_ARRAY:
|
||||
case V_038000_SQ_TEX_DIM_2D_ARRAY:
|
||||
case V_038000_SQ_TEX_DIM_2D_MSAA:
|
||||
case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
|
||||
default:
|
||||
dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r600_bpe_from_format(&bpe, G_038004_DATA_FORMAT(word1))) {
|
||||
dev_warn(p->dev, "%s:%d texture invalid format %d\n",
|
||||
__func__, __LINE__, G_038004_DATA_FORMAT(word1));
|
||||
return -EINVAL;
|
||||
}
|
||||
word0 = radeon_get_ib_value(p, idx + 4);
|
||||
word1 = radeon_get_ib_value(p, idx + 5);
|
||||
blevel = G_038010_BASE_LEVEL(word0);
|
||||
nlevels = G_038014_LAST_LEVEL(word1);
|
||||
r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, &l0_size, &mipmap_size);
|
||||
/* using get ib will give us the offset into the texture bo */
|
||||
word0 = radeon_get_ib_value(p, idx + 2);
|
||||
if ((l0_size + word0) > radeon_bo_size(texture)) {
|
||||
dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
|
||||
w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
|
||||
return -EINVAL;
|
||||
}
|
||||
/* using get ib will give us the offset into the mipmap bo */
|
||||
word0 = radeon_get_ib_value(p, idx + 3);
|
||||
if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
|
||||
dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
|
||||
w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r600_packet3_check(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt)
|
||||
{
|
||||
|
@ -408,12 +1039,22 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
}
|
||||
ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
|
||||
ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
|
||||
r = r600_cs_track_check(p);
|
||||
if (r) {
|
||||
dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_DRAW_INDEX_AUTO:
|
||||
if (pkt->count != 1) {
|
||||
DRM_ERROR("bad DRAW_INDEX_AUTO\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = r600_cs_track_check(p);
|
||||
if (r) {
|
||||
dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_DRAW_INDEX_IMMD_BE:
|
||||
case PACKET3_DRAW_INDEX_IMMD:
|
||||
|
@ -421,6 +1062,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
DRM_ERROR("bad DRAW_INDEX_IMMD\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = r600_cs_track_check(p);
|
||||
if (r) {
|
||||
dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_WAIT_REG_MEM:
|
||||
if (pkt->count != 5) {
|
||||
|
@ -493,30 +1139,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
}
|
||||
for (i = 0; i < pkt->count; i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
switch (reg) {
|
||||
case SQ_ESGS_RING_BASE:
|
||||
case SQ_GSVS_RING_BASE:
|
||||
case SQ_ESTMP_RING_BASE:
|
||||
case SQ_GSTMP_RING_BASE:
|
||||
case SQ_VSTMP_RING_BASE:
|
||||
case SQ_PSTMP_RING_BASE:
|
||||
case SQ_FBUF_RING_BASE:
|
||||
case SQ_REDUC_RING_BASE:
|
||||
case SX_MEMORY_EXPORT_BASE:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_CONFIG_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
break;
|
||||
case CP_COHER_BASE:
|
||||
/* use PACKET3_SURFACE_SYNC */
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
r = r600_cs_check_reg(p, reg, idx+1+i);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_CONTEXT_REG:
|
||||
|
@ -530,106 +1155,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
}
|
||||
for (i = 0; i < pkt->count; i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
switch (reg) {
|
||||
/* This register were added late, there is userspace
|
||||
* which does provide relocation for those but set
|
||||
* 0 offset. In order to avoid breaking old userspace
|
||||
* we detect this and set address to point to last
|
||||
* CB_COLOR0_BASE, note that if userspace doesn't set
|
||||
* CB_COLOR0_BASE before this register we will report
|
||||
* error. Old userspace always set CB_COLOR0_BASE
|
||||
* before any of this.
|
||||
*/
|
||||
case R_0280E0_CB_COLOR0_FRAG:
|
||||
case R_0280E4_CB_COLOR1_FRAG:
|
||||
case R_0280E8_CB_COLOR2_FRAG:
|
||||
case R_0280EC_CB_COLOR3_FRAG:
|
||||
case R_0280F0_CB_COLOR4_FRAG:
|
||||
case R_0280F4_CB_COLOR5_FRAG:
|
||||
case R_0280F8_CB_COLOR6_FRAG:
|
||||
case R_0280FC_CB_COLOR7_FRAG:
|
||||
case R_0280C0_CB_COLOR0_TILE:
|
||||
case R_0280C4_CB_COLOR1_TILE:
|
||||
case R_0280C8_CB_COLOR2_TILE:
|
||||
case R_0280CC_CB_COLOR3_TILE:
|
||||
case R_0280D0_CB_COLOR4_TILE:
|
||||
case R_0280D4_CB_COLOR5_TILE:
|
||||
case R_0280D8_CB_COLOR6_TILE:
|
||||
case R_0280DC_CB_COLOR7_TILE:
|
||||
if (!r600_cs_packet_next_is_pkt3_nop(p)) {
|
||||
if (!track->cb_color0_base_last) {
|
||||
dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+i] = track->cb_color0_base_last;
|
||||
printk_once(KERN_WARNING "radeon: You have old & broken userspace "
|
||||
"please consider updating mesa & xf86-video-ati\n");
|
||||
} else {
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
}
|
||||
break;
|
||||
case DB_DEPTH_BASE:
|
||||
case DB_HTILE_DATA_BASE:
|
||||
case CB_COLOR0_BASE:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_CONTEXT_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
track->cb_color0_base_last = ib[idx+1+i];
|
||||
break;
|
||||
case CB_COLOR1_BASE:
|
||||
case CB_COLOR2_BASE:
|
||||
case CB_COLOR3_BASE:
|
||||
case CB_COLOR4_BASE:
|
||||
case CB_COLOR5_BASE:
|
||||
case CB_COLOR6_BASE:
|
||||
case CB_COLOR7_BASE:
|
||||
case SQ_PGM_START_FS:
|
||||
case SQ_PGM_START_ES:
|
||||
case SQ_PGM_START_VS:
|
||||
case SQ_PGM_START_GS:
|
||||
case SQ_PGM_START_PS:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_CONTEXT_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
break;
|
||||
case VGT_DMA_BASE:
|
||||
case VGT_DMA_BASE_HI:
|
||||
/* These should be handled by DRAW_INDEX packet 3 */
|
||||
case VGT_STRMOUT_BASE_OFFSET_0:
|
||||
case VGT_STRMOUT_BASE_OFFSET_1:
|
||||
case VGT_STRMOUT_BASE_OFFSET_2:
|
||||
case VGT_STRMOUT_BASE_OFFSET_3:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_0:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_1:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_2:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_3:
|
||||
case VGT_STRMOUT_BUFFER_BASE_0:
|
||||
case VGT_STRMOUT_BUFFER_BASE_1:
|
||||
case VGT_STRMOUT_BUFFER_BASE_2:
|
||||
case VGT_STRMOUT_BUFFER_BASE_3:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_0:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_1:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_2:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_3:
|
||||
/* These should be handled by STRMOUT_BUFFER packet 3 */
|
||||
DRM_ERROR("bad context reg: 0x%08x\n", reg);
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
r = r600_cs_check_reg(p, reg, idx+1+i);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_RESOURCE:
|
||||
|
@ -646,6 +1174,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < (pkt->count / 7); i++) {
|
||||
struct radeon_bo *texture, *mipmap;
|
||||
u32 size, offset;
|
||||
|
||||
switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
|
||||
case SQ_TEX_VTX_VALID_TEXTURE:
|
||||
/* tex base */
|
||||
|
@ -655,6 +1186,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
texture = reloc->robj;
|
||||
/* tex mip base */
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
|
@ -662,6 +1194,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
mipmap = reloc->robj;
|
||||
r = r600_check_texture_resource(p, idx+(i*7)+1,
|
||||
texture, mipmap);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
case SQ_TEX_VTX_VALID_BUFFER:
|
||||
/* vtx base */
|
||||
|
@ -670,6 +1207,13 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
|
||||
size = radeon_get_ib_value(p, idx+1+(i*7)+1);
|
||||
if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
|
||||
/* force size to size of the buffer */
|
||||
dev_warn(p->dev, "vbo resource seems too big for the bo\n");
|
||||
ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj);
|
||||
}
|
||||
ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
|
||||
ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
|
||||
break;
|
||||
|
@ -760,11 +1304,28 @@ int r600_cs_parse(struct radeon_cs_parser *p)
|
|||
struct r600_cs_track *track;
|
||||
int r;
|
||||
|
||||
track = kzalloc(sizeof(*track), GFP_KERNEL);
|
||||
p->track = track;
|
||||
if (p->track == NULL) {
|
||||
/* initialize tracker, we are in kms */
|
||||
track = kzalloc(sizeof(*track), GFP_KERNEL);
|
||||
if (track == NULL)
|
||||
return -ENOMEM;
|
||||
r600_cs_track_init(track);
|
||||
if (p->rdev->family < CHIP_RV770) {
|
||||
track->npipes = p->rdev->config.r600.tiling_npipes;
|
||||
track->nbanks = p->rdev->config.r600.tiling_nbanks;
|
||||
track->group_size = p->rdev->config.r600.tiling_group_size;
|
||||
} else if (p->rdev->family <= CHIP_RV740) {
|
||||
track->npipes = p->rdev->config.rv770.tiling_npipes;
|
||||
track->nbanks = p->rdev->config.rv770.tiling_nbanks;
|
||||
track->group_size = p->rdev->config.rv770.tiling_group_size;
|
||||
}
|
||||
p->track = track;
|
||||
}
|
||||
do {
|
||||
r = r600_cs_packet_parse(p, &pkt, p->idx);
|
||||
if (r) {
|
||||
kfree(p->track);
|
||||
p->track = NULL;
|
||||
return r;
|
||||
}
|
||||
p->idx += pkt.count + 2;
|
||||
|
@ -779,9 +1340,13 @@ int r600_cs_parse(struct radeon_cs_parser *p)
|
|||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown packet type %d !\n", pkt.type);
|
||||
kfree(p->track);
|
||||
p->track = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r) {
|
||||
kfree(p->track);
|
||||
p->track = NULL;
|
||||
return r;
|
||||
}
|
||||
} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
|
||||
|
@ -791,6 +1356,8 @@ int r600_cs_parse(struct radeon_cs_parser *p)
|
|||
mdelay(1);
|
||||
}
|
||||
#endif
|
||||
kfree(p->track);
|
||||
p->track = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -833,9 +1400,16 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
|
|||
{
|
||||
struct radeon_cs_parser parser;
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_ib fake_ib;
|
||||
struct radeon_ib fake_ib;
|
||||
struct r600_cs_track *track;
|
||||
int r;
|
||||
|
||||
/* initialize tracker */
|
||||
track = kzalloc(sizeof(*track), GFP_KERNEL);
|
||||
if (track == NULL)
|
||||
return -ENOMEM;
|
||||
r600_cs_track_init(track);
|
||||
r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size);
|
||||
/* initialize parser */
|
||||
memset(&parser, 0, sizeof(struct radeon_cs_parser));
|
||||
parser.filp = filp;
|
||||
|
@ -843,6 +1417,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
|
|||
parser.rdev = NULL;
|
||||
parser.family = family;
|
||||
parser.ib = &fake_ib;
|
||||
parser.track = track;
|
||||
fake_ib.ptr = ib;
|
||||
r = radeon_cs_parser_init(&parser, data);
|
||||
if (r) {
|
||||
|
|
|
@ -883,6 +883,16 @@
|
|||
|
||||
#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480
|
||||
|
||||
#define R_028C04_PA_SC_AA_CONFIG 0x028C04
|
||||
#define S_028C04_MSAA_NUM_SAMPLES(x) (((x) & 0x3) << 0)
|
||||
#define G_028C04_MSAA_NUM_SAMPLES(x) (((x) >> 0) & 0x3)
|
||||
#define C_028C04_MSAA_NUM_SAMPLES 0xFFFFFFFC
|
||||
#define S_028C04_AA_MASK_CENTROID_DTMN(x) (((x) & 0x1) << 4)
|
||||
#define G_028C04_AA_MASK_CENTROID_DTMN(x) (((x) >> 4) & 0x1)
|
||||
#define C_028C04_AA_MASK_CENTROID_DTMN 0xFFFFFFEF
|
||||
#define S_028C04_MAX_SAMPLE_DIST(x) (((x) & 0xF) << 13)
|
||||
#define G_028C04_MAX_SAMPLE_DIST(x) (((x) >> 13) & 0xF)
|
||||
#define C_028C04_MAX_SAMPLE_DIST 0xFFFE1FFF
|
||||
#define R_0280E0_CB_COLOR0_FRAG 0x0280E0
|
||||
#define S_0280E0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_0280E0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
|
@ -905,6 +915,461 @@
|
|||
#define R_0280D4_CB_COLOR5_TILE 0x0280D4
|
||||
#define R_0280D8_CB_COLOR6_TILE 0x0280D8
|
||||
#define R_0280DC_CB_COLOR7_TILE 0x0280DC
|
||||
|
||||
#define R_0280A0_CB_COLOR0_INFO 0x0280A0
|
||||
#define S_0280A0_ENDIAN(x) (((x) & 0x3) << 0)
|
||||
#define G_0280A0_ENDIAN(x) (((x) >> 0) & 0x3)
|
||||
#define C_0280A0_ENDIAN 0xFFFFFFFC
|
||||
#define S_0280A0_FORMAT(x) (((x) & 0x3F) << 2)
|
||||
#define G_0280A0_FORMAT(x) (((x) >> 2) & 0x3F)
|
||||
#define C_0280A0_FORMAT 0xFFFFFF03
|
||||
#define V_0280A0_COLOR_INVALID 0x00000000
|
||||
#define V_0280A0_COLOR_8 0x00000001
|
||||
#define V_0280A0_COLOR_4_4 0x00000002
|
||||
#define V_0280A0_COLOR_3_3_2 0x00000003
|
||||
#define V_0280A0_COLOR_16 0x00000005
|
||||
#define V_0280A0_COLOR_16_FLOAT 0x00000006
|
||||
#define V_0280A0_COLOR_8_8 0x00000007
|
||||
#define V_0280A0_COLOR_5_6_5 0x00000008
|
||||
#define V_0280A0_COLOR_6_5_5 0x00000009
|
||||
#define V_0280A0_COLOR_1_5_5_5 0x0000000A
|
||||
#define V_0280A0_COLOR_4_4_4_4 0x0000000B
|
||||
#define V_0280A0_COLOR_5_5_5_1 0x0000000C
|
||||
#define V_0280A0_COLOR_32 0x0000000D
|
||||
#define V_0280A0_COLOR_32_FLOAT 0x0000000E
|
||||
#define V_0280A0_COLOR_16_16 0x0000000F
|
||||
#define V_0280A0_COLOR_16_16_FLOAT 0x00000010
|
||||
#define V_0280A0_COLOR_8_24 0x00000011
|
||||
#define V_0280A0_COLOR_8_24_FLOAT 0x00000012
|
||||
#define V_0280A0_COLOR_24_8 0x00000013
|
||||
#define V_0280A0_COLOR_24_8_FLOAT 0x00000014
|
||||
#define V_0280A0_COLOR_10_11_11 0x00000015
|
||||
#define V_0280A0_COLOR_10_11_11_FLOAT 0x00000016
|
||||
#define V_0280A0_COLOR_11_11_10 0x00000017
|
||||
#define V_0280A0_COLOR_11_11_10_FLOAT 0x00000018
|
||||
#define V_0280A0_COLOR_2_10_10_10 0x00000019
|
||||
#define V_0280A0_COLOR_8_8_8_8 0x0000001A
|
||||
#define V_0280A0_COLOR_10_10_10_2 0x0000001B
|
||||
#define V_0280A0_COLOR_X24_8_32_FLOAT 0x0000001C
|
||||
#define V_0280A0_COLOR_32_32 0x0000001D
|
||||
#define V_0280A0_COLOR_32_32_FLOAT 0x0000001E
|
||||
#define V_0280A0_COLOR_16_16_16_16 0x0000001F
|
||||
#define V_0280A0_COLOR_16_16_16_16_FLOAT 0x00000020
|
||||
#define V_0280A0_COLOR_32_32_32_32 0x00000022
|
||||
#define V_0280A0_COLOR_32_32_32_32_FLOAT 0x00000023
|
||||
#define S_0280A0_ARRAY_MODE(x) (((x) & 0xF) << 8)
|
||||
#define G_0280A0_ARRAY_MODE(x) (((x) >> 8) & 0xF)
|
||||
#define C_0280A0_ARRAY_MODE 0xFFFFF0FF
|
||||
#define V_0280A0_ARRAY_LINEAR_GENERAL 0x00000000
|
||||
#define V_0280A0_ARRAY_LINEAR_ALIGNED 0x00000001
|
||||
#define V_0280A0_ARRAY_1D_TILED_THIN1 0x00000002
|
||||
#define V_0280A0_ARRAY_2D_TILED_THIN1 0x00000004
|
||||
#define S_0280A0_NUMBER_TYPE(x) (((x) & 0x7) << 12)
|
||||
#define G_0280A0_NUMBER_TYPE(x) (((x) >> 12) & 0x7)
|
||||
#define C_0280A0_NUMBER_TYPE 0xFFFF8FFF
|
||||
#define S_0280A0_READ_SIZE(x) (((x) & 0x1) << 15)
|
||||
#define G_0280A0_READ_SIZE(x) (((x) >> 15) & 0x1)
|
||||
#define C_0280A0_READ_SIZE 0xFFFF7FFF
|
||||
#define S_0280A0_COMP_SWAP(x) (((x) & 0x3) << 16)
|
||||
#define G_0280A0_COMP_SWAP(x) (((x) >> 16) & 0x3)
|
||||
#define C_0280A0_COMP_SWAP 0xFFFCFFFF
|
||||
#define S_0280A0_TILE_MODE(x) (((x) & 0x3) << 18)
|
||||
#define G_0280A0_TILE_MODE(x) (((x) >> 18) & 0x3)
|
||||
#define C_0280A0_TILE_MODE 0xFFF3FFFF
|
||||
#define S_0280A0_BLEND_CLAMP(x) (((x) & 0x1) << 20)
|
||||
#define G_0280A0_BLEND_CLAMP(x) (((x) >> 20) & 0x1)
|
||||
#define C_0280A0_BLEND_CLAMP 0xFFEFFFFF
|
||||
#define S_0280A0_CLEAR_COLOR(x) (((x) & 0x1) << 21)
|
||||
#define G_0280A0_CLEAR_COLOR(x) (((x) >> 21) & 0x1)
|
||||
#define C_0280A0_CLEAR_COLOR 0xFFDFFFFF
|
||||
#define S_0280A0_BLEND_BYPASS(x) (((x) & 0x1) << 22)
|
||||
#define G_0280A0_BLEND_BYPASS(x) (((x) >> 22) & 0x1)
|
||||
#define C_0280A0_BLEND_BYPASS 0xFFBFFFFF
|
||||
#define S_0280A0_BLEND_FLOAT32(x) (((x) & 0x1) << 23)
|
||||
#define G_0280A0_BLEND_FLOAT32(x) (((x) >> 23) & 0x1)
|
||||
#define C_0280A0_BLEND_FLOAT32 0xFF7FFFFF
|
||||
#define S_0280A0_SIMPLE_FLOAT(x) (((x) & 0x1) << 24)
|
||||
#define G_0280A0_SIMPLE_FLOAT(x) (((x) >> 24) & 0x1)
|
||||
#define C_0280A0_SIMPLE_FLOAT 0xFEFFFFFF
|
||||
#define S_0280A0_ROUND_MODE(x) (((x) & 0x1) << 25)
|
||||
#define G_0280A0_ROUND_MODE(x) (((x) >> 25) & 0x1)
|
||||
#define C_0280A0_ROUND_MODE 0xFDFFFFFF
|
||||
#define S_0280A0_TILE_COMPACT(x) (((x) & 0x1) << 26)
|
||||
#define G_0280A0_TILE_COMPACT(x) (((x) >> 26) & 0x1)
|
||||
#define C_0280A0_TILE_COMPACT 0xFBFFFFFF
|
||||
#define S_0280A0_SOURCE_FORMAT(x) (((x) & 0x1) << 27)
|
||||
#define G_0280A0_SOURCE_FORMAT(x) (((x) >> 27) & 0x1)
|
||||
#define C_0280A0_SOURCE_FORMAT 0xF7FFFFFF
|
||||
#define R_0280A4_CB_COLOR1_INFO 0x0280A4
|
||||
#define R_0280A8_CB_COLOR2_INFO 0x0280A8
|
||||
#define R_0280AC_CB_COLOR3_INFO 0x0280AC
|
||||
#define R_0280B0_CB_COLOR4_INFO 0x0280B0
|
||||
#define R_0280B4_CB_COLOR5_INFO 0x0280B4
|
||||
#define R_0280B8_CB_COLOR6_INFO 0x0280B8
|
||||
#define R_0280BC_CB_COLOR7_INFO 0x0280BC
|
||||
#define R_028060_CB_COLOR0_SIZE 0x028060
|
||||
#define S_028060_PITCH_TILE_MAX(x) (((x) & 0x3FF) << 0)
|
||||
#define G_028060_PITCH_TILE_MAX(x) (((x) >> 0) & 0x3FF)
|
||||
#define C_028060_PITCH_TILE_MAX 0xFFFFFC00
|
||||
#define S_028060_SLICE_TILE_MAX(x) (((x) & 0xFFFFF) << 10)
|
||||
#define G_028060_SLICE_TILE_MAX(x) (((x) >> 10) & 0xFFFFF)
|
||||
#define C_028060_SLICE_TILE_MAX 0xC00003FF
|
||||
#define R_028064_CB_COLOR1_SIZE 0x028064
|
||||
#define R_028068_CB_COLOR2_SIZE 0x028068
|
||||
#define R_02806C_CB_COLOR3_SIZE 0x02806C
|
||||
#define R_028070_CB_COLOR4_SIZE 0x028070
|
||||
#define R_028074_CB_COLOR5_SIZE 0x028074
|
||||
#define R_028078_CB_COLOR6_SIZE 0x028078
|
||||
#define R_02807C_CB_COLOR7_SIZE 0x02807C
|
||||
#define R_028238_CB_TARGET_MASK 0x028238
|
||||
#define S_028238_TARGET0_ENABLE(x) (((x) & 0xF) << 0)
|
||||
#define G_028238_TARGET0_ENABLE(x) (((x) >> 0) & 0xF)
|
||||
#define C_028238_TARGET0_ENABLE 0xFFFFFFF0
|
||||
#define S_028238_TARGET1_ENABLE(x) (((x) & 0xF) << 4)
|
||||
#define G_028238_TARGET1_ENABLE(x) (((x) >> 4) & 0xF)
|
||||
#define C_028238_TARGET1_ENABLE 0xFFFFFF0F
|
||||
#define S_028238_TARGET2_ENABLE(x) (((x) & 0xF) << 8)
|
||||
#define G_028238_TARGET2_ENABLE(x) (((x) >> 8) & 0xF)
|
||||
#define C_028238_TARGET2_ENABLE 0xFFFFF0FF
|
||||
#define S_028238_TARGET3_ENABLE(x) (((x) & 0xF) << 12)
|
||||
#define G_028238_TARGET3_ENABLE(x) (((x) >> 12) & 0xF)
|
||||
#define C_028238_TARGET3_ENABLE 0xFFFF0FFF
|
||||
#define S_028238_TARGET4_ENABLE(x) (((x) & 0xF) << 16)
|
||||
#define G_028238_TARGET4_ENABLE(x) (((x) >> 16) & 0xF)
|
||||
#define C_028238_TARGET4_ENABLE 0xFFF0FFFF
|
||||
#define S_028238_TARGET5_ENABLE(x) (((x) & 0xF) << 20)
|
||||
#define G_028238_TARGET5_ENABLE(x) (((x) >> 20) & 0xF)
|
||||
#define C_028238_TARGET5_ENABLE 0xFF0FFFFF
|
||||
#define S_028238_TARGET6_ENABLE(x) (((x) & 0xF) << 24)
|
||||
#define G_028238_TARGET6_ENABLE(x) (((x) >> 24) & 0xF)
|
||||
#define C_028238_TARGET6_ENABLE 0xF0FFFFFF
|
||||
#define S_028238_TARGET7_ENABLE(x) (((x) & 0xF) << 28)
|
||||
#define G_028238_TARGET7_ENABLE(x) (((x) >> 28) & 0xF)
|
||||
#define C_028238_TARGET7_ENABLE 0x0FFFFFFF
|
||||
#define R_02823C_CB_SHADER_MASK 0x02823C
|
||||
#define S_02823C_OUTPUT0_ENABLE(x) (((x) & 0xF) << 0)
|
||||
#define G_02823C_OUTPUT0_ENABLE(x) (((x) >> 0) & 0xF)
|
||||
#define C_02823C_OUTPUT0_ENABLE 0xFFFFFFF0
|
||||
#define S_02823C_OUTPUT1_ENABLE(x) (((x) & 0xF) << 4)
|
||||
#define G_02823C_OUTPUT1_ENABLE(x) (((x) >> 4) & 0xF)
|
||||
#define C_02823C_OUTPUT1_ENABLE 0xFFFFFF0F
|
||||
#define S_02823C_OUTPUT2_ENABLE(x) (((x) & 0xF) << 8)
|
||||
#define G_02823C_OUTPUT2_ENABLE(x) (((x) >> 8) & 0xF)
|
||||
#define C_02823C_OUTPUT2_ENABLE 0xFFFFF0FF
|
||||
#define S_02823C_OUTPUT3_ENABLE(x) (((x) & 0xF) << 12)
|
||||
#define G_02823C_OUTPUT3_ENABLE(x) (((x) >> 12) & 0xF)
|
||||
#define C_02823C_OUTPUT3_ENABLE 0xFFFF0FFF
|
||||
#define S_02823C_OUTPUT4_ENABLE(x) (((x) & 0xF) << 16)
|
||||
#define G_02823C_OUTPUT4_ENABLE(x) (((x) >> 16) & 0xF)
|
||||
#define C_02823C_OUTPUT4_ENABLE 0xFFF0FFFF
|
||||
#define S_02823C_OUTPUT5_ENABLE(x) (((x) & 0xF) << 20)
|
||||
#define G_02823C_OUTPUT5_ENABLE(x) (((x) >> 20) & 0xF)
|
||||
#define C_02823C_OUTPUT5_ENABLE 0xFF0FFFFF
|
||||
#define S_02823C_OUTPUT6_ENABLE(x) (((x) & 0xF) << 24)
|
||||
#define G_02823C_OUTPUT6_ENABLE(x) (((x) >> 24) & 0xF)
|
||||
#define C_02823C_OUTPUT6_ENABLE 0xF0FFFFFF
|
||||
#define S_02823C_OUTPUT7_ENABLE(x) (((x) & 0xF) << 28)
|
||||
#define G_02823C_OUTPUT7_ENABLE(x) (((x) >> 28) & 0xF)
|
||||
#define C_02823C_OUTPUT7_ENABLE 0x0FFFFFFF
|
||||
#define R_028AB0_VGT_STRMOUT_EN 0x028AB0
|
||||
#define S_028AB0_STREAMOUT(x) (((x) & 0x1) << 0)
|
||||
#define G_028AB0_STREAMOUT(x) (((x) >> 0) & 0x1)
|
||||
#define C_028AB0_STREAMOUT 0xFFFFFFFE
|
||||
#define R_028B20_VGT_STRMOUT_BUFFER_EN 0x028B20
|
||||
#define S_028B20_BUFFER_0_EN(x) (((x) & 0x1) << 0)
|
||||
#define G_028B20_BUFFER_0_EN(x) (((x) >> 0) & 0x1)
|
||||
#define C_028B20_BUFFER_0_EN 0xFFFFFFFE
|
||||
#define S_028B20_BUFFER_1_EN(x) (((x) & 0x1) << 1)
|
||||
#define G_028B20_BUFFER_1_EN(x) (((x) >> 1) & 0x1)
|
||||
#define C_028B20_BUFFER_1_EN 0xFFFFFFFD
|
||||
#define S_028B20_BUFFER_2_EN(x) (((x) & 0x1) << 2)
|
||||
#define G_028B20_BUFFER_2_EN(x) (((x) >> 2) & 0x1)
|
||||
#define C_028B20_BUFFER_2_EN 0xFFFFFFFB
|
||||
#define S_028B20_BUFFER_3_EN(x) (((x) & 0x1) << 3)
|
||||
#define G_028B20_BUFFER_3_EN(x) (((x) >> 3) & 0x1)
|
||||
#define C_028B20_BUFFER_3_EN 0xFFFFFFF7
|
||||
#define S_028B20_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_028B20_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_028B20_SIZE 0x00000000
|
||||
#define R_038000_SQ_TEX_RESOURCE_WORD0_0 0x038000
|
||||
#define S_038000_DIM(x) (((x) & 0x7) << 0)
|
||||
#define G_038000_DIM(x) (((x) >> 0) & 0x7)
|
||||
#define C_038000_DIM 0xFFFFFFF8
|
||||
#define V_038000_SQ_TEX_DIM_1D 0x00000000
|
||||
#define V_038000_SQ_TEX_DIM_2D 0x00000001
|
||||
#define V_038000_SQ_TEX_DIM_3D 0x00000002
|
||||
#define V_038000_SQ_TEX_DIM_CUBEMAP 0x00000003
|
||||
#define V_038000_SQ_TEX_DIM_1D_ARRAY 0x00000004
|
||||
#define V_038000_SQ_TEX_DIM_2D_ARRAY 0x00000005
|
||||
#define V_038000_SQ_TEX_DIM_2D_MSAA 0x00000006
|
||||
#define V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007
|
||||
#define S_038000_TILE_MODE(x) (((x) & 0xF) << 3)
|
||||
#define G_038000_TILE_MODE(x) (((x) >> 3) & 0xF)
|
||||
#define C_038000_TILE_MODE 0xFFFFFF87
|
||||
#define S_038000_TILE_TYPE(x) (((x) & 0x1) << 7)
|
||||
#define G_038000_TILE_TYPE(x) (((x) >> 7) & 0x1)
|
||||
#define C_038000_TILE_TYPE 0xFFFFFF7F
|
||||
#define S_038000_PITCH(x) (((x) & 0x7FF) << 8)
|
||||
#define G_038000_PITCH(x) (((x) >> 8) & 0x7FF)
|
||||
#define C_038000_PITCH 0xFFF800FF
|
||||
#define S_038000_TEX_WIDTH(x) (((x) & 0x1FFF) << 19)
|
||||
#define G_038000_TEX_WIDTH(x) (((x) >> 19) & 0x1FFF)
|
||||
#define C_038000_TEX_WIDTH 0x0007FFFF
|
||||
#define R_038004_SQ_TEX_RESOURCE_WORD1_0 0x038004
|
||||
#define S_038004_TEX_HEIGHT(x) (((x) & 0x1FFF) << 0)
|
||||
#define G_038004_TEX_HEIGHT(x) (((x) >> 0) & 0x1FFF)
|
||||
#define C_038004_TEX_HEIGHT 0xFFFFE000
|
||||
#define S_038004_TEX_DEPTH(x) (((x) & 0x1FFF) << 13)
|
||||
#define G_038004_TEX_DEPTH(x) (((x) >> 13) & 0x1FFF)
|
||||
#define C_038004_TEX_DEPTH 0xFC001FFF
|
||||
#define S_038004_DATA_FORMAT(x) (((x) & 0x3F) << 26)
|
||||
#define G_038004_DATA_FORMAT(x) (((x) >> 26) & 0x3F)
|
||||
#define C_038004_DATA_FORMAT 0x03FFFFFF
|
||||
#define V_038004_COLOR_INVALID 0x00000000
|
||||
#define V_038004_COLOR_8 0x00000001
|
||||
#define V_038004_COLOR_4_4 0x00000002
|
||||
#define V_038004_COLOR_3_3_2 0x00000003
|
||||
#define V_038004_COLOR_16 0x00000005
|
||||
#define V_038004_COLOR_16_FLOAT 0x00000006
|
||||
#define V_038004_COLOR_8_8 0x00000007
|
||||
#define V_038004_COLOR_5_6_5 0x00000008
|
||||
#define V_038004_COLOR_6_5_5 0x00000009
|
||||
#define V_038004_COLOR_1_5_5_5 0x0000000A
|
||||
#define V_038004_COLOR_4_4_4_4 0x0000000B
|
||||
#define V_038004_COLOR_5_5_5_1 0x0000000C
|
||||
#define V_038004_COLOR_32 0x0000000D
|
||||
#define V_038004_COLOR_32_FLOAT 0x0000000E
|
||||
#define V_038004_COLOR_16_16 0x0000000F
|
||||
#define V_038004_COLOR_16_16_FLOAT 0x00000010
|
||||
#define V_038004_COLOR_8_24 0x00000011
|
||||
#define V_038004_COLOR_8_24_FLOAT 0x00000012
|
||||
#define V_038004_COLOR_24_8 0x00000013
|
||||
#define V_038004_COLOR_24_8_FLOAT 0x00000014
|
||||
#define V_038004_COLOR_10_11_11 0x00000015
|
||||
#define V_038004_COLOR_10_11_11_FLOAT 0x00000016
|
||||
#define V_038004_COLOR_11_11_10 0x00000017
|
||||
#define V_038004_COLOR_11_11_10_FLOAT 0x00000018
|
||||
#define V_038004_COLOR_2_10_10_10 0x00000019
|
||||
#define V_038004_COLOR_8_8_8_8 0x0000001A
|
||||
#define V_038004_COLOR_10_10_10_2 0x0000001B
|
||||
#define V_038004_COLOR_X24_8_32_FLOAT 0x0000001C
|
||||
#define V_038004_COLOR_32_32 0x0000001D
|
||||
#define V_038004_COLOR_32_32_FLOAT 0x0000001E
|
||||
#define V_038004_COLOR_16_16_16_16 0x0000001F
|
||||
#define V_038004_COLOR_16_16_16_16_FLOAT 0x00000020
|
||||
#define V_038004_COLOR_32_32_32_32 0x00000022
|
||||
#define V_038004_COLOR_32_32_32_32_FLOAT 0x00000023
|
||||
#define V_038004_FMT_1 0x00000025
|
||||
#define V_038004_FMT_GB_GR 0x00000027
|
||||
#define V_038004_FMT_BG_RG 0x00000028
|
||||
#define V_038004_FMT_32_AS_8 0x00000029
|
||||
#define V_038004_FMT_32_AS_8_8 0x0000002A
|
||||
#define V_038004_FMT_5_9_9_9_SHAREDEXP 0x0000002B
|
||||
#define V_038004_FMT_8_8_8 0x0000002C
|
||||
#define V_038004_FMT_16_16_16 0x0000002D
|
||||
#define V_038004_FMT_16_16_16_FLOAT 0x0000002E
|
||||
#define V_038004_FMT_32_32_32 0x0000002F
|
||||
#define V_038004_FMT_32_32_32_FLOAT 0x00000030
|
||||
#define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010
|
||||
#define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0)
|
||||
#define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3)
|
||||
#define C_038010_FORMAT_COMP_X 0xFFFFFFFC
|
||||
#define S_038010_FORMAT_COMP_Y(x) (((x) & 0x3) << 2)
|
||||
#define G_038010_FORMAT_COMP_Y(x) (((x) >> 2) & 0x3)
|
||||
#define C_038010_FORMAT_COMP_Y 0xFFFFFFF3
|
||||
#define S_038010_FORMAT_COMP_Z(x) (((x) & 0x3) << 4)
|
||||
#define G_038010_FORMAT_COMP_Z(x) (((x) >> 4) & 0x3)
|
||||
#define C_038010_FORMAT_COMP_Z 0xFFFFFFCF
|
||||
#define S_038010_FORMAT_COMP_W(x) (((x) & 0x3) << 6)
|
||||
#define G_038010_FORMAT_COMP_W(x) (((x) >> 6) & 0x3)
|
||||
#define C_038010_FORMAT_COMP_W 0xFFFFFF3F
|
||||
#define S_038010_NUM_FORMAT_ALL(x) (((x) & 0x3) << 8)
|
||||
#define G_038010_NUM_FORMAT_ALL(x) (((x) >> 8) & 0x3)
|
||||
#define C_038010_NUM_FORMAT_ALL 0xFFFFFCFF
|
||||
#define S_038010_SRF_MODE_ALL(x) (((x) & 0x1) << 10)
|
||||
#define G_038010_SRF_MODE_ALL(x) (((x) >> 10) & 0x1)
|
||||
#define C_038010_SRF_MODE_ALL 0xFFFFFBFF
|
||||
#define S_038010_FORCE_DEGAMMA(x) (((x) & 0x1) << 11)
|
||||
#define G_038010_FORCE_DEGAMMA(x) (((x) >> 11) & 0x1)
|
||||
#define C_038010_FORCE_DEGAMMA 0xFFFFF7FF
|
||||
#define S_038010_ENDIAN_SWAP(x) (((x) & 0x3) << 12)
|
||||
#define G_038010_ENDIAN_SWAP(x) (((x) >> 12) & 0x3)
|
||||
#define C_038010_ENDIAN_SWAP 0xFFFFCFFF
|
||||
#define S_038010_REQUEST_SIZE(x) (((x) & 0x3) << 14)
|
||||
#define G_038010_REQUEST_SIZE(x) (((x) >> 14) & 0x3)
|
||||
#define C_038010_REQUEST_SIZE 0xFFFF3FFF
|
||||
#define S_038010_DST_SEL_X(x) (((x) & 0x7) << 16)
|
||||
#define G_038010_DST_SEL_X(x) (((x) >> 16) & 0x7)
|
||||
#define C_038010_DST_SEL_X 0xFFF8FFFF
|
||||
#define S_038010_DST_SEL_Y(x) (((x) & 0x7) << 19)
|
||||
#define G_038010_DST_SEL_Y(x) (((x) >> 19) & 0x7)
|
||||
#define C_038010_DST_SEL_Y 0xFFC7FFFF
|
||||
#define S_038010_DST_SEL_Z(x) (((x) & 0x7) << 22)
|
||||
#define G_038010_DST_SEL_Z(x) (((x) >> 22) & 0x7)
|
||||
#define C_038010_DST_SEL_Z 0xFE3FFFFF
|
||||
#define S_038010_DST_SEL_W(x) (((x) & 0x7) << 25)
|
||||
#define G_038010_DST_SEL_W(x) (((x) >> 25) & 0x7)
|
||||
#define C_038010_DST_SEL_W 0xF1FFFFFF
|
||||
#define S_038010_BASE_LEVEL(x) (((x) & 0xF) << 28)
|
||||
#define G_038010_BASE_LEVEL(x) (((x) >> 28) & 0xF)
|
||||
#define C_038010_BASE_LEVEL 0x0FFFFFFF
|
||||
#define R_038014_SQ_TEX_RESOURCE_WORD5_0 0x038014
|
||||
#define S_038014_LAST_LEVEL(x) (((x) & 0xF) << 0)
|
||||
#define G_038014_LAST_LEVEL(x) (((x) >> 0) & 0xF)
|
||||
#define C_038014_LAST_LEVEL 0xFFFFFFF0
|
||||
#define S_038014_BASE_ARRAY(x) (((x) & 0x1FFF) << 4)
|
||||
#define G_038014_BASE_ARRAY(x) (((x) >> 4) & 0x1FFF)
|
||||
#define C_038014_BASE_ARRAY 0xFFFE000F
|
||||
#define S_038014_LAST_ARRAY(x) (((x) & 0x1FFF) << 17)
|
||||
#define G_038014_LAST_ARRAY(x) (((x) >> 17) & 0x1FFF)
|
||||
#define C_038014_LAST_ARRAY 0xC001FFFF
|
||||
#define R_0288A8_SQ_ESGS_RING_ITEMSIZE 0x0288A8
|
||||
#define S_0288A8_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288A8_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288A8_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C44_SQ_ESGS_RING_SIZE 0x008C44
|
||||
#define S_008C44_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C44_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C44_MEM_SIZE 0x00000000
|
||||
#define R_0288B0_SQ_ESTMP_RING_ITEMSIZE 0x0288B0
|
||||
#define S_0288B0_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288B0_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288B0_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C54_SQ_ESTMP_RING_SIZE 0x008C54
|
||||
#define S_008C54_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C54_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C54_MEM_SIZE 0x00000000
|
||||
#define R_0288C0_SQ_FBUF_RING_ITEMSIZE 0x0288C0
|
||||
#define S_0288C0_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288C0_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288C0_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C74_SQ_FBUF_RING_SIZE 0x008C74
|
||||
#define S_008C74_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C74_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C74_MEM_SIZE 0x00000000
|
||||
#define R_0288B4_SQ_GSTMP_RING_ITEMSIZE 0x0288B4
|
||||
#define S_0288B4_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288B4_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288B4_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C5C_SQ_GSTMP_RING_SIZE 0x008C5C
|
||||
#define S_008C5C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C5C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C5C_MEM_SIZE 0x00000000
|
||||
#define R_0288AC_SQ_GSVS_RING_ITEMSIZE 0x0288AC
|
||||
#define S_0288AC_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288AC_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288AC_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C4C_SQ_GSVS_RING_SIZE 0x008C4C
|
||||
#define S_008C4C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C4C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C4C_MEM_SIZE 0x00000000
|
||||
#define R_0288BC_SQ_PSTMP_RING_ITEMSIZE 0x0288BC
|
||||
#define S_0288BC_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288BC_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288BC_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C6C_SQ_PSTMP_RING_SIZE 0x008C6C
|
||||
#define S_008C6C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C6C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C6C_MEM_SIZE 0x00000000
|
||||
#define R_0288C4_SQ_REDUC_RING_ITEMSIZE 0x0288C4
|
||||
#define S_0288C4_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288C4_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288C4_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C7C_SQ_REDUC_RING_SIZE 0x008C7C
|
||||
#define S_008C7C_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C7C_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C7C_MEM_SIZE 0x00000000
|
||||
#define R_0288B8_SQ_VSTMP_RING_ITEMSIZE 0x0288B8
|
||||
#define S_0288B8_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288B8_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288B8_ITEMSIZE 0xFFFF8000
|
||||
#define R_008C64_SQ_VSTMP_RING_SIZE 0x008C64
|
||||
#define S_008C64_MEM_SIZE(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_008C64_MEM_SIZE(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_008C64_MEM_SIZE 0x00000000
|
||||
#define R_0288C8_SQ_GS_VERT_ITEMSIZE 0x0288C8
|
||||
#define S_0288C8_ITEMSIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define G_0288C8_ITEMSIZE(x) (((x) >> 0) & 0x7FFF)
|
||||
#define C_0288C8_ITEMSIZE 0xFFFF8000
|
||||
#define R_028010_DB_DEPTH_INFO 0x028010
|
||||
#define S_028010_FORMAT(x) (((x) & 0x7) << 0)
|
||||
#define G_028010_FORMAT(x) (((x) >> 0) & 0x7)
|
||||
#define C_028010_FORMAT 0xFFFFFFF8
|
||||
#define V_028010_DEPTH_INVALID 0x00000000
|
||||
#define V_028010_DEPTH_16 0x00000001
|
||||
#define V_028010_DEPTH_X8_24 0x00000002
|
||||
#define V_028010_DEPTH_8_24 0x00000003
|
||||
#define V_028010_DEPTH_X8_24_FLOAT 0x00000004
|
||||
#define V_028010_DEPTH_8_24_FLOAT 0x00000005
|
||||
#define V_028010_DEPTH_32_FLOAT 0x00000006
|
||||
#define V_028010_DEPTH_X24_8_32_FLOAT 0x00000007
|
||||
#define S_028010_READ_SIZE(x) (((x) & 0x1) << 3)
|
||||
#define G_028010_READ_SIZE(x) (((x) >> 3) & 0x1)
|
||||
#define C_028010_READ_SIZE 0xFFFFFFF7
|
||||
#define S_028010_ARRAY_MODE(x) (((x) & 0xF) << 15)
|
||||
#define G_028010_ARRAY_MODE(x) (((x) >> 15) & 0xF)
|
||||
#define C_028010_ARRAY_MODE 0xFFF87FFF
|
||||
#define S_028010_TILE_SURFACE_ENABLE(x) (((x) & 0x1) << 25)
|
||||
#define G_028010_TILE_SURFACE_ENABLE(x) (((x) >> 25) & 0x1)
|
||||
#define C_028010_TILE_SURFACE_ENABLE 0xFDFFFFFF
|
||||
#define S_028010_TILE_COMPACT(x) (((x) & 0x1) << 26)
|
||||
#define G_028010_TILE_COMPACT(x) (((x) >> 26) & 0x1)
|
||||
#define C_028010_TILE_COMPACT 0xFBFFFFFF
|
||||
#define S_028010_ZRANGE_PRECISION(x) (((x) & 0x1) << 31)
|
||||
#define G_028010_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1)
|
||||
#define C_028010_ZRANGE_PRECISION 0x7FFFFFFF
|
||||
#define R_028000_DB_DEPTH_SIZE 0x028000
|
||||
#define S_028000_PITCH_TILE_MAX(x) (((x) & 0x3FF) << 0)
|
||||
#define G_028000_PITCH_TILE_MAX(x) (((x) >> 0) & 0x3FF)
|
||||
#define C_028000_PITCH_TILE_MAX 0xFFFFFC00
|
||||
#define S_028000_SLICE_TILE_MAX(x) (((x) & 0xFFFFF) << 10)
|
||||
#define G_028000_SLICE_TILE_MAX(x) (((x) >> 10) & 0xFFFFF)
|
||||
#define C_028000_SLICE_TILE_MAX 0xC00003FF
|
||||
#define R_028004_DB_DEPTH_VIEW 0x028004
|
||||
#define S_028004_SLICE_START(x) (((x) & 0x7FF) << 0)
|
||||
#define G_028004_SLICE_START(x) (((x) >> 0) & 0x7FF)
|
||||
#define C_028004_SLICE_START 0xFFFFF800
|
||||
#define S_028004_SLICE_MAX(x) (((x) & 0x7FF) << 13)
|
||||
#define G_028004_SLICE_MAX(x) (((x) >> 13) & 0x7FF)
|
||||
#define C_028004_SLICE_MAX 0xFF001FFF
|
||||
#define R_028800_DB_DEPTH_CONTROL 0x028800
|
||||
#define S_028800_STENCIL_ENABLE(x) (((x) & 0x1) << 0)
|
||||
#define G_028800_STENCIL_ENABLE(x) (((x) >> 0) & 0x1)
|
||||
#define C_028800_STENCIL_ENABLE 0xFFFFFFFE
|
||||
#define S_028800_Z_ENABLE(x) (((x) & 0x1) << 1)
|
||||
#define G_028800_Z_ENABLE(x) (((x) >> 1) & 0x1)
|
||||
#define C_028800_Z_ENABLE 0xFFFFFFFD
|
||||
#define S_028800_Z_WRITE_ENABLE(x) (((x) & 0x1) << 2)
|
||||
#define G_028800_Z_WRITE_ENABLE(x) (((x) >> 2) & 0x1)
|
||||
#define C_028800_Z_WRITE_ENABLE 0xFFFFFFFB
|
||||
#define S_028800_ZFUNC(x) (((x) & 0x7) << 4)
|
||||
#define G_028800_ZFUNC(x) (((x) >> 4) & 0x7)
|
||||
#define C_028800_ZFUNC 0xFFFFFF8F
|
||||
#define S_028800_BACKFACE_ENABLE(x) (((x) & 0x1) << 7)
|
||||
#define G_028800_BACKFACE_ENABLE(x) (((x) >> 7) & 0x1)
|
||||
#define C_028800_BACKFACE_ENABLE 0xFFFFFF7F
|
||||
#define S_028800_STENCILFUNC(x) (((x) & 0x7) << 8)
|
||||
#define G_028800_STENCILFUNC(x) (((x) >> 8) & 0x7)
|
||||
#define C_028800_STENCILFUNC 0xFFFFF8FF
|
||||
#define S_028800_STENCILFAIL(x) (((x) & 0x7) << 11)
|
||||
#define G_028800_STENCILFAIL(x) (((x) >> 11) & 0x7)
|
||||
#define C_028800_STENCILFAIL 0xFFFFC7FF
|
||||
#define S_028800_STENCILZPASS(x) (((x) & 0x7) << 14)
|
||||
#define G_028800_STENCILZPASS(x) (((x) >> 14) & 0x7)
|
||||
#define C_028800_STENCILZPASS 0xFFFE3FFF
|
||||
#define S_028800_STENCILZFAIL(x) (((x) & 0x7) << 17)
|
||||
#define G_028800_STENCILZFAIL(x) (((x) >> 17) & 0x7)
|
||||
#define C_028800_STENCILZFAIL 0xFFF1FFFF
|
||||
#define S_028800_STENCILFUNC_BF(x) (((x) & 0x7) << 20)
|
||||
#define G_028800_STENCILFUNC_BF(x) (((x) >> 20) & 0x7)
|
||||
#define C_028800_STENCILFUNC_BF 0xFF8FFFFF
|
||||
#define S_028800_STENCILFAIL_BF(x) (((x) & 0x7) << 23)
|
||||
#define G_028800_STENCILFAIL_BF(x) (((x) >> 23) & 0x7)
|
||||
#define C_028800_STENCILFAIL_BF 0xFC7FFFFF
|
||||
#define S_028800_STENCILZPASS_BF(x) (((x) & 0x7) << 26)
|
||||
#define G_028800_STENCILZPASS_BF(x) (((x) >> 26) & 0x7)
|
||||
#define C_028800_STENCILZPASS_BF 0xE3FFFFFF
|
||||
#define S_028800_STENCILZFAIL_BF(x) (((x) & 0x7) << 29)
|
||||
#define G_028800_STENCILZFAIL_BF(x) (((x) >> 29) & 0x7)
|
||||
#define C_028800_STENCILZFAIL_BF 0x1FFFFFFF
|
||||
|
||||
#endif
|
||||
|
|
|
@ -89,6 +89,7 @@ extern int radeon_testing;
|
|||
extern int radeon_connector_table;
|
||||
extern int radeon_tv;
|
||||
extern int radeon_new_pll;
|
||||
extern int radeon_dynpm;
|
||||
extern int radeon_audio;
|
||||
|
||||
/*
|
||||
|
@ -138,17 +139,23 @@ void radeon_dummy_page_fini(struct radeon_device *rdev);
|
|||
struct radeon_clock {
|
||||
struct radeon_pll p1pll;
|
||||
struct radeon_pll p2pll;
|
||||
struct radeon_pll dcpll;
|
||||
struct radeon_pll spll;
|
||||
struct radeon_pll mpll;
|
||||
/* 10 Khz units */
|
||||
uint32_t default_mclk;
|
||||
uint32_t default_sclk;
|
||||
uint32_t default_dispclk;
|
||||
uint32_t dp_extclk;
|
||||
};
|
||||
|
||||
/*
|
||||
* Power management
|
||||
*/
|
||||
int radeon_pm_init(struct radeon_device *rdev);
|
||||
void radeon_pm_compute_clocks(struct radeon_device *rdev);
|
||||
void radeon_combios_get_power_modes(struct radeon_device *rdev);
|
||||
void radeon_atombios_get_power_modes(struct radeon_device *rdev);
|
||||
|
||||
/*
|
||||
* Fences.
|
||||
|
@ -275,6 +282,7 @@ union radeon_gart_table {
|
|||
};
|
||||
|
||||
#define RADEON_GPU_PAGE_SIZE 4096
|
||||
#define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1)
|
||||
|
||||
struct radeon_gart {
|
||||
dma_addr_t table_addr;
|
||||
|
@ -309,21 +317,19 @@ struct radeon_mc {
|
|||
/* for some chips with <= 32MB we need to lie
|
||||
* about vram size near mc fb location */
|
||||
u64 mc_vram_size;
|
||||
u64 gtt_location;
|
||||
u64 visible_vram_size;
|
||||
u64 gtt_size;
|
||||
u64 gtt_start;
|
||||
u64 gtt_end;
|
||||
u64 vram_location;
|
||||
u64 vram_start;
|
||||
u64 vram_end;
|
||||
unsigned vram_width;
|
||||
u64 real_vram_size;
|
||||
int vram_mtrr;
|
||||
bool vram_is_ddr;
|
||||
bool igp_sideport_enabled;
|
||||
bool igp_sideport_enabled;
|
||||
};
|
||||
|
||||
int radeon_mc_setup(struct radeon_device *rdev);
|
||||
bool radeon_combios_sideport_present(struct radeon_device *rdev);
|
||||
bool radeon_atombios_sideport_present(struct radeon_device *rdev);
|
||||
|
||||
|
@ -348,6 +354,7 @@ struct radeon_irq {
|
|||
bool sw_int;
|
||||
/* FIXME: use a define max crtc rather than hardcode it */
|
||||
bool crtc_vblank_int[2];
|
||||
wait_queue_head_t vblank_queue;
|
||||
/* FIXME: use defines for max hpd/dacs */
|
||||
bool hpd[6];
|
||||
spinlock_t sw_lock;
|
||||
|
@ -379,6 +386,7 @@ struct radeon_ib {
|
|||
struct radeon_ib_pool {
|
||||
struct mutex mutex;
|
||||
struct radeon_bo *robj;
|
||||
struct list_head bogus_ib;
|
||||
struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
|
||||
bool ready;
|
||||
unsigned head_id;
|
||||
|
@ -433,6 +441,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
|
|||
int radeon_ib_pool_init(struct radeon_device *rdev);
|
||||
void radeon_ib_pool_fini(struct radeon_device *rdev);
|
||||
int radeon_ib_test(struct radeon_device *rdev);
|
||||
extern void radeon_ib_bogus_add(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||
/* Ring access between begin & end cannot sleep */
|
||||
void radeon_ring_free_size(struct radeon_device *rdev);
|
||||
int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw);
|
||||
|
@ -570,7 +579,99 @@ struct radeon_wb {
|
|||
* Equation between gpu/memory clock and available bandwidth is hw dependent
|
||||
* (type of memory, bus size, efficiency, ...)
|
||||
*/
|
||||
enum radeon_pm_state {
|
||||
PM_STATE_DISABLED,
|
||||
PM_STATE_MINIMUM,
|
||||
PM_STATE_PAUSED,
|
||||
PM_STATE_ACTIVE
|
||||
};
|
||||
enum radeon_pm_action {
|
||||
PM_ACTION_NONE,
|
||||
PM_ACTION_MINIMUM,
|
||||
PM_ACTION_DOWNCLOCK,
|
||||
PM_ACTION_UPCLOCK
|
||||
};
|
||||
|
||||
enum radeon_voltage_type {
|
||||
VOLTAGE_NONE = 0,
|
||||
VOLTAGE_GPIO,
|
||||
VOLTAGE_VDDC,
|
||||
VOLTAGE_SW
|
||||
};
|
||||
|
||||
enum radeon_pm_state_type {
|
||||
POWER_STATE_TYPE_DEFAULT,
|
||||
POWER_STATE_TYPE_POWERSAVE,
|
||||
POWER_STATE_TYPE_BATTERY,
|
||||
POWER_STATE_TYPE_BALANCED,
|
||||
POWER_STATE_TYPE_PERFORMANCE,
|
||||
};
|
||||
|
||||
enum radeon_pm_clock_mode_type {
|
||||
POWER_MODE_TYPE_DEFAULT,
|
||||
POWER_MODE_TYPE_LOW,
|
||||
POWER_MODE_TYPE_MID,
|
||||
POWER_MODE_TYPE_HIGH,
|
||||
};
|
||||
|
||||
struct radeon_voltage {
|
||||
enum radeon_voltage_type type;
|
||||
/* gpio voltage */
|
||||
struct radeon_gpio_rec gpio;
|
||||
u32 delay; /* delay in usec from voltage drop to sclk change */
|
||||
bool active_high; /* voltage drop is active when bit is high */
|
||||
/* VDDC voltage */
|
||||
u8 vddc_id; /* index into vddc voltage table */
|
||||
u8 vddci_id; /* index into vddci voltage table */
|
||||
bool vddci_enabled;
|
||||
/* r6xx+ sw */
|
||||
u32 voltage;
|
||||
};
|
||||
|
||||
struct radeon_pm_non_clock_info {
|
||||
/* pcie lanes */
|
||||
int pcie_lanes;
|
||||
/* standardized non-clock flags */
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct radeon_pm_clock_info {
|
||||
/* memory clock */
|
||||
u32 mclk;
|
||||
/* engine clock */
|
||||
u32 sclk;
|
||||
/* voltage info */
|
||||
struct radeon_voltage voltage;
|
||||
/* standardized clock flags - not sure we'll need these */
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct radeon_power_state {
|
||||
enum radeon_pm_state_type type;
|
||||
/* XXX: use a define for num clock modes */
|
||||
struct radeon_pm_clock_info clock_info[8];
|
||||
/* number of valid clock modes in this power state */
|
||||
int num_clock_modes;
|
||||
struct radeon_pm_clock_info *default_clock_mode;
|
||||
/* non clock info about this state */
|
||||
struct radeon_pm_non_clock_info non_clock_info;
|
||||
bool voltage_drop_active;
|
||||
};
|
||||
|
||||
/*
|
||||
* Some modes are overclocked by very low value, accept them
|
||||
*/
|
||||
#define RADEON_MODE_OVERCLOCK_MARGIN 500 /* 5 MHz */
|
||||
|
||||
struct radeon_pm {
|
||||
struct mutex mutex;
|
||||
struct delayed_work idle_work;
|
||||
enum radeon_pm_state state;
|
||||
enum radeon_pm_action planned_action;
|
||||
unsigned long action_timeout;
|
||||
bool downclocked;
|
||||
int active_crtcs;
|
||||
int req_vblank;
|
||||
fixed20_12 max_bandwidth;
|
||||
fixed20_12 igp_sideport_mclk;
|
||||
fixed20_12 igp_system_mclk;
|
||||
|
@ -582,6 +683,15 @@ struct radeon_pm {
|
|||
fixed20_12 core_bandwidth;
|
||||
fixed20_12 sclk;
|
||||
fixed20_12 needed_bandwidth;
|
||||
/* XXX: use a define for num power modes */
|
||||
struct radeon_power_state power_state[8];
|
||||
/* number of valid power states */
|
||||
int num_power_states;
|
||||
struct radeon_power_state *current_power_state;
|
||||
struct radeon_pm_clock_info *current_clock_mode;
|
||||
struct radeon_power_state *requested_power_state;
|
||||
struct radeon_pm_clock_info *requested_clock_mode;
|
||||
struct radeon_power_state *default_power_state;
|
||||
};
|
||||
|
||||
|
||||
|
@ -651,6 +761,7 @@ struct radeon_asic {
|
|||
void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock);
|
||||
uint32_t (*get_memory_clock)(struct radeon_device *rdev);
|
||||
void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
|
||||
int (*get_pcie_lanes)(struct radeon_device *rdev);
|
||||
void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
|
||||
void (*set_clock_gating)(struct radeon_device *rdev, int enable);
|
||||
int (*set_surface_reg)(struct radeon_device *rdev, int reg,
|
||||
|
@ -701,6 +812,9 @@ struct r600_asic {
|
|||
unsigned sx_max_export_pos_size;
|
||||
unsigned sx_max_export_smx_size;
|
||||
unsigned sq_num_cf_insts;
|
||||
unsigned tiling_nbanks;
|
||||
unsigned tiling_npipes;
|
||||
unsigned tiling_group_size;
|
||||
};
|
||||
|
||||
struct rv770_asic {
|
||||
|
@ -721,6 +835,9 @@ struct rv770_asic {
|
|||
unsigned sc_prim_fifo_size;
|
||||
unsigned sc_hiz_tile_fifo_size;
|
||||
unsigned sc_earlyz_tile_fifo_fize;
|
||||
unsigned tiling_nbanks;
|
||||
unsigned tiling_npipes;
|
||||
unsigned tiling_group_size;
|
||||
};
|
||||
|
||||
union radeon_asic_config {
|
||||
|
@ -830,6 +947,8 @@ struct radeon_device {
|
|||
struct r600_ih ih; /* r6/700 interrupt ring */
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct hotplug_work;
|
||||
int num_crtc; /* number of crtcs */
|
||||
struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
|
||||
|
||||
/* audio stuff */
|
||||
struct timer_list audio_timer;
|
||||
|
@ -895,6 +1014,8 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32
|
|||
#define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v))
|
||||
#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg))
|
||||
#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v))
|
||||
#define RREG32_PCIE_P(reg) rdev->pciep_rreg(rdev, (reg))
|
||||
#define WREG32_PCIE_P(reg, v) rdev->pciep_wreg(rdev, (reg), (v))
|
||||
#define WREG32_P(reg, val, mask) \
|
||||
do { \
|
||||
uint32_t tmp_ = RREG32(reg); \
|
||||
|
@ -956,7 +1077,7 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
|
|||
#define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
|
||||
#define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
|
||||
#define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
|
||||
|
||||
#define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
|
||||
|
||||
/*
|
||||
* BIOS helpers.
|
||||
|
@ -1015,6 +1136,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
|||
#define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
|
||||
#define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev))
|
||||
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e))
|
||||
#define radeon_get_pcie_lanes(rdev) (rdev)->asic->get_pcie_lanes((rdev))
|
||||
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
|
||||
#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
|
||||
#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
|
||||
|
@ -1029,6 +1151,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
|||
/* AGP */
|
||||
extern void radeon_agp_disable(struct radeon_device *rdev);
|
||||
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
|
||||
extern void radeon_gart_restore(struct radeon_device *rdev);
|
||||
extern int radeon_modeset_init(struct radeon_device *rdev);
|
||||
extern void radeon_modeset_fini(struct radeon_device *rdev);
|
||||
extern bool radeon_card_posted(struct radeon_device *rdev);
|
||||
|
@ -1042,6 +1165,8 @@ extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enabl
|
|||
extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
|
||||
extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
|
||||
extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
|
||||
extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
|
||||
extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
|
||||
|
||||
/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
|
||||
struct r100_mc_save {
|
||||
|
@ -1096,7 +1221,7 @@ extern void r200_set_safe_registers(struct radeon_device *rdev);
|
|||
/* r300,r350,rv350,rv370,rv380 */
|
||||
extern void r300_set_reg_safe(struct radeon_device *rdev);
|
||||
extern void r300_mc_program(struct radeon_device *rdev);
|
||||
extern void r300_vram_info(struct radeon_device *rdev);
|
||||
extern void r300_mc_init(struct radeon_device *rdev);
|
||||
extern void r300_clock_startup(struct radeon_device *rdev);
|
||||
extern int r300_mc_wait_for_idle(struct radeon_device *rdev);
|
||||
extern int rv370_pcie_gart_init(struct radeon_device *rdev);
|
||||
|
@ -1105,7 +1230,6 @@ extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
|
|||
extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
|
||||
|
||||
/* r420,r423,rv410 */
|
||||
extern int r420_mc_init(struct radeon_device *rdev);
|
||||
extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
|
||||
extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
|
||||
|
@ -1147,13 +1271,13 @@ extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
|
|||
struct drm_display_mode *mode2);
|
||||
|
||||
/* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
|
||||
extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
|
||||
extern bool r600_card_posted(struct radeon_device *rdev);
|
||||
extern void r600_cp_stop(struct radeon_device *rdev);
|
||||
extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
|
||||
extern int r600_cp_resume(struct radeon_device *rdev);
|
||||
extern void r600_cp_fini(struct radeon_device *rdev);
|
||||
extern int r600_count_pipe_bits(uint32_t val);
|
||||
extern int r600_gart_clear_page(struct radeon_device *rdev, int i);
|
||||
extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
|
||||
extern int r600_pcie_gart_init(struct radeon_device *rdev);
|
||||
extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
|
||||
|
@ -1189,6 +1313,14 @@ extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
|
|||
uint8_t status_bits,
|
||||
uint8_t category_code);
|
||||
|
||||
/* evergreen */
|
||||
struct evergreen_mc_save {
|
||||
u32 vga_control[6];
|
||||
u32 vga_render_control;
|
||||
u32 vga_hdp_control;
|
||||
u32 crtc_control[6];
|
||||
};
|
||||
|
||||
#include "radeon_object.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -237,6 +237,10 @@ int radeon_agp_init(struct radeon_device *rdev)
|
|||
|
||||
rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base;
|
||||
rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20;
|
||||
rdev->mc.gtt_start = rdev->mc.agp_base;
|
||||
rdev->mc.gtt_end = rdev->mc.gtt_start + rdev->mc.gtt_size - 1;
|
||||
dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
|
||||
rdev->mc.gtt_size >> 20, rdev->mc.gtt_start, rdev->mc.gtt_end);
|
||||
|
||||
/* workaround some hw issues */
|
||||
if (rdev->family < CHIP_R200) {
|
||||
|
|
|
@ -43,7 +43,7 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock
|
|||
void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
|
||||
|
||||
/*
|
||||
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
|
||||
* r100,rv100,rs100,rv200,rs200
|
||||
*/
|
||||
extern int r100_init(struct radeon_device *rdev);
|
||||
extern void r100_fini(struct radeon_device *rdev);
|
||||
|
@ -108,6 +108,52 @@ static struct radeon_asic r100_asic = {
|
|||
.set_engine_clock = &radeon_legacy_set_engine_clock,
|
||||
.get_memory_clock = &radeon_legacy_get_memory_clock,
|
||||
.set_memory_clock = NULL,
|
||||
.get_pcie_lanes = NULL,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_legacy_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &r100_bandwidth_update,
|
||||
.hpd_init = &r100_hpd_init,
|
||||
.hpd_fini = &r100_hpd_fini,
|
||||
.hpd_sense = &r100_hpd_sense,
|
||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||
.ioctl_wait_idle = NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* r200,rv250,rs300,rv280
|
||||
*/
|
||||
extern int r200_copy_dma(struct radeon_device *rdev,
|
||||
uint64_t src_offset,
|
||||
uint64_t dst_offset,
|
||||
unsigned num_pages,
|
||||
struct radeon_fence *fence);
|
||||
static struct radeon_asic r200_asic = {
|
||||
.init = &r100_init,
|
||||
.fini = &r100_fini,
|
||||
.suspend = &r100_suspend,
|
||||
.resume = &r100_resume,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r100_gpu_reset,
|
||||
.gart_tlb_flush = &r100_pci_gart_tlb_flush,
|
||||
.gart_set_page = &r100_pci_gart_set_page,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r100_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.irq_set = &r100_irq_set,
|
||||
.irq_process = &r100_irq_process,
|
||||
.get_vblank_counter = &r100_get_vblank_counter,
|
||||
.fence_ring_emit = &r100_fence_ring_emit,
|
||||
.cs_parse = &r100_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_legacy_get_engine_clock,
|
||||
.set_engine_clock = &radeon_legacy_set_engine_clock,
|
||||
.get_memory_clock = &radeon_legacy_get_memory_clock,
|
||||
.set_memory_clock = NULL,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_legacy_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
|
@ -138,11 +184,8 @@ extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t
|
|||
extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
|
||||
extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||
extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
|
||||
extern int r300_copy_dma(struct radeon_device *rdev,
|
||||
uint64_t src_offset,
|
||||
uint64_t dst_offset,
|
||||
unsigned num_pages,
|
||||
struct radeon_fence *fence);
|
||||
extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
|
||||
|
||||
static struct radeon_asic r300_asic = {
|
||||
.init = &r300_init,
|
||||
.fini = &r300_fini,
|
||||
|
@ -162,7 +205,46 @@ static struct radeon_asic r300_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_legacy_get_engine_clock,
|
||||
.set_engine_clock = &radeon_legacy_set_engine_clock,
|
||||
.get_memory_clock = &radeon_legacy_get_memory_clock,
|
||||
.set_memory_clock = NULL,
|
||||
.get_pcie_lanes = &rv370_get_pcie_lanes,
|
||||
.set_pcie_lanes = &rv370_set_pcie_lanes,
|
||||
.set_clock_gating = &radeon_legacy_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &r100_bandwidth_update,
|
||||
.hpd_init = &r100_hpd_init,
|
||||
.hpd_fini = &r100_hpd_fini,
|
||||
.hpd_sense = &r100_hpd_sense,
|
||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||
.ioctl_wait_idle = NULL,
|
||||
};
|
||||
|
||||
|
||||
static struct radeon_asic r300_asic_pcie = {
|
||||
.init = &r300_init,
|
||||
.fini = &r300_fini,
|
||||
.suspend = &r300_suspend,
|
||||
.resume = &r300_resume,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r300_gpu_reset,
|
||||
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rv370_pcie_gart_set_page,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r300_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.irq_set = &r100_irq_set,
|
||||
.irq_process = &r100_irq_process,
|
||||
.get_vblank_counter = &r100_get_vblank_counter,
|
||||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_legacy_get_engine_clock,
|
||||
.set_engine_clock = &radeon_legacy_set_engine_clock,
|
||||
|
@ -206,12 +288,13 @@ static struct radeon_asic r420_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_atom_get_engine_clock,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = &rv370_get_pcie_lanes,
|
||||
.set_pcie_lanes = &rv370_set_pcie_lanes,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
|
@ -255,12 +338,13 @@ static struct radeon_asic rs400_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_legacy_get_engine_clock,
|
||||
.set_engine_clock = &radeon_legacy_set_engine_clock,
|
||||
.get_memory_clock = &radeon_legacy_get_memory_clock,
|
||||
.set_memory_clock = NULL,
|
||||
.get_pcie_lanes = NULL,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_legacy_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
|
@ -314,12 +398,13 @@ static struct radeon_asic rs600_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_atom_get_engine_clock,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = NULL,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.bandwidth_update = &rs600_bandwidth_update,
|
||||
|
@ -360,12 +445,13 @@ static struct radeon_asic rs690_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r200_copy_dma,
|
||||
.get_engine_clock = &radeon_atom_get_engine_clock,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = NULL,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
|
@ -412,12 +498,13 @@ static struct radeon_asic rv515_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_atom_get_engine_clock,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = &rv370_get_pcie_lanes,
|
||||
.set_pcie_lanes = &rv370_set_pcie_lanes,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
|
@ -455,12 +542,13 @@ static struct radeon_asic r520_asic = {
|
|||
.fence_ring_emit = &r300_fence_ring_emit,
|
||||
.cs_parse = &r300_cs_parse,
|
||||
.copy_blit = &r100_copy_blit,
|
||||
.copy_dma = &r300_copy_dma,
|
||||
.copy_dma = &r200_copy_dma,
|
||||
.copy = &r100_copy_blit,
|
||||
.get_engine_clock = &radeon_atom_get_engine_clock,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = &rv370_get_pcie_lanes,
|
||||
.set_pcie_lanes = &rv370_set_pcie_lanes,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r100_set_surface_reg,
|
||||
|
@ -538,8 +626,9 @@ static struct radeon_asic r600_asic = {
|
|||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = &rv370_get_pcie_lanes,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_clock_gating = NULL,
|
||||
.set_surface_reg = r600_set_surface_reg,
|
||||
.clear_surface_reg = r600_clear_surface_reg,
|
||||
.bandwidth_update = &rv515_bandwidth_update,
|
||||
|
@ -583,6 +672,7 @@ static struct radeon_asic rv770_asic = {
|
|||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.get_pcie_lanes = &rv370_get_pcie_lanes,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r600_set_surface_reg,
|
||||
|
@ -595,4 +685,54 @@ static struct radeon_asic rv770_asic = {
|
|||
.ioctl_wait_idle = r600_ioctl_wait_idle,
|
||||
};
|
||||
|
||||
/*
|
||||
* evergreen
|
||||
*/
|
||||
int evergreen_init(struct radeon_device *rdev);
|
||||
void evergreen_fini(struct radeon_device *rdev);
|
||||
int evergreen_suspend(struct radeon_device *rdev);
|
||||
int evergreen_resume(struct radeon_device *rdev);
|
||||
int evergreen_gpu_reset(struct radeon_device *rdev);
|
||||
void evergreen_bandwidth_update(struct radeon_device *rdev);
|
||||
void evergreen_hpd_init(struct radeon_device *rdev);
|
||||
void evergreen_hpd_fini(struct radeon_device *rdev);
|
||||
bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||
void evergreen_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd);
|
||||
|
||||
static struct radeon_asic evergreen_asic = {
|
||||
.init = &evergreen_init,
|
||||
.fini = &evergreen_fini,
|
||||
.suspend = &evergreen_suspend,
|
||||
.resume = &evergreen_resume,
|
||||
.cp_commit = NULL,
|
||||
.gpu_reset = &evergreen_gpu_reset,
|
||||
.vga_set_state = &r600_vga_set_state,
|
||||
.gart_tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rs600_gart_set_page,
|
||||
.ring_test = NULL,
|
||||
.ring_ib_execute = NULL,
|
||||
.irq_set = NULL,
|
||||
.irq_process = NULL,
|
||||
.get_vblank_counter = NULL,
|
||||
.fence_ring_emit = NULL,
|
||||
.cs_parse = NULL,
|
||||
.copy_blit = NULL,
|
||||
.copy_dma = NULL,
|
||||
.copy = NULL,
|
||||
.get_engine_clock = &radeon_atom_get_engine_clock,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.get_memory_clock = &radeon_atom_get_memory_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = NULL,
|
||||
.set_surface_reg = r600_set_surface_reg,
|
||||
.clear_surface_reg = r600_clear_surface_reg,
|
||||
.bandwidth_update = &evergreen_bandwidth_update,
|
||||
.hpd_init = &evergreen_hpd_init,
|
||||
.hpd_fini = &evergreen_hpd_fini,
|
||||
.hpd_sense = &evergreen_hpd_sense,
|
||||
.hpd_set_polarity = &evergreen_hpd_set_polarity,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -159,8 +159,15 @@ static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device
|
|||
struct radeon_gpio_rec *gpio)
|
||||
{
|
||||
struct radeon_hpd hpd;
|
||||
u32 reg;
|
||||
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
reg = EVERGREEN_DC_GPIO_HPD_A;
|
||||
else
|
||||
reg = AVIVO_DC_GPIO_HPD_A;
|
||||
|
||||
hpd.gpio = *gpio;
|
||||
if (gpio->reg == AVIVO_DC_GPIO_HPD_A) {
|
||||
if (gpio->reg == reg) {
|
||||
switch(gpio->mask) {
|
||||
case (1 << 0):
|
||||
hpd.hpd = RADEON_HPD_1;
|
||||
|
@ -574,6 +581,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|||
ddc_bus.valid = false;
|
||||
}
|
||||
|
||||
/* needed for aux chan transactions */
|
||||
ddc_bus.hpd_id = hpd.hpd ? (hpd.hpd - 1) : 0;
|
||||
|
||||
conn_id = le16_to_cpu(path->usConnObjectId);
|
||||
|
||||
if (!radeon_atom_apply_quirks
|
||||
|
@ -838,6 +848,7 @@ union firmware_info {
|
|||
ATOM_FIRMWARE_INFO_V1_2 info_12;
|
||||
ATOM_FIRMWARE_INFO_V1_3 info_13;
|
||||
ATOM_FIRMWARE_INFO_V1_4 info_14;
|
||||
ATOM_FIRMWARE_INFO_V2_1 info_21;
|
||||
};
|
||||
|
||||
bool radeon_atom_get_clock_info(struct drm_device *dev)
|
||||
|
@ -849,6 +860,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
|
|||
uint8_t frev, crev;
|
||||
struct radeon_pll *p1pll = &rdev->clock.p1pll;
|
||||
struct radeon_pll *p2pll = &rdev->clock.p2pll;
|
||||
struct radeon_pll *dcpll = &rdev->clock.dcpll;
|
||||
struct radeon_pll *spll = &rdev->clock.spll;
|
||||
struct radeon_pll *mpll = &rdev->clock.mpll;
|
||||
uint16_t data_offset;
|
||||
|
@ -951,8 +963,19 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
|
|||
rdev->clock.default_mclk =
|
||||
le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
|
||||
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
rdev->clock.default_dispclk =
|
||||
le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
|
||||
if (rdev->clock.default_dispclk == 0)
|
||||
rdev->clock.default_dispclk = 60000; /* 600 Mhz */
|
||||
rdev->clock.dp_extclk =
|
||||
le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
|
||||
}
|
||||
*dcpll = *p1pll;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1091,6 +1114,30 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
|
|||
return ss;
|
||||
}
|
||||
|
||||
static void radeon_atom_apply_lvds_quirks(struct drm_device *dev,
|
||||
struct radeon_encoder_atom_dig *lvds)
|
||||
{
|
||||
|
||||
/* Toshiba A300-1BU laptop panel doesn't like new pll divider algo */
|
||||
if ((dev->pdev->device == 0x95c4) &&
|
||||
(dev->pdev->subsystem_vendor == 0x1179) &&
|
||||
(dev->pdev->subsystem_device == 0xff50)) {
|
||||
if ((lvds->native_mode.hdisplay == 1280) &&
|
||||
(lvds->native_mode.vdisplay == 800))
|
||||
lvds->pll_algo = PLL_ALGO_LEGACY;
|
||||
}
|
||||
|
||||
/* Dell Studio 15 laptop panel doesn't like new pll divider algo */
|
||||
if ((dev->pdev->device == 0x95c4) &&
|
||||
(dev->pdev->subsystem_vendor == 0x1028) &&
|
||||
(dev->pdev->subsystem_device == 0x029f)) {
|
||||
if ((lvds->native_mode.hdisplay == 1280) &&
|
||||
(lvds->native_mode.vdisplay == 800))
|
||||
lvds->pll_algo = PLL_ALGO_LEGACY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
union lvds_info {
|
||||
struct _ATOM_LVDS_INFO info;
|
||||
struct _ATOM_LVDS_INFO_V12 info_12;
|
||||
|
@ -1161,6 +1208,21 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
|
|||
|
||||
lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (radeon_new_pll == 0)
|
||||
lvds->pll_algo = PLL_ALGO_LEGACY;
|
||||
else
|
||||
lvds->pll_algo = PLL_ALGO_NEW;
|
||||
} else {
|
||||
if (radeon_new_pll == 1)
|
||||
lvds->pll_algo = PLL_ALGO_NEW;
|
||||
else
|
||||
lvds->pll_algo = PLL_ALGO_LEGACY;
|
||||
}
|
||||
|
||||
/* LVDS quirks */
|
||||
radeon_atom_apply_lvds_quirks(dev, lvds);
|
||||
|
||||
encoder->native_mode = lvds->native_mode;
|
||||
}
|
||||
return lvds;
|
||||
|
@ -1385,6 +1447,371 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
|
|||
return tv_dac;
|
||||
}
|
||||
|
||||
union power_info {
|
||||
struct _ATOM_POWERPLAY_INFO info;
|
||||
struct _ATOM_POWERPLAY_INFO_V2 info_2;
|
||||
struct _ATOM_POWERPLAY_INFO_V3 info_3;
|
||||
struct _ATOM_PPLIB_POWERPLAYTABLE info_4;
|
||||
};
|
||||
|
||||
void radeon_atombios_get_power_modes(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_mode_info *mode_info = &rdev->mode_info;
|
||||
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
|
||||
u16 data_offset;
|
||||
u8 frev, crev;
|
||||
u32 misc, misc2 = 0, sclk, mclk;
|
||||
union power_info *power_info;
|
||||
struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
|
||||
struct _ATOM_PPLIB_STATE *power_state;
|
||||
int num_modes = 0, i, j;
|
||||
int state_index = 0, mode_index = 0;
|
||||
|
||||
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
|
||||
|
||||
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
rdev->pm.default_power_state = NULL;
|
||||
|
||||
if (power_info) {
|
||||
if (frev < 4) {
|
||||
num_modes = power_info->info.ucNumOfPowerModeEntries;
|
||||
if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
|
||||
num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
|
||||
for (i = 0; i < num_modes; i++) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
||||
switch (frev) {
|
||||
case 1:
|
||||
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
||||
rdev->pm.power_state[state_index].clock_info[0].mclk =
|
||||
le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
|
||||
rdev->pm.power_state[state_index].clock_info[0].sclk =
|
||||
le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
|
||||
/* skip invalid modes */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
|
||||
continue;
|
||||
/* skip overclock modes for now */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
|
||||
rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk >
|
||||
rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
|
||||
continue;
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
|
||||
power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
|
||||
misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
|
||||
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
|
||||
VOLTAGE_GPIO;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
|
||||
radeon_lookup_gpio(rdev,
|
||||
power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
|
||||
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
true;
|
||||
else
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
false;
|
||||
} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
|
||||
VOLTAGE_VDDC;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
|
||||
power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
|
||||
}
|
||||
/* order matters! */
|
||||
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_POWERSAVE;
|
||||
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BALANCED;
|
||||
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_PERFORMANCE;
|
||||
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_DEFAULT;
|
||||
rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
|
||||
rdev->pm.power_state[state_index].default_clock_mode =
|
||||
&rdev->pm.power_state[state_index].clock_info[0];
|
||||
}
|
||||
state_index++;
|
||||
break;
|
||||
case 2:
|
||||
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
||||
rdev->pm.power_state[state_index].clock_info[0].mclk =
|
||||
le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
|
||||
rdev->pm.power_state[state_index].clock_info[0].sclk =
|
||||
le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
|
||||
/* skip invalid modes */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
|
||||
continue;
|
||||
/* skip overclock modes for now */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
|
||||
rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk >
|
||||
rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
|
||||
continue;
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
|
||||
power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
|
||||
misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
|
||||
misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
|
||||
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
|
||||
VOLTAGE_GPIO;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
|
||||
radeon_lookup_gpio(rdev,
|
||||
power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
|
||||
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
true;
|
||||
else
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
false;
|
||||
} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
|
||||
VOLTAGE_VDDC;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
|
||||
power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
|
||||
}
|
||||
/* order matters! */
|
||||
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_POWERSAVE;
|
||||
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BALANCED;
|
||||
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_PERFORMANCE;
|
||||
if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BALANCED;
|
||||
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_DEFAULT;
|
||||
rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
|
||||
rdev->pm.power_state[state_index].default_clock_mode =
|
||||
&rdev->pm.power_state[state_index].clock_info[0];
|
||||
}
|
||||
state_index++;
|
||||
break;
|
||||
case 3:
|
||||
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
||||
rdev->pm.power_state[state_index].clock_info[0].mclk =
|
||||
le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
|
||||
rdev->pm.power_state[state_index].clock_info[0].sclk =
|
||||
le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
|
||||
/* skip invalid modes */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
|
||||
continue;
|
||||
/* skip overclock modes for now */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
|
||||
rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk >
|
||||
rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
|
||||
continue;
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
|
||||
power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
|
||||
misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
|
||||
misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
|
||||
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
|
||||
VOLTAGE_GPIO;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
|
||||
radeon_lookup_gpio(rdev,
|
||||
power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
|
||||
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
true;
|
||||
else
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
false;
|
||||
} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
|
||||
VOLTAGE_VDDC;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
|
||||
power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
|
||||
if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
|
||||
true;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
|
||||
power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
|
||||
}
|
||||
}
|
||||
/* order matters! */
|
||||
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_POWERSAVE;
|
||||
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BALANCED;
|
||||
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_PERFORMANCE;
|
||||
if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BALANCED;
|
||||
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_DEFAULT;
|
||||
rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
|
||||
rdev->pm.power_state[state_index].default_clock_mode =
|
||||
&rdev->pm.power_state[state_index].clock_info[0];
|
||||
}
|
||||
state_index++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (frev == 4) {
|
||||
for (i = 0; i < power_info->info_4.ucNumStates; i++) {
|
||||
mode_index = 0;
|
||||
power_state = (struct _ATOM_PPLIB_STATE *)
|
||||
(mode_info->atom_context->bios +
|
||||
data_offset +
|
||||
le16_to_cpu(power_info->info_4.usStateArrayOffset) +
|
||||
i * power_info->info_4.ucStateEntrySize);
|
||||
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
|
||||
(mode_info->atom_context->bios +
|
||||
data_offset +
|
||||
le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) +
|
||||
(power_state->ucNonClockStateIndex *
|
||||
power_info->info_4.ucNonClockSize));
|
||||
for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) {
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info =
|
||||
(struct _ATOM_PPLIB_RS780_CLOCK_INFO *)
|
||||
(mode_info->atom_context->bios +
|
||||
data_offset +
|
||||
le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
|
||||
(power_state->ucClockStateIndices[j] *
|
||||
power_info->info_4.ucClockInfoSize));
|
||||
sclk = le16_to_cpu(clock_info->usLowEngineClockLow);
|
||||
sclk |= clock_info->ucLowEngineClockHigh << 16;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
|
||||
/* skip invalid modes */
|
||||
if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
|
||||
continue;
|
||||
/* skip overclock modes for now */
|
||||
if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
|
||||
rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN)
|
||||
continue;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
|
||||
VOLTAGE_SW;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
|
||||
clock_info->usVDDC;
|
||||
mode_index++;
|
||||
} else {
|
||||
struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
|
||||
(struct _ATOM_PPLIB_R600_CLOCK_INFO *)
|
||||
(mode_info->atom_context->bios +
|
||||
data_offset +
|
||||
le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
|
||||
(power_state->ucClockStateIndices[j] *
|
||||
power_info->info_4.ucClockInfoSize));
|
||||
sclk = le16_to_cpu(clock_info->usEngineClockLow);
|
||||
sclk |= clock_info->ucEngineClockHigh << 16;
|
||||
mclk = le16_to_cpu(clock_info->usMemoryClockLow);
|
||||
mclk |= clock_info->ucMemoryClockHigh << 16;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
|
||||
/* skip invalid modes */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
|
||||
continue;
|
||||
/* skip overclock modes for now */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
|
||||
rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
|
||||
rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
|
||||
continue;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
|
||||
VOLTAGE_SW;
|
||||
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
|
||||
clock_info->usVDDC;
|
||||
mode_index++;
|
||||
}
|
||||
}
|
||||
rdev->pm.power_state[state_index].num_clock_modes = mode_index;
|
||||
if (mode_index) {
|
||||
misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
|
||||
misc2 = le16_to_cpu(non_clock_info->usClassification);
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
|
||||
((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
|
||||
ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
|
||||
switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
|
||||
case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
break;
|
||||
case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BALANCED;
|
||||
break;
|
||||
case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_PERFORMANCE;
|
||||
break;
|
||||
}
|
||||
if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_DEFAULT;
|
||||
rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
|
||||
rdev->pm.power_state[state_index].default_clock_mode =
|
||||
&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
|
||||
}
|
||||
state_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* XXX figure out some good default low power mode for cards w/out power tables */
|
||||
}
|
||||
|
||||
if (rdev->pm.default_power_state == NULL) {
|
||||
/* add the default mode */
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_DEFAULT;
|
||||
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
||||
rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
|
||||
rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
|
||||
rdev->pm.power_state[state_index].default_clock_mode =
|
||||
&rdev->pm.power_state[state_index].clock_info[0];
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
||||
if (rdev->asic->get_pcie_lanes)
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
|
||||
else
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
|
||||
rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
|
||||
state_index++;
|
||||
}
|
||||
rdev->pm.num_power_states = state_index;
|
||||
|
||||
rdev->pm.current_power_state = rdev->pm.default_power_state;
|
||||
rdev->pm.current_clock_mode =
|
||||
rdev->pm.default_power_state->default_clock_mode;
|
||||
}
|
||||
|
||||
void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
|
||||
{
|
||||
DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
|
||||
|
@ -1395,16 +1822,6 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
|
|||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
void radeon_atom_static_pwrmgt_setup(struct radeon_device *rdev, int enable)
|
||||
{
|
||||
ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt);
|
||||
|
||||
args.ucEnable = enable;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
|
||||
{
|
||||
GET_ENGINE_CLOCK_PS_ALLOCATION args;
|
||||
|
|
|
@ -411,6 +411,12 @@ bool radeon_get_bios(struct radeon_device *rdev)
|
|||
goto free_bios;
|
||||
}
|
||||
|
||||
tmp = RBIOS16(0x18);
|
||||
if (RBIOS8(tmp + 0x14) != 0x0) {
|
||||
DRM_INFO("Not an x86 BIOS ROM, not using.\n");
|
||||
goto free_bios;
|
||||
}
|
||||
|
||||
rdev->bios_header_start = RBIOS16(0x48);
|
||||
if (!rdev->bios_header_start) {
|
||||
goto free_bios;
|
||||
|
|
|
@ -96,6 +96,7 @@ void radeon_get_clock_info(struct drm_device *dev)
|
|||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_pll *p1pll = &rdev->clock.p1pll;
|
||||
struct radeon_pll *p2pll = &rdev->clock.p2pll;
|
||||
struct radeon_pll *dcpll = &rdev->clock.dcpll;
|
||||
struct radeon_pll *spll = &rdev->clock.spll;
|
||||
struct radeon_pll *mpll = &rdev->clock.mpll;
|
||||
int ret;
|
||||
|
@ -204,6 +205,17 @@ void radeon_get_clock_info(struct drm_device *dev)
|
|||
p2pll->max_frac_feedback_div = 0;
|
||||
}
|
||||
|
||||
/* dcpll is DCE4 only */
|
||||
dcpll->min_post_div = 2;
|
||||
dcpll->max_post_div = 0x7f;
|
||||
dcpll->min_frac_feedback_div = 0;
|
||||
dcpll->max_frac_feedback_div = 9;
|
||||
dcpll->min_ref_div = 2;
|
||||
dcpll->max_ref_div = 0x3ff;
|
||||
dcpll->min_feedback_div = 4;
|
||||
dcpll->max_feedback_div = 0xfff;
|
||||
dcpll->best_vco = 0;
|
||||
|
||||
p1pll->min_ref_div = 2;
|
||||
p1pll->max_ref_div = 0x3ff;
|
||||
p1pll->min_feedback_div = 4;
|
||||
|
@ -846,8 +858,10 @@ int radeon_static_clocks_init(struct drm_device *dev)
|
|||
/* XXX make sure engine is idle */
|
||||
|
||||
if (radeon_dynclks != -1) {
|
||||
if (radeon_dynclks)
|
||||
radeon_set_clock_gating(rdev, 1);
|
||||
if (radeon_dynclks) {
|
||||
if (rdev->asic->set_clock_gating)
|
||||
radeon_set_clock_gating(rdev, 1);
|
||||
}
|
||||
}
|
||||
radeon_apply_clock_quirks(rdev);
|
||||
return 0;
|
||||
|
|
|
@ -150,6 +150,9 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
|
|||
int rev;
|
||||
uint16_t offset = 0, check_offset;
|
||||
|
||||
if (!rdev->bios)
|
||||
return 0;
|
||||
|
||||
switch (table) {
|
||||
/* absolute offset tables */
|
||||
case COMBIOS_ASIC_INIT_1_TABLE:
|
||||
|
@ -443,6 +446,39 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
|
|||
|
||||
}
|
||||
|
||||
bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
|
||||
{
|
||||
int edid_info;
|
||||
struct edid *edid;
|
||||
edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
|
||||
if (!edid_info)
|
||||
return false;
|
||||
|
||||
edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
|
||||
GFP_KERNEL);
|
||||
if (edid == NULL)
|
||||
return false;
|
||||
|
||||
memcpy((unsigned char *)edid,
|
||||
(unsigned char *)(rdev->bios + edid_info), EDID_LENGTH);
|
||||
|
||||
if (!drm_edid_is_valid(edid)) {
|
||||
kfree(edid);
|
||||
return false;
|
||||
}
|
||||
|
||||
rdev->mode_info.bios_hardcoded_edid = edid;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct edid *
|
||||
radeon_combios_get_hardcoded_edid(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->mode_info.bios_hardcoded_edid)
|
||||
return rdev->mode_info.bios_hardcoded_edid;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
|
||||
int ddc_line)
|
||||
{
|
||||
|
@ -486,9 +522,65 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
|
|||
i2c.y_data_reg = ddc_line;
|
||||
}
|
||||
|
||||
if (rdev->family < CHIP_R200)
|
||||
i2c.hw_capable = false;
|
||||
else {
|
||||
switch (rdev->family) {
|
||||
case CHIP_R100:
|
||||
case CHIP_RV100:
|
||||
case CHIP_RS100:
|
||||
case CHIP_RV200:
|
||||
case CHIP_RS200:
|
||||
case CHIP_RS300:
|
||||
switch (ddc_line) {
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
/* in theory this should be hw capable,
|
||||
* but it doesn't seem to work
|
||||
*/
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
default:
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CHIP_R200:
|
||||
switch (ddc_line) {
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
case RADEON_GPIO_MONID:
|
||||
i2c.hw_capable = true;
|
||||
break;
|
||||
default:
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CHIP_RV250:
|
||||
case CHIP_RV280:
|
||||
switch (ddc_line) {
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
case RADEON_GPIO_CRT2_DDC:
|
||||
i2c.hw_capable = true;
|
||||
break;
|
||||
default:
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CHIP_R300:
|
||||
case CHIP_R350:
|
||||
switch (ddc_line) {
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
i2c.hw_capable = true;
|
||||
break;
|
||||
default:
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CHIP_RV350:
|
||||
case CHIP_RV380:
|
||||
case CHIP_RS400:
|
||||
case CHIP_RS480:
|
||||
switch (ddc_line) {
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
|
@ -504,9 +596,14 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
|
|||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
i2c.mm_i2c = false;
|
||||
i2c.i2c_id = 0;
|
||||
i2c.hpd_id = 0;
|
||||
|
||||
if (ddc_line)
|
||||
i2c.valid = true;
|
||||
|
@ -527,9 +624,6 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
|
|||
int8_t rev;
|
||||
uint16_t sclk, mclk;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return false;
|
||||
|
||||
pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
|
||||
if (pll_info) {
|
||||
rev = RBIOS8(pll_info);
|
||||
|
@ -654,9 +748,6 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
|
|||
if (!p_dac)
|
||||
return NULL;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
goto out;
|
||||
|
||||
/* check CRT table */
|
||||
dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
|
||||
if (dac_info) {
|
||||
|
@ -673,7 +764,6 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
|
|||
found = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!found) /* fallback to defaults */
|
||||
radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
|
||||
|
||||
|
@ -687,9 +777,6 @@ radeon_combios_get_tv_info(struct radeon_device *rdev)
|
|||
uint16_t tv_info;
|
||||
enum radeon_tv_std tv_std = TV_STD_NTSC;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return tv_std;
|
||||
|
||||
tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
|
||||
if (tv_info) {
|
||||
if (RBIOS8(tv_info + 6) == 'T') {
|
||||
|
@ -793,9 +880,6 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
|
|||
if (!tv_dac)
|
||||
return NULL;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
goto out;
|
||||
|
||||
/* first check TV table */
|
||||
dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
|
||||
if (dac_info) {
|
||||
|
@ -857,7 +941,6 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (!found) /* fallback to defaults */
|
||||
radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac);
|
||||
|
||||
|
@ -945,11 +1028,6 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
|
|||
int tmp, i;
|
||||
struct radeon_encoder_lvds *lvds = NULL;
|
||||
|
||||
if (rdev->bios == NULL) {
|
||||
lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
|
||||
|
||||
if (lcd_info) {
|
||||
|
@ -1050,7 +1128,7 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
|
|||
DRM_INFO("No panel info found in BIOS\n");
|
||||
lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
|
||||
}
|
||||
out:
|
||||
|
||||
if (lvds)
|
||||
encoder->native_mode = lvds->native_mode;
|
||||
return lvds;
|
||||
|
@ -1102,9 +1180,6 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
|
|||
int i, n;
|
||||
uint8_t ver;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return false;
|
||||
|
||||
tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
|
||||
|
||||
if (tmds_info) {
|
||||
|
@ -1184,9 +1259,6 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
|
|||
enum radeon_combios_ddc gpio;
|
||||
struct radeon_i2c_bus_rec i2c_bus;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return false;
|
||||
|
||||
tmds->i2c_bus = NULL;
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
|
||||
|
@ -1253,7 +1325,10 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
|
|||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
break;
|
||||
case DDC_LCD: /* MM i2c */
|
||||
DRM_ERROR("MM i2c requires hw i2c engine\n");
|
||||
i2c_bus.valid = true;
|
||||
i2c_bus.hw_capable = true;
|
||||
i2c_bus.mm_i2c = true;
|
||||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported gpio %d\n", gpio);
|
||||
|
@ -1909,9 +1984,6 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
|||
struct radeon_i2c_bus_rec ddc_i2c;
|
||||
struct radeon_hpd hpd;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return false;
|
||||
|
||||
conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE);
|
||||
if (conn_info) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -2278,6 +2350,115 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
|||
return true;
|
||||
}
|
||||
|
||||
void radeon_combios_get_power_modes(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
u16 offset, misc, misc2 = 0;
|
||||
u8 rev, blocks, tmp;
|
||||
int state_index = 0;
|
||||
|
||||
rdev->pm.default_power_state = NULL;
|
||||
|
||||
if (rdev->flags & RADEON_IS_MOBILITY) {
|
||||
offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
|
||||
if (offset) {
|
||||
rev = RBIOS8(offset);
|
||||
blocks = RBIOS8(offset + 0x2);
|
||||
/* power mode 0 tends to be the only valid one */
|
||||
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
||||
rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2);
|
||||
rdev->pm.power_state[state_index].clock_info[0].sclk = RBIOS32(offset + 0x5 + 0x6);
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
|
||||
goto default_mode;
|
||||
/* skip overclock modes for now */
|
||||
if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
|
||||
rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
|
||||
(rdev->pm.power_state[state_index].clock_info[0].sclk >
|
||||
rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
|
||||
goto default_mode;
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_BATTERY;
|
||||
misc = RBIOS16(offset + 0x5 + 0x0);
|
||||
if (rev > 4)
|
||||
misc2 = RBIOS16(offset + 0x5 + 0xe);
|
||||
if (misc & 0x4) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO;
|
||||
if (misc & 0x8)
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
true;
|
||||
else
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
|
||||
false;
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = true;
|
||||
if (rev < 6) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
|
||||
RBIOS16(offset + 0x5 + 0xb) * 4;
|
||||
tmp = RBIOS8(offset + 0x5 + 0xd);
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
|
||||
} else {
|
||||
u8 entries = RBIOS8(offset + 0x5 + 0xb);
|
||||
u16 voltage_table_offset = RBIOS16(offset + 0x5 + 0xc);
|
||||
if (entries && voltage_table_offset) {
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
|
||||
RBIOS16(voltage_table_offset) * 4;
|
||||
tmp = RBIOS8(voltage_table_offset + 0x2);
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
|
||||
} else
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = false;
|
||||
}
|
||||
switch ((misc2 & 0x700) >> 8) {
|
||||
case 0:
|
||||
default:
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 0;
|
||||
break;
|
||||
case 1:
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 33;
|
||||
break;
|
||||
case 2:
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 66;
|
||||
break;
|
||||
case 3:
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 99;
|
||||
break;
|
||||
case 4:
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 132;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
||||
if (rev > 6)
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
|
||||
RBIOS8(offset + 0x5 + 0x10);
|
||||
state_index++;
|
||||
} else {
|
||||
/* XXX figure out some good default low power mode for mobility cards w/out power tables */
|
||||
}
|
||||
} else {
|
||||
/* XXX figure out some good default low power mode for desktop cards */
|
||||
}
|
||||
|
||||
default_mode:
|
||||
/* add the default mode */
|
||||
rdev->pm.power_state[state_index].type =
|
||||
POWER_STATE_TYPE_DEFAULT;
|
||||
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
||||
rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
|
||||
rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
|
||||
rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
|
||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
||||
if (rdev->asic->get_pcie_lanes)
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
|
||||
else
|
||||
rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
|
||||
rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
|
||||
rdev->pm.num_power_states = state_index + 1;
|
||||
|
||||
rdev->pm.current_power_state = rdev->pm.default_power_state;
|
||||
rdev->pm.current_clock_mode =
|
||||
rdev->pm.default_power_state->default_clock_mode;
|
||||
}
|
||||
|
||||
void radeon_external_tmds_setup(struct drm_encoder *encoder)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
@ -2289,23 +2470,21 @@ void radeon_external_tmds_setup(struct drm_encoder *encoder)
|
|||
switch (tmds->dvo_chip) {
|
||||
case DVO_SIL164:
|
||||
/* sil 164 */
|
||||
radeon_i2c_do_lock(tmds->i2c_bus, 1);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x08, 0x30);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x08, 0x30);
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x09, 0x00);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x0a, 0x90);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x0c, 0x89);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x0a, 0x90);
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x0c, 0x89);
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
0x08, 0x3b);
|
||||
radeon_i2c_do_lock(tmds->i2c_bus, 0);
|
||||
break;
|
||||
case DVO_SIL1178:
|
||||
/* sil 1178 - untested */
|
||||
|
@ -2338,9 +2517,6 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
|
|||
uint32_t reg, val, and_mask, or_mask;
|
||||
struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return false;
|
||||
|
||||
if (!tmds)
|
||||
return false;
|
||||
|
||||
|
@ -2390,11 +2566,9 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
|
|||
index++;
|
||||
val = RBIOS8(index);
|
||||
index++;
|
||||
radeon_i2c_do_lock(tmds->i2c_bus, 1);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
slave_addr,
|
||||
reg, val);
|
||||
radeon_i2c_do_lock(tmds->i2c_bus, 0);
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
slave_addr,
|
||||
reg, val);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown id %d\n", id >> 13);
|
||||
|
@ -2447,11 +2621,9 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
|
|||
reg = id & 0x1fff;
|
||||
val = RBIOS8(index);
|
||||
index += 1;
|
||||
radeon_i2c_do_lock(tmds->i2c_bus, 1);
|
||||
radeon_i2c_sw_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
reg, val);
|
||||
radeon_i2c_do_lock(tmds->i2c_bus, 0);
|
||||
radeon_i2c_put_byte(tmds->i2c_bus,
|
||||
tmds->slave_addr,
|
||||
reg, val);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown id %d\n", id >> 13);
|
||||
|
|
|
@ -479,10 +479,8 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec
|
|||
ret = connector_status_connected;
|
||||
else {
|
||||
if (radeon_connector->ddc_bus) {
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base,
|
||||
&radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
if (radeon_connector->edid)
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
|
@ -587,19 +585,14 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
|
|||
if (!encoder)
|
||||
ret = connector_status_disconnected;
|
||||
|
||||
if (radeon_connector->ddc_bus) {
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
if (radeon_connector->ddc_bus)
|
||||
dret = radeon_ddc_probe(radeon_connector);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
}
|
||||
if (dret) {
|
||||
if (radeon_connector->edid) {
|
||||
kfree(radeon_connector->edid);
|
||||
radeon_connector->edid = NULL;
|
||||
}
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
|
||||
if (!radeon_connector->edid) {
|
||||
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
|
||||
|
@ -744,19 +737,14 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
|
|||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool dret = false;
|
||||
|
||||
if (radeon_connector->ddc_bus) {
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
if (radeon_connector->ddc_bus)
|
||||
dret = radeon_ddc_probe(radeon_connector);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
}
|
||||
if (dret) {
|
||||
if (radeon_connector->edid) {
|
||||
kfree(radeon_connector->edid);
|
||||
radeon_connector->edid = NULL;
|
||||
}
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
|
||||
if (!radeon_connector->edid) {
|
||||
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
|
||||
|
@ -952,7 +940,7 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector)
|
|||
if (radeon_connector->edid)
|
||||
kfree(radeon_connector->edid);
|
||||
if (radeon_dig_connector->dp_i2c_bus)
|
||||
radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
|
||||
radeon_i2c_destroy_dp(radeon_dig_connector->dp_i2c_bus);
|
||||
kfree(radeon_connector->con_priv);
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
|
@ -988,12 +976,10 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
|
|||
ret = connector_status_connected;
|
||||
}
|
||||
} else {
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
if (radeon_ddc_probe(radeon_connector)) {
|
||||
radeon_dig_connector->dp_sink_type = sink_type;
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -36,7 +36,14 @@ static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
|
|||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
uint32_t cur_lock;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
|
||||
if (lock)
|
||||
cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
|
||||
else
|
||||
cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
|
||||
WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
|
||||
} else if (ASIC_IS_AVIVO(rdev)) {
|
||||
cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
|
||||
if (lock)
|
||||
cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
|
||||
|
@ -58,7 +65,10 @@ static void radeon_hide_cursor(struct drm_crtc *crtc)
|
|||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct radeon_device *rdev = crtc->dev->dev_private;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
|
||||
WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
|
||||
} else if (ASIC_IS_AVIVO(rdev)) {
|
||||
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
|
||||
WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
|
||||
} else {
|
||||
|
@ -81,10 +91,14 @@ static void radeon_show_cursor(struct drm_crtc *crtc)
|
|||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct radeon_device *rdev = crtc->dev->dev_private;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
|
||||
WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
|
||||
EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
|
||||
} else if (ASIC_IS_AVIVO(rdev)) {
|
||||
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
|
||||
WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
|
||||
(AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
|
||||
(AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
|
||||
} else {
|
||||
switch (radeon_crtc->crtc_id) {
|
||||
case 0:
|
||||
|
@ -109,7 +123,10 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
|
|||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct radeon_device *rdev = crtc->dev->dev_private;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
|
||||
} else if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (rdev->family >= CHIP_RV770) {
|
||||
if (radeon_crtc->crtc_id)
|
||||
WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, 0);
|
||||
|
@ -197,7 +214,20 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
|
|||
yorigin = CURSOR_HEIGHT - 1;
|
||||
|
||||
radeon_lock_cursor(crtc, true);
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
/* cursors are offset into the total surface */
|
||||
x += crtc->x;
|
||||
y += crtc->y;
|
||||
DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
|
||||
|
||||
/* XXX: check if evergreen has the same issues as avivo chips */
|
||||
WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
|
||||
((xorigin ? 0 : x) << 16) |
|
||||
(yorigin ? 0 : y));
|
||||
WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
|
||||
WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
|
||||
((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1));
|
||||
} else if (ASIC_IS_AVIVO(rdev)) {
|
||||
int w = radeon_crtc->cursor_width;
|
||||
int i = 0;
|
||||
struct drm_crtc *crtc_p;
|
||||
|
|
|
@ -100,79 +100,102 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MC common functions
|
||||
/**
|
||||
* radeon_vram_location - try to find VRAM location
|
||||
* @rdev: radeon device structure holding all necessary informations
|
||||
* @mc: memory controller structure holding memory informations
|
||||
* @base: base address at which to put VRAM
|
||||
*
|
||||
* Function will place try to place VRAM at base address provided
|
||||
* as parameter (which is so far either PCI aperture address or
|
||||
* for IGP TOM base address).
|
||||
*
|
||||
* If there is not enough space to fit the unvisible VRAM in the 32bits
|
||||
* address space then we limit the VRAM size to the aperture.
|
||||
*
|
||||
* If we are using AGP and if the AGP aperture doesn't allow us to have
|
||||
* room for all the VRAM than we restrict the VRAM to the PCI aperture
|
||||
* size and print a warning.
|
||||
*
|
||||
* This function will never fails, worst case are limiting VRAM.
|
||||
*
|
||||
* Note: GTT start, end, size should be initialized before calling this
|
||||
* function on AGP platform.
|
||||
*
|
||||
* Note: We don't explictly enforce VRAM start to be aligned on VRAM size,
|
||||
* this shouldn't be a problem as we are using the PCI aperture as a reference.
|
||||
* Otherwise this would be needed for rv280, all r3xx, and all r4xx, but
|
||||
* not IGP.
|
||||
*
|
||||
* Note: we use mc_vram_size as on some board we need to program the mc to
|
||||
* cover the whole aperture even if VRAM size is inferior to aperture size
|
||||
* Novell bug 204882 + along with lots of ubuntu ones
|
||||
*
|
||||
* Note: when limiting vram it's safe to overwritte real_vram_size because
|
||||
* we are not in case where real_vram_size is inferior to mc_vram_size (ie
|
||||
* note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu
|
||||
* ones)
|
||||
*
|
||||
* Note: IGP TOM addr should be the same as the aperture addr, we don't
|
||||
* explicitly check for that thought.
|
||||
*
|
||||
* FIXME: when reducing VRAM size align new size on power of 2.
|
||||
*/
|
||||
int radeon_mc_setup(struct radeon_device *rdev)
|
||||
void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* Some chips have an "issue" with the memory controller, the
|
||||
* location must be aligned to the size. We just align it down,
|
||||
* too bad if we walk over the top of system memory, we don't
|
||||
* use DMA without a remapped anyway.
|
||||
* Affected chips are rv280, all r3xx, and all r4xx, but not IGP
|
||||
*/
|
||||
/* FGLRX seems to setup like this, VRAM a 0, then GART.
|
||||
*/
|
||||
/*
|
||||
* Note: from R6xx the address space is 40bits but here we only
|
||||
* use 32bits (still have to see a card which would exhaust 4G
|
||||
* address space).
|
||||
*/
|
||||
if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
|
||||
/* vram location was already setup try to put gtt after
|
||||
* if it fits */
|
||||
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
|
||||
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
|
||||
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
|
||||
rdev->mc.gtt_location = tmp;
|
||||
} else {
|
||||
if (rdev->mc.gtt_size >= rdev->mc.vram_location) {
|
||||
printk(KERN_ERR "[drm] GTT too big to fit "
|
||||
"before or after vram location.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
rdev->mc.gtt_location = 0;
|
||||
}
|
||||
} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
|
||||
/* gtt location was already setup try to put vram before
|
||||
* if it fits */
|
||||
if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
|
||||
rdev->mc.vram_location = 0;
|
||||
} else {
|
||||
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
|
||||
tmp += (rdev->mc.mc_vram_size - 1);
|
||||
tmp &= ~(rdev->mc.mc_vram_size - 1);
|
||||
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
|
||||
rdev->mc.vram_location = tmp;
|
||||
} else {
|
||||
printk(KERN_ERR "[drm] vram too big to fit "
|
||||
"before or after GTT location.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rdev->mc.vram_location = 0;
|
||||
tmp = rdev->mc.mc_vram_size;
|
||||
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
|
||||
rdev->mc.gtt_location = tmp;
|
||||
mc->vram_start = base;
|
||||
if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
|
||||
dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
|
||||
mc->real_vram_size = mc->aper_size;
|
||||
mc->mc_vram_size = mc->aper_size;
|
||||
}
|
||||
rdev->mc.vram_start = rdev->mc.vram_location;
|
||||
rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
|
||||
rdev->mc.gtt_start = rdev->mc.gtt_location;
|
||||
rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
|
||||
DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20));
|
||||
DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
|
||||
(unsigned)rdev->mc.vram_location,
|
||||
(unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1));
|
||||
DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20));
|
||||
DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
|
||||
(unsigned)rdev->mc.gtt_location,
|
||||
(unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1));
|
||||
return 0;
|
||||
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
|
||||
if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) {
|
||||
dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
|
||||
mc->real_vram_size = mc->aper_size;
|
||||
mc->mc_vram_size = mc->aper_size;
|
||||
}
|
||||
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
|
||||
dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
|
||||
mc->mc_vram_size >> 20, mc->vram_start,
|
||||
mc->vram_end, mc->real_vram_size >> 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* radeon_gtt_location - try to find GTT location
|
||||
* @rdev: radeon device structure holding all necessary informations
|
||||
* @mc: memory controller structure holding memory informations
|
||||
*
|
||||
* Function will place try to place GTT before or after VRAM.
|
||||
*
|
||||
* If GTT size is bigger than space left then we ajust GTT size.
|
||||
* Thus function will never fails.
|
||||
*
|
||||
* FIXME: when reducing GTT size align new size on power of 2.
|
||||
*/
|
||||
void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
|
||||
{
|
||||
u64 size_af, size_bf;
|
||||
|
||||
size_af = 0xFFFFFFFF - mc->vram_end;
|
||||
size_bf = mc->vram_start;
|
||||
if (size_bf > size_af) {
|
||||
if (mc->gtt_size > size_bf) {
|
||||
dev_warn(rdev->dev, "limiting GTT\n");
|
||||
mc->gtt_size = size_bf;
|
||||
}
|
||||
mc->gtt_start = mc->vram_start - mc->gtt_size;
|
||||
} else {
|
||||
if (mc->gtt_size > size_af) {
|
||||
dev_warn(rdev->dev, "limiting GTT\n");
|
||||
mc->gtt_size = size_af;
|
||||
}
|
||||
mc->gtt_start = mc->vram_end + 1;
|
||||
}
|
||||
mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
|
||||
dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
|
||||
mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end);
|
||||
}
|
||||
|
||||
/*
|
||||
* GPU helpers function.
|
||||
|
@ -182,7 +205,16 @@ bool radeon_card_posted(struct radeon_device *rdev)
|
|||
uint32_t reg;
|
||||
|
||||
/* first check CRTCs */
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
|
||||
RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
|
||||
if (reg & EVERGREEN_CRTC_MASTER_EN)
|
||||
return true;
|
||||
} else if (ASIC_IS_AVIVO(rdev)) {
|
||||
reg = RREG32(AVIVO_D1CRTC_CONTROL) |
|
||||
RREG32(AVIVO_D2CRTC_CONTROL);
|
||||
if (reg & AVIVO_CRTC_EN) {
|
||||
|
@ -229,6 +261,8 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev)
|
|||
|
||||
int radeon_dummy_page_init(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->dummy_page.page)
|
||||
return 0;
|
||||
rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO);
|
||||
if (rdev->dummy_page.page == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -310,7 +344,7 @@ void radeon_register_accessor_init(struct radeon_device *rdev)
|
|||
rdev->mc_rreg = &rs600_mc_rreg;
|
||||
rdev->mc_wreg = &rs600_mc_wreg;
|
||||
}
|
||||
if (rdev->family >= CHIP_R600) {
|
||||
if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_RV740)) {
|
||||
rdev->pciep_rreg = &r600_pciep_rreg;
|
||||
rdev->pciep_wreg = &r600_pciep_wreg;
|
||||
}
|
||||
|
@ -329,21 +363,22 @@ int radeon_asic_init(struct radeon_device *rdev)
|
|||
case CHIP_RS100:
|
||||
case CHIP_RV200:
|
||||
case CHIP_RS200:
|
||||
rdev->asic = &r100_asic;
|
||||
break;
|
||||
case CHIP_R200:
|
||||
case CHIP_RV250:
|
||||
case CHIP_RS300:
|
||||
case CHIP_RV280:
|
||||
rdev->asic = &r100_asic;
|
||||
rdev->asic = &r200_asic;
|
||||
break;
|
||||
case CHIP_R300:
|
||||
case CHIP_R350:
|
||||
case CHIP_RV350:
|
||||
case CHIP_RV380:
|
||||
rdev->asic = &r300_asic;
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
|
||||
}
|
||||
if (rdev->flags & RADEON_IS_PCIE)
|
||||
rdev->asic = &r300_asic_pcie;
|
||||
else
|
||||
rdev->asic = &r300_asic;
|
||||
break;
|
||||
case CHIP_R420:
|
||||
case CHIP_R423:
|
||||
|
@ -387,6 +422,13 @@ int radeon_asic_init(struct radeon_device *rdev)
|
|||
case CHIP_RV740:
|
||||
rdev->asic = &rv770_asic;
|
||||
break;
|
||||
case CHIP_CEDAR:
|
||||
case CHIP_REDWOOD:
|
||||
case CHIP_JUNIPER:
|
||||
case CHIP_CYPRESS:
|
||||
case CHIP_HEMLOCK:
|
||||
rdev->asic = &evergreen_asic;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: not supported yet */
|
||||
return -EINVAL;
|
||||
|
@ -638,11 +680,14 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
mutex_init(&rdev->cs_mutex);
|
||||
mutex_init(&rdev->ib_pool.mutex);
|
||||
mutex_init(&rdev->cp.mutex);
|
||||
mutex_init(&rdev->dc_hw_i2c_mutex);
|
||||
if (rdev->family >= CHIP_R600)
|
||||
spin_lock_init(&rdev->ih.lock);
|
||||
mutex_init(&rdev->gem.mutex);
|
||||
mutex_init(&rdev->pm.mutex);
|
||||
rwlock_init(&rdev->fence_drv.lock);
|
||||
INIT_LIST_HEAD(&rdev->gem.objects);
|
||||
init_waitqueue_head(&rdev->irq.vblank_queue);
|
||||
|
||||
/* setup workqueue */
|
||||
rdev->wq = create_workqueue("radeon");
|
||||
|
|
|
@ -68,6 +68,36 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc)
|
|||
WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
|
||||
}
|
||||
|
||||
static void evergreen_crtc_load_lut(struct drm_crtc *crtc)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("%d\n", radeon_crtc->crtc_id);
|
||||
WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0);
|
||||
|
||||
WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
|
||||
WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
|
||||
|
||||
WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
|
||||
WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
|
||||
WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
|
||||
|
||||
WREG32(EVERGREEN_DC_LUT_RW_MODE, radeon_crtc->crtc_id);
|
||||
WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK, 0x00000007);
|
||||
|
||||
WREG32(EVERGREEN_DC_LUT_RW_INDEX, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
WREG32(EVERGREEN_DC_LUT_30_COLOR,
|
||||
(radeon_crtc->lut_r[i] << 20) |
|
||||
(radeon_crtc->lut_g[i] << 10) |
|
||||
(radeon_crtc->lut_b[i] << 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void legacy_crtc_load_lut(struct drm_crtc *crtc)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
|
@ -100,7 +130,9 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc)
|
|||
if (!crtc->enabled)
|
||||
return;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
evergreen_crtc_load_lut(crtc);
|
||||
else if (ASIC_IS_AVIVO(rdev))
|
||||
avivo_crtc_load_lut(crtc);
|
||||
else
|
||||
legacy_crtc_load_lut(crtc);
|
||||
|
@ -361,6 +393,8 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
|
|||
|
||||
int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct drm_device *dev = radeon_connector->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
|
||||
|
@ -373,11 +407,11 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
|
|||
if (!radeon_connector->ddc_bus)
|
||||
return -1;
|
||||
if (!radeon_connector->edid) {
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
}
|
||||
|
||||
/* some servers provide a hardcoded edid in rom for KVMs */
|
||||
if (!radeon_connector->edid)
|
||||
radeon_connector->edid = radeon_combios_get_hardcoded_edid(rdev);
|
||||
if (radeon_connector->edid) {
|
||||
drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
|
||||
ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
|
||||
|
@ -395,9 +429,7 @@ static int radeon_ddc_dump(struct drm_connector *connector)
|
|||
|
||||
if (!radeon_connector->ddc_bus)
|
||||
return -1;
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
if (edid) {
|
||||
kfree(edid);
|
||||
}
|
||||
|
@ -414,13 +446,13 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d)
|
|||
return n;
|
||||
}
|
||||
|
||||
void radeon_compute_pll(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
uint32_t *dot_clock_p,
|
||||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p)
|
||||
static void radeon_compute_pll_legacy(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
uint32_t *dot_clock_p,
|
||||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p)
|
||||
{
|
||||
uint32_t min_ref_div = pll->min_ref_div;
|
||||
uint32_t max_ref_div = pll->max_ref_div;
|
||||
|
@ -580,95 +612,194 @@ void radeon_compute_pll(struct radeon_pll *pll,
|
|||
*post_div_p = best_post_div;
|
||||
}
|
||||
|
||||
void radeon_compute_pll_avivo(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
uint32_t *dot_clock_p,
|
||||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p)
|
||||
static bool
|
||||
calc_fb_div(struct radeon_pll *pll,
|
||||
uint32_t freq,
|
||||
uint32_t post_div,
|
||||
uint32_t ref_div,
|
||||
uint32_t *fb_div,
|
||||
uint32_t *fb_div_frac)
|
||||
{
|
||||
fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq;
|
||||
fixed20_12 pll_out_max, pll_out_min;
|
||||
fixed20_12 pll_in_max, pll_in_min;
|
||||
fixed20_12 reference_freq;
|
||||
fixed20_12 error, ffreq, a, b;
|
||||
fixed20_12 feedback_divider, a, b;
|
||||
u32 vco_freq;
|
||||
|
||||
vco_freq = freq * post_div;
|
||||
/* feedback_divider = vco_freq * ref_div / pll->reference_freq; */
|
||||
a.full = rfixed_const(pll->reference_freq);
|
||||
feedback_divider.full = rfixed_const(vco_freq);
|
||||
feedback_divider.full = rfixed_div(feedback_divider, a);
|
||||
a.full = rfixed_const(ref_div);
|
||||
feedback_divider.full = rfixed_mul(feedback_divider, a);
|
||||
|
||||
if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
|
||||
/* feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1; */
|
||||
a.full = rfixed_const(10);
|
||||
feedback_divider.full = rfixed_mul(feedback_divider, a);
|
||||
feedback_divider.full += rfixed_const_half(0);
|
||||
feedback_divider.full = rfixed_floor(feedback_divider);
|
||||
feedback_divider.full = rfixed_div(feedback_divider, a);
|
||||
|
||||
/* *fb_div = floor(feedback_divider); */
|
||||
a.full = rfixed_floor(feedback_divider);
|
||||
*fb_div = rfixed_trunc(a);
|
||||
/* *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0; */
|
||||
a.full = rfixed_const(10);
|
||||
b.full = rfixed_mul(feedback_divider, a);
|
||||
|
||||
feedback_divider.full = rfixed_floor(feedback_divider);
|
||||
feedback_divider.full = rfixed_mul(feedback_divider, a);
|
||||
feedback_divider.full = b.full - feedback_divider.full;
|
||||
*fb_div_frac = rfixed_trunc(feedback_divider);
|
||||
} else {
|
||||
/* *fb_div = floor(feedback_divider + 0.5); */
|
||||
feedback_divider.full += rfixed_const_half(0);
|
||||
feedback_divider.full = rfixed_floor(feedback_divider);
|
||||
|
||||
*fb_div = rfixed_trunc(feedback_divider);
|
||||
*fb_div_frac = 0;
|
||||
}
|
||||
|
||||
if (((*fb_div) < pll->min_feedback_div) || ((*fb_div) > pll->max_feedback_div))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
calc_fb_ref_div(struct radeon_pll *pll,
|
||||
uint32_t freq,
|
||||
uint32_t post_div,
|
||||
uint32_t *fb_div,
|
||||
uint32_t *fb_div_frac,
|
||||
uint32_t *ref_div)
|
||||
{
|
||||
fixed20_12 ffreq, max_error, error, pll_out, a;
|
||||
u32 vco;
|
||||
|
||||
pll_out_max.full = rfixed_const(pll->pll_out_max);
|
||||
pll_out_min.full = rfixed_const(pll->pll_out_min);
|
||||
pll_in_max.full = rfixed_const(pll->pll_in_max);
|
||||
pll_in_min.full = rfixed_const(pll->pll_in_min);
|
||||
reference_freq.full = rfixed_const(pll->reference_freq);
|
||||
do_div(freq, 10);
|
||||
ffreq.full = rfixed_const(freq);
|
||||
error.full = rfixed_const(100 * 100);
|
||||
/* max_error = ffreq * 0.0025; */
|
||||
a.full = rfixed_const(400);
|
||||
max_error.full = rfixed_div(ffreq, a);
|
||||
|
||||
/* max p */
|
||||
p.full = rfixed_div(pll_out_max, ffreq);
|
||||
p.full = rfixed_floor(p);
|
||||
for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
|
||||
if (calc_fb_div(pll, freq, post_div, (*ref_div), fb_div, fb_div_frac)) {
|
||||
vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac));
|
||||
vco = vco / ((*ref_div) * 10);
|
||||
|
||||
/* min m */
|
||||
m.full = rfixed_div(reference_freq, pll_in_max);
|
||||
m.full = rfixed_ceil(m);
|
||||
if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
|
||||
continue;
|
||||
|
||||
while (1) {
|
||||
n.full = rfixed_div(ffreq, reference_freq);
|
||||
n.full = rfixed_mul(n, m);
|
||||
n.full = rfixed_mul(n, p);
|
||||
/* pll_out = vco / post_div; */
|
||||
a.full = rfixed_const(post_div);
|
||||
pll_out.full = rfixed_const(vco);
|
||||
pll_out.full = rfixed_div(pll_out, a);
|
||||
|
||||
f_vco.full = rfixed_div(n, m);
|
||||
f_vco.full = rfixed_mul(f_vco, reference_freq);
|
||||
if (pll_out.full >= ffreq.full) {
|
||||
error.full = pll_out.full - ffreq.full;
|
||||
if (error.full <= max_error.full)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
f_pclk.full = rfixed_div(f_vco, p);
|
||||
static void radeon_compute_pll_new(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
uint32_t *dot_clock_p,
|
||||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p)
|
||||
{
|
||||
u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
|
||||
u32 best_freq = 0, vco_frequency;
|
||||
|
||||
if (f_pclk.full > ffreq.full)
|
||||
error.full = f_pclk.full - ffreq.full;
|
||||
else
|
||||
error.full = ffreq.full - f_pclk.full;
|
||||
error.full = rfixed_div(error, f_pclk);
|
||||
a.full = rfixed_const(100 * 100);
|
||||
error.full = rfixed_mul(error, a);
|
||||
/* freq = freq / 10; */
|
||||
do_div(freq, 10);
|
||||
|
||||
a.full = rfixed_mul(m, p);
|
||||
a.full = rfixed_div(n, a);
|
||||
best_freq.full = rfixed_mul(reference_freq, a);
|
||||
if (pll->flags & RADEON_PLL_USE_POST_DIV) {
|
||||
post_div = pll->post_div;
|
||||
if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
|
||||
goto done;
|
||||
|
||||
if (rfixed_trunc(error) < 25)
|
||||
break;
|
||||
vco_frequency = freq * post_div;
|
||||
if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
|
||||
goto done;
|
||||
|
||||
a.full = rfixed_const(1);
|
||||
m.full = m.full + a.full;
|
||||
a.full = rfixed_div(reference_freq, m);
|
||||
if (a.full >= pll_in_min.full)
|
||||
continue;
|
||||
if (pll->flags & RADEON_PLL_USE_REF_DIV) {
|
||||
ref_div = pll->reference_div;
|
||||
if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
|
||||
goto done;
|
||||
if (!calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
|
||||
if (pll->flags & RADEON_PLL_LEGACY) {
|
||||
if ((post_div == 5) ||
|
||||
(post_div == 7) ||
|
||||
(post_div == 9) ||
|
||||
(post_div == 10) ||
|
||||
(post_div == 11))
|
||||
continue;
|
||||
}
|
||||
|
||||
m.full = rfixed_div(reference_freq, pll_in_max);
|
||||
m.full = rfixed_ceil(m);
|
||||
a.full= rfixed_const(1);
|
||||
p.full = p.full - a.full;
|
||||
a.full = rfixed_mul(p, ffreq);
|
||||
if (a.full >= pll_out_min.full)
|
||||
continue;
|
||||
else {
|
||||
DRM_ERROR("Unable to find pll dividers\n");
|
||||
break;
|
||||
if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
|
||||
continue;
|
||||
|
||||
vco_frequency = freq * post_div;
|
||||
if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
|
||||
continue;
|
||||
if (pll->flags & RADEON_PLL_USE_REF_DIV) {
|
||||
ref_div = pll->reference_div;
|
||||
if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
|
||||
goto done;
|
||||
if (calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
|
||||
break;
|
||||
} else {
|
||||
if (calc_fb_ref_div(pll, freq, post_div, &fb_div, &fb_div_frac, &ref_div))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.full = rfixed_const(10);
|
||||
b.full = rfixed_mul(n, a);
|
||||
best_freq = pll->reference_freq * 10 * fb_div;
|
||||
best_freq += pll->reference_freq * fb_div_frac;
|
||||
best_freq = best_freq / (ref_div * post_div);
|
||||
|
||||
frac_n.full = rfixed_floor(n);
|
||||
frac_n.full = rfixed_mul(frac_n, a);
|
||||
frac_n.full = b.full - frac_n.full;
|
||||
done:
|
||||
if (best_freq == 0)
|
||||
DRM_ERROR("Couldn't find valid PLL dividers\n");
|
||||
|
||||
*dot_clock_p = rfixed_trunc(best_freq);
|
||||
*fb_div_p = rfixed_trunc(n);
|
||||
*frac_fb_div_p = rfixed_trunc(frac_n);
|
||||
*ref_div_p = rfixed_trunc(m);
|
||||
*post_div_p = rfixed_trunc(p);
|
||||
*dot_clock_p = best_freq / 10;
|
||||
*fb_div_p = fb_div;
|
||||
*frac_fb_div_p = fb_div_frac;
|
||||
*ref_div_p = ref_div;
|
||||
*post_div_p = post_div;
|
||||
|
||||
DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
|
||||
DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
|
||||
}
|
||||
|
||||
void radeon_compute_pll(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
uint32_t *dot_clock_p,
|
||||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p)
|
||||
{
|
||||
switch (pll->algo) {
|
||||
case PLL_ALGO_NEW:
|
||||
radeon_compute_pll_new(pll, freq, dot_clock_p, fb_div_p,
|
||||
frac_fb_div_p, ref_div_p, post_div_p);
|
||||
break;
|
||||
case PLL_ALGO_LEGACY:
|
||||
default:
|
||||
radeon_compute_pll_legacy(pll, freq, dot_clock_p, fb_div_p,
|
||||
frac_fb_div_p, ref_div_p, post_div_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
||||
|
@ -816,7 +947,7 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
|
|||
|
||||
int radeon_modeset_init(struct radeon_device *rdev)
|
||||
{
|
||||
int num_crtc = 2, i;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
drm_mode_config_init(rdev->ddev);
|
||||
|
@ -839,11 +970,23 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* check combios for a valid hardcoded EDID - Sun servers */
|
||||
if (!rdev->is_atom_bios) {
|
||||
/* check for hardcoded EDID in BIOS */
|
||||
radeon_combios_check_hardcoded_edid(rdev);
|
||||
}
|
||||
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
num_crtc = 1;
|
||||
rdev->num_crtc = 1;
|
||||
else {
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
rdev->num_crtc = 6;
|
||||
else
|
||||
rdev->num_crtc = 2;
|
||||
}
|
||||
|
||||
/* allocate crtcs */
|
||||
for (i = 0; i < num_crtc; i++) {
|
||||
for (i = 0; i < rdev->num_crtc; i++) {
|
||||
radeon_crtc_init(rdev->ddev, i);
|
||||
}
|
||||
|
||||
|
@ -860,6 +1003,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|||
|
||||
void radeon_modeset_fini(struct radeon_device *rdev)
|
||||
{
|
||||
kfree(rdev->mode_info.bios_hardcoded_edid);
|
||||
|
||||
if (rdev->mode_info.mode_config_initialized) {
|
||||
radeon_hpd_fini(rdev);
|
||||
drm_mode_config_cleanup(rdev->ddev);
|
||||
|
|
|
@ -86,7 +86,8 @@ int radeon_benchmarking = 0;
|
|||
int radeon_testing = 0;
|
||||
int radeon_connector_table = 0;
|
||||
int radeon_tv = 1;
|
||||
int radeon_new_pll = 1;
|
||||
int radeon_new_pll = -1;
|
||||
int radeon_dynpm = -1;
|
||||
int radeon_audio = 1;
|
||||
|
||||
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
|
||||
|
@ -122,9 +123,12 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);
|
|||
MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
|
||||
module_param_named(tv, radeon_tv, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(new_pll, "Select new PLL code for AVIVO chips");
|
||||
MODULE_PARM_DESC(new_pll, "Select new PLL code");
|
||||
module_param_named(new_pll, radeon_new_pll, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(dynpm, "Disable/Enable dynamic power management (1 = enable)");
|
||||
module_param_named(dynpm, radeon_dynpm, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
|
||||
module_param_named(audio, radeon_audio, int, 0444);
|
||||
|
||||
|
|
|
@ -295,6 +295,9 @@ typedef struct drm_radeon_private {
|
|||
int r700_sc_prim_fifo_size;
|
||||
int r700_sc_hiz_tile_fifo_size;
|
||||
int r700_sc_earlyz_tile_fifo_fize;
|
||||
int r600_group_size;
|
||||
int r600_npipes;
|
||||
int r600_nbanks;
|
||||
|
||||
struct mutex cs_mutex;
|
||||
u32 cs_id_scnt;
|
||||
|
@ -310,9 +313,11 @@ typedef struct drm_radeon_buf_priv {
|
|||
u32 age;
|
||||
} drm_radeon_buf_priv_t;
|
||||
|
||||
struct drm_buffer;
|
||||
|
||||
typedef struct drm_radeon_kcmd_buffer {
|
||||
int bufsz;
|
||||
char *buf;
|
||||
struct drm_buffer *buffer;
|
||||
int nbox;
|
||||
struct drm_clip_rect __user *boxes;
|
||||
} drm_radeon_kcmd_buffer_t;
|
||||
|
@ -2122,4 +2127,32 @@ extern void radeon_commit_ring(drm_radeon_private_t *dev_priv);
|
|||
write &= mask; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Copy given number of dwords from drm buffer to the ring buffer.
|
||||
*/
|
||||
#define OUT_RING_DRM_BUFFER(buf, sz) do { \
|
||||
int _size = (sz) * 4; \
|
||||
struct drm_buffer *_buf = (buf); \
|
||||
int _part_size; \
|
||||
while (_size > 0) { \
|
||||
_part_size = _size; \
|
||||
\
|
||||
if (write + _part_size/4 > mask) \
|
||||
_part_size = ((mask + 1) - write)*4; \
|
||||
\
|
||||
if (drm_buffer_index(_buf) + _part_size > PAGE_SIZE) \
|
||||
_part_size = PAGE_SIZE - drm_buffer_index(_buf);\
|
||||
\
|
||||
\
|
||||
\
|
||||
memcpy(ring + write, &_buf->data[drm_buffer_page(_buf)] \
|
||||
[drm_buffer_index(_buf)], _part_size); \
|
||||
\
|
||||
_size -= _part_size; \
|
||||
write = (write + _part_size/4) & mask; \
|
||||
drm_buffer_advance(_buf, _part_size); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif /* __RADEON_DRV_H__ */
|
||||
|
|
|
@ -53,7 +53,7 @@ static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
|
|||
/* DVO requires 2x ppll clocks depending on tmds chip */
|
||||
if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
|
||||
return index_mask;
|
||||
|
||||
|
||||
count = -1;
|
||||
list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
|
||||
|
@ -228,6 +228,32 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct radeon_connector_atom_dig *
|
||||
radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
if (!rdev->is_atom_bios)
|
||||
return NULL;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
return NULL;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (!radeon_connector->con_priv)
|
||||
return NULL;
|
||||
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
return dig_connector;
|
||||
}
|
||||
|
||||
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
|
@ -236,6 +262,9 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
|
|||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
/* adjust pm to upcoming mode change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
|
||||
/* set the active encoder to connector routing */
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
||||
|
@ -458,34 +487,20 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
|
|||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
struct radeon_connector_atom_dig *dig_connector =
|
||||
radeon_get_atom_connector_priv_from_encoder(encoder);
|
||||
union lvds_encoder_control args;
|
||||
int index = 0;
|
||||
int hdmi_detected = 0;
|
||||
uint8_t frev, crev;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
if (!dig || !dig_connector)
|
||||
return;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return;
|
||||
|
||||
dig = radeon_encoder->enc_priv;
|
||||
|
||||
if (!radeon_connector->con_priv)
|
||||
return;
|
||||
|
||||
if (drm_detect_hdmi_monitor(radeon_connector->edid))
|
||||
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
|
||||
hdmi_detected = 1;
|
||||
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
|
@ -586,7 +601,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
|||
{
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
|
@ -617,9 +632,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
|||
break;
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
radeon_dig_connector = radeon_connector->con_priv;
|
||||
if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
|
||||
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
|
||||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
|
||||
return ATOM_ENCODER_MODE_DP;
|
||||
else if (drm_detect_hdmi_monitor(radeon_connector->edid))
|
||||
return ATOM_ENCODER_MODE_HDMI;
|
||||
|
@ -656,6 +671,18 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
|||
* - 2 DIG encoder blocks.
|
||||
* DIG1/2 can drive UNIPHY0/1/2 link A or link B
|
||||
*
|
||||
* DCE 4.0
|
||||
* - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B).
|
||||
* Supports up to 6 digital outputs
|
||||
* - 6 DIG encoder blocks.
|
||||
* - DIG to PHY mapping is hardcoded
|
||||
* DIG1 drives UNIPHY0 link A, A+B
|
||||
* DIG2 drives UNIPHY0 link B
|
||||
* DIG3 drives UNIPHY1 link A, A+B
|
||||
* DIG4 drives UNIPHY1 link B
|
||||
* DIG5 drives UNIPHY2 link A, A+B
|
||||
* DIG6 drives UNIPHY2 link B
|
||||
*
|
||||
* Routing
|
||||
* crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
|
||||
* Examples:
|
||||
|
@ -664,88 +691,78 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
|||
* crtc0 -> dig1 -> UNIPHY2 link A -> LVDS
|
||||
* crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI
|
||||
*/
|
||||
static void
|
||||
|
||||
union dig_encoder_control {
|
||||
DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
|
||||
DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
|
||||
DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
|
||||
};
|
||||
|
||||
void
|
||||
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
DIG_ENCODER_CONTROL_PS_ALLOCATION args;
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
struct radeon_connector_atom_dig *dig_connector =
|
||||
radeon_get_atom_connector_priv_from_encoder(encoder);
|
||||
union dig_encoder_control args;
|
||||
int index = 0, num = 0;
|
||||
uint8_t frev, crev;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
if (!dig || !dig_connector)
|
||||
return;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (!radeon_connector->con_priv)
|
||||
return;
|
||||
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return;
|
||||
|
||||
dig = radeon_encoder->enc_priv;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
if (dig->dig_encoder)
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
|
||||
else
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
|
||||
if (ASIC_IS_DCE4(rdev))
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
|
||||
else {
|
||||
if (dig->dig_encoder)
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
|
||||
else
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
|
||||
}
|
||||
num = dig->dig_encoder + 1;
|
||||
|
||||
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
|
||||
|
||||
args.ucAction = action;
|
||||
args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
|
||||
args.v1.ucAction = action;
|
||||
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
|
||||
args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
|
||||
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
|
||||
break;
|
||||
}
|
||||
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
|
||||
if (dig_connector->dp_clock == 270000)
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
args.v1.ucLaneNum = dig_connector->dp_lane_count;
|
||||
} else if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v1.ucLaneNum = 8;
|
||||
else
|
||||
args.v1.ucLaneNum = 4;
|
||||
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
args.v3.acConfig.ucDigSel = dig->dig_encoder;
|
||||
args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
|
||||
} else {
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2;
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
|
||||
break;
|
||||
}
|
||||
if (dig_connector->linkb)
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
}
|
||||
|
||||
args.ucEncoderMode = atombios_get_encoder_mode(encoder);
|
||||
|
||||
if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
|
||||
if (dig_connector->dp_clock == 270000)
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
args.ucLaneNum = dig_connector->dp_lane_count;
|
||||
} else if (radeon_encoder->pixel_clock > 165000)
|
||||
args.ucLaneNum = 8;
|
||||
else
|
||||
args.ucLaneNum = 4;
|
||||
|
||||
if (dig_connector->linkb)
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
}
|
||||
|
@ -753,6 +770,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
|
|||
union dig_transmitter_control {
|
||||
DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
|
||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
|
||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -761,37 +779,29 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
|
|||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
struct radeon_connector_atom_dig *dig_connector =
|
||||
radeon_get_atom_connector_priv_from_encoder(encoder);
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
union dig_transmitter_control args;
|
||||
int index = 0, num = 0;
|
||||
uint8_t frev, crev;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
bool is_dp = false;
|
||||
int pll_id = 0;
|
||||
|
||||
if (!dig || !dig_connector)
|
||||
return;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
return;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return;
|
||||
|
||||
dig = radeon_encoder->enc_priv;
|
||||
|
||||
if (!radeon_connector->con_priv)
|
||||
return;
|
||||
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
|
||||
is_dp = true;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
if (ASIC_IS_DCE32(rdev))
|
||||
if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev))
|
||||
index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
|
||||
else {
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
|
@ -821,7 +831,54 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
|
|||
else
|
||||
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
|
||||
}
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
if (is_dp)
|
||||
args.v3.ucLaneNum = dig_connector->dp_lane_count;
|
||||
else if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v3.ucLaneNum = 8;
|
||||
else
|
||||
args.v3.ucLaneNum = 4;
|
||||
|
||||
if (dig_connector->linkb) {
|
||||
args.v3.acConfig.ucLinkSel = 1;
|
||||
args.v3.acConfig.ucEncoderSel = 1;
|
||||
}
|
||||
|
||||
/* Select the PLL for the PHY
|
||||
* DP PHY should be clocked from external src if there is
|
||||
* one.
|
||||
*/
|
||||
if (encoder->crtc) {
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
|
||||
pll_id = radeon_crtc->pll_id;
|
||||
}
|
||||
if (is_dp && rdev->clock.dp_extclk)
|
||||
args.v3.acConfig.ucRefClkSource = 2; /* external src */
|
||||
else
|
||||
args.v3.acConfig.ucRefClkSource = pll_id;
|
||||
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.v3.acConfig.ucTransmitterSel = 0;
|
||||
num = 0;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
args.v3.acConfig.ucTransmitterSel = 1;
|
||||
num = 1;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
args.v3.acConfig.ucTransmitterSel = 2;
|
||||
num = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_dp)
|
||||
args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||
if (dig->coherent_mode)
|
||||
args.v3.acConfig.fCoherentMode = 1;
|
||||
}
|
||||
} else if (ASIC_IS_DCE32(rdev)) {
|
||||
if (dig->dig_encoder == 1)
|
||||
args.v2.acConfig.ucEncoderSel = 1;
|
||||
if (dig_connector->linkb)
|
||||
|
@ -849,7 +906,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
|
|||
args.v2.acConfig.fCoherentMode = 1;
|
||||
}
|
||||
} else {
|
||||
|
||||
args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
|
||||
|
||||
if (dig->dig_encoder)
|
||||
|
@ -1024,9 +1080,12 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
|
||||
/* adjust pm to dpms change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
}
|
||||
|
||||
union crtc_sourc_param {
|
||||
union crtc_source_param {
|
||||
SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
|
||||
SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
|
||||
};
|
||||
|
@ -1038,7 +1097,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
|
|||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
|
||||
union crtc_sourc_param args;
|
||||
union crtc_source_param args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
|
||||
uint8_t frev, crev;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
|
@ -1107,10 +1166,26 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
|
|||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
dig = radeon_encoder->enc_priv;
|
||||
if (dig->dig_encoder)
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
else
|
||||
switch (dig->dig_encoder) {
|
||||
case 0:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
|
||||
break;
|
||||
case 1:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
break;
|
||||
case 2:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
|
||||
break;
|
||||
case 3:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
|
||||
break;
|
||||
case 4:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
|
||||
break;
|
||||
case 5:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
|
||||
args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
|
||||
|
@ -1167,6 +1242,7 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,
|
|||
}
|
||||
|
||||
/* set scaler clears this on some chips */
|
||||
/* XXX check DCE4 */
|
||||
if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
|
||||
if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
|
||||
WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
|
||||
|
@ -1183,6 +1259,33 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
|
|||
struct drm_encoder *test_encoder;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
uint32_t dig_enc_in_use = 0;
|
||||
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
struct radeon_connector_atom_dig *dig_connector =
|
||||
radeon_get_atom_connector_priv_from_encoder(encoder);
|
||||
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
if (dig_connector->linkb)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
if (dig_connector->linkb)
|
||||
return 3;
|
||||
else
|
||||
return 2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
if (dig_connector->linkb)
|
||||
return 5;
|
||||
else
|
||||
return 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* on DCE32 and encoder can driver any block so just crtc id */
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
return radeon_crtc->crtc_id;
|
||||
|
@ -1254,15 +1357,26 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
/* disable the encoder and transmitter */
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
||||
atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
/* disable the transmitter */
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
||||
/* setup and enable the encoder */
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP);
|
||||
|
||||
/* setup and enable the encoder and transmitter */
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
||||
/* init and enable the transmitter */
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
||||
} else {
|
||||
/* disable the encoder and transmitter */
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
||||
atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
|
||||
|
||||
/* setup and enable the encoder and transmitter */
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
||||
}
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DDI:
|
||||
atombios_ddia_setup(encoder, ATOM_ENABLE);
|
||||
|
@ -1282,7 +1396,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|||
}
|
||||
atombios_apply_encoder_quirks(encoder, adjusted_mode);
|
||||
|
||||
r600_hdmi_setmode(encoder, adjusted_mode);
|
||||
/* XXX */
|
||||
if (!ASIC_IS_DCE4(rdev))
|
||||
r600_hdmi_setmode(encoder, adjusted_mode);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1480,10 +1596,18 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
|
|||
return;
|
||||
|
||||
encoder = &radeon_encoder->base;
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
switch (rdev->num_crtc) {
|
||||
case 1:
|
||||
encoder->possible_crtcs = 0x1;
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
encoder->possible_crtcs = 0x3;
|
||||
break;
|
||||
case 6:
|
||||
encoder->possible_crtcs = 0x3f;
|
||||
break;
|
||||
}
|
||||
|
||||
radeon_encoder->enc_priv = NULL;
|
||||
|
||||
|
|
|
@ -75,6 +75,11 @@ enum radeon_family {
|
|||
CHIP_RV730,
|
||||
CHIP_RV710,
|
||||
CHIP_RV740,
|
||||
CHIP_CEDAR,
|
||||
CHIP_REDWOOD,
|
||||
CHIP_JUNIPER,
|
||||
CHIP_CYPRESS,
|
||||
CHIP_HEMLOCK,
|
||||
CHIP_LAST,
|
||||
};
|
||||
|
||||
|
|
|
@ -148,7 +148,6 @@ int radeonfb_create(struct drm_device *dev,
|
|||
unsigned long tmp;
|
||||
bool fb_tiled = false; /* useful for testing */
|
||||
u32 tiling_flags = 0;
|
||||
int crtc_count;
|
||||
|
||||
mode_cmd.width = surface_width;
|
||||
mode_cmd.height = surface_height;
|
||||
|
@ -239,11 +238,7 @@ int radeonfb_create(struct drm_device *dev,
|
|||
rfbdev = info->par;
|
||||
rfbdev->helper.funcs = &radeon_fb_helper_funcs;
|
||||
rfbdev->helper.dev = dev;
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
crtc_count = 1;
|
||||
else
|
||||
crtc_count = 2;
|
||||
ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, crtc_count,
|
||||
ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, rdev->num_crtc,
|
||||
RADEONFB_CONN_LIMIT);
|
||||
if (ret)
|
||||
goto out_unref;
|
||||
|
@ -257,7 +252,7 @@ int radeonfb_create(struct drm_device *dev,
|
|||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &radeonfb_ops;
|
||||
|
||||
tmp = fb_gpuaddr - rdev->mc.vram_location;
|
||||
tmp = fb_gpuaddr - rdev->mc.vram_start;
|
||||
info->fix.smem_start = rdev->mc.aper_base + tmp;
|
||||
info->fix.smem_len = size;
|
||||
info->screen_base = fbptr;
|
||||
|
|
|
@ -139,6 +139,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
|
|||
unsigned t;
|
||||
unsigned p;
|
||||
int i, j;
|
||||
u64 page_base;
|
||||
|
||||
if (!rdev->gart.ready) {
|
||||
WARN(1, "trying to unbind memory to unitialized GART !\n");
|
||||
|
@ -151,9 +152,11 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
|
|||
pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
rdev->gart.pages[p] = NULL;
|
||||
rdev->gart.pages_addr[p] = 0;
|
||||
rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
|
||||
page_base = rdev->gart.pages_addr[p];
|
||||
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
|
||||
radeon_gart_set_page(rdev, t, 0);
|
||||
radeon_gart_set_page(rdev, t, page_base);
|
||||
page_base += RADEON_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,8 +202,26 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void radeon_gart_restore(struct radeon_device *rdev)
|
||||
{
|
||||
int i, j, t;
|
||||
u64 page_base;
|
||||
|
||||
for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
|
||||
page_base = rdev->gart.pages_addr[i];
|
||||
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
|
||||
radeon_gart_set_page(rdev, t, page_base);
|
||||
page_base += RADEON_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
mb();
|
||||
radeon_gart_tlb_flush(rdev);
|
||||
}
|
||||
|
||||
int radeon_gart_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r, i;
|
||||
|
||||
if (rdev->gart.pages) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -209,6 +230,9 @@ int radeon_gart_init(struct radeon_device *rdev)
|
|||
DRM_ERROR("Page size is smaller than GPU page size!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = radeon_dummy_page_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* Compute table size */
|
||||
rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
|
||||
rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE;
|
||||
|
@ -227,6 +251,10 @@ int radeon_gart_init(struct radeon_device *rdev)
|
|||
radeon_gart_fini(rdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* set GART entry to point to the dummy page by default */
|
||||
for (i = 0; i < rdev->gart.num_cpu_pages; i++) {
|
||||
rdev->gart.pages_addr[i] = rdev->dummy_page.addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "drmP.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
|
||||
/**
|
||||
* radeon_ddc_probe
|
||||
|
@ -59,7 +60,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
|
|||
}
|
||||
|
||||
|
||||
void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
|
||||
static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
|
||||
{
|
||||
struct radeon_device *rdev = i2c->dev->dev_private;
|
||||
struct radeon_i2c_bus_rec *rec = &i2c->rec;
|
||||
|
@ -71,13 +72,25 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
|
|||
*/
|
||||
if (rec->hw_capable) {
|
||||
if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
|
||||
if (rec->a_clk_reg == RADEON_GPIO_MONID) {
|
||||
u32 reg;
|
||||
|
||||
if (rdev->family >= CHIP_RV350)
|
||||
reg = RADEON_GPIO_MONID;
|
||||
else if ((rdev->family == CHIP_R300) ||
|
||||
(rdev->family == CHIP_R350))
|
||||
reg = RADEON_GPIO_DVI_DDC;
|
||||
else
|
||||
reg = RADEON_GPIO_CRT2_DDC;
|
||||
|
||||
mutex_lock(&rdev->dc_hw_i2c_mutex);
|
||||
if (rec->a_clk_reg == reg) {
|
||||
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
|
||||
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
|
||||
} else {
|
||||
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
|
||||
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
|
||||
}
|
||||
mutex_unlock(&rdev->dc_hw_i2c_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,6 +181,692 @@ static void set_data(void *i2c_priv, int data)
|
|||
WREG32(rec->en_data_reg, val);
|
||||
}
|
||||
|
||||
static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_pll *spll = &rdev->clock.spll;
|
||||
u32 sclk = radeon_get_engine_clock(rdev);
|
||||
u32 prescale = 0;
|
||||
u32 n, m;
|
||||
u8 loop;
|
||||
int i2c_clock;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_R100:
|
||||
case CHIP_RV100:
|
||||
case CHIP_RS100:
|
||||
case CHIP_RV200:
|
||||
case CHIP_RS200:
|
||||
case CHIP_R200:
|
||||
case CHIP_RV250:
|
||||
case CHIP_RS300:
|
||||
case CHIP_RV280:
|
||||
case CHIP_R300:
|
||||
case CHIP_R350:
|
||||
case CHIP_RV350:
|
||||
n = (spll->reference_freq) / (4 * 6);
|
||||
for (loop = 1; loop < 255; loop++) {
|
||||
if ((loop * (loop - 1)) > n)
|
||||
break;
|
||||
}
|
||||
m = loop - 1;
|
||||
prescale = m | (loop << 8);
|
||||
break;
|
||||
case CHIP_RV380:
|
||||
case CHIP_RS400:
|
||||
case CHIP_RS480:
|
||||
case CHIP_R420:
|
||||
case CHIP_R423:
|
||||
case CHIP_RV410:
|
||||
sclk = radeon_get_engine_clock(rdev);
|
||||
prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
|
||||
break;
|
||||
case CHIP_RS600:
|
||||
case CHIP_RS690:
|
||||
case CHIP_RS740:
|
||||
/* todo */
|
||||
break;
|
||||
case CHIP_RV515:
|
||||
case CHIP_R520:
|
||||
case CHIP_RV530:
|
||||
case CHIP_RV560:
|
||||
case CHIP_RV570:
|
||||
case CHIP_R580:
|
||||
i2c_clock = 50;
|
||||
sclk = radeon_get_engine_clock(rdev);
|
||||
if (rdev->family == CHIP_R520)
|
||||
prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock));
|
||||
else
|
||||
prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
|
||||
break;
|
||||
case CHIP_R600:
|
||||
case CHIP_RV610:
|
||||
case CHIP_RV630:
|
||||
case CHIP_RV670:
|
||||
/* todo */
|
||||
break;
|
||||
case CHIP_RV620:
|
||||
case CHIP_RV635:
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880:
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
/* todo */
|
||||
break;
|
||||
case CHIP_CEDAR:
|
||||
case CHIP_REDWOOD:
|
||||
case CHIP_JUNIPER:
|
||||
case CHIP_CYPRESS:
|
||||
case CHIP_HEMLOCK:
|
||||
/* todo */
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("i2c: unhandled radeon chip\n");
|
||||
break;
|
||||
}
|
||||
return prescale;
|
||||
}
|
||||
|
||||
|
||||
/* hw i2c engine for r1xx-4xx hardware
|
||||
* hw can buffer up to 15 bytes
|
||||
*/
|
||||
static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
|
||||
struct radeon_device *rdev = i2c->dev->dev_private;
|
||||
struct radeon_i2c_bus_rec *rec = &i2c->rec;
|
||||
struct i2c_msg *p;
|
||||
int i, j, k, ret = num;
|
||||
u32 prescale;
|
||||
u32 i2c_cntl_0, i2c_cntl_1, i2c_data;
|
||||
u32 tmp, reg;
|
||||
|
||||
mutex_lock(&rdev->dc_hw_i2c_mutex);
|
||||
/* take the pm lock since we need a constant sclk */
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
|
||||
prescale = radeon_get_i2c_prescale(rdev);
|
||||
|
||||
reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) |
|
||||
RADEON_I2C_START |
|
||||
RADEON_I2C_STOP |
|
||||
RADEON_I2C_GO);
|
||||
|
||||
if (rdev->is_atom_bios) {
|
||||
tmp = RREG32(RADEON_BIOS_6_SCRATCH);
|
||||
WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE);
|
||||
}
|
||||
|
||||
if (rec->mm_i2c) {
|
||||
i2c_cntl_0 = RADEON_I2C_CNTL_0;
|
||||
i2c_cntl_1 = RADEON_I2C_CNTL_1;
|
||||
i2c_data = RADEON_I2C_DATA;
|
||||
} else {
|
||||
i2c_cntl_0 = RADEON_DVI_I2C_CNTL_0;
|
||||
i2c_cntl_1 = RADEON_DVI_I2C_CNTL_1;
|
||||
i2c_data = RADEON_DVI_I2C_DATA;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_R100:
|
||||
case CHIP_RV100:
|
||||
case CHIP_RS100:
|
||||
case CHIP_RV200:
|
||||
case CHIP_RS200:
|
||||
case CHIP_RS300:
|
||||
switch (rec->mask_clk_reg) {
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
/* no gpio select bit */
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("gpio not supported with hw i2c\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case CHIP_R200:
|
||||
/* only bit 4 on r200 */
|
||||
switch (rec->mask_clk_reg) {
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
|
||||
break;
|
||||
case RADEON_GPIO_MONID:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("gpio not supported with hw i2c\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case CHIP_RV250:
|
||||
case CHIP_RV280:
|
||||
/* bits 3 and 4 */
|
||||
switch (rec->mask_clk_reg) {
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
|
||||
break;
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2);
|
||||
break;
|
||||
case RADEON_GPIO_CRT2_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("gpio not supported with hw i2c\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case CHIP_R300:
|
||||
case CHIP_R350:
|
||||
/* only bit 4 on r300/r350 */
|
||||
switch (rec->mask_clk_reg) {
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
|
||||
break;
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("gpio not supported with hw i2c\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case CHIP_RV350:
|
||||
case CHIP_RV380:
|
||||
case CHIP_R420:
|
||||
case CHIP_R423:
|
||||
case CHIP_RV410:
|
||||
case CHIP_RS400:
|
||||
case CHIP_RS480:
|
||||
/* bits 3 and 4 */
|
||||
switch (rec->mask_clk_reg) {
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
|
||||
break;
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2);
|
||||
break;
|
||||
case RADEON_GPIO_MONID:
|
||||
reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("gpio not supported with hw i2c\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unsupported asic\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for bus probe */
|
||||
p = &msgs[0];
|
||||
if ((num == 1) && (p->len == 0)) {
|
||||
WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
|
||||
RADEON_I2C_NACK |
|
||||
RADEON_I2C_HALT |
|
||||
RADEON_I2C_SOFT_RST));
|
||||
WREG32(i2c_data, (p->addr << 1) & 0xff);
|
||||
WREG32(i2c_data, 0);
|
||||
WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
|
||||
(1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
|
||||
RADEON_I2C_EN |
|
||||
(48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
|
||||
WREG32(i2c_cntl_0, reg);
|
||||
for (k = 0; k < 32; k++) {
|
||||
udelay(10);
|
||||
tmp = RREG32(i2c_cntl_0);
|
||||
if (tmp & RADEON_I2C_GO)
|
||||
continue;
|
||||
tmp = RREG32(i2c_cntl_0);
|
||||
if (tmp & RADEON_I2C_DONE)
|
||||
break;
|
||||
else {
|
||||
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
|
||||
WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
p = &msgs[i];
|
||||
for (j = 0; j < p->len; j++) {
|
||||
if (p->flags & I2C_M_RD) {
|
||||
WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
|
||||
RADEON_I2C_NACK |
|
||||
RADEON_I2C_HALT |
|
||||
RADEON_I2C_SOFT_RST));
|
||||
WREG32(i2c_data, ((p->addr << 1) & 0xff) | 0x1);
|
||||
WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
|
||||
(1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
|
||||
RADEON_I2C_EN |
|
||||
(48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
|
||||
WREG32(i2c_cntl_0, reg | RADEON_I2C_RECEIVE);
|
||||
for (k = 0; k < 32; k++) {
|
||||
udelay(10);
|
||||
tmp = RREG32(i2c_cntl_0);
|
||||
if (tmp & RADEON_I2C_GO)
|
||||
continue;
|
||||
tmp = RREG32(i2c_cntl_0);
|
||||
if (tmp & RADEON_I2C_DONE)
|
||||
break;
|
||||
else {
|
||||
DRM_DEBUG("i2c read error 0x%08x\n", tmp);
|
||||
WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
p->buf[j] = RREG32(i2c_data) & 0xff;
|
||||
} else {
|
||||
WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
|
||||
RADEON_I2C_NACK |
|
||||
RADEON_I2C_HALT |
|
||||
RADEON_I2C_SOFT_RST));
|
||||
WREG32(i2c_data, (p->addr << 1) & 0xff);
|
||||
WREG32(i2c_data, p->buf[j]);
|
||||
WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
|
||||
(1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
|
||||
RADEON_I2C_EN |
|
||||
(48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
|
||||
WREG32(i2c_cntl_0, reg);
|
||||
for (k = 0; k < 32; k++) {
|
||||
udelay(10);
|
||||
tmp = RREG32(i2c_cntl_0);
|
||||
if (tmp & RADEON_I2C_GO)
|
||||
continue;
|
||||
tmp = RREG32(i2c_cntl_0);
|
||||
if (tmp & RADEON_I2C_DONE)
|
||||
break;
|
||||
else {
|
||||
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
|
||||
WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
WREG32(i2c_cntl_0, 0);
|
||||
WREG32(i2c_cntl_1, 0);
|
||||
WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
|
||||
RADEON_I2C_NACK |
|
||||
RADEON_I2C_HALT |
|
||||
RADEON_I2C_SOFT_RST));
|
||||
|
||||
if (rdev->is_atom_bios) {
|
||||
tmp = RREG32(RADEON_BIOS_6_SCRATCH);
|
||||
tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE;
|
||||
WREG32(RADEON_BIOS_6_SCRATCH, tmp);
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->pm.mutex);
|
||||
mutex_unlock(&rdev->dc_hw_i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* hw i2c engine for r5xx hardware
|
||||
* hw can buffer up to 15 bytes
|
||||
*/
|
||||
static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
|
||||
struct radeon_device *rdev = i2c->dev->dev_private;
|
||||
struct radeon_i2c_bus_rec *rec = &i2c->rec;
|
||||
struct i2c_msg *p;
|
||||
int i, j, remaining, current_count, buffer_offset, ret = num;
|
||||
u32 prescale;
|
||||
u32 tmp, reg;
|
||||
u32 saved1, saved2;
|
||||
|
||||
mutex_lock(&rdev->dc_hw_i2c_mutex);
|
||||
/* take the pm lock since we need a constant sclk */
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
|
||||
prescale = radeon_get_i2c_prescale(rdev);
|
||||
|
||||
/* clear gpio mask bits */
|
||||
tmp = RREG32(rec->mask_clk_reg);
|
||||
tmp &= ~rec->mask_clk_mask;
|
||||
WREG32(rec->mask_clk_reg, tmp);
|
||||
tmp = RREG32(rec->mask_clk_reg);
|
||||
|
||||
tmp = RREG32(rec->mask_data_reg);
|
||||
tmp &= ~rec->mask_data_mask;
|
||||
WREG32(rec->mask_data_reg, tmp);
|
||||
tmp = RREG32(rec->mask_data_reg);
|
||||
|
||||
/* clear pin values */
|
||||
tmp = RREG32(rec->a_clk_reg);
|
||||
tmp &= ~rec->a_clk_mask;
|
||||
WREG32(rec->a_clk_reg, tmp);
|
||||
tmp = RREG32(rec->a_clk_reg);
|
||||
|
||||
tmp = RREG32(rec->a_data_reg);
|
||||
tmp &= ~rec->a_data_mask;
|
||||
WREG32(rec->a_data_reg, tmp);
|
||||
tmp = RREG32(rec->a_data_reg);
|
||||
|
||||
/* set the pins to input */
|
||||
tmp = RREG32(rec->en_clk_reg);
|
||||
tmp &= ~rec->en_clk_mask;
|
||||
WREG32(rec->en_clk_reg, tmp);
|
||||
tmp = RREG32(rec->en_clk_reg);
|
||||
|
||||
tmp = RREG32(rec->en_data_reg);
|
||||
tmp &= ~rec->en_data_mask;
|
||||
WREG32(rec->en_data_reg, tmp);
|
||||
tmp = RREG32(rec->en_data_reg);
|
||||
|
||||
/* */
|
||||
tmp = RREG32(RADEON_BIOS_6_SCRATCH);
|
||||
WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE);
|
||||
saved1 = RREG32(AVIVO_DC_I2C_CONTROL1);
|
||||
saved2 = RREG32(0x494);
|
||||
WREG32(0x494, saved2 | 0x1);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C);
|
||||
for (i = 0; i < 50; i++) {
|
||||
udelay(1);
|
||||
if (RREG32(AVIVO_DC_I2C_ARBITRATION) & AVIVO_DC_I2C_SW_CAN_USE_I2C)
|
||||
break;
|
||||
}
|
||||
if (i == 50) {
|
||||
DRM_ERROR("failed to get i2c bus\n");
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN;
|
||||
switch (rec->mask_clk_reg) {
|
||||
case AVIVO_DC_GPIO_DDC1_MASK:
|
||||
reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC1);
|
||||
break;
|
||||
case AVIVO_DC_GPIO_DDC2_MASK:
|
||||
reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC2);
|
||||
break;
|
||||
case AVIVO_DC_GPIO_DDC3_MASK:
|
||||
reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC3);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("gpio not supported with hw i2c\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* check for bus probe */
|
||||
p = &msgs[0];
|
||||
if ((num == 1) && (p->len == 0)) {
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
|
||||
AVIVO_DC_I2C_NACK |
|
||||
AVIVO_DC_I2C_HALT));
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
|
||||
udelay(1);
|
||||
WREG32(AVIVO_DC_I2C_RESET, 0);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff);
|
||||
WREG32(AVIVO_DC_I2C_DATA, 0);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
|
||||
WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
|
||||
AVIVO_DC_I2C_DATA_COUNT(1) |
|
||||
(prescale << 16)));
|
||||
WREG32(AVIVO_DC_I2C_CONTROL1, reg);
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
|
||||
for (j = 0; j < 200; j++) {
|
||||
udelay(50);
|
||||
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
|
||||
if (tmp & AVIVO_DC_I2C_GO)
|
||||
continue;
|
||||
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
|
||||
if (tmp & AVIVO_DC_I2C_DONE)
|
||||
break;
|
||||
else {
|
||||
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
p = &msgs[i];
|
||||
remaining = p->len;
|
||||
buffer_offset = 0;
|
||||
if (p->flags & I2C_M_RD) {
|
||||
while (remaining) {
|
||||
if (remaining > 15)
|
||||
current_count = 15;
|
||||
else
|
||||
current_count = remaining;
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
|
||||
AVIVO_DC_I2C_NACK |
|
||||
AVIVO_DC_I2C_HALT));
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
|
||||
udelay(1);
|
||||
WREG32(AVIVO_DC_I2C_RESET, 0);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_DATA, ((p->addr << 1) & 0xff) | 0x1);
|
||||
WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
|
||||
WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
|
||||
AVIVO_DC_I2C_DATA_COUNT(current_count) |
|
||||
(prescale << 16)));
|
||||
WREG32(AVIVO_DC_I2C_CONTROL1, reg | AVIVO_DC_I2C_RECEIVE);
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
|
||||
for (j = 0; j < 200; j++) {
|
||||
udelay(50);
|
||||
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
|
||||
if (tmp & AVIVO_DC_I2C_GO)
|
||||
continue;
|
||||
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
|
||||
if (tmp & AVIVO_DC_I2C_DONE)
|
||||
break;
|
||||
else {
|
||||
DRM_DEBUG("i2c read error 0x%08x\n", tmp);
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < current_count; j++)
|
||||
p->buf[buffer_offset + j] = RREG32(AVIVO_DC_I2C_DATA) & 0xff;
|
||||
remaining -= current_count;
|
||||
buffer_offset += current_count;
|
||||
}
|
||||
} else {
|
||||
while (remaining) {
|
||||
if (remaining > 15)
|
||||
current_count = 15;
|
||||
else
|
||||
current_count = remaining;
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
|
||||
AVIVO_DC_I2C_NACK |
|
||||
AVIVO_DC_I2C_HALT));
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
|
||||
udelay(1);
|
||||
WREG32(AVIVO_DC_I2C_RESET, 0);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff);
|
||||
for (j = 0; j < current_count; j++)
|
||||
WREG32(AVIVO_DC_I2C_DATA, p->buf[buffer_offset + j]);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
|
||||
WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
|
||||
AVIVO_DC_I2C_DATA_COUNT(current_count) |
|
||||
(prescale << 16)));
|
||||
WREG32(AVIVO_DC_I2C_CONTROL1, reg);
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
|
||||
for (j = 0; j < 200; j++) {
|
||||
udelay(50);
|
||||
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
|
||||
if (tmp & AVIVO_DC_I2C_GO)
|
||||
continue;
|
||||
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
|
||||
if (tmp & AVIVO_DC_I2C_DONE)
|
||||
break;
|
||||
else {
|
||||
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
remaining -= current_count;
|
||||
buffer_offset += current_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
|
||||
AVIVO_DC_I2C_NACK |
|
||||
AVIVO_DC_I2C_HALT));
|
||||
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
|
||||
udelay(1);
|
||||
WREG32(AVIVO_DC_I2C_RESET, 0);
|
||||
|
||||
WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_DONE_USING_I2C);
|
||||
WREG32(AVIVO_DC_I2C_CONTROL1, saved1);
|
||||
WREG32(0x494, saved2);
|
||||
tmp = RREG32(RADEON_BIOS_6_SCRATCH);
|
||||
tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE;
|
||||
WREG32(RADEON_BIOS_6_SCRATCH, tmp);
|
||||
|
||||
mutex_unlock(&rdev->pm.mutex);
|
||||
mutex_unlock(&rdev->dc_hw_i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int radeon_sw_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
|
||||
int ret;
|
||||
|
||||
radeon_i2c_do_lock(i2c, 1);
|
||||
ret = i2c_transfer(&i2c->algo.radeon.bit_adapter, msgs, num);
|
||||
radeon_i2c_do_lock(i2c, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
|
||||
struct radeon_device *rdev = i2c->dev->dev_private;
|
||||
struct radeon_i2c_bus_rec *rec = &i2c->rec;
|
||||
int ret;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_R100:
|
||||
case CHIP_RV100:
|
||||
case CHIP_RS100:
|
||||
case CHIP_RV200:
|
||||
case CHIP_RS200:
|
||||
case CHIP_R200:
|
||||
case CHIP_RV250:
|
||||
case CHIP_RS300:
|
||||
case CHIP_RV280:
|
||||
case CHIP_R300:
|
||||
case CHIP_R350:
|
||||
case CHIP_RV350:
|
||||
case CHIP_RV380:
|
||||
case CHIP_R420:
|
||||
case CHIP_R423:
|
||||
case CHIP_RV410:
|
||||
case CHIP_RS400:
|
||||
case CHIP_RS480:
|
||||
if (rec->hw_capable)
|
||||
ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
|
||||
else
|
||||
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
|
||||
break;
|
||||
case CHIP_RS600:
|
||||
case CHIP_RS690:
|
||||
case CHIP_RS740:
|
||||
/* XXX fill in hw i2c implementation */
|
||||
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
|
||||
break;
|
||||
case CHIP_RV515:
|
||||
case CHIP_R520:
|
||||
case CHIP_RV530:
|
||||
case CHIP_RV560:
|
||||
case CHIP_RV570:
|
||||
case CHIP_R580:
|
||||
if (rec->hw_capable) {
|
||||
if (rec->mm_i2c)
|
||||
ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
|
||||
else
|
||||
ret = r500_hw_i2c_xfer(i2c_adap, msgs, num);
|
||||
} else
|
||||
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
|
||||
break;
|
||||
case CHIP_R600:
|
||||
case CHIP_RV610:
|
||||
case CHIP_RV630:
|
||||
case CHIP_RV670:
|
||||
/* XXX fill in hw i2c implementation */
|
||||
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
|
||||
break;
|
||||
case CHIP_RV620:
|
||||
case CHIP_RV635:
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880:
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
/* XXX fill in hw i2c implementation */
|
||||
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
|
||||
break;
|
||||
case CHIP_CEDAR:
|
||||
case CHIP_REDWOOD:
|
||||
case CHIP_JUNIPER:
|
||||
case CHIP_CYPRESS:
|
||||
case CHIP_HEMLOCK:
|
||||
/* XXX fill in hw i2c implementation */
|
||||
ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("i2c: unhandled radeon chip\n");
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 radeon_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm radeon_i2c_algo = {
|
||||
.master_xfer = radeon_i2c_xfer,
|
||||
.functionality = radeon_i2c_func,
|
||||
};
|
||||
|
||||
struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
|
||||
struct radeon_i2c_bus_rec *rec,
|
||||
const char *name)
|
||||
|
@ -179,23 +878,36 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
|
|||
if (i2c == NULL)
|
||||
return NULL;
|
||||
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
i2c->adapter.algo_data = &i2c->algo.bit;
|
||||
i2c->algo.bit.setsda = set_data;
|
||||
i2c->algo.bit.setscl = set_clock;
|
||||
i2c->algo.bit.getsda = get_data;
|
||||
i2c->algo.bit.getscl = get_clock;
|
||||
i2c->algo.bit.udelay = 20;
|
||||
/* set the internal bit adapter */
|
||||
i2c->algo.radeon.bit_adapter.owner = THIS_MODULE;
|
||||
i2c_set_adapdata(&i2c->algo.radeon.bit_adapter, i2c);
|
||||
sprintf(i2c->algo.radeon.bit_adapter.name, "Radeon internal i2c bit bus %s", name);
|
||||
i2c->algo.radeon.bit_adapter.algo_data = &i2c->algo.radeon.bit_data;
|
||||
i2c->algo.radeon.bit_data.setsda = set_data;
|
||||
i2c->algo.radeon.bit_data.setscl = set_clock;
|
||||
i2c->algo.radeon.bit_data.getsda = get_data;
|
||||
i2c->algo.radeon.bit_data.getscl = get_clock;
|
||||
i2c->algo.radeon.bit_data.udelay = 20;
|
||||
/* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
|
||||
* make this, 2 jiffies is a lot more reliable */
|
||||
i2c->algo.bit.timeout = 2;
|
||||
i2c->algo.bit.data = i2c;
|
||||
i2c->rec = *rec;
|
||||
ret = i2c_bit_add_bus(&i2c->adapter);
|
||||
i2c->algo.radeon.bit_data.timeout = 2;
|
||||
i2c->algo.radeon.bit_data.data = i2c;
|
||||
ret = i2c_bit_add_bus(&i2c->algo.radeon.bit_adapter);
|
||||
if (ret) {
|
||||
DRM_INFO("Failed to register i2c %s\n", name);
|
||||
DRM_ERROR("Failed to register internal bit i2c %s\n", name);
|
||||
goto out_free;
|
||||
}
|
||||
/* set the radeon i2c adapter */
|
||||
i2c->dev = dev;
|
||||
i2c->rec = *rec;
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
sprintf(i2c->adapter.name, "Radeon i2c %s", name);
|
||||
i2c->adapter.algo_data = &i2c->algo.radeon;
|
||||
i2c->adapter.algo = &radeon_i2c_algo;
|
||||
ret = i2c_add_adapter(&i2c->adapter);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to register i2c %s\n", name);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
@ -237,8 +949,16 @@ out_free:
|
|||
|
||||
}
|
||||
|
||||
|
||||
void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
|
||||
{
|
||||
if (!i2c)
|
||||
return;
|
||||
i2c_del_adapter(&i2c->algo.radeon.bit_adapter);
|
||||
i2c_del_adapter(&i2c->adapter);
|
||||
kfree(i2c);
|
||||
}
|
||||
|
||||
void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c)
|
||||
{
|
||||
if (!i2c)
|
||||
return;
|
||||
|
@ -252,10 +972,10 @@ struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 *val)
|
||||
void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 *val)
|
||||
{
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
@ -286,10 +1006,10 @@ void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
|
|||
}
|
||||
}
|
||||
|
||||
void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 val)
|
||||
void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 val)
|
||||
{
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
|
|
|
@ -276,17 +276,17 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
|
|||
DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
|
||||
/* KMS */
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
};
|
||||
int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
|
||||
|
|
|
@ -403,7 +403,7 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
|
||||
/* if scanout was in GTT this really wouldn't work */
|
||||
/* crtc offset is from display base addr not FB location */
|
||||
radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
|
||||
radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start;
|
||||
|
||||
base -= radeon_crtc->legacy_display_base_addr;
|
||||
|
||||
|
@ -582,29 +582,6 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
|||
? RADEON_CRTC_V_SYNC_POL
|
||||
: 0));
|
||||
|
||||
/* TODO -> Dell Server */
|
||||
if (0) {
|
||||
uint32_t disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
|
||||
uint32_t tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
uint32_t dac2_cntl = RREG32(RADEON_DAC_CNTL2);
|
||||
uint32_t crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
|
||||
dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
|
||||
dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
|
||||
|
||||
/* For CRT on DAC2, don't turn it on if BIOS didn't
|
||||
enable it, even it's detected.
|
||||
*/
|
||||
disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
|
||||
tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
|
||||
tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
|
||||
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
}
|
||||
|
||||
if (radeon_crtc->crtc_id) {
|
||||
uint32_t crtc2_gen_cntl;
|
||||
uint32_t disp2_merge_cntl;
|
||||
|
@ -726,6 +703,10 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
pll = &rdev->clock.p1pll;
|
||||
|
||||
pll->flags = RADEON_PLL_LEGACY;
|
||||
if (radeon_new_pll == 1)
|
||||
pll->algo = PLL_ALGO_NEW;
|
||||
else
|
||||
pll->algo = PLL_ALGO_LEGACY;
|
||||
|
||||
if (mode->clock > 200000) /* range limits??? */
|
||||
pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
|
|
|
@ -115,6 +115,9 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
|
|||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
else
|
||||
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
|
||||
/* adjust pm to dpms change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
}
|
||||
|
||||
static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
|
||||
|
@ -214,6 +217,11 @@ static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
|
|||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
/* adjust pm to upcoming mode change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
|
||||
/* set the active encoder to connector routing */
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
|
@ -285,6 +293,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
|
|||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
else
|
||||
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
|
||||
/* adjust pm to dpms change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
}
|
||||
|
||||
static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
|
||||
|
@ -470,6 +481,9 @@ static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
|
|||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
else
|
||||
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
|
||||
/* adjust pm to dpms change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
}
|
||||
|
||||
static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
|
||||
|
@ -635,6 +649,9 @@ static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
|
|||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
else
|
||||
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
|
||||
/* adjust pm to dpms change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
}
|
||||
|
||||
static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
|
||||
|
@ -842,6 +859,9 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
|||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
else
|
||||
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
|
||||
/* adjust pm to dpms change */
|
||||
radeon_pm_compute_clocks(rdev);
|
||||
}
|
||||
|
||||
static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
|
||||
|
|
|
@ -83,6 +83,8 @@ struct radeon_i2c_bus_rec {
|
|||
bool valid;
|
||||
/* id used by atom */
|
||||
uint8_t i2c_id;
|
||||
/* id used by atom */
|
||||
uint8_t hpd_id;
|
||||
/* can be used with hw i2c engine */
|
||||
bool hw_capable;
|
||||
/* uses multi-media i2c engine */
|
||||
|
@ -113,6 +115,7 @@ struct radeon_tmds_pll {
|
|||
|
||||
#define RADEON_MAX_BIOS_CONNECTOR 16
|
||||
|
||||
/* pll flags */
|
||||
#define RADEON_PLL_USE_BIOS_DIVS (1 << 0)
|
||||
#define RADEON_PLL_NO_ODD_POST_DIV (1 << 1)
|
||||
#define RADEON_PLL_USE_REF_DIV (1 << 2)
|
||||
|
@ -127,6 +130,12 @@ struct radeon_tmds_pll {
|
|||
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
|
||||
#define RADEON_PLL_USE_POST_DIV (1 << 12)
|
||||
|
||||
/* pll algo */
|
||||
enum radeon_pll_algo {
|
||||
PLL_ALGO_LEGACY,
|
||||
PLL_ALGO_NEW
|
||||
};
|
||||
|
||||
struct radeon_pll {
|
||||
/* reference frequency */
|
||||
uint32_t reference_freq;
|
||||
|
@ -157,6 +166,13 @@ struct radeon_pll {
|
|||
|
||||
/* pll id */
|
||||
uint32_t id;
|
||||
/* pll algo */
|
||||
enum radeon_pll_algo algo;
|
||||
};
|
||||
|
||||
struct i2c_algo_radeon_data {
|
||||
struct i2c_adapter bit_adapter;
|
||||
struct i2c_algo_bit_data bit_data;
|
||||
};
|
||||
|
||||
struct radeon_i2c_chan {
|
||||
|
@ -164,7 +180,7 @@ struct radeon_i2c_chan {
|
|||
struct drm_device *dev;
|
||||
union {
|
||||
struct i2c_algo_dp_aux_data dp;
|
||||
struct i2c_algo_bit_data bit;
|
||||
struct i2c_algo_radeon_data radeon;
|
||||
} algo;
|
||||
struct radeon_i2c_bus_rec rec;
|
||||
};
|
||||
|
@ -193,7 +209,7 @@ struct radeon_mode_info {
|
|||
struct card_info *atom_card_info;
|
||||
enum radeon_connector_table connector_table;
|
||||
bool mode_config_initialized;
|
||||
struct radeon_crtc *crtcs[2];
|
||||
struct radeon_crtc *crtcs[6];
|
||||
/* DVI-I properties */
|
||||
struct drm_property *coherent_mode_property;
|
||||
/* DAC enable load detect */
|
||||
|
@ -202,7 +218,8 @@ struct radeon_mode_info {
|
|||
struct drm_property *tv_std_property;
|
||||
/* legacy TMDS PLL detect */
|
||||
struct drm_property *tmds_pll_property;
|
||||
|
||||
/* hardcoded DFP edid from BIOS */
|
||||
struct edid *bios_hardcoded_edid;
|
||||
};
|
||||
|
||||
#define MAX_H_CODE_TIMING_LEN 32
|
||||
|
@ -237,6 +254,7 @@ struct radeon_crtc {
|
|||
fixed20_12 vsc;
|
||||
fixed20_12 hsc;
|
||||
struct drm_display_mode native_mode;
|
||||
int pll_id;
|
||||
};
|
||||
|
||||
struct radeon_encoder_primary_dac {
|
||||
|
@ -303,6 +321,7 @@ struct radeon_encoder_atom_dig {
|
|||
/* atom lvds */
|
||||
uint32_t lvds_misc;
|
||||
uint16_t panel_pwr_delay;
|
||||
enum radeon_pll_algo pll_algo;
|
||||
struct radeon_atom_ss *ss;
|
||||
/* panel mode */
|
||||
struct drm_display_mode native_mode;
|
||||
|
@ -398,6 +417,7 @@ extern void dp_link_train(struct drm_encoder *encoder,
|
|||
struct drm_connector *connector);
|
||||
extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
|
||||
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
|
||||
extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action);
|
||||
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
|
||||
int action, uint8_t lane_num,
|
||||
uint8_t lane_set);
|
||||
|
@ -411,14 +431,15 @@ extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
|
|||
struct radeon_i2c_bus_rec *rec,
|
||||
const char *name);
|
||||
extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
|
||||
extern void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 *val);
|
||||
extern void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 val);
|
||||
extern void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c);
|
||||
extern void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 *val);
|
||||
extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 val);
|
||||
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
|
||||
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
|
||||
|
||||
|
@ -432,14 +453,6 @@ extern void radeon_compute_pll(struct radeon_pll *pll,
|
|||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p);
|
||||
|
||||
extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
uint32_t *dot_clock_p,
|
||||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p);
|
||||
|
||||
extern void radeon_setup_encoder_clones(struct drm_device *dev);
|
||||
|
||||
struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);
|
||||
|
@ -473,6 +486,9 @@ extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
|
||||
int x, int y);
|
||||
|
||||
extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
|
||||
extern struct edid *
|
||||
radeon_combios_get_hardcoded_edid(struct radeon_device *rdev);
|
||||
extern bool radeon_atom_get_clock_info(struct drm_device *dev);
|
||||
extern bool radeon_combios_get_clock_info(struct drm_device *dev);
|
||||
extern struct radeon_encoder_atom_dig *
|
||||
|
@ -531,7 +547,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
|
|||
struct radeon_crtc *radeon_crtc);
|
||||
void radeon_legacy_init_crtc(struct drm_device *dev,
|
||||
struct radeon_crtc *radeon_crtc);
|
||||
extern void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state);
|
||||
|
||||
void radeon_get_clock_info(struct drm_device *dev);
|
||||
|
||||
|
|
|
@ -178,7 +178,6 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
|
|||
{
|
||||
int r, i;
|
||||
|
||||
radeon_ttm_placement_from_domain(bo, domain);
|
||||
if (bo->pin_count) {
|
||||
bo->pin_count++;
|
||||
if (gpu_addr)
|
||||
|
@ -186,6 +185,8 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
|
|||
return 0;
|
||||
}
|
||||
radeon_ttm_placement_from_domain(bo, domain);
|
||||
/* force to pin into visible video ram */
|
||||
bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
|
||||
for (i = 0; i < bo->placement.num_placement; i++)
|
||||
bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
|
||||
|
|
|
@ -18,21 +18,413 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rafał Miłecki <zajec5@gmail.com>
|
||||
* Alex Deucher <alexdeucher@gmail.com>
|
||||
*/
|
||||
#include "drmP.h"
|
||||
#include "radeon.h"
|
||||
#include "avivod.h"
|
||||
|
||||
int radeon_debugfs_pm_init(struct radeon_device *rdev);
|
||||
#define RADEON_IDLE_LOOP_MS 100
|
||||
#define RADEON_RECLOCK_DELAY_MS 200
|
||||
#define RADEON_WAIT_VBLANK_TIMEOUT 200
|
||||
|
||||
static void radeon_pm_set_clocks_locked(struct radeon_device *rdev);
|
||||
static void radeon_pm_set_clocks(struct radeon_device *rdev);
|
||||
static void radeon_pm_idle_work_handler(struct work_struct *work);
|
||||
static int radeon_debugfs_pm_init(struct radeon_device *rdev);
|
||||
|
||||
static const char *pm_state_names[4] = {
|
||||
"PM_STATE_DISABLED",
|
||||
"PM_STATE_MINIMUM",
|
||||
"PM_STATE_PAUSED",
|
||||
"PM_STATE_ACTIVE"
|
||||
};
|
||||
|
||||
static const char *pm_state_types[5] = {
|
||||
"Default",
|
||||
"Powersave",
|
||||
"Battery",
|
||||
"Balanced",
|
||||
"Performance",
|
||||
};
|
||||
|
||||
static void radeon_print_power_mode_info(struct radeon_device *rdev)
|
||||
{
|
||||
int i, j;
|
||||
bool is_default;
|
||||
|
||||
DRM_INFO("%d Power State(s)\n", rdev->pm.num_power_states);
|
||||
for (i = 0; i < rdev->pm.num_power_states; i++) {
|
||||
if (rdev->pm.default_power_state == &rdev->pm.power_state[i])
|
||||
is_default = true;
|
||||
else
|
||||
is_default = false;
|
||||
DRM_INFO("State %d %s %s\n", i,
|
||||
pm_state_types[rdev->pm.power_state[i].type],
|
||||
is_default ? "(default)" : "");
|
||||
if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
|
||||
DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].non_clock_info.pcie_lanes);
|
||||
DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes);
|
||||
for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) {
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
DRM_INFO("\t\t%d engine: %d\n",
|
||||
j,
|
||||
rdev->pm.power_state[i].clock_info[j].sclk * 10);
|
||||
else
|
||||
DRM_INFO("\t\t%d engine/memory: %d/%d\n",
|
||||
j,
|
||||
rdev->pm.power_state[i].clock_info[j].sclk * 10,
|
||||
rdev->pm.power_state[i].clock_info[j].mclk * 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct radeon_power_state * radeon_pick_power_state(struct radeon_device *rdev,
|
||||
enum radeon_pm_state_type type)
|
||||
{
|
||||
int i, j;
|
||||
enum radeon_pm_state_type wanted_types[2];
|
||||
int wanted_count;
|
||||
|
||||
switch (type) {
|
||||
case POWER_STATE_TYPE_DEFAULT:
|
||||
default:
|
||||
return rdev->pm.default_power_state;
|
||||
case POWER_STATE_TYPE_POWERSAVE:
|
||||
if (rdev->flags & RADEON_IS_MOBILITY) {
|
||||
wanted_types[0] = POWER_STATE_TYPE_POWERSAVE;
|
||||
wanted_types[1] = POWER_STATE_TYPE_BATTERY;
|
||||
wanted_count = 2;
|
||||
} else {
|
||||
wanted_types[0] = POWER_STATE_TYPE_PERFORMANCE;
|
||||
wanted_count = 1;
|
||||
}
|
||||
break;
|
||||
case POWER_STATE_TYPE_BATTERY:
|
||||
if (rdev->flags & RADEON_IS_MOBILITY) {
|
||||
wanted_types[0] = POWER_STATE_TYPE_BATTERY;
|
||||
wanted_types[1] = POWER_STATE_TYPE_POWERSAVE;
|
||||
wanted_count = 2;
|
||||
} else {
|
||||
wanted_types[0] = POWER_STATE_TYPE_PERFORMANCE;
|
||||
wanted_count = 1;
|
||||
}
|
||||
break;
|
||||
case POWER_STATE_TYPE_BALANCED:
|
||||
case POWER_STATE_TYPE_PERFORMANCE:
|
||||
wanted_types[0] = type;
|
||||
wanted_count = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < wanted_count; i++) {
|
||||
for (j = 0; j < rdev->pm.num_power_states; j++) {
|
||||
if (rdev->pm.power_state[j].type == wanted_types[i])
|
||||
return &rdev->pm.power_state[j];
|
||||
}
|
||||
}
|
||||
|
||||
return rdev->pm.default_power_state;
|
||||
}
|
||||
|
||||
static struct radeon_pm_clock_info * radeon_pick_clock_mode(struct radeon_device *rdev,
|
||||
struct radeon_power_state *power_state,
|
||||
enum radeon_pm_clock_mode_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case POWER_MODE_TYPE_DEFAULT:
|
||||
default:
|
||||
return power_state->default_clock_mode;
|
||||
case POWER_MODE_TYPE_LOW:
|
||||
return &power_state->clock_info[0];
|
||||
case POWER_MODE_TYPE_MID:
|
||||
if (power_state->num_clock_modes > 2)
|
||||
return &power_state->clock_info[1];
|
||||
else
|
||||
return &power_state->clock_info[0];
|
||||
break;
|
||||
case POWER_MODE_TYPE_HIGH:
|
||||
return &power_state->clock_info[power_state->num_clock_modes - 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void radeon_get_power_state(struct radeon_device *rdev,
|
||||
enum radeon_pm_action action)
|
||||
{
|
||||
switch (action) {
|
||||
case PM_ACTION_MINIMUM:
|
||||
rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_BATTERY);
|
||||
rdev->pm.requested_clock_mode =
|
||||
radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_LOW);
|
||||
break;
|
||||
case PM_ACTION_DOWNCLOCK:
|
||||
rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_POWERSAVE);
|
||||
rdev->pm.requested_clock_mode =
|
||||
radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_MID);
|
||||
break;
|
||||
case PM_ACTION_UPCLOCK:
|
||||
rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_DEFAULT);
|
||||
rdev->pm.requested_clock_mode =
|
||||
radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_HIGH);
|
||||
break;
|
||||
case PM_ACTION_NONE:
|
||||
default:
|
||||
DRM_ERROR("Requested mode for not defined action\n");
|
||||
return;
|
||||
}
|
||||
DRM_INFO("Requested: e: %d m: %d p: %d\n",
|
||||
rdev->pm.requested_clock_mode->sclk,
|
||||
rdev->pm.requested_clock_mode->mclk,
|
||||
rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
|
||||
}
|
||||
|
||||
static void radeon_set_power_state(struct radeon_device *rdev)
|
||||
{
|
||||
/* if *_clock_mode are the same, *_power_state are as well */
|
||||
if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
|
||||
return;
|
||||
|
||||
DRM_INFO("Setting: e: %d m: %d p: %d\n",
|
||||
rdev->pm.requested_clock_mode->sclk,
|
||||
rdev->pm.requested_clock_mode->mclk,
|
||||
rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
|
||||
/* set pcie lanes */
|
||||
/* set voltage */
|
||||
/* set engine clock */
|
||||
radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
|
||||
/* set memory clock */
|
||||
|
||||
rdev->pm.current_power_state = rdev->pm.requested_power_state;
|
||||
rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
|
||||
}
|
||||
|
||||
int radeon_pm_init(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->pm.state = PM_STATE_DISABLED;
|
||||
rdev->pm.planned_action = PM_ACTION_NONE;
|
||||
rdev->pm.downclocked = false;
|
||||
|
||||
if (rdev->bios) {
|
||||
if (rdev->is_atom_bios)
|
||||
radeon_atombios_get_power_modes(rdev);
|
||||
else
|
||||
radeon_combios_get_power_modes(rdev);
|
||||
radeon_print_power_mode_info(rdev);
|
||||
}
|
||||
|
||||
if (radeon_debugfs_pm_init(rdev)) {
|
||||
DRM_ERROR("Failed to register debugfs file for PM!\n");
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&rdev->pm.idle_work, radeon_pm_idle_work_handler);
|
||||
|
||||
if (radeon_dynpm != -1 && radeon_dynpm) {
|
||||
rdev->pm.state = PM_STATE_PAUSED;
|
||||
DRM_INFO("radeon: dynamic power management enabled\n");
|
||||
}
|
||||
|
||||
DRM_INFO("radeon: power management initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_pm_compute_clocks(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *ddev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_crtc *radeon_crtc;
|
||||
int count = 0;
|
||||
|
||||
if (rdev->pm.state == PM_STATE_DISABLED)
|
||||
return;
|
||||
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
|
||||
rdev->pm.active_crtcs = 0;
|
||||
list_for_each_entry(connector,
|
||||
&ddev->mode_config.connector_list, head) {
|
||||
if (connector->encoder &&
|
||||
connector->dpms != DRM_MODE_DPMS_OFF) {
|
||||
radeon_crtc = to_radeon_crtc(connector->encoder->crtc);
|
||||
rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
if (rdev->pm.state == PM_STATE_ACTIVE) {
|
||||
cancel_delayed_work(&rdev->pm.idle_work);
|
||||
|
||||
rdev->pm.state = PM_STATE_PAUSED;
|
||||
rdev->pm.planned_action = PM_ACTION_UPCLOCK;
|
||||
if (rdev->pm.downclocked)
|
||||
radeon_pm_set_clocks(rdev);
|
||||
|
||||
DRM_DEBUG("radeon: dynamic power management deactivated\n");
|
||||
}
|
||||
} else if (count == 1) {
|
||||
/* TODO: Increase clocks if needed for current mode */
|
||||
|
||||
if (rdev->pm.state == PM_STATE_MINIMUM) {
|
||||
rdev->pm.state = PM_STATE_ACTIVE;
|
||||
rdev->pm.planned_action = PM_ACTION_UPCLOCK;
|
||||
radeon_pm_set_clocks(rdev);
|
||||
|
||||
queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
|
||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||
}
|
||||
else if (rdev->pm.state == PM_STATE_PAUSED) {
|
||||
rdev->pm.state = PM_STATE_ACTIVE;
|
||||
queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
|
||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||
DRM_DEBUG("radeon: dynamic power management activated\n");
|
||||
}
|
||||
}
|
||||
else { /* count == 0 */
|
||||
if (rdev->pm.state != PM_STATE_MINIMUM) {
|
||||
cancel_delayed_work(&rdev->pm.idle_work);
|
||||
|
||||
rdev->pm.state = PM_STATE_MINIMUM;
|
||||
rdev->pm.planned_action = PM_ACTION_MINIMUM;
|
||||
radeon_pm_set_clocks(rdev);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->pm.mutex);
|
||||
}
|
||||
|
||||
static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
|
||||
{
|
||||
u32 stat_crtc1 = 0, stat_crtc2 = 0;
|
||||
bool in_vbl = true;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (rdev->pm.active_crtcs & (1 << 0)) {
|
||||
stat_crtc1 = RREG32(D1CRTC_STATUS);
|
||||
if (!(stat_crtc1 & 1))
|
||||
in_vbl = false;
|
||||
}
|
||||
if (rdev->pm.active_crtcs & (1 << 1)) {
|
||||
stat_crtc2 = RREG32(D2CRTC_STATUS);
|
||||
if (!(stat_crtc2 & 1))
|
||||
in_vbl = false;
|
||||
}
|
||||
}
|
||||
if (in_vbl == false)
|
||||
DRM_INFO("not in vbl for pm change %08x %08x at %s\n", stat_crtc1,
|
||||
stat_crtc2, finish ? "exit" : "entry");
|
||||
return in_vbl;
|
||||
}
|
||||
static void radeon_pm_set_clocks_locked(struct radeon_device *rdev)
|
||||
{
|
||||
/*radeon_fence_wait_last(rdev);*/
|
||||
switch (rdev->pm.planned_action) {
|
||||
case PM_ACTION_UPCLOCK:
|
||||
rdev->pm.downclocked = false;
|
||||
break;
|
||||
case PM_ACTION_DOWNCLOCK:
|
||||
rdev->pm.downclocked = true;
|
||||
break;
|
||||
case PM_ACTION_MINIMUM:
|
||||
break;
|
||||
case PM_ACTION_NONE:
|
||||
DRM_ERROR("%s: PM_ACTION_NONE\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if we are in vblank */
|
||||
radeon_pm_debug_check_in_vbl(rdev, false);
|
||||
radeon_set_power_state(rdev);
|
||||
radeon_pm_debug_check_in_vbl(rdev, true);
|
||||
rdev->pm.planned_action = PM_ACTION_NONE;
|
||||
}
|
||||
|
||||
static void radeon_pm_set_clocks(struct radeon_device *rdev)
|
||||
{
|
||||
radeon_get_power_state(rdev, rdev->pm.planned_action);
|
||||
mutex_lock(&rdev->cp.mutex);
|
||||
|
||||
if (rdev->pm.active_crtcs & (1 << 0)) {
|
||||
rdev->pm.req_vblank |= (1 << 0);
|
||||
drm_vblank_get(rdev->ddev, 0);
|
||||
}
|
||||
if (rdev->pm.active_crtcs & (1 << 1)) {
|
||||
rdev->pm.req_vblank |= (1 << 1);
|
||||
drm_vblank_get(rdev->ddev, 1);
|
||||
}
|
||||
if (rdev->pm.active_crtcs)
|
||||
wait_event_interruptible_timeout(
|
||||
rdev->irq.vblank_queue, 0,
|
||||
msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
|
||||
if (rdev->pm.req_vblank & (1 << 0)) {
|
||||
rdev->pm.req_vblank &= ~(1 << 0);
|
||||
drm_vblank_put(rdev->ddev, 0);
|
||||
}
|
||||
if (rdev->pm.req_vblank & (1 << 1)) {
|
||||
rdev->pm.req_vblank &= ~(1 << 1);
|
||||
drm_vblank_put(rdev->ddev, 1);
|
||||
}
|
||||
|
||||
radeon_pm_set_clocks_locked(rdev);
|
||||
mutex_unlock(&rdev->cp.mutex);
|
||||
}
|
||||
|
||||
static void radeon_pm_idle_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct radeon_device *rdev;
|
||||
rdev = container_of(work, struct radeon_device,
|
||||
pm.idle_work.work);
|
||||
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
if (rdev->pm.state == PM_STATE_ACTIVE) {
|
||||
unsigned long irq_flags;
|
||||
int not_processed = 0;
|
||||
|
||||
read_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
|
||||
if (!list_empty(&rdev->fence_drv.emited)) {
|
||||
struct list_head *ptr;
|
||||
list_for_each(ptr, &rdev->fence_drv.emited) {
|
||||
/* count up to 3, that's enought info */
|
||||
if (++not_processed >= 3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
|
||||
|
||||
if (not_processed >= 3) { /* should upclock */
|
||||
if (rdev->pm.planned_action == PM_ACTION_DOWNCLOCK) {
|
||||
rdev->pm.planned_action = PM_ACTION_NONE;
|
||||
} else if (rdev->pm.planned_action == PM_ACTION_NONE &&
|
||||
rdev->pm.downclocked) {
|
||||
rdev->pm.planned_action =
|
||||
PM_ACTION_UPCLOCK;
|
||||
rdev->pm.action_timeout = jiffies +
|
||||
msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS);
|
||||
}
|
||||
} else if (not_processed == 0) { /* should downclock */
|
||||
if (rdev->pm.planned_action == PM_ACTION_UPCLOCK) {
|
||||
rdev->pm.planned_action = PM_ACTION_NONE;
|
||||
} else if (rdev->pm.planned_action == PM_ACTION_NONE &&
|
||||
!rdev->pm.downclocked) {
|
||||
rdev->pm.planned_action =
|
||||
PM_ACTION_DOWNCLOCK;
|
||||
rdev->pm.action_timeout = jiffies +
|
||||
msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (rdev->pm.planned_action != PM_ACTION_NONE &&
|
||||
jiffies > rdev->pm.action_timeout) {
|
||||
radeon_pm_set_clocks(rdev);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&rdev->pm.mutex);
|
||||
|
||||
queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
|
||||
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugfs info
|
||||
*/
|
||||
|
@ -44,11 +436,14 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
seq_printf(m, "state: %s\n", pm_state_names[rdev->pm.state]);
|
||||
seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk);
|
||||
seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
|
||||
seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
|
||||
if (rdev->asic->get_memory_clock)
|
||||
seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
|
||||
if (rdev->asic->get_pcie_lanes)
|
||||
seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,7 +453,7 @@ static struct drm_info_list radeon_pm_info_list[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
int radeon_debugfs_pm_init(struct radeon_device *rdev)
|
||||
static int radeon_debugfs_pm_init(struct radeon_device *rdev)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
return radeon_debugfs_add_files(rdev, radeon_pm_info_list, ARRAY_SIZE(radeon_pm_info_list));
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#include "r300_reg.h"
|
||||
#include "r500_reg.h"
|
||||
#include "r600_reg.h"
|
||||
|
||||
#include "evergreen_reg.h"
|
||||
|
||||
#define RADEON_MC_AGP_LOCATION 0x014c
|
||||
#define RADEON_MC_AGP_START_MASK 0x0000FFFF
|
||||
|
@ -1060,32 +1060,38 @@
|
|||
|
||||
/* Multimedia I2C bus */
|
||||
#define RADEON_I2C_CNTL_0 0x0090
|
||||
#define RADEON_I2C_DONE (1 << 0)
|
||||
#define RADEON_I2C_NACK (1 << 1)
|
||||
#define RADEON_I2C_HALT (1 << 2)
|
||||
#define RADEON_I2C_SOFT_RST (1 << 5)
|
||||
#define RADEON_I2C_DRIVE_EN (1 << 6)
|
||||
#define RADEON_I2C_DRIVE_SEL (1 << 7)
|
||||
#define RADEON_I2C_START (1 << 8)
|
||||
#define RADEON_I2C_STOP (1 << 9)
|
||||
#define RADEON_I2C_RECEIVE (1 << 10)
|
||||
#define RADEON_I2C_ABORT (1 << 11)
|
||||
#define RADEON_I2C_GO (1 << 12)
|
||||
#define RADEON_I2C_PRESCALE_SHIFT 16
|
||||
# define RADEON_I2C_DONE (1 << 0)
|
||||
# define RADEON_I2C_NACK (1 << 1)
|
||||
# define RADEON_I2C_HALT (1 << 2)
|
||||
# define RADEON_I2C_SOFT_RST (1 << 5)
|
||||
# define RADEON_I2C_DRIVE_EN (1 << 6)
|
||||
# define RADEON_I2C_DRIVE_SEL (1 << 7)
|
||||
# define RADEON_I2C_START (1 << 8)
|
||||
# define RADEON_I2C_STOP (1 << 9)
|
||||
# define RADEON_I2C_RECEIVE (1 << 10)
|
||||
# define RADEON_I2C_ABORT (1 << 11)
|
||||
# define RADEON_I2C_GO (1 << 12)
|
||||
# define RADEON_I2C_PRESCALE_SHIFT 16
|
||||
#define RADEON_I2C_CNTL_1 0x0094
|
||||
#define RADEON_I2C_DATA_COUNT_SHIFT 0
|
||||
#define RADEON_I2C_ADDR_COUNT_SHIFT 4
|
||||
#define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT 8
|
||||
#define RADEON_I2C_SEL (1 << 16)
|
||||
#define RADEON_I2C_EN (1 << 17)
|
||||
#define RADEON_I2C_TIME_LIMIT_SHIFT 24
|
||||
# define RADEON_I2C_DATA_COUNT_SHIFT 0
|
||||
# define RADEON_I2C_ADDR_COUNT_SHIFT 4
|
||||
# define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT 8
|
||||
# define RADEON_I2C_SEL (1 << 16)
|
||||
# define RADEON_I2C_EN (1 << 17)
|
||||
# define RADEON_I2C_TIME_LIMIT_SHIFT 24
|
||||
#define RADEON_I2C_DATA 0x0098
|
||||
|
||||
#define RADEON_DVI_I2C_CNTL_0 0x02e0
|
||||
# define R200_DVI_I2C_PIN_SEL(x) ((x) << 3)
|
||||
# define R200_SEL_DDC1 0 /* 0x60 - VGA_DDC */
|
||||
# define R200_SEL_DDC2 1 /* 0x64 - DVI_DDC */
|
||||
# define R200_SEL_DDC3 2 /* 0x68 - MONID_DDC */
|
||||
# define R200_SEL_DDC1 0 /* depends on asic */
|
||||
# define R200_SEL_DDC2 1 /* depends on asic */
|
||||
# define R200_SEL_DDC3 2 /* depends on asic */
|
||||
# define RADEON_SW_WANTS_TO_USE_DVI_I2C (1 << 13)
|
||||
# define RADEON_SW_CAN_USE_DVI_I2C (1 << 13)
|
||||
# define RADEON_SW_DONE_USING_DVI_I2C (1 << 14)
|
||||
# define RADEON_HW_NEEDS_DVI_I2C (1 << 14)
|
||||
# define RADEON_ABORT_HW_DVI_I2C (1 << 15)
|
||||
# define RADEON_HW_USING_DVI_I2C (1 << 15)
|
||||
#define RADEON_DVI_I2C_CNTL_1 0x02e4
|
||||
#define RADEON_DVI_I2C_DATA 0x02e8
|
||||
|
||||
|
|
|
@ -34,6 +34,36 @@
|
|||
|
||||
int radeon_debugfs_ib_init(struct radeon_device *rdev);
|
||||
|
||||
void radeon_ib_bogus_cleanup(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ib *ib, *n;
|
||||
|
||||
list_for_each_entry_safe(ib, n, &rdev->ib_pool.bogus_ib, list) {
|
||||
list_del(&ib->list);
|
||||
vfree(ib->ptr);
|
||||
kfree(ib);
|
||||
}
|
||||
}
|
||||
|
||||
void radeon_ib_bogus_add(struct radeon_device *rdev, struct radeon_ib *ib)
|
||||
{
|
||||
struct radeon_ib *bib;
|
||||
|
||||
bib = kmalloc(sizeof(*bib), GFP_KERNEL);
|
||||
if (bib == NULL)
|
||||
return;
|
||||
bib->ptr = vmalloc(ib->length_dw * 4);
|
||||
if (bib->ptr == NULL) {
|
||||
kfree(bib);
|
||||
return;
|
||||
}
|
||||
memcpy(bib->ptr, ib->ptr, ib->length_dw * 4);
|
||||
bib->length_dw = ib->length_dw;
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
list_add_tail(&bib->list, &rdev->ib_pool.bogus_ib);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* IB.
|
||||
*/
|
||||
|
@ -142,6 +172,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
|
|||
|
||||
if (rdev->ib_pool.robj)
|
||||
return 0;
|
||||
INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
|
||||
/* Allocate 1M object buffer */
|
||||
r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
|
||||
true, RADEON_GEM_DOMAIN_GTT,
|
||||
|
@ -192,6 +223,8 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
|
|||
return;
|
||||
}
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
radeon_ib_bogus_cleanup(rdev);
|
||||
|
||||
if (rdev->ib_pool.robj) {
|
||||
r = radeon_bo_reserve(rdev->ib_pool.robj, false);
|
||||
if (likely(r == 0)) {
|
||||
|
@ -349,15 +382,49 @@ static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_debugfs_ib_bogus_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct radeon_device *rdev = node->info_ent->data;
|
||||
struct radeon_ib *ib;
|
||||
unsigned i;
|
||||
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
if (list_empty(&rdev->ib_pool.bogus_ib)) {
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
seq_printf(m, "no bogus IB recorded\n");
|
||||
return 0;
|
||||
}
|
||||
ib = list_first_entry(&rdev->ib_pool.bogus_ib, struct radeon_ib, list);
|
||||
list_del_init(&ib->list);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
|
||||
for (i = 0; i < ib->length_dw; i++) {
|
||||
seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
|
||||
}
|
||||
vfree(ib->ptr);
|
||||
kfree(ib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
|
||||
static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
|
||||
|
||||
static struct drm_info_list radeon_debugfs_ib_bogus_info_list[] = {
|
||||
{"radeon_ib_bogus", radeon_debugfs_ib_bogus_info, 0, NULL},
|
||||
};
|
||||
#endif
|
||||
|
||||
int radeon_debugfs_ib_init(struct radeon_device *rdev)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
radeon_debugfs_ib_bogus_info_list[0].data = rdev;
|
||||
r = radeon_debugfs_add_files(rdev, radeon_debugfs_ib_bogus_info_list, 1);
|
||||
if (r)
|
||||
return r;
|
||||
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
|
||||
sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
|
||||
radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_buffer.h"
|
||||
#include "drm_sarea.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
@ -91,21 +92,26 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
|
|||
static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
|
||||
dev_priv,
|
||||
struct drm_file *file_priv,
|
||||
int id, u32 *data)
|
||||
int id, struct drm_buffer *buf)
|
||||
{
|
||||
u32 *data;
|
||||
switch (id) {
|
||||
|
||||
case RADEON_EMIT_PP_MISC:
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv,
|
||||
&data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
|
||||
data = drm_buffer_pointer_to_dword(buf,
|
||||
(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4);
|
||||
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
|
||||
DRM_ERROR("Invalid depth buffer offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case RADEON_EMIT_PP_CNTL:
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv,
|
||||
&data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
|
||||
data = drm_buffer_pointer_to_dword(buf,
|
||||
(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4);
|
||||
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
|
||||
DRM_ERROR("Invalid colour buffer offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -117,8 +123,8 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
|
|||
case R200_EMIT_PP_TXOFFSET_3:
|
||||
case R200_EMIT_PP_TXOFFSET_4:
|
||||
case R200_EMIT_PP_TXOFFSET_5:
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv,
|
||||
&data[0])) {
|
||||
data = drm_buffer_pointer_to_dword(buf, 0);
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
|
||||
DRM_ERROR("Invalid R200 texture offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -127,8 +133,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
|
|||
case RADEON_EMIT_PP_TXFILTER_0:
|
||||
case RADEON_EMIT_PP_TXFILTER_1:
|
||||
case RADEON_EMIT_PP_TXFILTER_2:
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv,
|
||||
&data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
|
||||
data = drm_buffer_pointer_to_dword(buf,
|
||||
(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4);
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
|
||||
DRM_ERROR("Invalid R100 texture offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -142,9 +149,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
|
|||
case R200_EMIT_PP_CUBIC_OFFSETS_5:{
|
||||
int i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
data = drm_buffer_pointer_to_dword(buf, i);
|
||||
if (radeon_check_and_fixup_offset(dev_priv,
|
||||
file_priv,
|
||||
&data[i])) {
|
||||
data)) {
|
||||
DRM_ERROR
|
||||
("Invalid R200 cubic texture offset\n");
|
||||
return -EINVAL;
|
||||
|
@ -158,9 +166,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
|
|||
case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
|
||||
int i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
data = drm_buffer_pointer_to_dword(buf, i);
|
||||
if (radeon_check_and_fixup_offset(dev_priv,
|
||||
file_priv,
|
||||
&data[i])) {
|
||||
data)) {
|
||||
DRM_ERROR
|
||||
("Invalid R100 cubic texture offset\n");
|
||||
return -EINVAL;
|
||||
|
@ -269,23 +278,24 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
cmdbuf,
|
||||
unsigned int *cmdsz)
|
||||
{
|
||||
u32 *cmd = (u32 *) cmdbuf->buf;
|
||||
u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
|
||||
u32 offset, narrays;
|
||||
int count, i, k;
|
||||
|
||||
*cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
|
||||
count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16);
|
||||
*cmdsz = 2 + count;
|
||||
|
||||
if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
|
||||
if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) {
|
||||
DRM_ERROR("Not a type 3 packet\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (4 * *cmdsz > cmdbuf->bufsz) {
|
||||
if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) {
|
||||
DRM_ERROR("Packet size larger than size of data provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch(cmd[0] & 0xff00) {
|
||||
switch (*cmd & 0xff00) {
|
||||
/* XXX Are there old drivers needing other packets? */
|
||||
|
||||
case RADEON_3D_DRAW_IMMD:
|
||||
|
@ -312,7 +322,6 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
break;
|
||||
|
||||
case RADEON_3D_LOAD_VBPNTR:
|
||||
count = (cmd[0] >> 16) & 0x3fff;
|
||||
|
||||
if (count > 18) { /* 12 arrays max */
|
||||
DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
|
||||
|
@ -321,13 +330,16 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
}
|
||||
|
||||
/* carefully check packet contents */
|
||||
narrays = cmd[1] & ~0xc000;
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
|
||||
narrays = *cmd & ~0xc000;
|
||||
k = 0;
|
||||
i = 2;
|
||||
while ((k < narrays) && (i < (count + 2))) {
|
||||
i++; /* skip attribute field */
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv,
|
||||
&cmd[i])) {
|
||||
cmd)) {
|
||||
DRM_ERROR
|
||||
("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
|
||||
k, i);
|
||||
|
@ -338,8 +350,10 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
if (k == narrays)
|
||||
break;
|
||||
/* have one more to process, they come in pairs */
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
|
||||
|
||||
if (radeon_check_and_fixup_offset(dev_priv,
|
||||
file_priv, &cmd[i]))
|
||||
file_priv, cmd))
|
||||
{
|
||||
DRM_ERROR
|
||||
("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
|
||||
|
@ -363,7 +377,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
DRM_ERROR("Invalid 3d packet for r200-class chip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
|
||||
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
|
||||
DRM_ERROR("Invalid rndr_gen_indx offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -374,12 +390,15 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
DRM_ERROR("Invalid 3d packet for r100-class chip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((cmd[1] & 0x8000ffff) != 0x80000810) {
|
||||
DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
|
||||
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
if ((*cmd & 0x8000ffff) != 0x80000810) {
|
||||
DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) {
|
||||
DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
|
||||
if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
|
||||
DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
@ -388,31 +407,34 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
|
|||
case RADEON_CNTL_PAINT_MULTI:
|
||||
case RADEON_CNTL_BITBLT_MULTI:
|
||||
/* MSB of opcode: next DWORD GUI_CNTL */
|
||||
if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
||||
cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
|
||||
if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
||||
| RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
offset = cmd[2] << 10;
|
||||
u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
|
||||
offset = *cmd2 << 10;
|
||||
if (radeon_check_and_fixup_offset
|
||||
(dev_priv, file_priv, &offset)) {
|
||||
DRM_ERROR("Invalid first packet offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
|
||||
*cmd2 = (*cmd2 & 0xffc00000) | offset >> 10;
|
||||
}
|
||||
|
||||
if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
|
||||
(cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
offset = cmd[3] << 10;
|
||||
if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
|
||||
(*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
|
||||
offset = *cmd << 10;
|
||||
if (radeon_check_and_fixup_offset
|
||||
(dev_priv, file_priv, &offset)) {
|
||||
DRM_ERROR("Invalid second packet offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
|
||||
*cmd3 = (*cmd3 & 0xffc00000) | offset >> 10;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
|
||||
DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2611,7 +2633,6 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
|
|||
{
|
||||
int id = (int)header.packet.packet_id;
|
||||
int sz, reg;
|
||||
int *data = (int *)cmdbuf->buf;
|
||||
RING_LOCALS;
|
||||
|
||||
if (id >= RADEON_MAX_STATE_PACKETS)
|
||||
|
@ -2620,23 +2641,22 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
|
|||
sz = packet[id].len;
|
||||
reg = packet[id].start;
|
||||
|
||||
if (sz * sizeof(int) > cmdbuf->bufsz) {
|
||||
if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) {
|
||||
DRM_ERROR("Packet size provided larger than data provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
|
||||
if (radeon_check_and_fixup_packets(dev_priv, file_priv, id,
|
||||
cmdbuf->buffer)) {
|
||||
DRM_ERROR("Packet verification failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BEGIN_RING(sz + 1);
|
||||
OUT_RING(CP_PACKET0(reg, (sz - 1)));
|
||||
OUT_RING_TABLE(data, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * sizeof(int);
|
||||
cmdbuf->bufsz -= sz * sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2653,10 +2673,8 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
|
|||
OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
|
||||
OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
|
||||
OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
|
||||
OUT_RING_TABLE(cmdbuf->buf, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
cmdbuf->buf += sz * sizeof(int);
|
||||
cmdbuf->bufsz -= sz * sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2675,10 +2693,8 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
|
|||
OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
|
||||
OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
|
||||
OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
|
||||
OUT_RING_TABLE(cmdbuf->buf, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
cmdbuf->buf += sz * sizeof(int);
|
||||
cmdbuf->bufsz -= sz * sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2696,11 +2712,9 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
|
|||
OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
|
||||
OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
|
||||
OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
|
||||
OUT_RING_TABLE(cmdbuf->buf, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * sizeof(int);
|
||||
cmdbuf->bufsz -= sz * sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2714,7 +2728,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
|
|||
|
||||
if (!sz)
|
||||
return 0;
|
||||
if (sz * 4 > cmdbuf->bufsz)
|
||||
if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
|
||||
return -EINVAL;
|
||||
|
||||
BEGIN_RING(5 + sz);
|
||||
|
@ -2722,11 +2736,9 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
|
|||
OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
|
||||
OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
|
||||
OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
|
||||
OUT_RING_TABLE(cmdbuf->buf, sz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * sizeof(int);
|
||||
cmdbuf->bufsz -= sz * sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2748,11 +2760,9 @@ static int radeon_emit_packet3(struct drm_device * dev,
|
|||
}
|
||||
|
||||
BEGIN_RING(cmdsz);
|
||||
OUT_RING_TABLE(cmdbuf->buf, cmdsz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += cmdsz * 4;
|
||||
cmdbuf->bufsz -= cmdsz * 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2805,16 +2815,16 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev,
|
|||
}
|
||||
|
||||
BEGIN_RING(cmdsz);
|
||||
OUT_RING_TABLE(cmdbuf->buf, cmdsz);
|
||||
OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
|
||||
ADVANCE_RING();
|
||||
|
||||
} while (++i < cmdbuf->nbox);
|
||||
if (cmdbuf->nbox == 1)
|
||||
cmdbuf->nbox = 0;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
cmdbuf->buf += cmdsz * 4;
|
||||
cmdbuf->bufsz -= cmdsz * 4;
|
||||
drm_buffer_advance(cmdbuf->buffer, cmdsz * 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2847,16 +2857,16 @@ static int radeon_emit_wait(struct drm_device * dev, int flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf = NULL;
|
||||
drm_radeon_cmd_header_t stack_header;
|
||||
int idx;
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf = data;
|
||||
drm_radeon_cmd_header_t header;
|
||||
int orig_nbox, orig_bufsz;
|
||||
char *kbuf = NULL;
|
||||
int orig_nbox;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
@ -2871,17 +2881,16 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
* races between checking values and using those values in other code,
|
||||
* and simply to avoid a lot of function calls to copy in data.
|
||||
*/
|
||||
orig_bufsz = cmdbuf->bufsz;
|
||||
if (orig_bufsz != 0) {
|
||||
kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL);
|
||||
if (kbuf == NULL)
|
||||
return -ENOMEM;
|
||||
if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
|
||||
cmdbuf->bufsz)) {
|
||||
kfree(kbuf);
|
||||
return -EFAULT;
|
||||
}
|
||||
cmdbuf->buf = kbuf;
|
||||
if (cmdbuf->bufsz != 0) {
|
||||
int rv;
|
||||
void __user *buffer = cmdbuf->buffer;
|
||||
rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz);
|
||||
if (rv)
|
||||
return rv;
|
||||
rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
|
||||
cmdbuf->bufsz);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
|
||||
orig_nbox = cmdbuf->nbox;
|
||||
|
@ -2890,24 +2899,24 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
int temp;
|
||||
temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
|
||||
|
||||
if (orig_bufsz != 0)
|
||||
kfree(kbuf);
|
||||
if (cmdbuf->bufsz != 0)
|
||||
drm_buffer_free(cmdbuf->buffer);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* microcode_version != r300 */
|
||||
while (cmdbuf->bufsz >= sizeof(header)) {
|
||||
while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) {
|
||||
|
||||
header.i = *(int *)cmdbuf->buf;
|
||||
cmdbuf->buf += sizeof(header);
|
||||
cmdbuf->bufsz -= sizeof(header);
|
||||
drm_radeon_cmd_header_t *header;
|
||||
header = drm_buffer_read_object(cmdbuf->buffer,
|
||||
sizeof(stack_header), &stack_header);
|
||||
|
||||
switch (header.header.cmd_type) {
|
||||
switch (header->header.cmd_type) {
|
||||
case RADEON_CMD_PACKET:
|
||||
DRM_DEBUG("RADEON_CMD_PACKET\n");
|
||||
if (radeon_emit_packets
|
||||
(dev_priv, file_priv, header, cmdbuf)) {
|
||||
(dev_priv, file_priv, *header, cmdbuf)) {
|
||||
DRM_ERROR("radeon_emit_packets failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
@ -2915,7 +2924,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
case RADEON_CMD_SCALARS:
|
||||
DRM_DEBUG("RADEON_CMD_SCALARS\n");
|
||||
if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
|
||||
if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) {
|
||||
DRM_ERROR("radeon_emit_scalars failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
@ -2923,7 +2932,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
case RADEON_CMD_VECTORS:
|
||||
DRM_DEBUG("RADEON_CMD_VECTORS\n");
|
||||
if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
|
||||
if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) {
|
||||
DRM_ERROR("radeon_emit_vectors failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
@ -2931,7 +2940,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
case RADEON_CMD_DMA_DISCARD:
|
||||
DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
|
||||
idx = header.dma.buf_idx;
|
||||
idx = header->dma.buf_idx;
|
||||
if (idx < 0 || idx >= dma->buf_count) {
|
||||
DRM_ERROR("buffer index %d (of %d max)\n",
|
||||
idx, dma->buf_count - 1);
|
||||
|
@ -2968,7 +2977,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
case RADEON_CMD_SCALARS2:
|
||||
DRM_DEBUG("RADEON_CMD_SCALARS2\n");
|
||||
if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
|
||||
if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) {
|
||||
DRM_ERROR("radeon_emit_scalars2 failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
@ -2976,37 +2985,37 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
case RADEON_CMD_WAIT:
|
||||
DRM_DEBUG("RADEON_CMD_WAIT\n");
|
||||
if (radeon_emit_wait(dev, header.wait.flags)) {
|
||||
if (radeon_emit_wait(dev, header->wait.flags)) {
|
||||
DRM_ERROR("radeon_emit_wait failed\n");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case RADEON_CMD_VECLINEAR:
|
||||
DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
|
||||
if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
|
||||
if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) {
|
||||
DRM_ERROR("radeon_emit_veclinear failed\n");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DRM_ERROR("bad cmd_type %d at %p\n",
|
||||
header.header.cmd_type,
|
||||
cmdbuf->buf - sizeof(header));
|
||||
DRM_ERROR("bad cmd_type %d at byte %d\n",
|
||||
header->header.cmd_type,
|
||||
cmdbuf->buffer->iterator);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (orig_bufsz != 0)
|
||||
kfree(kbuf);
|
||||
if (cmdbuf->bufsz != 0)
|
||||
drm_buffer_free(cmdbuf->buffer);
|
||||
|
||||
DRM_DEBUG("DONE\n");
|
||||
COMMIT_RING();
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (orig_bufsz != 0)
|
||||
kfree(kbuf);
|
||||
if (cmdbuf->bufsz != 0)
|
||||
drm_buffer_free(cmdbuf->buffer);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ void radeon_test_moves(struct radeon_device *rdev)
|
|||
radeon_bo_kunmap(gtt_obj[i]);
|
||||
|
||||
DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
|
||||
gtt_addr - rdev->mc.gtt_location);
|
||||
gtt_addr - rdev->mc.gtt_start);
|
||||
}
|
||||
|
||||
out_cleanup:
|
||||
|
|
|
@ -150,7 +150,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
|
|||
man->default_caching = TTM_PL_FLAG_CACHED;
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
man->gpu_offset = rdev->mc.gtt_location;
|
||||
man->gpu_offset = rdev->mc.gtt_start;
|
||||
man->available_caching = TTM_PL_MASK_CACHING;
|
||||
man->default_caching = TTM_PL_FLAG_CACHED;
|
||||
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
|
||||
|
@ -180,7 +180,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
|
|||
break;
|
||||
case TTM_PL_VRAM:
|
||||
/* "On-card" video ram */
|
||||
man->gpu_offset = rdev->mc.vram_location;
|
||||
man->gpu_offset = rdev->mc.vram_start;
|
||||
man->flags = TTM_MEMTYPE_FLAG_FIXED |
|
||||
TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
|
||||
TTM_MEMTYPE_FLAG_MAPPABLE;
|
||||
|
@ -262,10 +262,10 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
|
|||
|
||||
switch (old_mem->mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
old_start += rdev->mc.vram_location;
|
||||
old_start += rdev->mc.vram_start;
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
old_start += rdev->mc.gtt_location;
|
||||
old_start += rdev->mc.gtt_start;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
|
||||
|
@ -273,10 +273,10 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
|
|||
}
|
||||
switch (new_mem->mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
new_start += rdev->mc.vram_location;
|
||||
new_start += rdev->mc.vram_start;
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
new_start += rdev->mc.gtt_location;
|
||||
new_start += rdev->mc.gtt_start;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
|
||||
|
|
837
drivers/gpu/drm/radeon/reg_srcs/r600
Normal file
837
drivers/gpu/drm/radeon/reg_srcs/r600
Normal file
|
@ -0,0 +1,837 @@
|
|||
r600 0x9400
|
||||
0x000287A0 R7xx_CB_SHADER_CONTROL
|
||||
0x00028230 R7xx_PA_SC_EDGERULE
|
||||
0x000286C8 R7xx_SPI_THREAD_GROUPING
|
||||
0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
|
||||
0x000088C4 VGT_CACHE_INVALIDATION
|
||||
0x00028A50 VGT_ENHANCE
|
||||
0x000088CC VGT_ES_PER_GS
|
||||
0x00028A2C VGT_GROUP_DECR
|
||||
0x00028A28 VGT_GROUP_FIRST_DECR
|
||||
0x00028A24 VGT_GROUP_PRIM_TYPE
|
||||
0x00028A30 VGT_GROUP_VECT_0_CNTL
|
||||
0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
|
||||
0x00028A34 VGT_GROUP_VECT_1_CNTL
|
||||
0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
|
||||
0x00028A40 VGT_GS_MODE
|
||||
0x00028A6C VGT_GS_OUT_PRIM_TYPE
|
||||
0x000088C8 VGT_GS_PER_ES
|
||||
0x000088E8 VGT_GS_PER_VS
|
||||
0x000088D4 VGT_GS_VERTEX_REUSE
|
||||
0x00028A14 VGT_HOS_CNTL
|
||||
0x00028A18 VGT_HOS_MAX_TESS_LEVEL
|
||||
0x00028A1C VGT_HOS_MIN_TESS_LEVEL
|
||||
0x00028A20 VGT_HOS_REUSE_DEPTH
|
||||
0x0000895C VGT_INDEX_TYPE
|
||||
0x00028408 VGT_INDX_OFFSET
|
||||
0x00028AA0 VGT_INSTANCE_STEP_RATE_0
|
||||
0x00028AA4 VGT_INSTANCE_STEP_RATE_1
|
||||
0x000088C0 VGT_LAST_COPY_STATE
|
||||
0x00028400 VGT_MAX_VTX_INDX
|
||||
0x000088D8 VGT_MC_LAT_CNTL
|
||||
0x00028404 VGT_MIN_VTX_INDX
|
||||
0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
|
||||
0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
|
||||
0x00008970 VGT_NUM_INDICES
|
||||
0x00008974 VGT_NUM_INSTANCES
|
||||
0x00028A10 VGT_OUTPUT_PATH_CNTL
|
||||
0x00028C5C VGT_OUT_DEALLOC_CNTL
|
||||
0x00028A84 VGT_PRIMITIVEID_EN
|
||||
0x00008958 VGT_PRIMITIVE_TYPE
|
||||
0x00028AB4 VGT_REUSE_OFF
|
||||
0x00028C58 VGT_VERTEX_REUSE_BLOCK_CNTL
|
||||
0x00028AB8 VGT_VTX_CNT_EN
|
||||
0x000088B0 VGT_VTX_VECT_EJECT_REG
|
||||
0x00028810 PA_CL_CLIP_CNTL
|
||||
0x00008A14 PA_CL_ENHANCE
|
||||
0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
|
||||
0x00028C18 PA_CL_GB_HORZ_DISC_ADJ
|
||||
0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
|
||||
0x00028C10 PA_CL_GB_VERT_DISC_ADJ
|
||||
0x00028820 PA_CL_NANINF_CNTL
|
||||
0x00028E1C PA_CL_POINT_CULL_RAD
|
||||
0x00028E18 PA_CL_POINT_SIZE
|
||||
0x00028E10 PA_CL_POINT_X_RAD
|
||||
0x00028E14 PA_CL_POINT_Y_RAD
|
||||
0x00028E2C PA_CL_UCP_0_W
|
||||
0x00028E3C PA_CL_UCP_1_W
|
||||
0x00028E4C PA_CL_UCP_2_W
|
||||
0x00028E5C PA_CL_UCP_3_W
|
||||
0x00028E6C PA_CL_UCP_4_W
|
||||
0x00028E7C PA_CL_UCP_5_W
|
||||
0x00028E20 PA_CL_UCP_0_X
|
||||
0x00028E30 PA_CL_UCP_1_X
|
||||
0x00028E40 PA_CL_UCP_2_X
|
||||
0x00028E50 PA_CL_UCP_3_X
|
||||
0x00028E60 PA_CL_UCP_4_X
|
||||
0x00028E70 PA_CL_UCP_5_X
|
||||
0x00028E24 PA_CL_UCP_0_Y
|
||||
0x00028E34 PA_CL_UCP_1_Y
|
||||
0x00028E44 PA_CL_UCP_2_Y
|
||||
0x00028E54 PA_CL_UCP_3_Y
|
||||
0x00028E64 PA_CL_UCP_4_Y
|
||||
0x00028E74 PA_CL_UCP_5_Y
|
||||
0x00028E28 PA_CL_UCP_0_Z
|
||||
0x00028E38 PA_CL_UCP_1_Z
|
||||
0x00028E48 PA_CL_UCP_2_Z
|
||||
0x00028E58 PA_CL_UCP_3_Z
|
||||
0x00028E68 PA_CL_UCP_4_Z
|
||||
0x00028E78 PA_CL_UCP_5_Z
|
||||
0x00028440 PA_CL_VPORT_XOFFSET_0
|
||||
0x00028458 PA_CL_VPORT_XOFFSET_1
|
||||
0x00028470 PA_CL_VPORT_XOFFSET_2
|
||||
0x00028488 PA_CL_VPORT_XOFFSET_3
|
||||
0x000284A0 PA_CL_VPORT_XOFFSET_4
|
||||
0x000284B8 PA_CL_VPORT_XOFFSET_5
|
||||
0x000284D0 PA_CL_VPORT_XOFFSET_6
|
||||
0x000284E8 PA_CL_VPORT_XOFFSET_7
|
||||
0x00028500 PA_CL_VPORT_XOFFSET_8
|
||||
0x00028518 PA_CL_VPORT_XOFFSET_9
|
||||
0x00028530 PA_CL_VPORT_XOFFSET_10
|
||||
0x00028548 PA_CL_VPORT_XOFFSET_11
|
||||
0x00028560 PA_CL_VPORT_XOFFSET_12
|
||||
0x00028578 PA_CL_VPORT_XOFFSET_13
|
||||
0x00028590 PA_CL_VPORT_XOFFSET_14
|
||||
0x000285A8 PA_CL_VPORT_XOFFSET_15
|
||||
0x0002843C PA_CL_VPORT_XSCALE_0
|
||||
0x00028454 PA_CL_VPORT_XSCALE_1
|
||||
0x0002846C PA_CL_VPORT_XSCALE_2
|
||||
0x00028484 PA_CL_VPORT_XSCALE_3
|
||||
0x0002849C PA_CL_VPORT_XSCALE_4
|
||||
0x000284B4 PA_CL_VPORT_XSCALE_5
|
||||
0x000284CC PA_CL_VPORT_XSCALE_6
|
||||
0x000284E4 PA_CL_VPORT_XSCALE_7
|
||||
0x000284FC PA_CL_VPORT_XSCALE_8
|
||||
0x00028514 PA_CL_VPORT_XSCALE_9
|
||||
0x0002852C PA_CL_VPORT_XSCALE_10
|
||||
0x00028544 PA_CL_VPORT_XSCALE_11
|
||||
0x0002855C PA_CL_VPORT_XSCALE_12
|
||||
0x00028574 PA_CL_VPORT_XSCALE_13
|
||||
0x0002858C PA_CL_VPORT_XSCALE_14
|
||||
0x000285A4 PA_CL_VPORT_XSCALE_15
|
||||
0x00028448 PA_CL_VPORT_YOFFSET_0
|
||||
0x00028460 PA_CL_VPORT_YOFFSET_1
|
||||
0x00028478 PA_CL_VPORT_YOFFSET_2
|
||||
0x00028490 PA_CL_VPORT_YOFFSET_3
|
||||
0x000284A8 PA_CL_VPORT_YOFFSET_4
|
||||
0x000284C0 PA_CL_VPORT_YOFFSET_5
|
||||
0x000284D8 PA_CL_VPORT_YOFFSET_6
|
||||
0x000284F0 PA_CL_VPORT_YOFFSET_7
|
||||
0x00028508 PA_CL_VPORT_YOFFSET_8
|
||||
0x00028520 PA_CL_VPORT_YOFFSET_9
|
||||
0x00028538 PA_CL_VPORT_YOFFSET_10
|
||||
0x00028550 PA_CL_VPORT_YOFFSET_11
|
||||
0x00028568 PA_CL_VPORT_YOFFSET_12
|
||||
0x00028580 PA_CL_VPORT_YOFFSET_13
|
||||
0x00028598 PA_CL_VPORT_YOFFSET_14
|
||||
0x000285B0 PA_CL_VPORT_YOFFSET_15
|
||||
0x00028444 PA_CL_VPORT_YSCALE_0
|
||||
0x0002845C PA_CL_VPORT_YSCALE_1
|
||||
0x00028474 PA_CL_VPORT_YSCALE_2
|
||||
0x0002848C PA_CL_VPORT_YSCALE_3
|
||||
0x000284A4 PA_CL_VPORT_YSCALE_4
|
||||
0x000284BC PA_CL_VPORT_YSCALE_5
|
||||
0x000284D4 PA_CL_VPORT_YSCALE_6
|
||||
0x000284EC PA_CL_VPORT_YSCALE_7
|
||||
0x00028504 PA_CL_VPORT_YSCALE_8
|
||||
0x0002851C PA_CL_VPORT_YSCALE_9
|
||||
0x00028534 PA_CL_VPORT_YSCALE_10
|
||||
0x0002854C PA_CL_VPORT_YSCALE_11
|
||||
0x00028564 PA_CL_VPORT_YSCALE_12
|
||||
0x0002857C PA_CL_VPORT_YSCALE_13
|
||||
0x00028594 PA_CL_VPORT_YSCALE_14
|
||||
0x000285AC PA_CL_VPORT_YSCALE_15
|
||||
0x00028450 PA_CL_VPORT_ZOFFSET_0
|
||||
0x00028468 PA_CL_VPORT_ZOFFSET_1
|
||||
0x00028480 PA_CL_VPORT_ZOFFSET_2
|
||||
0x00028498 PA_CL_VPORT_ZOFFSET_3
|
||||
0x000284B0 PA_CL_VPORT_ZOFFSET_4
|
||||
0x000284C8 PA_CL_VPORT_ZOFFSET_5
|
||||
0x000284E0 PA_CL_VPORT_ZOFFSET_6
|
||||
0x000284F8 PA_CL_VPORT_ZOFFSET_7
|
||||
0x00028510 PA_CL_VPORT_ZOFFSET_8
|
||||
0x00028528 PA_CL_VPORT_ZOFFSET_9
|
||||
0x00028540 PA_CL_VPORT_ZOFFSET_10
|
||||
0x00028558 PA_CL_VPORT_ZOFFSET_11
|
||||
0x00028570 PA_CL_VPORT_ZOFFSET_12
|
||||
0x00028588 PA_CL_VPORT_ZOFFSET_13
|
||||
0x000285A0 PA_CL_VPORT_ZOFFSET_14
|
||||
0x000285B8 PA_CL_VPORT_ZOFFSET_15
|
||||
0x0002844C PA_CL_VPORT_ZSCALE_0
|
||||
0x00028464 PA_CL_VPORT_ZSCALE_1
|
||||
0x0002847C PA_CL_VPORT_ZSCALE_2
|
||||
0x00028494 PA_CL_VPORT_ZSCALE_3
|
||||
0x000284AC PA_CL_VPORT_ZSCALE_4
|
||||
0x000284C4 PA_CL_VPORT_ZSCALE_5
|
||||
0x000284DC PA_CL_VPORT_ZSCALE_6
|
||||
0x000284F4 PA_CL_VPORT_ZSCALE_7
|
||||
0x0002850C PA_CL_VPORT_ZSCALE_8
|
||||
0x00028524 PA_CL_VPORT_ZSCALE_9
|
||||
0x0002853C PA_CL_VPORT_ZSCALE_10
|
||||
0x00028554 PA_CL_VPORT_ZSCALE_11
|
||||
0x0002856C PA_CL_VPORT_ZSCALE_12
|
||||
0x00028584 PA_CL_VPORT_ZSCALE_13
|
||||
0x0002859C PA_CL_VPORT_ZSCALE_14
|
||||
0x000285B4 PA_CL_VPORT_ZSCALE_15
|
||||
0x0002881C PA_CL_VS_OUT_CNTL
|
||||
0x00028818 PA_CL_VTE_CNTL
|
||||
0x00028C48 PA_SC_AA_MASK
|
||||
0x00008B40 PA_SC_AA_SAMPLE_LOCS_2S
|
||||
0x00008B44 PA_SC_AA_SAMPLE_LOCS_4S
|
||||
0x00008B48 PA_SC_AA_SAMPLE_LOCS_8S_WD0
|
||||
0x00008B4C PA_SC_AA_SAMPLE_LOCS_8S_WD1
|
||||
0x00028C20 PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX
|
||||
0x00028C1C PA_SC_AA_SAMPLE_LOCS_MCTX
|
||||
0x00028214 PA_SC_CLIPRECT_0_BR
|
||||
0x0002821C PA_SC_CLIPRECT_1_BR
|
||||
0x00028224 PA_SC_CLIPRECT_2_BR
|
||||
0x0002822C PA_SC_CLIPRECT_3_BR
|
||||
0x00028210 PA_SC_CLIPRECT_0_TL
|
||||
0x00028218 PA_SC_CLIPRECT_1_TL
|
||||
0x00028220 PA_SC_CLIPRECT_2_TL
|
||||
0x00028228 PA_SC_CLIPRECT_3_TL
|
||||
0x0002820C PA_SC_CLIPRECT_RULE
|
||||
0x00008BF0 PA_SC_ENHANCE
|
||||
0x00028244 PA_SC_GENERIC_SCISSOR_BR
|
||||
0x00028240 PA_SC_GENERIC_SCISSOR_TL
|
||||
0x00028C00 PA_SC_LINE_CNTL
|
||||
0x00028A0C PA_SC_LINE_STIPPLE
|
||||
0x00008B10 PA_SC_LINE_STIPPLE_STATE
|
||||
0x00028A4C PA_SC_MODE_CNTL
|
||||
0x00028A48 PA_SC_MPASS_PS_CNTL
|
||||
0x00008B20 PA_SC_MULTI_CHIP_CNTL
|
||||
0x00028034 PA_SC_SCREEN_SCISSOR_BR
|
||||
0x00028030 PA_SC_SCREEN_SCISSOR_TL
|
||||
0x00028254 PA_SC_VPORT_SCISSOR_0_BR
|
||||
0x0002825C PA_SC_VPORT_SCISSOR_1_BR
|
||||
0x00028264 PA_SC_VPORT_SCISSOR_2_BR
|
||||
0x0002826C PA_SC_VPORT_SCISSOR_3_BR
|
||||
0x00028274 PA_SC_VPORT_SCISSOR_4_BR
|
||||
0x0002827C PA_SC_VPORT_SCISSOR_5_BR
|
||||
0x00028284 PA_SC_VPORT_SCISSOR_6_BR
|
||||
0x0002828C PA_SC_VPORT_SCISSOR_7_BR
|
||||
0x00028294 PA_SC_VPORT_SCISSOR_8_BR
|
||||
0x0002829C PA_SC_VPORT_SCISSOR_9_BR
|
||||
0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
|
||||
0x000282AC PA_SC_VPORT_SCISSOR_11_BR
|
||||
0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
|
||||
0x000282BC PA_SC_VPORT_SCISSOR_13_BR
|
||||
0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
|
||||
0x000282CC PA_SC_VPORT_SCISSOR_15_BR
|
||||
0x00028250 PA_SC_VPORT_SCISSOR_0_TL
|
||||
0x00028258 PA_SC_VPORT_SCISSOR_1_TL
|
||||
0x00028260 PA_SC_VPORT_SCISSOR_2_TL
|
||||
0x00028268 PA_SC_VPORT_SCISSOR_3_TL
|
||||
0x00028270 PA_SC_VPORT_SCISSOR_4_TL
|
||||
0x00028278 PA_SC_VPORT_SCISSOR_5_TL
|
||||
0x00028280 PA_SC_VPORT_SCISSOR_6_TL
|
||||
0x00028288 PA_SC_VPORT_SCISSOR_7_TL
|
||||
0x00028290 PA_SC_VPORT_SCISSOR_8_TL
|
||||
0x00028298 PA_SC_VPORT_SCISSOR_9_TL
|
||||
0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
|
||||
0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
|
||||
0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
|
||||
0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
|
||||
0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
|
||||
0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
|
||||
0x000282D4 PA_SC_VPORT_ZMAX_0
|
||||
0x000282DC PA_SC_VPORT_ZMAX_1
|
||||
0x000282E4 PA_SC_VPORT_ZMAX_2
|
||||
0x000282EC PA_SC_VPORT_ZMAX_3
|
||||
0x000282F4 PA_SC_VPORT_ZMAX_4
|
||||
0x000282FC PA_SC_VPORT_ZMAX_5
|
||||
0x00028304 PA_SC_VPORT_ZMAX_6
|
||||
0x0002830C PA_SC_VPORT_ZMAX_7
|
||||
0x00028314 PA_SC_VPORT_ZMAX_8
|
||||
0x0002831C PA_SC_VPORT_ZMAX_9
|
||||
0x00028324 PA_SC_VPORT_ZMAX_10
|
||||
0x0002832C PA_SC_VPORT_ZMAX_11
|
||||
0x00028334 PA_SC_VPORT_ZMAX_12
|
||||
0x0002833C PA_SC_VPORT_ZMAX_13
|
||||
0x00028344 PA_SC_VPORT_ZMAX_14
|
||||
0x0002834C PA_SC_VPORT_ZMAX_15
|
||||
0x000282D0 PA_SC_VPORT_ZMIN_0
|
||||
0x000282D8 PA_SC_VPORT_ZMIN_1
|
||||
0x000282E0 PA_SC_VPORT_ZMIN_2
|
||||
0x000282E8 PA_SC_VPORT_ZMIN_3
|
||||
0x000282F0 PA_SC_VPORT_ZMIN_4
|
||||
0x000282F8 PA_SC_VPORT_ZMIN_5
|
||||
0x00028300 PA_SC_VPORT_ZMIN_6
|
||||
0x00028308 PA_SC_VPORT_ZMIN_7
|
||||
0x00028310 PA_SC_VPORT_ZMIN_8
|
||||
0x00028318 PA_SC_VPORT_ZMIN_9
|
||||
0x00028320 PA_SC_VPORT_ZMIN_10
|
||||
0x00028328 PA_SC_VPORT_ZMIN_11
|
||||
0x00028330 PA_SC_VPORT_ZMIN_12
|
||||
0x00028338 PA_SC_VPORT_ZMIN_13
|
||||
0x00028340 PA_SC_VPORT_ZMIN_14
|
||||
0x00028348 PA_SC_VPORT_ZMIN_15
|
||||
0x00028200 PA_SC_WINDOW_OFFSET
|
||||
0x00028208 PA_SC_WINDOW_SCISSOR_BR
|
||||
0x00028204 PA_SC_WINDOW_SCISSOR_TL
|
||||
0x00028A08 PA_SU_LINE_CNTL
|
||||
0x00028A04 PA_SU_POINT_MINMAX
|
||||
0x00028A00 PA_SU_POINT_SIZE
|
||||
0x00028E0C PA_SU_POLY_OFFSET_BACK_OFFSET
|
||||
0x00028E08 PA_SU_POLY_OFFSET_BACK_SCALE
|
||||
0x00028DFC PA_SU_POLY_OFFSET_CLAMP
|
||||
0x00028DF8 PA_SU_POLY_OFFSET_DB_FMT_CNTL
|
||||
0x00028E04 PA_SU_POLY_OFFSET_FRONT_OFFSET
|
||||
0x00028E00 PA_SU_POLY_OFFSET_FRONT_SCALE
|
||||
0x00028814 PA_SU_SC_MODE_CNTL
|
||||
0x00028C08 PA_SU_VTX_CNTL
|
||||
0x00008C00 SQ_CONFIG
|
||||
0x00008C04 SQ_GPR_RESOURCE_MGMT_1
|
||||
0x00008C08 SQ_GPR_RESOURCE_MGMT_2
|
||||
0x00008C10 SQ_STACK_RESOURCE_MGMT_1
|
||||
0x00008C14 SQ_STACK_RESOURCE_MGMT_2
|
||||
0x00008C0C SQ_THREAD_RESOURCE_MGMT
|
||||
0x00028380 SQ_VTX_SEMANTIC_0
|
||||
0x00028384 SQ_VTX_SEMANTIC_1
|
||||
0x00028388 SQ_VTX_SEMANTIC_2
|
||||
0x0002838C SQ_VTX_SEMANTIC_3
|
||||
0x00028390 SQ_VTX_SEMANTIC_4
|
||||
0x00028394 SQ_VTX_SEMANTIC_5
|
||||
0x00028398 SQ_VTX_SEMANTIC_6
|
||||
0x0002839C SQ_VTX_SEMANTIC_7
|
||||
0x000283A0 SQ_VTX_SEMANTIC_8
|
||||
0x000283A4 SQ_VTX_SEMANTIC_9
|
||||
0x000283A8 SQ_VTX_SEMANTIC_10
|
||||
0x000283AC SQ_VTX_SEMANTIC_11
|
||||
0x000283B0 SQ_VTX_SEMANTIC_12
|
||||
0x000283B4 SQ_VTX_SEMANTIC_13
|
||||
0x000283B8 SQ_VTX_SEMANTIC_14
|
||||
0x000283BC SQ_VTX_SEMANTIC_15
|
||||
0x000283C0 SQ_VTX_SEMANTIC_16
|
||||
0x000283C4 SQ_VTX_SEMANTIC_17
|
||||
0x000283C8 SQ_VTX_SEMANTIC_18
|
||||
0x000283CC SQ_VTX_SEMANTIC_19
|
||||
0x000283D0 SQ_VTX_SEMANTIC_20
|
||||
0x000283D4 SQ_VTX_SEMANTIC_21
|
||||
0x000283D8 SQ_VTX_SEMANTIC_22
|
||||
0x000283DC SQ_VTX_SEMANTIC_23
|
||||
0x000283E0 SQ_VTX_SEMANTIC_24
|
||||
0x000283E4 SQ_VTX_SEMANTIC_25
|
||||
0x000283E8 SQ_VTX_SEMANTIC_26
|
||||
0x000283EC SQ_VTX_SEMANTIC_27
|
||||
0x000283F0 SQ_VTX_SEMANTIC_28
|
||||
0x000283F4 SQ_VTX_SEMANTIC_29
|
||||
0x000283F8 SQ_VTX_SEMANTIC_30
|
||||
0x000283FC SQ_VTX_SEMANTIC_31
|
||||
0x000288E0 SQ_VTX_SEMANTIC_CLEAR
|
||||
0x0003CFF4 SQ_VTX_START_INST_LOC
|
||||
0x0003C000 SQ_TEX_SAMPLER_WORD0_0
|
||||
0x0003C004 SQ_TEX_SAMPLER_WORD1_0
|
||||
0x0003C008 SQ_TEX_SAMPLER_WORD2_0
|
||||
0x00030000 SQ_ALU_CONSTANT0_0
|
||||
0x00030004 SQ_ALU_CONSTANT1_0
|
||||
0x00030008 SQ_ALU_CONSTANT2_0
|
||||
0x0003000C SQ_ALU_CONSTANT3_0
|
||||
0x0003E380 SQ_BOOL_CONST_0
|
||||
0x0003E384 SQ_BOOL_CONST_1
|
||||
0x0003E388 SQ_BOOL_CONST_2
|
||||
0x0003E200 SQ_LOOP_CONST_0
|
||||
0x0003E200 SQ_LOOP_CONST_DX10_0
|
||||
0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
|
||||
0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
|
||||
0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
|
||||
0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
|
||||
0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
|
||||
0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
|
||||
0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
|
||||
0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
|
||||
0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
|
||||
0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
|
||||
0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
|
||||
0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
|
||||
0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
|
||||
0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
|
||||
0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
|
||||
0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
|
||||
0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
|
||||
0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
|
||||
0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
|
||||
0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
|
||||
0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
|
||||
0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
|
||||
0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
|
||||
0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
|
||||
0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
|
||||
0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
|
||||
0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
|
||||
0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
|
||||
0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
|
||||
0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
|
||||
0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
|
||||
0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
|
||||
0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
|
||||
0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
|
||||
0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
|
||||
0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
|
||||
0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
|
||||
0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
|
||||
0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
|
||||
0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
|
||||
0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
|
||||
0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
|
||||
0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
|
||||
0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
|
||||
0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
|
||||
0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
|
||||
0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
|
||||
0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
|
||||
0x000289C0 SQ_ALU_CONST_CACHE_GS_0
|
||||
0x000289C4 SQ_ALU_CONST_CACHE_GS_1
|
||||
0x000289C8 SQ_ALU_CONST_CACHE_GS_2
|
||||
0x000289CC SQ_ALU_CONST_CACHE_GS_3
|
||||
0x000289D0 SQ_ALU_CONST_CACHE_GS_4
|
||||
0x000289D4 SQ_ALU_CONST_CACHE_GS_5
|
||||
0x000289D8 SQ_ALU_CONST_CACHE_GS_6
|
||||
0x000289DC SQ_ALU_CONST_CACHE_GS_7
|
||||
0x000289E0 SQ_ALU_CONST_CACHE_GS_8
|
||||
0x000289E4 SQ_ALU_CONST_CACHE_GS_9
|
||||
0x000289E8 SQ_ALU_CONST_CACHE_GS_10
|
||||
0x000289EC SQ_ALU_CONST_CACHE_GS_11
|
||||
0x000289F0 SQ_ALU_CONST_CACHE_GS_12
|
||||
0x000289F4 SQ_ALU_CONST_CACHE_GS_13
|
||||
0x000289F8 SQ_ALU_CONST_CACHE_GS_14
|
||||
0x000289FC SQ_ALU_CONST_CACHE_GS_15
|
||||
0x00028940 SQ_ALU_CONST_CACHE_PS_0
|
||||
0x00028944 SQ_ALU_CONST_CACHE_PS_1
|
||||
0x00028948 SQ_ALU_CONST_CACHE_PS_2
|
||||
0x0002894C SQ_ALU_CONST_CACHE_PS_3
|
||||
0x00028950 SQ_ALU_CONST_CACHE_PS_4
|
||||
0x00028954 SQ_ALU_CONST_CACHE_PS_5
|
||||
0x00028958 SQ_ALU_CONST_CACHE_PS_6
|
||||
0x0002895C SQ_ALU_CONST_CACHE_PS_7
|
||||
0x00028960 SQ_ALU_CONST_CACHE_PS_8
|
||||
0x00028964 SQ_ALU_CONST_CACHE_PS_9
|
||||
0x00028968 SQ_ALU_CONST_CACHE_PS_10
|
||||
0x0002896C SQ_ALU_CONST_CACHE_PS_11
|
||||
0x00028970 SQ_ALU_CONST_CACHE_PS_12
|
||||
0x00028974 SQ_ALU_CONST_CACHE_PS_13
|
||||
0x00028978 SQ_ALU_CONST_CACHE_PS_14
|
||||
0x0002897C SQ_ALU_CONST_CACHE_PS_15
|
||||
0x00028980 SQ_ALU_CONST_CACHE_VS_0
|
||||
0x00028984 SQ_ALU_CONST_CACHE_VS_1
|
||||
0x00028988 SQ_ALU_CONST_CACHE_VS_2
|
||||
0x0002898C SQ_ALU_CONST_CACHE_VS_3
|
||||
0x00028990 SQ_ALU_CONST_CACHE_VS_4
|
||||
0x00028994 SQ_ALU_CONST_CACHE_VS_5
|
||||
0x00028998 SQ_ALU_CONST_CACHE_VS_6
|
||||
0x0002899C SQ_ALU_CONST_CACHE_VS_7
|
||||
0x000289A0 SQ_ALU_CONST_CACHE_VS_8
|
||||
0x000289A4 SQ_ALU_CONST_CACHE_VS_9
|
||||
0x000289A8 SQ_ALU_CONST_CACHE_VS_10
|
||||
0x000289AC SQ_ALU_CONST_CACHE_VS_11
|
||||
0x000289B0 SQ_ALU_CONST_CACHE_VS_12
|
||||
0x000289B4 SQ_ALU_CONST_CACHE_VS_13
|
||||
0x000289B8 SQ_ALU_CONST_CACHE_VS_14
|
||||
0x000289BC SQ_ALU_CONST_CACHE_VS_15
|
||||
0x000288D8 SQ_PGM_CF_OFFSET_ES
|
||||
0x000288DC SQ_PGM_CF_OFFSET_FS
|
||||
0x000288D4 SQ_PGM_CF_OFFSET_GS
|
||||
0x000288CC SQ_PGM_CF_OFFSET_PS
|
||||
0x000288D0 SQ_PGM_CF_OFFSET_VS
|
||||
0x00028854 SQ_PGM_EXPORTS_PS
|
||||
0x00028890 SQ_PGM_RESOURCES_ES
|
||||
0x000288A4 SQ_PGM_RESOURCES_FS
|
||||
0x0002887C SQ_PGM_RESOURCES_GS
|
||||
0x00028850 SQ_PGM_RESOURCES_PS
|
||||
0x00028868 SQ_PGM_RESOURCES_VS
|
||||
0x00009100 SPI_CONFIG_CNTL
|
||||
0x0000913C SPI_CONFIG_CNTL_1
|
||||
0x000286DC SPI_FOG_CNTL
|
||||
0x000286E4 SPI_FOG_FUNC_BIAS
|
||||
0x000286E0 SPI_FOG_FUNC_SCALE
|
||||
0x000286D8 SPI_INPUT_Z
|
||||
0x000286D4 SPI_INTERP_CONTROL_0
|
||||
0x00028644 SPI_PS_INPUT_CNTL_0
|
||||
0x00028648 SPI_PS_INPUT_CNTL_1
|
||||
0x0002864C SPI_PS_INPUT_CNTL_2
|
||||
0x00028650 SPI_PS_INPUT_CNTL_3
|
||||
0x00028654 SPI_PS_INPUT_CNTL_4
|
||||
0x00028658 SPI_PS_INPUT_CNTL_5
|
||||
0x0002865C SPI_PS_INPUT_CNTL_6
|
||||
0x00028660 SPI_PS_INPUT_CNTL_7
|
||||
0x00028664 SPI_PS_INPUT_CNTL_8
|
||||
0x00028668 SPI_PS_INPUT_CNTL_9
|
||||
0x0002866C SPI_PS_INPUT_CNTL_10
|
||||
0x00028670 SPI_PS_INPUT_CNTL_11
|
||||
0x00028674 SPI_PS_INPUT_CNTL_12
|
||||
0x00028678 SPI_PS_INPUT_CNTL_13
|
||||
0x0002867C SPI_PS_INPUT_CNTL_14
|
||||
0x00028680 SPI_PS_INPUT_CNTL_15
|
||||
0x00028684 SPI_PS_INPUT_CNTL_16
|
||||
0x00028688 SPI_PS_INPUT_CNTL_17
|
||||
0x0002868C SPI_PS_INPUT_CNTL_18
|
||||
0x00028690 SPI_PS_INPUT_CNTL_19
|
||||
0x00028694 SPI_PS_INPUT_CNTL_20
|
||||
0x00028698 SPI_PS_INPUT_CNTL_21
|
||||
0x0002869C SPI_PS_INPUT_CNTL_22
|
||||
0x000286A0 SPI_PS_INPUT_CNTL_23
|
||||
0x000286A4 SPI_PS_INPUT_CNTL_24
|
||||
0x000286A8 SPI_PS_INPUT_CNTL_25
|
||||
0x000286AC SPI_PS_INPUT_CNTL_26
|
||||
0x000286B0 SPI_PS_INPUT_CNTL_27
|
||||
0x000286B4 SPI_PS_INPUT_CNTL_28
|
||||
0x000286B8 SPI_PS_INPUT_CNTL_29
|
||||
0x000286BC SPI_PS_INPUT_CNTL_30
|
||||
0x000286C0 SPI_PS_INPUT_CNTL_31
|
||||
0x000286CC SPI_PS_IN_CONTROL_0
|
||||
0x000286D0 SPI_PS_IN_CONTROL_1
|
||||
0x000286C4 SPI_VS_OUT_CONFIG
|
||||
0x00028614 SPI_VS_OUT_ID_0
|
||||
0x00028618 SPI_VS_OUT_ID_1
|
||||
0x0002861C SPI_VS_OUT_ID_2
|
||||
0x00028620 SPI_VS_OUT_ID_3
|
||||
0x00028624 SPI_VS_OUT_ID_4
|
||||
0x00028628 SPI_VS_OUT_ID_5
|
||||
0x0002862C SPI_VS_OUT_ID_6
|
||||
0x00028630 SPI_VS_OUT_ID_7
|
||||
0x00028634 SPI_VS_OUT_ID_8
|
||||
0x00028638 SPI_VS_OUT_ID_9
|
||||
0x00028438 SX_ALPHA_REF
|
||||
0x00028410 SX_ALPHA_TEST_CONTROL
|
||||
0x00028350 SX_MISC
|
||||
0x0000A020 SMX_DC_CTL0
|
||||
0x0000A024 SMX_DC_CTL1
|
||||
0x0000A028 SMX_DC_CTL2
|
||||
0x00009608 TC_CNTL
|
||||
0x00009604 TC_INVALIDATE
|
||||
0x00009490 TD_CNTL
|
||||
0x00009400 TD_FILTER4
|
||||
0x00009404 TD_FILTER4_1
|
||||
0x00009408 TD_FILTER4_2
|
||||
0x0000940C TD_FILTER4_3
|
||||
0x00009410 TD_FILTER4_4
|
||||
0x00009414 TD_FILTER4_5
|
||||
0x00009418 TD_FILTER4_6
|
||||
0x0000941C TD_FILTER4_7
|
||||
0x00009420 TD_FILTER4_8
|
||||
0x00009424 TD_FILTER4_9
|
||||
0x00009428 TD_FILTER4_10
|
||||
0x0000942C TD_FILTER4_11
|
||||
0x00009430 TD_FILTER4_12
|
||||
0x00009434 TD_FILTER4_13
|
||||
0x00009438 TD_FILTER4_14
|
||||
0x0000943C TD_FILTER4_15
|
||||
0x00009440 TD_FILTER4_16
|
||||
0x00009444 TD_FILTER4_17
|
||||
0x00009448 TD_FILTER4_18
|
||||
0x0000944C TD_FILTER4_19
|
||||
0x00009450 TD_FILTER4_20
|
||||
0x00009454 TD_FILTER4_21
|
||||
0x00009458 TD_FILTER4_22
|
||||
0x0000945C TD_FILTER4_23
|
||||
0x00009460 TD_FILTER4_24
|
||||
0x00009464 TD_FILTER4_25
|
||||
0x00009468 TD_FILTER4_26
|
||||
0x0000946C TD_FILTER4_27
|
||||
0x00009470 TD_FILTER4_28
|
||||
0x00009474 TD_FILTER4_29
|
||||
0x00009478 TD_FILTER4_30
|
||||
0x0000947C TD_FILTER4_31
|
||||
0x00009480 TD_FILTER4_32
|
||||
0x00009484 TD_FILTER4_33
|
||||
0x00009488 TD_FILTER4_34
|
||||
0x0000948C TD_FILTER4_35
|
||||
0x0000A80C TD_GS_SAMPLER0_BORDER_ALPHA
|
||||
0x0000A81C TD_GS_SAMPLER1_BORDER_ALPHA
|
||||
0x0000A82C TD_GS_SAMPLER2_BORDER_ALPHA
|
||||
0x0000A83C TD_GS_SAMPLER3_BORDER_ALPHA
|
||||
0x0000A84C TD_GS_SAMPLER4_BORDER_ALPHA
|
||||
0x0000A85C TD_GS_SAMPLER5_BORDER_ALPHA
|
||||
0x0000A86C TD_GS_SAMPLER6_BORDER_ALPHA
|
||||
0x0000A87C TD_GS_SAMPLER7_BORDER_ALPHA
|
||||
0x0000A88C TD_GS_SAMPLER8_BORDER_ALPHA
|
||||
0x0000A89C TD_GS_SAMPLER9_BORDER_ALPHA
|
||||
0x0000A8AC TD_GS_SAMPLER10_BORDER_ALPHA
|
||||
0x0000A8BC TD_GS_SAMPLER11_BORDER_ALPHA
|
||||
0x0000A8CC TD_GS_SAMPLER12_BORDER_ALPHA
|
||||
0x0000A8DC TD_GS_SAMPLER13_BORDER_ALPHA
|
||||
0x0000A8EC TD_GS_SAMPLER14_BORDER_ALPHA
|
||||
0x0000A8FC TD_GS_SAMPLER15_BORDER_ALPHA
|
||||
0x0000A90C TD_GS_SAMPLER16_BORDER_ALPHA
|
||||
0x0000A91C TD_GS_SAMPLER17_BORDER_ALPHA
|
||||
0x0000A808 TD_GS_SAMPLER0_BORDER_BLUE
|
||||
0x0000A818 TD_GS_SAMPLER1_BORDER_BLUE
|
||||
0x0000A828 TD_GS_SAMPLER2_BORDER_BLUE
|
||||
0x0000A838 TD_GS_SAMPLER3_BORDER_BLUE
|
||||
0x0000A848 TD_GS_SAMPLER4_BORDER_BLUE
|
||||
0x0000A858 TD_GS_SAMPLER5_BORDER_BLUE
|
||||
0x0000A868 TD_GS_SAMPLER6_BORDER_BLUE
|
||||
0x0000A878 TD_GS_SAMPLER7_BORDER_BLUE
|
||||
0x0000A888 TD_GS_SAMPLER8_BORDER_BLUE
|
||||
0x0000A898 TD_GS_SAMPLER9_BORDER_BLUE
|
||||
0x0000A8A8 TD_GS_SAMPLER10_BORDER_BLUE
|
||||
0x0000A8B8 TD_GS_SAMPLER11_BORDER_BLUE
|
||||
0x0000A8C8 TD_GS_SAMPLER12_BORDER_BLUE
|
||||
0x0000A8D8 TD_GS_SAMPLER13_BORDER_BLUE
|
||||
0x0000A8E8 TD_GS_SAMPLER14_BORDER_BLUE
|
||||
0x0000A8F8 TD_GS_SAMPLER15_BORDER_BLUE
|
||||
0x0000A908 TD_GS_SAMPLER16_BORDER_BLUE
|
||||
0x0000A918 TD_GS_SAMPLER17_BORDER_BLUE
|
||||
0x0000A804 TD_GS_SAMPLER0_BORDER_GREEN
|
||||
0x0000A814 TD_GS_SAMPLER1_BORDER_GREEN
|
||||
0x0000A824 TD_GS_SAMPLER2_BORDER_GREEN
|
||||
0x0000A834 TD_GS_SAMPLER3_BORDER_GREEN
|
||||
0x0000A844 TD_GS_SAMPLER4_BORDER_GREEN
|
||||
0x0000A854 TD_GS_SAMPLER5_BORDER_GREEN
|
||||
0x0000A864 TD_GS_SAMPLER6_BORDER_GREEN
|
||||
0x0000A874 TD_GS_SAMPLER7_BORDER_GREEN
|
||||
0x0000A884 TD_GS_SAMPLER8_BORDER_GREEN
|
||||
0x0000A894 TD_GS_SAMPLER9_BORDER_GREEN
|
||||
0x0000A8A4 TD_GS_SAMPLER10_BORDER_GREEN
|
||||
0x0000A8B4 TD_GS_SAMPLER11_BORDER_GREEN
|
||||
0x0000A8C4 TD_GS_SAMPLER12_BORDER_GREEN
|
||||
0x0000A8D4 TD_GS_SAMPLER13_BORDER_GREEN
|
||||
0x0000A8E4 TD_GS_SAMPLER14_BORDER_GREEN
|
||||
0x0000A8F4 TD_GS_SAMPLER15_BORDER_GREEN
|
||||
0x0000A904 TD_GS_SAMPLER16_BORDER_GREEN
|
||||
0x0000A914 TD_GS_SAMPLER17_BORDER_GREEN
|
||||
0x0000A800 TD_GS_SAMPLER0_BORDER_RED
|
||||
0x0000A810 TD_GS_SAMPLER1_BORDER_RED
|
||||
0x0000A820 TD_GS_SAMPLER2_BORDER_RED
|
||||
0x0000A830 TD_GS_SAMPLER3_BORDER_RED
|
||||
0x0000A840 TD_GS_SAMPLER4_BORDER_RED
|
||||
0x0000A850 TD_GS_SAMPLER5_BORDER_RED
|
||||
0x0000A860 TD_GS_SAMPLER6_BORDER_RED
|
||||
0x0000A870 TD_GS_SAMPLER7_BORDER_RED
|
||||
0x0000A880 TD_GS_SAMPLER8_BORDER_RED
|
||||
0x0000A890 TD_GS_SAMPLER9_BORDER_RED
|
||||
0x0000A8A0 TD_GS_SAMPLER10_BORDER_RED
|
||||
0x0000A8B0 TD_GS_SAMPLER11_BORDER_RED
|
||||
0x0000A8C0 TD_GS_SAMPLER12_BORDER_RED
|
||||
0x0000A8D0 TD_GS_SAMPLER13_BORDER_RED
|
||||
0x0000A8E0 TD_GS_SAMPLER14_BORDER_RED
|
||||
0x0000A8F0 TD_GS_SAMPLER15_BORDER_RED
|
||||
0x0000A900 TD_GS_SAMPLER16_BORDER_RED
|
||||
0x0000A910 TD_GS_SAMPLER17_BORDER_RED
|
||||
0x0000A40C TD_PS_SAMPLER0_BORDER_ALPHA
|
||||
0x0000A41C TD_PS_SAMPLER1_BORDER_ALPHA
|
||||
0x0000A42C TD_PS_SAMPLER2_BORDER_ALPHA
|
||||
0x0000A43C TD_PS_SAMPLER3_BORDER_ALPHA
|
||||
0x0000A44C TD_PS_SAMPLER4_BORDER_ALPHA
|
||||
0x0000A45C TD_PS_SAMPLER5_BORDER_ALPHA
|
||||
0x0000A46C TD_PS_SAMPLER6_BORDER_ALPHA
|
||||
0x0000A47C TD_PS_SAMPLER7_BORDER_ALPHA
|
||||
0x0000A48C TD_PS_SAMPLER8_BORDER_ALPHA
|
||||
0x0000A49C TD_PS_SAMPLER9_BORDER_ALPHA
|
||||
0x0000A4AC TD_PS_SAMPLER10_BORDER_ALPHA
|
||||
0x0000A4BC TD_PS_SAMPLER11_BORDER_ALPHA
|
||||
0x0000A4CC TD_PS_SAMPLER12_BORDER_ALPHA
|
||||
0x0000A4DC TD_PS_SAMPLER13_BORDER_ALPHA
|
||||
0x0000A4EC TD_PS_SAMPLER14_BORDER_ALPHA
|
||||
0x0000A4FC TD_PS_SAMPLER15_BORDER_ALPHA
|
||||
0x0000A50C TD_PS_SAMPLER16_BORDER_ALPHA
|
||||
0x0000A51C TD_PS_SAMPLER17_BORDER_ALPHA
|
||||
0x0000A408 TD_PS_SAMPLER0_BORDER_BLUE
|
||||
0x0000A418 TD_PS_SAMPLER1_BORDER_BLUE
|
||||
0x0000A428 TD_PS_SAMPLER2_BORDER_BLUE
|
||||
0x0000A438 TD_PS_SAMPLER3_BORDER_BLUE
|
||||
0x0000A448 TD_PS_SAMPLER4_BORDER_BLUE
|
||||
0x0000A458 TD_PS_SAMPLER5_BORDER_BLUE
|
||||
0x0000A468 TD_PS_SAMPLER6_BORDER_BLUE
|
||||
0x0000A478 TD_PS_SAMPLER7_BORDER_BLUE
|
||||
0x0000A488 TD_PS_SAMPLER8_BORDER_BLUE
|
||||
0x0000A498 TD_PS_SAMPLER9_BORDER_BLUE
|
||||
0x0000A4A8 TD_PS_SAMPLER10_BORDER_BLUE
|
||||
0x0000A4B8 TD_PS_SAMPLER11_BORDER_BLUE
|
||||
0x0000A4C8 TD_PS_SAMPLER12_BORDER_BLUE
|
||||
0x0000A4D8 TD_PS_SAMPLER13_BORDER_BLUE
|
||||
0x0000A4E8 TD_PS_SAMPLER14_BORDER_BLUE
|
||||
0x0000A4F8 TD_PS_SAMPLER15_BORDER_BLUE
|
||||
0x0000A508 TD_PS_SAMPLER16_BORDER_BLUE
|
||||
0x0000A518 TD_PS_SAMPLER17_BORDER_BLUE
|
||||
0x0000A404 TD_PS_SAMPLER0_BORDER_GREEN
|
||||
0x0000A414 TD_PS_SAMPLER1_BORDER_GREEN
|
||||
0x0000A424 TD_PS_SAMPLER2_BORDER_GREEN
|
||||
0x0000A434 TD_PS_SAMPLER3_BORDER_GREEN
|
||||
0x0000A444 TD_PS_SAMPLER4_BORDER_GREEN
|
||||
0x0000A454 TD_PS_SAMPLER5_BORDER_GREEN
|
||||
0x0000A464 TD_PS_SAMPLER6_BORDER_GREEN
|
||||
0x0000A474 TD_PS_SAMPLER7_BORDER_GREEN
|
||||
0x0000A484 TD_PS_SAMPLER8_BORDER_GREEN
|
||||
0x0000A494 TD_PS_SAMPLER9_BORDER_GREEN
|
||||
0x0000A4A4 TD_PS_SAMPLER10_BORDER_GREEN
|
||||
0x0000A4B4 TD_PS_SAMPLER11_BORDER_GREEN
|
||||
0x0000A4C4 TD_PS_SAMPLER12_BORDER_GREEN
|
||||
0x0000A4D4 TD_PS_SAMPLER13_BORDER_GREEN
|
||||
0x0000A4E4 TD_PS_SAMPLER14_BORDER_GREEN
|
||||
0x0000A4F4 TD_PS_SAMPLER15_BORDER_GREEN
|
||||
0x0000A504 TD_PS_SAMPLER16_BORDER_GREEN
|
||||
0x0000A514 TD_PS_SAMPLER17_BORDER_GREEN
|
||||
0x0000A400 TD_PS_SAMPLER0_BORDER_RED
|
||||
0x0000A410 TD_PS_SAMPLER1_BORDER_RED
|
||||
0x0000A420 TD_PS_SAMPLER2_BORDER_RED
|
||||
0x0000A430 TD_PS_SAMPLER3_BORDER_RED
|
||||
0x0000A440 TD_PS_SAMPLER4_BORDER_RED
|
||||
0x0000A450 TD_PS_SAMPLER5_BORDER_RED
|
||||
0x0000A460 TD_PS_SAMPLER6_BORDER_RED
|
||||
0x0000A470 TD_PS_SAMPLER7_BORDER_RED
|
||||
0x0000A480 TD_PS_SAMPLER8_BORDER_RED
|
||||
0x0000A490 TD_PS_SAMPLER9_BORDER_RED
|
||||
0x0000A4A0 TD_PS_SAMPLER10_BORDER_RED
|
||||
0x0000A4B0 TD_PS_SAMPLER11_BORDER_RED
|
||||
0x0000A4C0 TD_PS_SAMPLER12_BORDER_RED
|
||||
0x0000A4D0 TD_PS_SAMPLER13_BORDER_RED
|
||||
0x0000A4E0 TD_PS_SAMPLER14_BORDER_RED
|
||||
0x0000A4F0 TD_PS_SAMPLER15_BORDER_RED
|
||||
0x0000A500 TD_PS_SAMPLER16_BORDER_RED
|
||||
0x0000A510 TD_PS_SAMPLER17_BORDER_RED
|
||||
0x0000AA00 TD_PS_SAMPLER0_CLEARTYPE_KERNEL
|
||||
0x0000AA04 TD_PS_SAMPLER1_CLEARTYPE_KERNEL
|
||||
0x0000AA08 TD_PS_SAMPLER2_CLEARTYPE_KERNEL
|
||||
0x0000AA0C TD_PS_SAMPLER3_CLEARTYPE_KERNEL
|
||||
0x0000AA10 TD_PS_SAMPLER4_CLEARTYPE_KERNEL
|
||||
0x0000AA14 TD_PS_SAMPLER5_CLEARTYPE_KERNEL
|
||||
0x0000AA18 TD_PS_SAMPLER6_CLEARTYPE_KERNEL
|
||||
0x0000AA1C TD_PS_SAMPLER7_CLEARTYPE_KERNEL
|
||||
0x0000AA20 TD_PS_SAMPLER8_CLEARTYPE_KERNEL
|
||||
0x0000AA24 TD_PS_SAMPLER9_CLEARTYPE_KERNEL
|
||||
0x0000AA28 TD_PS_SAMPLER10_CLEARTYPE_KERNEL
|
||||
0x0000AA2C TD_PS_SAMPLER11_CLEARTYPE_KERNEL
|
||||
0x0000AA30 TD_PS_SAMPLER12_CLEARTYPE_KERNEL
|
||||
0x0000AA34 TD_PS_SAMPLER13_CLEARTYPE_KERNEL
|
||||
0x0000AA38 TD_PS_SAMPLER14_CLEARTYPE_KERNEL
|
||||
0x0000AA3C TD_PS_SAMPLER15_CLEARTYPE_KERNEL
|
||||
0x0000AA40 TD_PS_SAMPLER16_CLEARTYPE_KERNEL
|
||||
0x0000AA44 TD_PS_SAMPLER17_CLEARTYPE_KERNEL
|
||||
0x0000A60C TD_VS_SAMPLER0_BORDER_ALPHA
|
||||
0x0000A61C TD_VS_SAMPLER1_BORDER_ALPHA
|
||||
0x0000A62C TD_VS_SAMPLER2_BORDER_ALPHA
|
||||
0x0000A63C TD_VS_SAMPLER3_BORDER_ALPHA
|
||||
0x0000A64C TD_VS_SAMPLER4_BORDER_ALPHA
|
||||
0x0000A65C TD_VS_SAMPLER5_BORDER_ALPHA
|
||||
0x0000A66C TD_VS_SAMPLER6_BORDER_ALPHA
|
||||
0x0000A67C TD_VS_SAMPLER7_BORDER_ALPHA
|
||||
0x0000A68C TD_VS_SAMPLER8_BORDER_ALPHA
|
||||
0x0000A69C TD_VS_SAMPLER9_BORDER_ALPHA
|
||||
0x0000A6AC TD_VS_SAMPLER10_BORDER_ALPHA
|
||||
0x0000A6BC TD_VS_SAMPLER11_BORDER_ALPHA
|
||||
0x0000A6CC TD_VS_SAMPLER12_BORDER_ALPHA
|
||||
0x0000A6DC TD_VS_SAMPLER13_BORDER_ALPHA
|
||||
0x0000A6EC TD_VS_SAMPLER14_BORDER_ALPHA
|
||||
0x0000A6FC TD_VS_SAMPLER15_BORDER_ALPHA
|
||||
0x0000A70C TD_VS_SAMPLER16_BORDER_ALPHA
|
||||
0x0000A71C TD_VS_SAMPLER17_BORDER_ALPHA
|
||||
0x0000A608 TD_VS_SAMPLER0_BORDER_BLUE
|
||||
0x0000A618 TD_VS_SAMPLER1_BORDER_BLUE
|
||||
0x0000A628 TD_VS_SAMPLER2_BORDER_BLUE
|
||||
0x0000A638 TD_VS_SAMPLER3_BORDER_BLUE
|
||||
0x0000A648 TD_VS_SAMPLER4_BORDER_BLUE
|
||||
0x0000A658 TD_VS_SAMPLER5_BORDER_BLUE
|
||||
0x0000A668 TD_VS_SAMPLER6_BORDER_BLUE
|
||||
0x0000A678 TD_VS_SAMPLER7_BORDER_BLUE
|
||||
0x0000A688 TD_VS_SAMPLER8_BORDER_BLUE
|
||||
0x0000A698 TD_VS_SAMPLER9_BORDER_BLUE
|
||||
0x0000A6A8 TD_VS_SAMPLER10_BORDER_BLUE
|
||||
0x0000A6B8 TD_VS_SAMPLER11_BORDER_BLUE
|
||||
0x0000A6C8 TD_VS_SAMPLER12_BORDER_BLUE
|
||||
0x0000A6D8 TD_VS_SAMPLER13_BORDER_BLUE
|
||||
0x0000A6E8 TD_VS_SAMPLER14_BORDER_BLUE
|
||||
0x0000A6F8 TD_VS_SAMPLER15_BORDER_BLUE
|
||||
0x0000A708 TD_VS_SAMPLER16_BORDER_BLUE
|
||||
0x0000A718 TD_VS_SAMPLER17_BORDER_BLUE
|
||||
0x0000A604 TD_VS_SAMPLER0_BORDER_GREEN
|
||||
0x0000A614 TD_VS_SAMPLER1_BORDER_GREEN
|
||||
0x0000A624 TD_VS_SAMPLER2_BORDER_GREEN
|
||||
0x0000A634 TD_VS_SAMPLER3_BORDER_GREEN
|
||||
0x0000A644 TD_VS_SAMPLER4_BORDER_GREEN
|
||||
0x0000A654 TD_VS_SAMPLER5_BORDER_GREEN
|
||||
0x0000A664 TD_VS_SAMPLER6_BORDER_GREEN
|
||||
0x0000A674 TD_VS_SAMPLER7_BORDER_GREEN
|
||||
0x0000A684 TD_VS_SAMPLER8_BORDER_GREEN
|
||||
0x0000A694 TD_VS_SAMPLER9_BORDER_GREEN
|
||||
0x0000A6A4 TD_VS_SAMPLER10_BORDER_GREEN
|
||||
0x0000A6B4 TD_VS_SAMPLER11_BORDER_GREEN
|
||||
0x0000A6C4 TD_VS_SAMPLER12_BORDER_GREEN
|
||||
0x0000A6D4 TD_VS_SAMPLER13_BORDER_GREEN
|
||||
0x0000A6E4 TD_VS_SAMPLER14_BORDER_GREEN
|
||||
0x0000A6F4 TD_VS_SAMPLER15_BORDER_GREEN
|
||||
0x0000A704 TD_VS_SAMPLER16_BORDER_GREEN
|
||||
0x0000A714 TD_VS_SAMPLER17_BORDER_GREEN
|
||||
0x0000A600 TD_VS_SAMPLER0_BORDER_RED
|
||||
0x0000A610 TD_VS_SAMPLER1_BORDER_RED
|
||||
0x0000A620 TD_VS_SAMPLER2_BORDER_RED
|
||||
0x0000A630 TD_VS_SAMPLER3_BORDER_RED
|
||||
0x0000A640 TD_VS_SAMPLER4_BORDER_RED
|
||||
0x0000A650 TD_VS_SAMPLER5_BORDER_RED
|
||||
0x0000A660 TD_VS_SAMPLER6_BORDER_RED
|
||||
0x0000A670 TD_VS_SAMPLER7_BORDER_RED
|
||||
0x0000A680 TD_VS_SAMPLER8_BORDER_RED
|
||||
0x0000A690 TD_VS_SAMPLER9_BORDER_RED
|
||||
0x0000A6A0 TD_VS_SAMPLER10_BORDER_RED
|
||||
0x0000A6B0 TD_VS_SAMPLER11_BORDER_RED
|
||||
0x0000A6C0 TD_VS_SAMPLER12_BORDER_RED
|
||||
0x0000A6D0 TD_VS_SAMPLER13_BORDER_RED
|
||||
0x0000A6E0 TD_VS_SAMPLER14_BORDER_RED
|
||||
0x0000A6F0 TD_VS_SAMPLER15_BORDER_RED
|
||||
0x0000A700 TD_VS_SAMPLER16_BORDER_RED
|
||||
0x0000A710 TD_VS_SAMPLER17_BORDER_RED
|
||||
0x00009508 TA_CNTL_AUX
|
||||
0x0002802C DB_DEPTH_CLEAR
|
||||
0x00028D24 DB_HTILE_SURFACE
|
||||
0x00028D34 DB_PREFETCH_LIMIT
|
||||
0x00028D30 DB_PRELOAD_CONTROL
|
||||
0x00028D0C DB_RENDER_CONTROL
|
||||
0x00028D10 DB_RENDER_OVERRIDE
|
||||
0x0002880C DB_SHADER_CONTROL
|
||||
0x00028D2C DB_SRESULTS_COMPARE_STATE1
|
||||
0x00028430 DB_STENCILREFMASK
|
||||
0x00028434 DB_STENCILREFMASK_BF
|
||||
0x00028028 DB_STENCIL_CLEAR
|
||||
0x00028780 CB_BLEND0_CONTROL
|
||||
0x00028784 CB_BLEND1_CONTROL
|
||||
0x00028788 CB_BLEND2_CONTROL
|
||||
0x0002878C CB_BLEND3_CONTROL
|
||||
0x00028790 CB_BLEND4_CONTROL
|
||||
0x00028794 CB_BLEND5_CONTROL
|
||||
0x00028798 CB_BLEND6_CONTROL
|
||||
0x0002879C CB_BLEND7_CONTROL
|
||||
0x00028804 CB_BLEND_CONTROL
|
||||
0x00028420 CB_BLEND_ALPHA
|
||||
0x0002841C CB_BLEND_BLUE
|
||||
0x00028418 CB_BLEND_GREEN
|
||||
0x00028414 CB_BLEND_RED
|
||||
0x0002812C CB_CLEAR_ALPHA
|
||||
0x00028128 CB_CLEAR_BLUE
|
||||
0x00028124 CB_CLEAR_GREEN
|
||||
0x00028120 CB_CLEAR_RED
|
||||
0x00028C30 CB_CLRCMP_CONTROL
|
||||
0x00028C38 CB_CLRCMP_DST
|
||||
0x00028C3C CB_CLRCMP_MSK
|
||||
0x00028C34 CB_CLRCMP_SRC
|
||||
0x00028100 CB_COLOR0_MASK
|
||||
0x00028104 CB_COLOR1_MASK
|
||||
0x00028108 CB_COLOR2_MASK
|
||||
0x0002810C CB_COLOR3_MASK
|
||||
0x00028110 CB_COLOR4_MASK
|
||||
0x00028114 CB_COLOR5_MASK
|
||||
0x00028118 CB_COLOR6_MASK
|
||||
0x0002811C CB_COLOR7_MASK
|
||||
0x00028080 CB_COLOR0_VIEW
|
||||
0x00028084 CB_COLOR1_VIEW
|
||||
0x00028088 CB_COLOR2_VIEW
|
||||
0x0002808C CB_COLOR3_VIEW
|
||||
0x00028090 CB_COLOR4_VIEW
|
||||
0x00028094 CB_COLOR5_VIEW
|
||||
0x00028098 CB_COLOR6_VIEW
|
||||
0x0002809C CB_COLOR7_VIEW
|
||||
0x00028808 CB_COLOR_CONTROL
|
||||
0x0002842C CB_FOG_BLUE
|
||||
0x00028428 CB_FOG_GREEN
|
||||
0x00028424 CB_FOG_RED
|
||||
0x00008040 WAIT_UNTIL
|
||||
0x00008950 CC_GC_SHADER_PIPE_CONFIG
|
||||
0x00008954 GC_USER_SHADER_PIPE_CONFIG
|
||||
0x00009714 VC_ENHANCE
|
||||
0x00009830 DB_DEBUG
|
||||
0x00009838 DB_WATERMARKS
|
||||
0x00028D28 DB_SRESULTS_COMPARE_STATE0
|
||||
0x00028D44 DB_ALPHA_TO_MASK
|
||||
0x00009504 TA_CNTL
|
||||
0x00009700 VC_CNTL
|
||||
0x00009718 VC_CONFIG
|
||||
0x0000A02C SMX_DC_MC_INTF_CTL
|
|
@ -113,6 +113,7 @@ int rs400_gart_enable(struct radeon_device *rdev)
|
|||
uint32_t size_reg;
|
||||
uint32_t tmp;
|
||||
|
||||
radeon_gart_restore(rdev);
|
||||
tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
|
||||
tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
|
||||
WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
|
||||
|
@ -150,9 +151,8 @@ int rs400_gart_enable(struct radeon_device *rdev)
|
|||
WREG32(RADEON_AGP_BASE, 0xFFFFFFFF);
|
||||
WREG32(RS480_AGP_BASE_2, 0);
|
||||
}
|
||||
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
|
||||
tmp = REG_SET(RS690_MC_AGP_TOP, tmp >> 16);
|
||||
tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_location >> 16);
|
||||
tmp = REG_SET(RS690_MC_AGP_TOP, rdev->mc.gtt_end >> 16);
|
||||
tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_start >> 16);
|
||||
if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) {
|
||||
WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp);
|
||||
tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
|
||||
|
@ -251,14 +251,19 @@ void rs400_gpu_init(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
|
||||
void rs400_vram_info(struct radeon_device *rdev)
|
||||
void rs400_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
u64 base;
|
||||
|
||||
rs400_gart_adjust_size(rdev);
|
||||
rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
|
||||
/* DDR for all card after R300 & IGP */
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
rdev->mc.vram_width = 128;
|
||||
|
||||
r100_vram_init_sizes(rdev);
|
||||
base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
}
|
||||
|
||||
uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
|
||||
|
@ -362,22 +367,6 @@ static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int rs400_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
u32 tmp;
|
||||
|
||||
/* Setup GPU memory space */
|
||||
tmp = RREG32(R_00015C_NB_TOM);
|
||||
rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16;
|
||||
rdev->mc.gtt_location = 0xFFFFFFFFUL;
|
||||
r = radeon_mc_setup(rdev);
|
||||
rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rs400_mc_program(struct radeon_device *rdev)
|
||||
{
|
||||
struct r100_mc_save save;
|
||||
|
@ -516,12 +505,8 @@ int rs400_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
rs400_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = rs400_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize memory controller */
|
||||
rs400_mc_init(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
|
|
|
@ -45,23 +45,6 @@
|
|||
void rs600_gpu_init(struct radeon_device *rdev);
|
||||
int rs600_mc_wait_for_idle(struct radeon_device *rdev);
|
||||
|
||||
int rs600_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
/* read back the MC value from the hw */
|
||||
int r;
|
||||
u32 tmp;
|
||||
|
||||
/* Setup GPU memory space */
|
||||
tmp = RREG32_MC(R_000004_MC_FB_LOCATION);
|
||||
rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16;
|
||||
rdev->mc.gtt_location = 0xffffffffUL;
|
||||
r = radeon_mc_setup(rdev);
|
||||
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hpd for digital panel detect/disconnect */
|
||||
bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
|
||||
{
|
||||
|
@ -213,6 +196,7 @@ int rs600_gart_enable(struct radeon_device *rdev)
|
|||
r = radeon_gart_table_vram_pin(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
radeon_gart_restore(rdev);
|
||||
/* Enable bus master */
|
||||
tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS;
|
||||
WREG32(R_00004C_BUS_CNTL, tmp);
|
||||
|
@ -406,10 +390,14 @@ int rs600_irq_process(struct radeon_device *rdev)
|
|||
if (G_000044_SW_INT(status))
|
||||
radeon_fence_process(rdev);
|
||||
/* Vertical blank interrupts */
|
||||
if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int))
|
||||
if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) {
|
||||
drm_handle_vblank(rdev->ddev, 0);
|
||||
if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int))
|
||||
wake_up(&rdev->irq.vblank_queue);
|
||||
}
|
||||
if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) {
|
||||
drm_handle_vblank(rdev->ddev, 1);
|
||||
wake_up(&rdev->irq.vblank_queue);
|
||||
}
|
||||
if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("HPD1\n");
|
||||
|
@ -470,22 +458,22 @@ void rs600_gpu_init(struct radeon_device *rdev)
|
|||
dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
|
||||
}
|
||||
|
||||
void rs600_vram_info(struct radeon_device *rdev)
|
||||
void rs600_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
rdev->mc.vram_width = 128;
|
||||
|
||||
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
|
||||
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
|
||||
u64 base;
|
||||
|
||||
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
|
||||
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
|
||||
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.mc_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
rdev->mc.vram_width = 128;
|
||||
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
|
||||
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
|
||||
rdev->mc.visible_vram_size = rdev->mc.aper_size;
|
||||
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
|
||||
base = RREG32_MC(R_000004_MC_FB_LOCATION);
|
||||
base = G_000004_MC_FB_START(base) << 16;
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
}
|
||||
|
||||
void rs600_bandwidth_update(struct radeon_device *rdev)
|
||||
|
@ -661,12 +649,8 @@ int rs600_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
rs600_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = rs600_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize memory controller */
|
||||
rs600_mc_init(rdev);
|
||||
rs600_debugfs(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
|
|
|
@ -129,27 +129,21 @@ void rs690_pm_info(struct radeon_device *rdev)
|
|||
rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp);
|
||||
}
|
||||
|
||||
void rs690_vram_info(struct radeon_device *rdev)
|
||||
void rs690_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
fixed20_12 a;
|
||||
u64 base;
|
||||
|
||||
rs400_gart_adjust_size(rdev);
|
||||
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
rdev->mc.vram_width = 128;
|
||||
|
||||
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
|
||||
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
|
||||
|
||||
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
|
||||
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
|
||||
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.mc_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
|
||||
rdev->mc.visible_vram_size = rdev->mc.aper_size;
|
||||
base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
|
||||
base = G_000100_MC_FB_START(base) << 16;
|
||||
rs690_pm_info(rdev);
|
||||
/* FIXME: we should enforce default clock in case GPU is not in
|
||||
* default setup
|
||||
|
@ -160,22 +154,9 @@ void rs690_vram_info(struct radeon_device *rdev)
|
|||
a.full = rfixed_const(16);
|
||||
/* core_bandwidth = sclk(Mhz) * 16 */
|
||||
rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
|
||||
}
|
||||
|
||||
static int rs690_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
u32 tmp;
|
||||
|
||||
/* Setup GPU memory space */
|
||||
tmp = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
|
||||
rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16;
|
||||
rdev->mc.gtt_location = 0xFFFFFFFFUL;
|
||||
r = radeon_mc_setup(rdev);
|
||||
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
radeon_vram_location(rdev, &rdev->mc, base);
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
}
|
||||
|
||||
void rs690_line_buffer_adjust(struct radeon_device *rdev,
|
||||
|
@ -728,12 +709,8 @@ int rs690_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
rs690_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = rs690_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize memory controller */
|
||||
rs690_mc_init(rdev);
|
||||
rv515_debugfs(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
|
|
|
@ -277,13 +277,15 @@ static void rv515_vram_get_type(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
|
||||
void rv515_vram_info(struct radeon_device *rdev)
|
||||
void rv515_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
fixed20_12 a;
|
||||
|
||||
rv515_vram_get_type(rdev);
|
||||
|
||||
r100_vram_init_sizes(rdev);
|
||||
radeon_vram_location(rdev, &rdev->mc, 0);
|
||||
if (!(rdev->flags & RADEON_IS_AGP))
|
||||
radeon_gtt_location(rdev, &rdev->mc);
|
||||
/* FIXME: we should enforce default clock in case GPU is not in
|
||||
* default setup
|
||||
*/
|
||||
|
@ -587,12 +589,15 @@ int rv515_init(struct radeon_device *rdev)
|
|||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Initialize power management */
|
||||
radeon_pm_init(rdev);
|
||||
/* Get vram informations */
|
||||
rv515_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = r420_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
}
|
||||
/* initialize memory controller */
|
||||
rv515_mc_init(rdev);
|
||||
rv515_debugfs(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
|
|
|
@ -56,6 +56,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
|
|||
r = radeon_gart_table_vram_pin(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
radeon_gart_restore(rdev);
|
||||
/* Setup L2 cache */
|
||||
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
|
||||
ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
|
||||
|
@ -273,9 +274,10 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev)
|
|||
/*
|
||||
* Core functions
|
||||
*/
|
||||
static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
||||
u32 num_backends,
|
||||
u32 backend_disable_mask)
|
||||
static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
|
||||
u32 num_tile_pipes,
|
||||
u32 num_backends,
|
||||
u32 backend_disable_mask)
|
||||
{
|
||||
u32 backend_map = 0;
|
||||
u32 enabled_backends_mask;
|
||||
|
@ -284,6 +286,7 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
u32 swizzle_pipe[R7XX_MAX_PIPES];
|
||||
u32 cur_backend;
|
||||
u32 i;
|
||||
bool force_no_swizzle;
|
||||
|
||||
if (num_tile_pipes > R7XX_MAX_PIPES)
|
||||
num_tile_pipes = R7XX_MAX_PIPES;
|
||||
|
@ -313,6 +316,18 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
if (enabled_backends_count != num_backends)
|
||||
num_backends = enabled_backends_count;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
force_no_swizzle = false;
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
default:
|
||||
force_no_swizzle = true;
|
||||
break;
|
||||
}
|
||||
|
||||
memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
|
||||
switch (num_tile_pipes) {
|
||||
case 1:
|
||||
|
@ -323,49 +338,100 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
swizzle_pipe[1] = 1;
|
||||
break;
|
||||
case 3:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 1;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 3;
|
||||
swizzle_pipe[3] = 1;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 3;
|
||||
swizzle_pipe[3] = 1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 1;
|
||||
swizzle_pipe[4] = 3;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 1;
|
||||
swizzle_pipe[4] = 3;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 5;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
swizzle_pipe[5] = 5;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 5;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 5;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
swizzle_pipe[5] = 5;
|
||||
swizzle_pipe[6] = 6;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 5;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 7;
|
||||
swizzle_pipe[7] = 5;
|
||||
if (force_no_swizzle) {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 1;
|
||||
swizzle_pipe[2] = 2;
|
||||
swizzle_pipe[3] = 3;
|
||||
swizzle_pipe[4] = 4;
|
||||
swizzle_pipe[5] = 5;
|
||||
swizzle_pipe[6] = 6;
|
||||
swizzle_pipe[7] = 7;
|
||||
} else {
|
||||
swizzle_pipe[0] = 0;
|
||||
swizzle_pipe[1] = 2;
|
||||
swizzle_pipe[2] = 4;
|
||||
swizzle_pipe[3] = 6;
|
||||
swizzle_pipe[4] = 3;
|
||||
swizzle_pipe[5] = 1;
|
||||
swizzle_pipe[6] = 7;
|
||||
swizzle_pipe[7] = 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -385,8 +451,10 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
|
|||
static void rv770_gpu_init(struct radeon_device *rdev)
|
||||
{
|
||||
int i, j, num_qd_pipes;
|
||||
u32 ta_aux_cntl;
|
||||
u32 sx_debug_1;
|
||||
u32 smx_dc_ctl0;
|
||||
u32 db_debug3;
|
||||
u32 num_gs_verts_per_thread;
|
||||
u32 vgt_gs_per_es;
|
||||
u32 gs_prim_buffer_depth = 0;
|
||||
|
@ -515,6 +583,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
|
||||
switch (rdev->config.rv770.max_tile_pipes) {
|
||||
case 1:
|
||||
default:
|
||||
gb_tiling_config |= PIPE_TILING(0);
|
||||
break;
|
||||
case 2:
|
||||
|
@ -526,16 +595,17 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
case 8:
|
||||
gb_tiling_config |= PIPE_TILING(3);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes;
|
||||
|
||||
if (rdev->family == CHIP_RV770)
|
||||
gb_tiling_config |= BANK_TILING(1);
|
||||
else
|
||||
gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
|
||||
rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3);
|
||||
|
||||
gb_tiling_config |= GROUP_SIZE(0);
|
||||
rdev->config.rv770.tiling_group_size = 256;
|
||||
|
||||
if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {
|
||||
gb_tiling_config |= ROW_TILING(3);
|
||||
|
@ -549,21 +619,27 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
|
||||
gb_tiling_config |= BANK_SWAPS(1);
|
||||
|
||||
if (rdev->family == CHIP_RV740)
|
||||
backend_map = 0x28;
|
||||
else
|
||||
backend_map = r700_get_tile_pipe_to_backend_map(rdev->config.rv770.max_tile_pipes,
|
||||
rdev->config.rv770.max_backends,
|
||||
(0xff << rdev->config.rv770.max_backends) & 0xff);
|
||||
gb_tiling_config |= BACKEND_MAP(backend_map);
|
||||
cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
|
||||
cc_rb_backend_disable |=
|
||||
BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK);
|
||||
|
||||
cc_gc_shader_pipe_config =
|
||||
cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
|
||||
cc_gc_shader_pipe_config |=
|
||||
INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << rdev->config.rv770.max_pipes) & R7XX_MAX_PIPES_MASK);
|
||||
cc_gc_shader_pipe_config |=
|
||||
INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << rdev->config.rv770.max_simds) & R7XX_MAX_SIMDS_MASK);
|
||||
|
||||
cc_rb_backend_disable =
|
||||
BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK);
|
||||
if (rdev->family == CHIP_RV740)
|
||||
backend_map = 0x28;
|
||||
else
|
||||
backend_map = r700_get_tile_pipe_to_backend_map(rdev,
|
||||
rdev->config.rv770.max_tile_pipes,
|
||||
(R7XX_MAX_BACKENDS -
|
||||
r600_count_pipe_bits((cc_rb_backend_disable &
|
||||
R7XX_MAX_BACKENDS_MASK) >> 16)),
|
||||
(cc_rb_backend_disable >> 16));
|
||||
gb_tiling_config |= BACKEND_MAP(backend_map);
|
||||
|
||||
|
||||
WREG32(GB_TILING_CONFIG, gb_tiling_config);
|
||||
WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
|
||||
|
@ -571,16 +647,13 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
|
||||
WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
|
||||
WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
|
||||
WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
|
||||
WREG32(CGTS_SYS_TCC_DISABLE, 0);
|
||||
WREG32(CGTS_TCC_DISABLE, 0);
|
||||
WREG32(CGTS_USER_SYS_TCC_DISABLE, 0);
|
||||
WREG32(CGTS_USER_TCC_DISABLE, 0);
|
||||
|
||||
num_qd_pipes =
|
||||
R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK);
|
||||
R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
|
||||
WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK);
|
||||
WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK);
|
||||
|
||||
|
@ -590,10 +663,8 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
|
||||
WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30));
|
||||
|
||||
WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO |
|
||||
SYNC_GRADIENT |
|
||||
SYNC_WALKER |
|
||||
SYNC_ALIGNER));
|
||||
ta_aux_cntl = RREG32(TA_CNTL_AUX);
|
||||
WREG32(TA_CNTL_AUX, ta_aux_cntl | DISABLE_CUBE_ANISO);
|
||||
|
||||
sx_debug_1 = RREG32(SX_DEBUG_1);
|
||||
sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
|
||||
|
@ -604,14 +675,28 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
smx_dc_ctl0 |= CACHE_DEPTH((rdev->config.rv770.sx_num_of_sets * 64) - 1);
|
||||
WREG32(SMX_DC_CTL0, smx_dc_ctl0);
|
||||
|
||||
WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
|
||||
GS_FLUSH_CTL(4) |
|
||||
ACK_FLUSH_CTL(3) |
|
||||
SYNC_FLUSH_CTL));
|
||||
if (rdev->family != CHIP_RV740)
|
||||
WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
|
||||
GS_FLUSH_CTL(4) |
|
||||
ACK_FLUSH_CTL(3) |
|
||||
SYNC_FLUSH_CTL));
|
||||
|
||||
if (rdev->family == CHIP_RV770)
|
||||
WREG32(DB_DEBUG3, DB_CLK_OFF_DELAY(0x1f));
|
||||
else {
|
||||
db_debug3 = RREG32(DB_DEBUG3);
|
||||
db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f);
|
||||
switch (rdev->family) {
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV740:
|
||||
db_debug3 |= DB_CLK_OFF_DELAY(0x1f);
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV730:
|
||||
default:
|
||||
db_debug3 |= DB_CLK_OFF_DELAY(2);
|
||||
break;
|
||||
}
|
||||
WREG32(DB_DEBUG3, db_debug3);
|
||||
|
||||
if (rdev->family != CHIP_RV770) {
|
||||
db_debug4 = RREG32(DB_DEBUG4);
|
||||
db_debug4 |= DISABLE_TILE_COVERED_FOR_PS_ITER;
|
||||
WREG32(DB_DEBUG4, db_debug4);
|
||||
|
@ -640,10 +725,10 @@ static void rv770_gpu_init(struct radeon_device *rdev)
|
|||
ALU_UPDATE_FIFO_HIWATER(0x8));
|
||||
switch (rdev->family) {
|
||||
case CHIP_RV770:
|
||||
sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
|
||||
break;
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
|
||||
break;
|
||||
case CHIP_RV740:
|
||||
default:
|
||||
sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x4);
|
||||
|
@ -816,45 +901,13 @@ int rv770_mc_init(struct radeon_device *rdev)
|
|||
/* Setup GPU memory space */
|
||||
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
|
||||
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
|
||||
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.visible_vram_size = rdev->mc.aper_size;
|
||||
/* FIXME remove this once we support unmappable VRAM */
|
||||
if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
|
||||
rdev->mc.mc_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
|
||||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
/* gtt_size is setup by radeon_agp_init */
|
||||
rdev->mc.gtt_location = rdev->mc.agp_base;
|
||||
tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
|
||||
/* Try to put vram before or after AGP because we
|
||||
* we want SYSTEM_APERTURE to cover both VRAM and
|
||||
* AGP so that GPU can catch out of VRAM/AGP access
|
||||
*/
|
||||
if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
|
||||
/* Enough place before */
|
||||
rdev->mc.vram_location = rdev->mc.gtt_location -
|
||||
rdev->mc.mc_vram_size;
|
||||
} else if (tmp > rdev->mc.mc_vram_size) {
|
||||
/* Enough place after */
|
||||
rdev->mc.vram_location = rdev->mc.gtt_location +
|
||||
rdev->mc.gtt_size;
|
||||
} else {
|
||||
/* Try to setup VRAM then AGP might not
|
||||
* not work on some card
|
||||
*/
|
||||
rdev->mc.vram_location = 0x00000000UL;
|
||||
rdev->mc.gtt_location = rdev->mc.mc_vram_size;
|
||||
}
|
||||
} else {
|
||||
rdev->mc.vram_location = 0x00000000UL;
|
||||
rdev->mc.gtt_location = rdev->mc.mc_vram_size;
|
||||
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
|
||||
}
|
||||
rdev->mc.vram_start = rdev->mc.vram_location;
|
||||
rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
|
||||
rdev->mc.gtt_start = rdev->mc.gtt_location;
|
||||
rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
|
||||
r600_vram_gtt_location(rdev, &rdev->mc);
|
||||
/* FIXME: we should enforce default clock in case GPU is not in
|
||||
* default setup
|
||||
*/
|
||||
|
@ -863,6 +916,7 @@ int rv770_mc_init(struct radeon_device *rdev)
|
|||
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rv770_gpu_reset(struct radeon_device *rdev)
|
||||
{
|
||||
/* FIXME: implement any rv770 specific bits */
|
||||
|
@ -1038,6 +1092,7 @@ int rv770_init(struct radeon_device *rdev)
|
|||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* initialize AGP */
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r)
|
||||
|
|
|
@ -343,4 +343,6 @@
|
|||
|
||||
#define WAIT_UNTIL 0x8040
|
||||
|
||||
#define SRBM_STATUS 0x0E50
|
||||
|
||||
#endif
|
||||
|
|
148
include/drm/drm_buffer.h
Normal file
148
include/drm/drm_buffer.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 Pauli Nieminen.
|
||||
* 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
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Multipart buffer for coping data which is larger than the page size.
|
||||
*
|
||||
* Authors:
|
||||
* Pauli Nieminen <suokkos-at-gmail-dot-com>
|
||||
*/
|
||||
|
||||
#ifndef _DRM_BUFFER_H_
|
||||
#define _DRM_BUFFER_H_
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
struct drm_buffer {
|
||||
int iterator;
|
||||
int size;
|
||||
char *data[];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the index of page that buffer is currently pointing at.
|
||||
*/
|
||||
static inline int drm_buffer_page(struct drm_buffer *buf)
|
||||
{
|
||||
return buf->iterator / PAGE_SIZE;
|
||||
}
|
||||
/**
|
||||
* Return the index of the current byte in the page
|
||||
*/
|
||||
static inline int drm_buffer_index(struct drm_buffer *buf)
|
||||
{
|
||||
return buf->iterator & (PAGE_SIZE - 1);
|
||||
}
|
||||
/**
|
||||
* Return number of bytes that is left to process
|
||||
*/
|
||||
static inline int drm_buffer_unprocessed(struct drm_buffer *buf)
|
||||
{
|
||||
return buf->size - buf->iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the buffer iterator number of bytes that is given.
|
||||
*/
|
||||
static inline void drm_buffer_advance(struct drm_buffer *buf, int bytes)
|
||||
{
|
||||
buf->iterator += bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the drm buffer object.
|
||||
*
|
||||
* buf: A pointer to a pointer where the object is stored.
|
||||
* size: The number of bytes to allocate.
|
||||
*/
|
||||
extern int drm_buffer_alloc(struct drm_buffer **buf, int size);
|
||||
|
||||
/**
|
||||
* Copy the user data to the begin of the buffer and reset the processing
|
||||
* iterator.
|
||||
*
|
||||
* user_data: A pointer the data that is copied to the buffer.
|
||||
* size: The Number of bytes to copy.
|
||||
*/
|
||||
extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
|
||||
void __user *user_data, int size);
|
||||
|
||||
/**
|
||||
* Free the drm buffer object
|
||||
*/
|
||||
extern void drm_buffer_free(struct drm_buffer *buf);
|
||||
|
||||
/**
|
||||
* Read an object from buffer that may be split to multiple parts. If object
|
||||
* is not split function just returns the pointer to object in buffer. But in
|
||||
* case of split object data is copied to given stack object that is suplied
|
||||
* by caller.
|
||||
*
|
||||
* The processing location of the buffer is also advanced to the next byte
|
||||
* after the object.
|
||||
*
|
||||
* objsize: The size of the objet in bytes.
|
||||
* stack_obj: A pointer to a memory location where object can be copied.
|
||||
*/
|
||||
extern void *drm_buffer_read_object(struct drm_buffer *buf,
|
||||
int objsize, void *stack_obj);
|
||||
|
||||
/**
|
||||
* Returns the pointer to the dword which is offset number of elements from the
|
||||
* current processing location.
|
||||
*
|
||||
* Caller must make sure that dword is not split in the buffer. This
|
||||
* requirement is easily met if all the sizes of objects in buffer are
|
||||
* multiples of dword and PAGE_SIZE is multiple dword.
|
||||
*
|
||||
* Call to this function doesn't change the processing location.
|
||||
*
|
||||
* offset: The index of the dword relative to the internat iterator.
|
||||
*/
|
||||
static inline void *drm_buffer_pointer_to_dword(struct drm_buffer *buffer,
|
||||
int offset)
|
||||
{
|
||||
int iter = buffer->iterator + offset * 4;
|
||||
return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)];
|
||||
}
|
||||
/**
|
||||
* Returns the pointer to the dword which is offset number of elements from
|
||||
* the current processing location.
|
||||
*
|
||||
* Call to this function doesn't change the processing location.
|
||||
*
|
||||
* offset: The index of the byte relative to the internat iterator.
|
||||
*/
|
||||
static inline void *drm_buffer_pointer_to_byte(struct drm_buffer *buffer,
|
||||
int offset)
|
||||
{
|
||||
int iter = buffer->iterator + offset;
|
||||
return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)];
|
||||
}
|
||||
|
||||
#endif
|
|
@ -801,4 +801,6 @@ extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev,
|
|||
bool interlaced, int margins);
|
||||
extern int drm_add_modes_noedid(struct drm_connector *connector,
|
||||
int hdisplay, int vdisplay);
|
||||
|
||||
extern bool drm_edid_is_valid(struct edid *edid);
|
||||
#endif /* __DRM_CRTC_H__ */
|
||||
|
|
|
@ -201,4 +201,7 @@ struct edid {
|
|||
|
||||
#define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
|
||||
|
||||
/* define the number of Extension EDID block */
|
||||
#define DRM_MAX_EDID_EXT_NUM 4
|
||||
|
||||
#endif /* __DRM_EDID_H__ */
|
||||
|
|
|
@ -141,6 +141,41 @@
|
|||
{0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x688A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x689d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x689e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68a9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68e0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68e1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68e5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68e8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68e9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
|
@ -558,4 +593,5 @@
|
|||
{0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0x8086, 0x0102, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
||||
{0, 0, 0}
|
||||
|
|
|
@ -808,6 +808,7 @@ struct drm_radeon_gem_create {
|
|||
#define RADEON_TILING_SWAP_32BIT 0x8
|
||||
#define RADEON_TILING_SURFACE 0x10 /* this object requires a surface
|
||||
* when mapped - i.e. front buffer */
|
||||
#define RADEON_TILING_MICRO_SQUARE 0x20
|
||||
|
||||
struct drm_radeon_gem_set_tiling {
|
||||
uint32_t handle;
|
||||
|
|
Loading…
Reference in a new issue