Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (95 commits) drm/radeon/kms: preface warning printk with driver name drm/radeon/kms: drop unnecessary printks. drm: fix regression in fb blank handling drm/radeon/kms: make hibernate work on IGPs drm/vmwgfx: Optimize memory footprint for DMA buffers. drm/ttm: Allow system memory as a busy placement. drm/ttm: Fix race condition in ttm_bo_delayed_delete (v3, final) drm/nv50: prevent switching off SOR when in use for DVI-over-DP drm/nv50: fail auxch transaction if reply count not what we expect drm/nouveau: fix failure path if userspace specifies no valid memtypes drm/nouveau: report LVDS as disconnected if lid closed drm/radeon/kms: fix legacy get_engine/memory clock drm/radeon/kms/atom: atom parser fixes drm/radeon/kms: clean up atombios pll code drm/radeon/kms: clean up pll struct drm/radeon/kms/atom: fix crtc lock ordering drm/radeon: r6xx/r7xx possible security issue, system ram access drm/radeon/kms: r600/r700 don't test ib if ib initialization fails drm/radeon/kms: Forbid creation of framebuffer with no valid GEM object drm/radeon/kms: r600 handle irq vector ring overflow ...
This commit is contained in:
commit
abefedd538
|
@ -633,8 +633,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
|
|||
return NULL;
|
||||
}
|
||||
if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
|
||||
printk(KERN_WARNING "integrated sync not supported\n");
|
||||
return NULL;
|
||||
printk(KERN_WARNING "composite sync not supported\n");
|
||||
}
|
||||
|
||||
/* it is incorrect if hsync/vsync width is zero */
|
||||
|
|
|
@ -389,7 +389,7 @@ int drm_fb_helper_blank(int blank, struct fb_info *info)
|
|||
break;
|
||||
/* Display: Off; HSync: On, VSync: On */
|
||||
case FB_BLANK_NORMAL:
|
||||
drm_fb_helper_off(info, DRM_MODE_DPMS_ON);
|
||||
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
/* Display: Off; HSync: Off, VSync: On */
|
||||
case FB_BLANK_HSYNC_SUSPEND:
|
||||
|
|
|
@ -310,63 +310,22 @@ valid_reg(struct nvbios *bios, uint32_t reg)
|
|||
struct drm_device *dev = bios->dev;
|
||||
|
||||
/* C51 has misaligned regs on purpose. Marvellous */
|
||||
if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) {
|
||||
NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n",
|
||||
reg);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Warn on C51 regs that have not been verified accessible in
|
||||
* mmiotracing
|
||||
*/
|
||||
if (reg & 0x2 ||
|
||||
(reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
|
||||
NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
|
||||
|
||||
/* warn on C51 regs that haven't been verified accessible in tracing */
|
||||
if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
|
||||
reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
|
||||
NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
|
||||
reg);
|
||||
|
||||
/* Trust the init scripts on G80 */
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
return 1;
|
||||
|
||||
#define WITHIN(x, y, z) ((x >= y) && (x < y + z))
|
||||
if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x30 &&
|
||||
(WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x40 &&
|
||||
WITHIN(reg, 0xc000, 0x48))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204)
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x40) {
|
||||
if (reg == 0x00011014 || reg == 0x00020328)
|
||||
return 1;
|
||||
if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */
|
||||
return 1;
|
||||
if (reg >= (8*1024*1024)) {
|
||||
NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg);
|
||||
return 0;
|
||||
}
|
||||
if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0)
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version == 0x51 &&
|
||||
WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE))
|
||||
return 1;
|
||||
#undef WITHIN
|
||||
|
||||
NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3196,16 +3155,25 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr
|
|||
}
|
||||
#ifdef __powerpc__
|
||||
/* Powerbook specific quirks */
|
||||
if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329))
|
||||
nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
|
||||
if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) {
|
||||
if (script == LVDS_PANEL_ON) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
|
||||
}
|
||||
if (script == LVDS_PANEL_OFF) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
|
||||
if ((dev->pci_device & 0xffff) == 0x0179 ||
|
||||
(dev->pci_device & 0xffff) == 0x0189 ||
|
||||
(dev->pci_device & 0xffff) == 0x0329) {
|
||||
if (script == LVDS_RESET) {
|
||||
nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
|
||||
|
||||
} else if (script == LVDS_PANEL_ON) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
|
||||
bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
|
||||
| (1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT,
|
||||
bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
|
||||
|
||||
} else if (script == LVDS_PANEL_OFF) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
|
||||
bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
|
||||
& ~(1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT,
|
||||
bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -5434,52 +5402,49 @@ static bool
|
|||
parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
|
||||
uint32_t conn, uint32_t conf, struct dcb_entry *entry)
|
||||
{
|
||||
if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 &&
|
||||
conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 &&
|
||||
conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 &&
|
||||
conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 &&
|
||||
conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 &&
|
||||
conn != 0xf2205004 && conn != 0xf2209004) {
|
||||
NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n");
|
||||
|
||||
/* cause output setting to fail for !TV, so message is seen */
|
||||
if ((conn & 0xf) != 0x1)
|
||||
dcb->entries = 0;
|
||||
|
||||
switch (conn & 0x0000000f) {
|
||||
case 0:
|
||||
entry->type = OUTPUT_ANALOG;
|
||||
break;
|
||||
case 1:
|
||||
entry->type = OUTPUT_TV;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
entry->type = OUTPUT_LVDS;
|
||||
break;
|
||||
case 4:
|
||||
switch ((conn & 0x000000f0) >> 4) {
|
||||
case 0:
|
||||
entry->type = OUTPUT_TMDS;
|
||||
break;
|
||||
case 1:
|
||||
entry->type = OUTPUT_LVDS;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
|
||||
(conn & 0x000000f0) >> 4);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
|
||||
return false;
|
||||
}
|
||||
/* most of the below is a "best guess" atm */
|
||||
entry->type = conn & 0xf;
|
||||
if (entry->type == 2)
|
||||
/* another way of specifying straps based lvds... */
|
||||
entry->type = OUTPUT_LVDS;
|
||||
if (entry->type == 4) { /* digital */
|
||||
if (conn & 0x10)
|
||||
entry->type = OUTPUT_LVDS;
|
||||
else
|
||||
entry->type = OUTPUT_TMDS;
|
||||
}
|
||||
/* what's in bits 5-13? could be some encoder maker thing, in tv case */
|
||||
entry->i2c_index = (conn >> 14) & 0xf;
|
||||
/* raw heads field is in range 0-1, so move to 1-2 */
|
||||
entry->heads = ((conn >> 18) & 0x7) + 1;
|
||||
entry->location = (conn >> 21) & 0xf;
|
||||
/* unused: entry->bus = (conn >> 25) & 0x7; */
|
||||
/* set or to be same as heads -- hopefully safe enough */
|
||||
entry->or = entry->heads;
|
||||
|
||||
entry->i2c_index = (conn & 0x0003c000) >> 14;
|
||||
entry->heads = ((conn & 0x001c0000) >> 18) + 1;
|
||||
entry->or = entry->heads; /* same as heads, hopefully safe enough */
|
||||
entry->location = (conn & 0x01e00000) >> 21;
|
||||
entry->bus = (conn & 0x0e000000) >> 25;
|
||||
entry->duallink_possible = false;
|
||||
|
||||
switch (entry->type) {
|
||||
case OUTPUT_ANALOG:
|
||||
entry->crtconf.maxfreq = (conf & 0xffff) * 10;
|
||||
break;
|
||||
case OUTPUT_LVDS:
|
||||
/*
|
||||
* This is probably buried in conn's unknown bits.
|
||||
* This will upset EDID-ful models, if they exist
|
||||
*/
|
||||
entry->lvdsconf.use_straps_for_mode = true;
|
||||
entry->lvdsconf.use_power_scripts = true;
|
||||
case OUTPUT_TV:
|
||||
entry->tvconf.has_component_output = false;
|
||||
break;
|
||||
case OUTPUT_TMDS:
|
||||
/*
|
||||
|
@ -5488,8 +5453,12 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
|
|||
*/
|
||||
fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
|
||||
break;
|
||||
case OUTPUT_TV:
|
||||
entry->tvconf.has_component_output = false;
|
||||
case OUTPUT_LVDS:
|
||||
if ((conn & 0x00003f00) != 0x10)
|
||||
entry->lvdsconf.use_straps_for_mode = true;
|
||||
entry->lvdsconf.use_power_scripts = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5564,11 +5533,13 @@ void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
|
|||
dcb->entries = newentries;
|
||||
}
|
||||
|
||||
static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||
static int
|
||||
parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct bios_parsed_dcb *bdcb = &bios->bdcb;
|
||||
struct parsed_dcb *dcb;
|
||||
uint16_t dcbptr, i2ctabptr = 0;
|
||||
uint16_t dcbptr = 0, i2ctabptr = 0;
|
||||
uint8_t *dcbtable;
|
||||
uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
|
||||
bool configblock = true;
|
||||
|
@ -5579,16 +5550,18 @@ static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool two
|
|||
dcb->entries = 0;
|
||||
|
||||
/* get the offset from 0x36 */
|
||||
dcbptr = ROM16(bios->data[0x36]);
|
||||
if (dev_priv->card_type > NV_04) {
|
||||
dcbptr = ROM16(bios->data[0x36]);
|
||||
if (dcbptr == 0x0000)
|
||||
NV_WARN(dev, "No output data (DCB) found in BIOS\n");
|
||||
}
|
||||
|
||||
/* this situation likely means a really old card, pre DCB */
|
||||
if (dcbptr == 0x0) {
|
||||
NV_WARN(dev, "No output data (DCB) found in BIOS, "
|
||||
"assuming a CRT output exists\n");
|
||||
/* this situation likely means a really old card, pre DCB */
|
||||
NV_INFO(dev, "Assuming a CRT output exists\n");
|
||||
fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
|
||||
|
||||
if (nv04_tv_identify(dev,
|
||||
bios->legacy.i2c_indices.tv) >= 0)
|
||||
if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
||||
fabricate_tv_output(dcb, twoHeads);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -469,6 +469,8 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
|
|||
|
||||
ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
|
||||
evict, no_wait, new_mem);
|
||||
if (nvbo->channel && nvbo->channel != chan)
|
||||
ret = nouveau_fence_wait(fence, NULL, false, false);
|
||||
nouveau_fence_unref((void *)&fence);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <acpi/button.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm_edid.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
|
||||
#include "nouveau_reg.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_encoder.h"
|
||||
|
@ -83,14 +86,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
|
|||
static void
|
||||
nouveau_connector_destroy(struct drm_connector *drm_connector)
|
||||
{
|
||||
struct nouveau_connector *connector = nouveau_connector(drm_connector);
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct nouveau_connector *nv_connector =
|
||||
nouveau_connector(drm_connector);
|
||||
struct drm_device *dev = nv_connector->base.dev;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
if (!connector)
|
||||
if (!nv_connector)
|
||||
return;
|
||||
|
||||
kfree(nv_connector->edid);
|
||||
drm_sysfs_connector_remove(drm_connector);
|
||||
drm_connector_cleanup(drm_connector);
|
||||
kfree(drm_connector);
|
||||
|
@ -233,10 +238,21 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
|
||||
if (nv_encoder && nv_connector->native_mode) {
|
||||
#ifdef CONFIG_ACPI
|
||||
if (!nouveau_ignorelid && !acpi_lid_open())
|
||||
return connector_status_disconnected;
|
||||
#endif
|
||||
nouveau_connector_set_encoder(connector, nv_encoder);
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
/* Cleanup the previous EDID block. */
|
||||
if (nv_connector->edid) {
|
||||
drm_mode_connector_update_edid_property(connector, NULL);
|
||||
kfree(nv_connector->edid);
|
||||
nv_connector->edid = NULL;
|
||||
}
|
||||
|
||||
i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
|
||||
if (i2c) {
|
||||
nouveau_connector_ddc_prepare(connector, &flags);
|
||||
|
@ -247,7 +263,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
if (!nv_connector->edid) {
|
||||
NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
|
||||
drm_get_connector_name(connector));
|
||||
return connector_status_disconnected;
|
||||
goto detect_analog;
|
||||
}
|
||||
|
||||
if (nv_encoder->dcb->type == OUTPUT_DP &&
|
||||
|
@ -281,6 +297,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
return connector_status_connected;
|
||||
}
|
||||
|
||||
detect_analog:
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
|
||||
if (!nv_encoder)
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
|
||||
|
@ -687,8 +704,12 @@ nouveau_connector_create_lvds(struct drm_device *dev,
|
|||
*/
|
||||
if (!nv_connector->edid && !nv_connector->native_mode &&
|
||||
!dev_priv->VBIOS.pub.fp_no_ddc) {
|
||||
nv_connector->edid =
|
||||
struct edid *edid =
|
||||
(struct edid *)nouveau_bios_embedded_edid(dev);
|
||||
if (edid) {
|
||||
nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
*(nv_connector->edid) = *edid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nv_connector->edid)
|
||||
|
|
|
@ -126,47 +126,52 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
|
|||
chan->dma.cur += nr_dwords;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
READ_GET(struct nouveau_channel *chan, uint32_t *get)
|
||||
/* Fetch and adjust GPU GET pointer
|
||||
*
|
||||
* Returns:
|
||||
* value >= 0, the adjusted GET pointer
|
||||
* -EINVAL if GET pointer currently outside main push buffer
|
||||
* -EBUSY if timeout exceeded
|
||||
*/
|
||||
static inline int
|
||||
READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = nvchan_rd32(chan, chan->user_get);
|
||||
if (val < chan->pushbuf_base ||
|
||||
val > chan->pushbuf_base + (chan->dma.max << 2)) {
|
||||
/* meaningless to dma_wait() except to know whether the
|
||||
* GPU has stalled or not
|
||||
*/
|
||||
*get = val;
|
||||
return false;
|
||||
|
||||
/* reset counter as long as GET is still advancing, this is
|
||||
* to avoid misdetecting a GPU lockup if the GPU happens to
|
||||
* just be processing an operation that takes a long time
|
||||
*/
|
||||
if (val != *prev_get) {
|
||||
*prev_get = val;
|
||||
*timeout = 0;
|
||||
}
|
||||
|
||||
*get = (val - chan->pushbuf_base) >> 2;
|
||||
return true;
|
||||
if ((++*timeout & 0xff) == 0) {
|
||||
DRM_UDELAY(1);
|
||||
if (*timeout > 100000)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (val < chan->pushbuf_base ||
|
||||
val > chan->pushbuf_base + (chan->dma.max << 2))
|
||||
return -EINVAL;
|
||||
|
||||
return (val - chan->pushbuf_base) >> 2;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_dma_wait(struct nouveau_channel *chan, int size)
|
||||
{
|
||||
uint32_t get, prev_get = 0, cnt = 0;
|
||||
bool get_valid;
|
||||
uint32_t prev_get = 0, cnt = 0;
|
||||
int get;
|
||||
|
||||
while (chan->dma.free < size) {
|
||||
/* reset counter as long as GET is still advancing, this is
|
||||
* to avoid misdetecting a GPU lockup if the GPU happens to
|
||||
* just be processing an operation that takes a long time
|
||||
*/
|
||||
get_valid = READ_GET(chan, &get);
|
||||
if (get != prev_get) {
|
||||
prev_get = get;
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
if ((++cnt & 0xff) == 0) {
|
||||
DRM_UDELAY(1);
|
||||
if (cnt > 100000)
|
||||
return -EBUSY;
|
||||
}
|
||||
get = READ_GET(chan, &prev_get, &cnt);
|
||||
if (unlikely(get == -EBUSY))
|
||||
return -EBUSY;
|
||||
|
||||
/* loop until we have a usable GET pointer. the value
|
||||
* we read from the GPU may be outside the main ring if
|
||||
|
@ -177,7 +182,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size)
|
|||
* from the SKIPS area, so the code below doesn't have to deal
|
||||
* with some fun corner cases.
|
||||
*/
|
||||
if (!get_valid || get < NOUVEAU_DMA_SKIPS)
|
||||
if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS)
|
||||
continue;
|
||||
|
||||
if (get <= chan->dma.cur) {
|
||||
|
@ -203,6 +208,19 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size)
|
|||
* after processing the currently pending commands.
|
||||
*/
|
||||
OUT_RING(chan, chan->pushbuf_base | 0x20000000);
|
||||
|
||||
/* wait for GET to depart from the skips area.
|
||||
* prevents writing GET==PUT and causing a race
|
||||
* condition that causes us to think the GPU is
|
||||
* idle when it's not.
|
||||
*/
|
||||
do {
|
||||
get = READ_GET(chan, &prev_get, &cnt);
|
||||
if (unlikely(get == -EBUSY))
|
||||
return -EBUSY;
|
||||
if (unlikely(get == -EINVAL))
|
||||
continue;
|
||||
} while (get <= NOUVEAU_DMA_SKIPS);
|
||||
WRITE_PUT(NOUVEAU_DMA_SKIPS);
|
||||
|
||||
/* we're now submitting commands at the start of
|
||||
|
|
|
@ -490,7 +490,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
|
|||
if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) {
|
||||
NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
|
||||
nv_rd32(dev, NV50_AUXCH_CTRL(index)));
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
udelay(400);
|
||||
|
@ -501,6 +502,11 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
|
|||
break;
|
||||
}
|
||||
|
||||
if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmd & 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
|
||||
|
|
|
@ -71,6 +71,10 @@ MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)");
|
|||
int nouveau_uscript_tmds = -1;
|
||||
module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
|
||||
int nouveau_ignorelid = 0;
|
||||
module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
|
||||
"\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
|
||||
"\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
|
||||
|
|
|
@ -509,6 +509,8 @@ struct drm_nouveau_private {
|
|||
void __iomem *ramin;
|
||||
uint32_t ramin_size;
|
||||
|
||||
struct nouveau_bo *vga_ram;
|
||||
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct irq_work;
|
||||
|
||||
|
@ -675,6 +677,7 @@ extern char *nouveau_tv_norm;
|
|||
extern int nouveau_reg_debug;
|
||||
extern char *nouveau_vbios;
|
||||
extern int nouveau_ctxfw;
|
||||
extern int nouveau_ignorelid;
|
||||
|
||||
/* nouveau_state.c */
|
||||
extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
|
||||
|
|
|
@ -321,6 +321,7 @@ retry:
|
|||
else {
|
||||
NV_ERROR(dev, "invalid valid domains: 0x%08x\n",
|
||||
b->valid_domains);
|
||||
list_add_tail(&nvbo->entry, &op->both_list);
|
||||
validate_fini(op, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -466,13 +467,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
|
|||
static int
|
||||
nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo,
|
||||
int nr_relocs, uint64_t ptr_relocs,
|
||||
int nr_dwords, int first_dword,
|
||||
unsigned nr_relocs, uint64_t ptr_relocs,
|
||||
unsigned nr_dwords, unsigned first_dword,
|
||||
uint32_t *pushbuf, bool is_iomem)
|
||||
{
|
||||
struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
|
||||
struct drm_device *dev = chan->dev;
|
||||
int ret = 0, i;
|
||||
int ret = 0;
|
||||
unsigned i;
|
||||
|
||||
reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
|
||||
if (IS_ERR(reloc))
|
||||
|
@ -667,6 +669,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
|
|||
}
|
||||
pbbo = nouveau_gem_object(gem);
|
||||
|
||||
if ((req->offset & 3) || req->nr_dwords < 2 ||
|
||||
(unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
|
||||
(unsigned long)req->nr_dwords >
|
||||
((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
|
||||
NV_ERROR(dev, "pb call misaligned or out of bounds: "
|
||||
"%d + %d * 4 > %ld\n",
|
||||
req->offset, req->nr_dwords, pbbo->bo.mem.size);
|
||||
ret = -EINVAL;
|
||||
drm_gem_object_unreference(gem);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
|
||||
chan->fence.sequence);
|
||||
if (ret) {
|
||||
|
|
|
@ -483,6 +483,13 @@ nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
|
|||
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
|
||||
if (nouveau_pgraph_intr_swmthd(dev, &trap))
|
||||
unhandled = 1;
|
||||
} else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
|
||||
uint32_t v = nv_rd32(dev, 0x402000);
|
||||
nv_wr32(dev, 0x402000, v);
|
||||
|
||||
/* dump the error anyway for now: it's useful for
|
||||
Gallium development */
|
||||
unhandled = 1;
|
||||
} else {
|
||||
unhandled = 1;
|
||||
}
|
||||
|
|
|
@ -383,9 +383,8 @@ void nouveau_mem_close(struct drm_device *dev)
|
|||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type)
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
nouveau_bo_unpin(dev_priv->vga_ram);
|
||||
nouveau_bo_ref(NULL, &dev_priv->vga_ram);
|
||||
|
||||
ttm_bo_device_release(&dev_priv->ttm.bdev);
|
||||
|
||||
|
@ -622,6 +621,15 @@ nouveau_mem_init(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
|
||||
0, 0, true, true, &dev_priv->vga_ram);
|
||||
if (ret == 0)
|
||||
ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
|
||||
if (ret) {
|
||||
NV_WARN(dev, "failed to reserve VGA memory\n");
|
||||
nouveau_bo_ref(NULL, &dev_priv->vga_ram);
|
||||
}
|
||||
|
||||
/* GART */
|
||||
#if !defined(__powerpc__) && !defined(__ia64__)
|
||||
if (drm_device_is_agp(dev) && dev->agp) {
|
||||
|
@ -653,6 +661,7 @@ nouveau_mem_init(struct drm_device *dev)
|
|||
dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
|
||||
drm_get_resource_len(dev, 1),
|
||||
DRM_MTRR_WC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -525,6 +525,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
|||
engine->mc.takedown(dev);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
nouveau_sgdma_takedown(dev);
|
||||
|
|
|
@ -30,7 +30,7 @@ nv04_instmem_determine_amount(struct drm_device *dev)
|
|||
* of vram. For now, only reserve a small piece until we know
|
||||
* more about what each chipset requires.
|
||||
*/
|
||||
switch (dev_priv->chipset & 0xf0) {
|
||||
switch (dev_priv->chipset) {
|
||||
case 0x40:
|
||||
case 0x47:
|
||||
case 0x49:
|
||||
|
|
|
@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
|
|||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_encoder *encoder;
|
||||
uint32_t dac = 0, sor = 0;
|
||||
|
||||
NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
|
||||
|
||||
|
@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
|
|||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
|
||||
if (drm_helper_encoder_in_use(encoder))
|
||||
if (!drm_helper_encoder_in_use(encoder))
|
||||
continue;
|
||||
|
||||
if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
|
||||
nv_encoder->dcb->type == OUTPUT_TV)
|
||||
dac |= (1 << nv_encoder->or);
|
||||
else
|
||||
sor |= (1 << nv_encoder->or);
|
||||
}
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
|
||||
if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
|
||||
nv_encoder->dcb->type == OUTPUT_TV) {
|
||||
if (dac & (1 << nv_encoder->or))
|
||||
continue;
|
||||
} else {
|
||||
if (sor & (1 << nv_encoder->or))
|
||||
continue;
|
||||
}
|
||||
|
||||
nv_encoder->disconnect(nv_encoder);
|
||||
}
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
|
|||
return ret;
|
||||
ramfc = chan->ramfc->gpuobj;
|
||||
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 256,
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024,
|
||||
0, &chan->cache);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -84,7 +84,7 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
|
|||
nv_wr32(dev, 0x400804, 0xc0000000);
|
||||
nv_wr32(dev, 0x406800, 0xc0000000);
|
||||
nv_wr32(dev, 0x400c04, 0xc0000000);
|
||||
nv_wr32(dev, 0x401804, 0xc0000000);
|
||||
nv_wr32(dev, 0x401800, 0xc0000000);
|
||||
nv_wr32(dev, 0x405018, 0xc0000000);
|
||||
nv_wr32(dev, 0x402000, 0xc0000000);
|
||||
|
||||
|
@ -282,6 +282,7 @@ nv50_graph_unload_context(struct drm_device *dev)
|
|||
return 0;
|
||||
inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
nv_wr32(dev, 0x400500, fifo & ~1);
|
||||
nv_wr32(dev, 0x400784, inst);
|
||||
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
|
||||
|
|
|
@ -90,11 +90,24 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
|
|||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
struct drm_encoder *enc;
|
||||
uint32_t val;
|
||||
int or = nv_encoder->or;
|
||||
|
||||
NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
|
||||
|
||||
nv_encoder->last_dpms = mode;
|
||||
list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
|
||||
struct nouveau_encoder *nvenc = nouveau_encoder(enc);
|
||||
|
||||
if (nvenc == nv_encoder ||
|
||||
nvenc->dcb->or != nv_encoder->dcb->or)
|
||||
continue;
|
||||
|
||||
if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for it to be done */
|
||||
if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or),
|
||||
NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) {
|
||||
|
|
|
@ -246,6 +246,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
|
|||
case ATOM_WS_ATTRIBUTES:
|
||||
val = gctx->io_attr;
|
||||
break;
|
||||
case ATOM_WS_REGPTR:
|
||||
val = gctx->reg_block;
|
||||
break;
|
||||
default:
|
||||
val = ctx->ws[idx];
|
||||
}
|
||||
|
@ -385,6 +388,32 @@ static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr)
|
|||
return atom_get_src_int(ctx, attr, ptr, NULL, 1);
|
||||
}
|
||||
|
||||
static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr)
|
||||
{
|
||||
uint32_t val = 0xCDCDCDCD;
|
||||
|
||||
switch (align) {
|
||||
case ATOM_SRC_DWORD:
|
||||
val = U32(*ptr);
|
||||
(*ptr) += 4;
|
||||
break;
|
||||
case ATOM_SRC_WORD0:
|
||||
case ATOM_SRC_WORD8:
|
||||
case ATOM_SRC_WORD16:
|
||||
val = U16(*ptr);
|
||||
(*ptr) += 2;
|
||||
break;
|
||||
case ATOM_SRC_BYTE0:
|
||||
case ATOM_SRC_BYTE8:
|
||||
case ATOM_SRC_BYTE16:
|
||||
case ATOM_SRC_BYTE24:
|
||||
val = U8(*ptr);
|
||||
(*ptr)++;
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
|
||||
int *ptr, uint32_t *saved, int print)
|
||||
{
|
||||
|
@ -482,6 +511,9 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
|
|||
case ATOM_WS_ATTRIBUTES:
|
||||
gctx->io_attr = val;
|
||||
break;
|
||||
case ATOM_WS_REGPTR:
|
||||
gctx->reg_block = val;
|
||||
break;
|
||||
default:
|
||||
ctx->ws[idx] = val;
|
||||
}
|
||||
|
@ -677,7 +709,7 @@ static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
|
|||
SDEBUG(" dst: ");
|
||||
dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
|
||||
SDEBUG(" src1: ");
|
||||
src1 = atom_get_src(ctx, attr, ptr);
|
||||
src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
|
||||
SDEBUG(" src2: ");
|
||||
src2 = atom_get_src(ctx, attr, ptr);
|
||||
dst &= src1;
|
||||
|
@ -809,6 +841,38 @@ static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg)
|
|||
SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block);
|
||||
}
|
||||
|
||||
static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg)
|
||||
{
|
||||
uint8_t attr = U8((*ptr)++), shift;
|
||||
uint32_t saved, dst;
|
||||
int dptr = *ptr;
|
||||
attr &= 0x38;
|
||||
attr |= atom_def_dst[attr >> 3] << 6;
|
||||
SDEBUG(" dst: ");
|
||||
dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
|
||||
shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
|
||||
SDEBUG(" shift: %d\n", shift);
|
||||
dst <<= shift;
|
||||
SDEBUG(" dst: ");
|
||||
atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
|
||||
}
|
||||
|
||||
static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg)
|
||||
{
|
||||
uint8_t attr = U8((*ptr)++), shift;
|
||||
uint32_t saved, dst;
|
||||
int dptr = *ptr;
|
||||
attr &= 0x38;
|
||||
attr |= atom_def_dst[attr >> 3] << 6;
|
||||
SDEBUG(" dst: ");
|
||||
dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
|
||||
shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
|
||||
SDEBUG(" shift: %d\n", shift);
|
||||
dst >>= shift;
|
||||
SDEBUG(" dst: ");
|
||||
atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
|
||||
}
|
||||
|
||||
static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
|
||||
{
|
||||
uint8_t attr = U8((*ptr)++), shift;
|
||||
|
@ -818,7 +882,7 @@ static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
|
|||
attr |= atom_def_dst[attr >> 3] << 6;
|
||||
SDEBUG(" dst: ");
|
||||
dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
|
||||
shift = U8((*ptr)++);
|
||||
shift = atom_get_src(ctx, attr, ptr);
|
||||
SDEBUG(" shift: %d\n", shift);
|
||||
dst <<= shift;
|
||||
SDEBUG(" dst: ");
|
||||
|
@ -834,7 +898,7 @@ static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
|
|||
attr |= atom_def_dst[attr >> 3] << 6;
|
||||
SDEBUG(" dst: ");
|
||||
dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
|
||||
shift = U8((*ptr)++);
|
||||
shift = atom_get_src(ctx, attr, ptr);
|
||||
SDEBUG(" shift: %d\n", shift);
|
||||
dst >>= shift;
|
||||
SDEBUG(" dst: ");
|
||||
|
@ -937,18 +1001,18 @@ static struct {
|
|||
atom_op_or, ATOM_ARG_FB}, {
|
||||
atom_op_or, ATOM_ARG_PLL}, {
|
||||
atom_op_or, ATOM_ARG_MC}, {
|
||||
atom_op_shl, ATOM_ARG_REG}, {
|
||||
atom_op_shl, ATOM_ARG_PS}, {
|
||||
atom_op_shl, ATOM_ARG_WS}, {
|
||||
atom_op_shl, ATOM_ARG_FB}, {
|
||||
atom_op_shl, ATOM_ARG_PLL}, {
|
||||
atom_op_shl, ATOM_ARG_MC}, {
|
||||
atom_op_shr, ATOM_ARG_REG}, {
|
||||
atom_op_shr, ATOM_ARG_PS}, {
|
||||
atom_op_shr, ATOM_ARG_WS}, {
|
||||
atom_op_shr, ATOM_ARG_FB}, {
|
||||
atom_op_shr, ATOM_ARG_PLL}, {
|
||||
atom_op_shr, ATOM_ARG_MC}, {
|
||||
atom_op_shift_left, ATOM_ARG_REG}, {
|
||||
atom_op_shift_left, ATOM_ARG_PS}, {
|
||||
atom_op_shift_left, ATOM_ARG_WS}, {
|
||||
atom_op_shift_left, ATOM_ARG_FB}, {
|
||||
atom_op_shift_left, ATOM_ARG_PLL}, {
|
||||
atom_op_shift_left, ATOM_ARG_MC}, {
|
||||
atom_op_shift_right, ATOM_ARG_REG}, {
|
||||
atom_op_shift_right, ATOM_ARG_PS}, {
|
||||
atom_op_shift_right, ATOM_ARG_WS}, {
|
||||
atom_op_shift_right, ATOM_ARG_FB}, {
|
||||
atom_op_shift_right, ATOM_ARG_PLL}, {
|
||||
atom_op_shift_right, ATOM_ARG_MC}, {
|
||||
atom_op_mul, ATOM_ARG_REG}, {
|
||||
atom_op_mul, ATOM_ARG_PS}, {
|
||||
atom_op_mul, ATOM_ARG_WS}, {
|
||||
|
@ -1058,8 +1122,6 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
|
|||
|
||||
SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
|
||||
|
||||
/* reset reg block */
|
||||
ctx->reg_block = 0;
|
||||
ectx.ctx = ctx;
|
||||
ectx.ps_shift = ps / 4;
|
||||
ectx.start = base;
|
||||
|
@ -1096,6 +1158,12 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
|
|||
void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
|
||||
{
|
||||
mutex_lock(&ctx->mutex);
|
||||
/* reset reg block */
|
||||
ctx->reg_block = 0;
|
||||
/* reset fb window */
|
||||
ctx->fb_base = 0;
|
||||
/* reset io mode */
|
||||
ctx->io_mode = ATOM_IO_MM;
|
||||
atom_execute_table_locked(ctx, index, params);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#define ATOM_WS_AND_MASK 0x45
|
||||
#define ATOM_WS_FB_WINDOW 0x46
|
||||
#define ATOM_WS_ATTRIBUTES 0x47
|
||||
#define ATOM_WS_REGPTR 0x48
|
||||
|
||||
#define ATOM_IIO_NOP 0
|
||||
#define ATOM_IIO_START 1
|
||||
|
|
|
@ -307,7 +307,6 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
|
|||
args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
|
||||
args.ucCRTC = radeon_crtc->crtc_id;
|
||||
|
||||
printk("executing set crtc dtd timing\n");
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
|
@ -347,7 +346,6 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
|
|||
args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
|
||||
args.ucCRTC = radeon_crtc->crtc_id;
|
||||
|
||||
printk("executing set crtc timing\n");
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
|
@ -409,59 +407,57 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
|
|||
}
|
||||
}
|
||||
|
||||
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
union adjust_pixel_clock {
|
||||
ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
|
||||
};
|
||||
|
||||
static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct radeon_pll *pll)
|
||||
{
|
||||
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 *encoder = NULL;
|
||||
struct radeon_encoder *radeon_encoder = NULL;
|
||||
uint8_t frev, crev;
|
||||
int index;
|
||||
SET_PIXEL_CLOCK_PS_ALLOCATION args;
|
||||
PIXEL_CLOCK_PARAMETERS *spc1_ptr;
|
||||
PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
|
||||
PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
|
||||
uint32_t pll_clock = mode->clock;
|
||||
uint32_t adjusted_clock;
|
||||
uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
|
||||
struct radeon_pll *pll;
|
||||
int pll_flags = 0;
|
||||
u32 adjusted_clock = mode->clock;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
/* reset the pll flags */
|
||||
pll->flags = 0;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if ((rdev->family == CHIP_RS600) ||
|
||||
(rdev->family == CHIP_RS690) ||
|
||||
(rdev->family == CHIP_RS740))
|
||||
pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
|
||||
RADEON_PLL_PREFER_CLOSEST_LOWER);
|
||||
pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
|
||||
RADEON_PLL_PREFER_CLOSEST_LOWER);
|
||||
|
||||
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
|
||||
pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
else
|
||||
pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
} else {
|
||||
pll_flags |= RADEON_PLL_LEGACY;
|
||||
pll->flags |= RADEON_PLL_LEGACY;
|
||||
|
||||
if (mode->clock > 200000) /* range limits??? */
|
||||
pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
else
|
||||
pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
|
||||
}
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
if (!ASIC_IS_AVIVO(rdev)) {
|
||||
if (encoder->encoder_type !=
|
||||
DRM_MODE_ENCODER_DAC)
|
||||
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
if (encoder->encoder_type ==
|
||||
DRM_MODE_ENCODER_LVDS)
|
||||
pll_flags |= RADEON_PLL_USE_REF_DIV;
|
||||
}
|
||||
radeon_encoder = to_radeon_encoder(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;
|
||||
} else {
|
||||
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
|
||||
pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
|
||||
pll->flags |= RADEON_PLL_USE_REF_DIV;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -471,46 +467,101 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
* special hw requirements.
|
||||
*/
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
|
||||
union adjust_pixel_clock args;
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
u8 frev, crev;
|
||||
int index;
|
||||
|
||||
if (!encoder)
|
||||
return;
|
||||
|
||||
memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
|
||||
adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
|
||||
adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return adjusted_clock;
|
||||
dig = radeon_encoder->enc_priv;
|
||||
|
||||
index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
|
||||
atom_execute_table(rdev->mode_info.atom_context,
|
||||
index, (uint32_t *)&adjust_pll_args);
|
||||
adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
|
||||
} else {
|
||||
/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
|
||||
if (ASIC_IS_AVIVO(rdev) &&
|
||||
(radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
|
||||
adjusted_clock = mode->clock * 2;
|
||||
else
|
||||
adjusted_clock = mode->clock;
|
||||
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
|
||||
&crev);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
switch (frev) {
|
||||
case 1:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
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);
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args);
|
||||
adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
|
||||
return adjusted_clock;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
|
||||
return adjusted_clock;
|
||||
}
|
||||
}
|
||||
return adjusted_clock;
|
||||
}
|
||||
|
||||
union set_pixel_clock {
|
||||
SET_PIXEL_CLOCK_PS_ALLOCATION base;
|
||||
PIXEL_CLOCK_PARAMETERS v1;
|
||||
PIXEL_CLOCK_PARAMETERS_V2 v2;
|
||||
PIXEL_CLOCK_PARAMETERS_V3 v3;
|
||||
};
|
||||
|
||||
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;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_encoder *encoder = NULL;
|
||||
struct radeon_encoder *radeon_encoder = NULL;
|
||||
u8 frev, crev;
|
||||
int index;
|
||||
union set_pixel_clock args;
|
||||
u32 pll_clock = mode->clock;
|
||||
u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
|
||||
struct radeon_pll *pll;
|
||||
u32 adjusted_clock;
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!radeon_encoder)
|
||||
return;
|
||||
|
||||
if (radeon_crtc->crtc_id == 0)
|
||||
pll = &rdev->clock.p1pll;
|
||||
else
|
||||
pll = &rdev->clock.p2pll;
|
||||
|
||||
/* 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, pll_flags);
|
||||
&ref_div, &post_div);
|
||||
else
|
||||
radeon_compute_pll(pll, adjusted_clock, &pll_clock,
|
||||
&fb_div, &frac_fb_div,
|
||||
&ref_div, &post_div, pll_flags);
|
||||
&ref_div, &post_div);
|
||||
} else
|
||||
radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
|
||||
&ref_div, &post_div, pll_flags);
|
||||
&ref_div, &post_div);
|
||||
|
||||
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
|
||||
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
|
||||
|
@ -520,45 +571,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
case 1:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
|
||||
spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
|
||||
spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
|
||||
spc1_ptr->ucFracFbDiv = frac_fb_div;
|
||||
spc1_ptr->ucPostDiv = post_div;
|
||||
spc1_ptr->ucPpll =
|
||||
args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
args.v1.usRefDiv = cpu_to_le16(ref_div);
|
||||
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;
|
||||
spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
|
||||
spc1_ptr->ucRefDivSrc = 1;
|
||||
args.v1.ucCRTC = radeon_crtc->crtc_id;
|
||||
args.v1.ucRefDivSrc = 1;
|
||||
break;
|
||||
case 2:
|
||||
spc2_ptr =
|
||||
(PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
|
||||
spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
|
||||
spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
|
||||
spc2_ptr->ucFracFbDiv = frac_fb_div;
|
||||
spc2_ptr->ucPostDiv = post_div;
|
||||
spc2_ptr->ucPpll =
|
||||
args.v2.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
args.v2.usRefDiv = cpu_to_le16(ref_div);
|
||||
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;
|
||||
spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
|
||||
spc2_ptr->ucRefDivSrc = 1;
|
||||
args.v2.ucCRTC = radeon_crtc->crtc_id;
|
||||
args.v2.ucRefDivSrc = 1;
|
||||
break;
|
||||
case 3:
|
||||
if (!encoder)
|
||||
return;
|
||||
spc3_ptr =
|
||||
(PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
|
||||
spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
|
||||
spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
|
||||
spc3_ptr->ucFracFbDiv = frac_fb_div;
|
||||
spc3_ptr->ucPostDiv = post_div;
|
||||
spc3_ptr->ucPpll =
|
||||
args.v3.usPixelClock = cpu_to_le16(mode->clock / 10);
|
||||
args.v3.usRefDiv = cpu_to_le16(ref_div);
|
||||
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;
|
||||
spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
|
||||
spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
|
||||
spc3_ptr->ucEncoderMode =
|
||||
args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
|
||||
args.v3.ucTransmitterId = radeon_encoder->encoder_id;
|
||||
args.v3.ucEncoderMode =
|
||||
atombios_get_encoder_mode(encoder);
|
||||
break;
|
||||
default:
|
||||
|
@ -571,12 +615,11 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
return;
|
||||
}
|
||||
|
||||
printk("executing set pll\n");
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
static int avivo_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;
|
||||
|
@ -706,6 +749,42 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* properly set additional regs when using atombios */
|
||||
static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
u32 disp_merge_cntl;
|
||||
|
||||
switch (radeon_crtc->crtc_id) {
|
||||
case 0:
|
||||
disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
|
||||
disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
|
||||
WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
|
||||
break;
|
||||
case 1:
|
||||
disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
|
||||
disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
|
||||
WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
|
||||
WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
|
||||
WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int atombios_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode,
|
||||
|
@ -727,8 +806,8 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
|
|||
else {
|
||||
if (radeon_crtc->crtc_id == 0)
|
||||
atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
|
||||
radeon_crtc_set_base(crtc, x, y, old_fb);
|
||||
radeon_legacy_atom_set_surface(crtc);
|
||||
atombios_crtc_set_base(crtc, x, y, old_fb);
|
||||
radeon_legacy_atom_fixup(crtc);
|
||||
}
|
||||
atombios_overscan_setup(crtc, mode, adjusted_mode);
|
||||
atombios_scaler_setup(crtc);
|
||||
|
@ -746,8 +825,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
|
|||
|
||||
static void atombios_crtc_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
atombios_lock_crtc(crtc, 1);
|
||||
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
static void atombios_crtc_commit(struct drm_crtc *crtc)
|
||||
|
|
|
@ -1504,6 +1504,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
|
|||
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0));
|
||||
track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
|
||||
track->immd_dwords = pkt->count - 1;
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
|
@ -3399,9 +3400,7 @@ int r100_mc_init(struct radeon_device *rdev)
|
|||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
printk(KERN_WARNING "[drm] Disabling AGP\n");
|
||||
rdev->flags &= ~RADEON_IS_AGP;
|
||||
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
|
||||
radeon_agp_disable(rdev);
|
||||
} else {
|
||||
rdev->mc.gtt_location = rdev->mc.agp_base;
|
||||
}
|
||||
|
|
|
@ -371,13 +371,16 @@ int r200_packet0_check(struct radeon_cs_parser *p,
|
|||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
/* 1D/2D */
|
||||
track->textures[i].tex_coord_type = 0;
|
||||
break;
|
||||
case 1:
|
||||
track->textures[i].tex_coord_type = 1;
|
||||
/* CUBE */
|
||||
track->textures[i].tex_coord_type = 2;
|
||||
break;
|
||||
case 2:
|
||||
track->textures[i].tex_coord_type = 2;
|
||||
/* 3D */
|
||||
track->textures[i].tex_coord_type = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -50,9 +50,7 @@ int r420_mc_init(struct radeon_device *rdev)
|
|||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r) {
|
||||
printk(KERN_WARNING "[drm] Disabling AGP\n");
|
||||
rdev->flags &= ~RADEON_IS_AGP;
|
||||
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
|
||||
radeon_agp_disable(rdev);
|
||||
} else {
|
||||
rdev->mc.gtt_location = rdev->mc.agp_base;
|
||||
}
|
||||
|
|
|
@ -624,7 +624,6 @@ int r600_mc_init(struct radeon_device *rdev)
|
|||
fixed20_12 a;
|
||||
u32 tmp;
|
||||
int chansize, numchan;
|
||||
int r;
|
||||
|
||||
/* Get VRAM informations */
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
|
@ -667,9 +666,6 @@ int r600_mc_init(struct radeon_device *rdev)
|
|||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* 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;
|
||||
|
@ -1958,14 +1954,17 @@ int r600_suspend(struct radeon_device *rdev)
|
|||
/* FIXME: we should wait for ring to be empty */
|
||||
r600_cp_stop(rdev);
|
||||
rdev->cp.ready = false;
|
||||
r600_irq_suspend(rdev);
|
||||
r600_wb_disable(rdev);
|
||||
r600_pcie_gart_disable(rdev);
|
||||
/* unpin shaders bo */
|
||||
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
radeon_bo_unpin(rdev->r600_blit.shader_obj);
|
||||
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
|
||||
if (rdev->r600_blit.shader_obj) {
|
||||
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
|
||||
if (!r) {
|
||||
radeon_bo_unpin(rdev->r600_blit.shader_obj);
|
||||
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2026,6 +2025,11 @@ int r600_init(struct radeon_device *rdev)
|
|||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r)
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
r = r600_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -2060,13 +2064,14 @@ int r600_init(struct radeon_device *rdev)
|
|||
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);
|
||||
dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
|
||||
rdev->accel_working = false;
|
||||
} else {
|
||||
r = r600_ib_test(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "IB test failed (%d).\n", r);
|
||||
rdev->accel_working = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2197,14 +2202,14 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
|
|||
rb_bufsz = drm_order(ring_size / 4);
|
||||
ring_size = (1 << rb_bufsz) * 4;
|
||||
rdev->ih.ring_size = ring_size;
|
||||
rdev->ih.align_mask = 4 - 1;
|
||||
rdev->ih.ptr_mask = rdev->ih.ring_size - 1;
|
||||
rdev->ih.rptr = 0;
|
||||
}
|
||||
|
||||
static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size)
|
||||
static int r600_ih_ring_alloc(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
rdev->ih.ring_size = ring_size;
|
||||
/* Allocate ring buffer */
|
||||
if (rdev->ih.ring_obj == NULL) {
|
||||
r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
|
||||
|
@ -2234,9 +2239,6 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size)
|
|||
return r;
|
||||
}
|
||||
}
|
||||
rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1;
|
||||
rdev->ih.rptr = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2386,7 +2388,7 @@ int r600_irq_init(struct radeon_device *rdev)
|
|||
u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
|
||||
|
||||
/* allocate ring */
|
||||
ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size);
|
||||
ret = r600_ih_ring_alloc(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -2449,10 +2451,15 @@ int r600_irq_init(struct radeon_device *rdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void r600_irq_fini(struct radeon_device *rdev)
|
||||
void r600_irq_suspend(struct radeon_device *rdev)
|
||||
{
|
||||
r600_disable_interrupts(rdev);
|
||||
r600_rlc_stop(rdev);
|
||||
}
|
||||
|
||||
void r600_irq_fini(struct radeon_device *rdev)
|
||||
{
|
||||
r600_irq_suspend(rdev);
|
||||
r600_ih_ring_fini(rdev);
|
||||
}
|
||||
|
||||
|
@ -2467,8 +2474,12 @@ int r600_irq_set(struct radeon_device *rdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
/* don't enable anything if the ih is disabled */
|
||||
if (!rdev->ih.enabled)
|
||||
if (!rdev->ih.enabled) {
|
||||
r600_disable_interrupts(rdev);
|
||||
/* force the active interrupt state to all disabled */
|
||||
r600_disable_interrupt_state(rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
|
@ -2638,16 +2649,18 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
|
|||
wptr = RREG32(IH_RB_WPTR);
|
||||
|
||||
if (wptr & RB_OVERFLOW) {
|
||||
WARN_ON(1);
|
||||
/* XXX deal with overflow */
|
||||
DRM_ERROR("IH RB overflow\n");
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||
tmp = RREG32(IH_RB_CNTL);
|
||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||
WREG32(IH_RB_CNTL, tmp);
|
||||
}
|
||||
wptr = wptr & WPTR_OFFSET_MASK;
|
||||
|
||||
return wptr;
|
||||
return (wptr & rdev->ih.ptr_mask);
|
||||
}
|
||||
|
||||
/* r600 IV Ring
|
||||
|
@ -2683,12 +2696,13 @@ int r600_irq_process(struct radeon_device *rdev)
|
|||
u32 wptr = r600_get_ih_wptr(rdev);
|
||||
u32 rptr = rdev->ih.rptr;
|
||||
u32 src_id, src_data;
|
||||
u32 last_entry = rdev->ih.ring_size - 16;
|
||||
u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
|
||||
unsigned long flags;
|
||||
bool queue_hotplug = false;
|
||||
|
||||
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
|
||||
if (!rdev->ih.enabled)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&rdev->ih.lock, flags);
|
||||
|
||||
|
@ -2817,10 +2831,8 @@ restart_ih:
|
|||
}
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
if (rptr == last_entry)
|
||||
rptr = 0;
|
||||
else
|
||||
rptr += 16;
|
||||
rptr += 16;
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
}
|
||||
/* make sure wptr hasn't changed while processing */
|
||||
wptr = r600_get_ih_wptr(rdev);
|
||||
|
|
|
@ -512,14 +512,16 @@ void r600_blit_fini(struct radeon_device *rdev)
|
|||
{
|
||||
int r;
|
||||
|
||||
if (rdev->r600_blit.shader_obj == NULL)
|
||||
return;
|
||||
/* If we can't reserve the bo, unref should be enough to destroy
|
||||
* it when it becomes idle.
|
||||
*/
|
||||
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
|
||||
if (unlikely(r != 0)) {
|
||||
dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r);
|
||||
goto out_unref;
|
||||
if (!r) {
|
||||
radeon_bo_unpin(rdev->r600_blit.shader_obj);
|
||||
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
|
||||
}
|
||||
radeon_bo_unpin(rdev->r600_blit.shader_obj);
|
||||
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
|
||||
out_unref:
|
||||
radeon_bo_unref(&rdev->r600_blit.shader_obj);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
|||
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;
|
||||
|
||||
struct r600_cs_track {
|
||||
u32 cb_color0_base_last;
|
||||
};
|
||||
|
||||
/**
|
||||
* r600_cs_packet_parse() - parse cp packet and point ib index to next packet
|
||||
* @parser: parser structure holding parsing context.
|
||||
|
@ -176,6 +180,28 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
|
||||
* @parser: parser structure holding parsing context.
|
||||
*
|
||||
* Check next packet is relocation packet3, do bo validation and compute
|
||||
* GPU offset using the provided start.
|
||||
**/
|
||||
static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
|
||||
{
|
||||
struct radeon_cs_packet p3reloc;
|
||||
int r;
|
||||
|
||||
r = r600_cs_packet_parse(p, &p3reloc, p->idx);
|
||||
if (r) {
|
||||
return 0;
|
||||
}
|
||||
if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_cs_packet_next_vline() - parse userspace VLINE packet
|
||||
* @parser: parser structure holding parsing context.
|
||||
|
@ -337,6 +363,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
struct radeon_cs_packet *pkt)
|
||||
{
|
||||
struct radeon_cs_reloc *reloc;
|
||||
struct r600_cs_track *track;
|
||||
volatile u32 *ib;
|
||||
unsigned idx;
|
||||
unsigned i;
|
||||
|
@ -344,6 +371,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
int r;
|
||||
u32 idx_value;
|
||||
|
||||
track = (struct r600_cs_track *)p->track;
|
||||
ib = p->ib->ptr;
|
||||
idx = pkt->idx + 1;
|
||||
idx_value = radeon_get_ib_value(p, idx);
|
||||
|
@ -503,9 +531,60 @@ 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:
|
||||
|
@ -678,8 +757,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
|
|||
int r600_cs_parse(struct radeon_cs_parser *p)
|
||||
{
|
||||
struct radeon_cs_packet pkt;
|
||||
struct r600_cs_track *track;
|
||||
int r;
|
||||
|
||||
track = kzalloc(sizeof(*track), GFP_KERNEL);
|
||||
p->track = track;
|
||||
do {
|
||||
r = r600_cs_packet_parse(p, &pkt, p->idx);
|
||||
if (r) {
|
||||
|
@ -757,6 +839,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
|
|||
/* initialize parser */
|
||||
memset(&parser, 0, sizeof(struct radeon_cs_parser));
|
||||
parser.filp = filp;
|
||||
parser.dev = &dev->pdev->dev;
|
||||
parser.rdev = NULL;
|
||||
parser.family = family;
|
||||
parser.ib = &fake_ib;
|
||||
|
|
|
@ -882,4 +882,29 @@
|
|||
#define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17)
|
||||
|
||||
#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480
|
||||
|
||||
#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)
|
||||
#define C_0280E0_BASE_256B 0x00000000
|
||||
#define R_0280E4_CB_COLOR1_FRAG 0x0280E4
|
||||
#define R_0280E8_CB_COLOR2_FRAG 0x0280E8
|
||||
#define R_0280EC_CB_COLOR3_FRAG 0x0280EC
|
||||
#define R_0280F0_CB_COLOR4_FRAG 0x0280F0
|
||||
#define R_0280F4_CB_COLOR5_FRAG 0x0280F4
|
||||
#define R_0280F8_CB_COLOR6_FRAG 0x0280F8
|
||||
#define R_0280FC_CB_COLOR7_FRAG 0x0280FC
|
||||
#define R_0280C0_CB_COLOR0_TILE 0x0280C0
|
||||
#define S_0280C0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_0280C0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_0280C0_BASE_256B 0x00000000
|
||||
#define R_0280C4_CB_COLOR1_TILE 0x0280C4
|
||||
#define R_0280C8_CB_COLOR2_TILE 0x0280C8
|
||||
#define R_0280CC_CB_COLOR3_TILE 0x0280CC
|
||||
#define R_0280D0_CB_COLOR4_TILE 0x0280D0
|
||||
#define R_0280D4_CB_COLOR5_TILE 0x0280D4
|
||||
#define R_0280D8_CB_COLOR6_TILE 0x0280D8
|
||||
#define R_0280DC_CB_COLOR7_TILE 0x0280DC
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -410,7 +410,6 @@ struct r600_ih {
|
|||
unsigned wptr_old;
|
||||
unsigned ring_size;
|
||||
uint64_t gpu_addr;
|
||||
uint32_t align_mask;
|
||||
uint32_t ptr_mask;
|
||||
spinlock_t lock;
|
||||
bool enabled;
|
||||
|
@ -465,6 +464,7 @@ struct radeon_cs_chunk {
|
|||
};
|
||||
|
||||
struct radeon_cs_parser {
|
||||
struct device *dev;
|
||||
struct radeon_device *rdev;
|
||||
struct drm_file *filp;
|
||||
/* chunks */
|
||||
|
@ -847,7 +847,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
|
|||
|
||||
static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
|
||||
{
|
||||
if (reg < 0x10000)
|
||||
if (reg < rdev->rmmio_size)
|
||||
return readl(((void __iomem *)rdev->rmmio) + reg);
|
||||
else {
|
||||
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
|
||||
|
@ -857,7 +857,7 @@ static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
|
|||
|
||||
static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
|
||||
{
|
||||
if (reg < 0x10000)
|
||||
if (reg < rdev->rmmio_size)
|
||||
writel(v, ((void __iomem *)rdev->rmmio) + reg);
|
||||
else {
|
||||
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
|
||||
|
@ -1017,6 +1017,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
|||
#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
|
||||
|
||||
/* Common functions */
|
||||
/* AGP */
|
||||
extern void radeon_agp_disable(struct radeon_device *rdev);
|
||||
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
|
||||
extern int radeon_modeset_init(struct radeon_device *rdev);
|
||||
extern void radeon_modeset_fini(struct radeon_device *rdev);
|
||||
|
@ -1160,7 +1162,8 @@ extern int r600_irq_init(struct radeon_device *rdev);
|
|||
extern void r600_irq_fini(struct radeon_device *rdev);
|
||||
extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
|
||||
extern int r600_irq_set(struct radeon_device *rdev);
|
||||
|
||||
extern void r600_irq_suspend(struct radeon_device *rdev);
|
||||
/* r600 audio */
|
||||
extern int r600_audio_init(struct radeon_device *rdev);
|
||||
extern int r600_audio_tmds_index(struct drm_encoder *encoder);
|
||||
extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
|
||||
|
|
|
@ -133,6 +133,13 @@ int radeon_agp_init(struct radeon_device *rdev)
|
|||
bool is_v3;
|
||||
int ret;
|
||||
|
||||
if (rdev->ddev->agp->agp_info.aper_size < 32) {
|
||||
dev_warn(rdev->dev, "AGP aperture to small (%dM) "
|
||||
"need at least 32M, disabling AGP\n",
|
||||
rdev->ddev->agp->agp_info.aper_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Acquire AGP. */
|
||||
if (!rdev->ddev->agp->acquired) {
|
||||
ret = drm_agp_acquire(rdev->ddev);
|
||||
|
|
|
@ -56,7 +56,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
|
|||
else if (post_div == 3)
|
||||
sclk >>= 2;
|
||||
else if (post_div == 4)
|
||||
sclk >>= 4;
|
||||
sclk >>= 3;
|
||||
|
||||
return sclk;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
|
|||
else if (post_div == 3)
|
||||
mclk >>= 2;
|
||||
else if (post_div == 4)
|
||||
mclk >>= 4;
|
||||
mclk >>= 3;
|
||||
|
||||
return mclk;
|
||||
}
|
||||
|
|
|
@ -231,6 +231,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
memset(&parser, 0, sizeof(struct radeon_cs_parser));
|
||||
parser.filp = filp;
|
||||
parser.rdev = rdev;
|
||||
parser.dev = rdev->dev;
|
||||
r = radeon_cs_parser_init(&parser, data);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to initialize parser !\n");
|
||||
|
|
|
@ -544,6 +544,7 @@ void radeon_agp_disable(struct radeon_device *rdev)
|
|||
rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &r100_pci_gart_set_page;
|
||||
}
|
||||
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
|
||||
}
|
||||
|
||||
void radeon_check_arguments(struct radeon_device *rdev)
|
||||
|
|
|
@ -357,7 +357,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
|
|||
if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
|
||||
(radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
|
||||
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
|
||||
if (dig->dp_i2c_bus)
|
||||
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
|
||||
dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
|
||||
}
|
||||
if (!radeon_connector->ddc_bus)
|
||||
|
@ -410,11 +411,12 @@ void radeon_compute_pll(struct radeon_pll *pll,
|
|||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p,
|
||||
int flags)
|
||||
uint32_t *post_div_p)
|
||||
{
|
||||
uint32_t min_ref_div = pll->min_ref_div;
|
||||
uint32_t max_ref_div = pll->max_ref_div;
|
||||
uint32_t min_post_div = pll->min_post_div;
|
||||
uint32_t max_post_div = pll->max_post_div;
|
||||
uint32_t min_fractional_feed_div = 0;
|
||||
uint32_t max_fractional_feed_div = 0;
|
||||
uint32_t best_vco = pll->best_vco;
|
||||
|
@ -430,7 +432,7 @@ void radeon_compute_pll(struct radeon_pll *pll,
|
|||
DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
|
||||
freq = freq * 1000;
|
||||
|
||||
if (flags & RADEON_PLL_USE_REF_DIV)
|
||||
if (pll->flags & RADEON_PLL_USE_REF_DIV)
|
||||
min_ref_div = max_ref_div = pll->reference_div;
|
||||
else {
|
||||
while (min_ref_div < max_ref_div-1) {
|
||||
|
@ -445,19 +447,22 @@ void radeon_compute_pll(struct radeon_pll *pll,
|
|||
}
|
||||
}
|
||||
|
||||
if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
|
||||
if (pll->flags & RADEON_PLL_USE_POST_DIV)
|
||||
min_post_div = max_post_div = pll->post_div;
|
||||
|
||||
if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
|
||||
min_fractional_feed_div = pll->min_frac_feedback_div;
|
||||
max_fractional_feed_div = pll->max_frac_feedback_div;
|
||||
}
|
||||
|
||||
for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
|
||||
for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
|
||||
uint32_t ref_div;
|
||||
|
||||
if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
|
||||
if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
|
||||
continue;
|
||||
|
||||
/* legacy radeons only have a few post_divs */
|
||||
if (flags & RADEON_PLL_LEGACY) {
|
||||
if (pll->flags & RADEON_PLL_LEGACY) {
|
||||
if ((post_div == 5) ||
|
||||
(post_div == 7) ||
|
||||
(post_div == 9) ||
|
||||
|
@ -504,7 +509,7 @@ void radeon_compute_pll(struct radeon_pll *pll,
|
|||
tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
|
||||
current_freq = radeon_div(tmp, ref_div * post_div);
|
||||
|
||||
if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
|
||||
if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
|
||||
error = freq - current_freq;
|
||||
error = error < 0 ? 0xffffffff : error;
|
||||
} else
|
||||
|
@ -531,12 +536,12 @@ void radeon_compute_pll(struct radeon_pll *pll,
|
|||
best_freq = current_freq;
|
||||
best_error = error;
|
||||
best_vco_diff = vco_diff;
|
||||
} else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
|
||||
((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
|
||||
((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
|
||||
((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
|
||||
((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
|
||||
((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
|
||||
} else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
|
||||
((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
|
||||
((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
|
||||
((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
|
||||
((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
|
||||
((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
|
||||
best_post_div = post_div;
|
||||
best_ref_div = ref_div;
|
||||
best_feedback_div = feedback_div;
|
||||
|
@ -572,8 +577,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
|
|||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p,
|
||||
int flags)
|
||||
uint32_t *post_div_p)
|
||||
{
|
||||
fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq;
|
||||
fixed20_12 pll_out_max, pll_out_min;
|
||||
|
@ -667,7 +671,6 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
|||
radeonfb_remove(dev, fb);
|
||||
|
||||
if (radeon_fb->obj) {
|
||||
radeon_gem_object_unpin(radeon_fb->obj);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference(radeon_fb->obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
@ -715,7 +718,11 @@ radeon_user_framebuffer_create(struct drm_device *dev,
|
|||
struct drm_gem_object *obj;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
|
||||
|
||||
if (obj == NULL) {
|
||||
dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
|
||||
"can't create framebuffer\n", mode_cmd->handle);
|
||||
return NULL;
|
||||
}
|
||||
return radeon_framebuffer_create(dev, mode_cmd, obj);
|
||||
}
|
||||
|
||||
|
|
|
@ -339,69 +339,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
}
|
||||
}
|
||||
|
||||
/* properly set crtc bpp when using atombios */
|
||||
void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
int format;
|
||||
uint32_t crtc_gen_cntl;
|
||||
uint32_t disp_merge_cntl;
|
||||
uint32_t crtc_pitch;
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
format = 2;
|
||||
break;
|
||||
case 15: /* 555 */
|
||||
format = 3;
|
||||
break;
|
||||
case 16: /* 565 */
|
||||
format = 4;
|
||||
break;
|
||||
case 24: /* RGB */
|
||||
format = 5;
|
||||
break;
|
||||
case 32: /* xRGB */
|
||||
format = 6;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
crtc_pitch = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) +
|
||||
((crtc->fb->bits_per_pixel * 8) - 1)) /
|
||||
(crtc->fb->bits_per_pixel * 8));
|
||||
crtc_pitch |= crtc_pitch << 16;
|
||||
|
||||
WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
|
||||
|
||||
switch (radeon_crtc->crtc_id) {
|
||||
case 0:
|
||||
disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
|
||||
disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
|
||||
WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
|
||||
|
||||
crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
|
||||
crtc_gen_cntl |= (format << 8);
|
||||
crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
|
||||
WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
|
||||
break;
|
||||
case 1:
|
||||
disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
|
||||
disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
|
||||
WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
|
||||
|
||||
crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
|
||||
crtc_gen_cntl |= (format << 8);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl);
|
||||
WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
|
||||
WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
|
@ -755,7 +692,6 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
uint32_t post_divider = 0;
|
||||
uint32_t freq = 0;
|
||||
uint8_t pll_gain;
|
||||
int pll_flags = RADEON_PLL_LEGACY;
|
||||
bool use_bios_divs = false;
|
||||
/* PLL registers */
|
||||
uint32_t pll_ref_div = 0;
|
||||
|
@ -789,10 +725,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
else
|
||||
pll = &rdev->clock.p1pll;
|
||||
|
||||
pll->flags = RADEON_PLL_LEGACY;
|
||||
|
||||
if (mode->clock > 200000) /* range limits??? */
|
||||
pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
|
||||
else
|
||||
pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
|
@ -804,7 +742,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
}
|
||||
|
||||
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
|
||||
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
|
||||
if (!rdev->is_atom_bios) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
@ -819,7 +757,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
}
|
||||
}
|
||||
}
|
||||
pll_flags |= RADEON_PLL_USE_REF_DIV;
|
||||
pll->flags |= RADEON_PLL_USE_REF_DIV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -829,8 +767,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
if (!use_bios_divs) {
|
||||
radeon_compute_pll(pll, mode->clock,
|
||||
&freq, &feedback_div, &frac_fb_div,
|
||||
&reference_div, &post_divider,
|
||||
pll_flags);
|
||||
&reference_div, &post_divider);
|
||||
|
||||
for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
|
||||
if (post_div->divider == post_divider)
|
||||
|
|
|
@ -125,16 +125,24 @@ struct radeon_tmds_pll {
|
|||
#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
|
||||
#define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10)
|
||||
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
|
||||
#define RADEON_PLL_USE_POST_DIV (1 << 12)
|
||||
|
||||
struct radeon_pll {
|
||||
uint16_t reference_freq;
|
||||
uint16_t reference_div;
|
||||
/* reference frequency */
|
||||
uint32_t reference_freq;
|
||||
|
||||
/* fixed dividers */
|
||||
uint32_t reference_div;
|
||||
uint32_t post_div;
|
||||
|
||||
/* pll in/out limits */
|
||||
uint32_t pll_in_min;
|
||||
uint32_t pll_in_max;
|
||||
uint32_t pll_out_min;
|
||||
uint32_t pll_out_max;
|
||||
uint16_t xclk;
|
||||
uint32_t best_vco;
|
||||
|
||||
/* divider limits */
|
||||
uint32_t min_ref_div;
|
||||
uint32_t max_ref_div;
|
||||
uint32_t min_post_div;
|
||||
|
@ -143,7 +151,12 @@ struct radeon_pll {
|
|||
uint32_t max_feedback_div;
|
||||
uint32_t min_frac_feedback_div;
|
||||
uint32_t max_frac_feedback_div;
|
||||
uint32_t best_vco;
|
||||
|
||||
/* flags for the current clock */
|
||||
uint32_t flags;
|
||||
|
||||
/* pll id */
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct radeon_i2c_chan {
|
||||
|
@ -417,8 +430,7 @@ extern void radeon_compute_pll(struct radeon_pll *pll,
|
|||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p,
|
||||
int flags);
|
||||
uint32_t *post_div_p);
|
||||
|
||||
extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
|
||||
uint64_t freq,
|
||||
|
@ -426,8 +438,7 @@ extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
|
|||
uint32_t *fb_div_p,
|
||||
uint32_t *frac_fb_div_p,
|
||||
uint32_t *ref_div_p,
|
||||
uint32_t *post_div_p,
|
||||
int flags);
|
||||
uint32_t *post_div_p);
|
||||
|
||||
extern void radeon_setup_encoder_clones(struct drm_device *dev);
|
||||
|
||||
|
@ -453,7 +464,6 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode);
|
|||
|
||||
extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc);
|
||||
|
||||
extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
struct drm_file *file_priv,
|
||||
|
|
|
@ -220,7 +220,8 @@ int radeon_bo_unpin(struct radeon_bo *bo)
|
|||
|
||||
int radeon_bo_evict_vram(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
|
||||
if (0 && (rdev->flags & RADEON_IS_IGP)) {
|
||||
if (rdev->mc.igp_sideport_enabled == false)
|
||||
/* Useless to evict on IGP chips */
|
||||
return 0;
|
||||
|
|
|
@ -91,6 +91,8 @@ r200 0x3294
|
|||
0x22b8 SE_TCL_TEX_CYL_WRAP_CTL
|
||||
0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL
|
||||
0x22c4 SE_TCL_POINT_SPRITE_CNTL
|
||||
0x22d0 SE_PVS_CNTL
|
||||
0x22d4 SE_PVS_CONST_CNTL
|
||||
0x2648 RE_POINTSIZE
|
||||
0x26c0 RE_TOP_LEFT
|
||||
0x26c4 RE_MISC
|
||||
|
|
|
@ -779,7 +779,6 @@ int rv770_mc_init(struct radeon_device *rdev)
|
|||
fixed20_12 a;
|
||||
u32 tmp;
|
||||
int chansize, numchan;
|
||||
int r;
|
||||
|
||||
/* Get VRAM informations */
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
|
@ -822,9 +821,6 @@ int rv770_mc_init(struct radeon_device *rdev)
|
|||
rdev->mc.real_vram_size = rdev->mc.aper_size;
|
||||
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* 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;
|
||||
|
@ -972,13 +968,16 @@ int rv770_suspend(struct radeon_device *rdev)
|
|||
/* FIXME: we should wait for ring to be empty */
|
||||
r700_cp_stop(rdev);
|
||||
rdev->cp.ready = false;
|
||||
r600_irq_suspend(rdev);
|
||||
r600_wb_disable(rdev);
|
||||
rv770_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);
|
||||
if (rdev->r600_blit.shader_obj) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1037,6 +1036,11 @@ int rv770_init(struct radeon_device *rdev)
|
|||
r = radeon_fence_driver_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
r = radeon_agp_init(rdev);
|
||||
if (r)
|
||||
radeon_agp_disable(rdev);
|
||||
}
|
||||
r = rv770_mc_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -1071,13 +1075,14 @@ int rv770_init(struct radeon_device *rdev)
|
|||
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);
|
||||
dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
|
||||
rdev->accel_working = false;
|
||||
} else {
|
||||
r = r600_ib_test(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "IB test failed (%d).\n", r);
|
||||
rdev->accel_working = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -426,7 +426,8 @@ moved:
|
|||
bdev->man[bo->mem.mem_type].gpu_offset;
|
||||
bo->cur_placement = bo->mem.placement;
|
||||
spin_unlock(&bo->lock);
|
||||
}
|
||||
} else
|
||||
bo->offset = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -523,52 +524,44 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
|
|||
static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
|
||||
{
|
||||
struct ttm_bo_global *glob = bdev->glob;
|
||||
struct ttm_buffer_object *entry, *nentry;
|
||||
struct list_head *list, *next;
|
||||
int ret;
|
||||
struct ttm_buffer_object *entry = NULL;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&glob->lru_lock);
|
||||
list_for_each_safe(list, next, &bdev->ddestroy) {
|
||||
entry = list_entry(list, struct ttm_buffer_object, ddestroy);
|
||||
nentry = NULL;
|
||||
if (list_empty(&bdev->ddestroy))
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* Protect the next list entry from destruction while we
|
||||
* unlock the lru_lock.
|
||||
*/
|
||||
entry = list_first_entry(&bdev->ddestroy,
|
||||
struct ttm_buffer_object, ddestroy);
|
||||
kref_get(&entry->list_kref);
|
||||
|
||||
if (next != &bdev->ddestroy) {
|
||||
nentry = list_entry(next, struct ttm_buffer_object,
|
||||
ddestroy);
|
||||
for (;;) {
|
||||
struct ttm_buffer_object *nentry = NULL;
|
||||
|
||||
if (entry->ddestroy.next != &bdev->ddestroy) {
|
||||
nentry = list_first_entry(&entry->ddestroy,
|
||||
struct ttm_buffer_object, ddestroy);
|
||||
kref_get(&nentry->list_kref);
|
||||
}
|
||||
kref_get(&entry->list_kref);
|
||||
|
||||
spin_unlock(&glob->lru_lock);
|
||||
ret = ttm_bo_cleanup_refs(entry, remove_all);
|
||||
kref_put(&entry->list_kref, ttm_bo_release_list);
|
||||
entry = nentry;
|
||||
|
||||
if (ret || !entry)
|
||||
goto out;
|
||||
|
||||
spin_lock(&glob->lru_lock);
|
||||
if (nentry) {
|
||||
bool next_onlist = !list_empty(next);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
kref_put(&nentry->list_kref, ttm_bo_release_list);
|
||||
spin_lock(&glob->lru_lock);
|
||||
/*
|
||||
* Someone might have raced us and removed the
|
||||
* next entry from the list. We don't bother restarting
|
||||
* list traversal.
|
||||
*/
|
||||
|
||||
if (!next_onlist)
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
if (list_empty(&entry->ddestroy))
|
||||
break;
|
||||
}
|
||||
ret = !list_empty(&bdev->ddestroy);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&glob->lru_lock);
|
||||
out:
|
||||
if (entry)
|
||||
kref_put(&entry->list_kref, ttm_bo_release_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -950,6 +943,14 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
|
|||
ttm_flag_masked(&cur_flags, placement->busy_placement[i],
|
||||
~TTM_PL_MASK_MEMTYPE);
|
||||
|
||||
|
||||
if (mem_type == TTM_PL_SYSTEM) {
|
||||
mem->mem_type = mem_type;
|
||||
mem->placement = cur_flags;
|
||||
mem->mm_node = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem,
|
||||
interruptible, no_wait);
|
||||
if (ret == 0 && mem->mm_node) {
|
||||
|
@ -1844,6 +1845,9 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
|
|||
* anyone tries to access a ttm page.
|
||||
*/
|
||||
|
||||
if (bo->bdev->driver->swap_notify)
|
||||
bo->bdev->driver->swap_notify(bo);
|
||||
|
||||
ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage);
|
||||
out:
|
||||
|
||||
|
@ -1864,3 +1868,4 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev)
|
|||
while (ttm_bo_swapout(&bdev->glob->shrink) == 0)
|
||||
;
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_bo_swapout_all);
|
||||
|
|
|
@ -288,6 +288,7 @@ void ttm_suspend_unlock(struct ttm_lock *lock)
|
|||
wake_up_all(&lock->queue);
|
||||
spin_unlock(&lock->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_suspend_unlock);
|
||||
|
||||
static bool __ttm_suspend_lock(struct ttm_lock *lock)
|
||||
{
|
||||
|
@ -309,3 +310,4 @@ void ttm_suspend_lock(struct ttm_lock *lock)
|
|||
{
|
||||
wait_event(lock->queue, __ttm_suspend_lock(lock));
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_suspend_lock);
|
||||
|
|
|
@ -48,6 +48,15 @@ struct ttm_placement vmw_vram_placement = {
|
|||
.busy_placement = &vram_placement_flags
|
||||
};
|
||||
|
||||
struct ttm_placement vmw_vram_sys_placement = {
|
||||
.fpfn = 0,
|
||||
.lpfn = 0,
|
||||
.num_placement = 1,
|
||||
.placement = &vram_placement_flags,
|
||||
.num_busy_placement = 1,
|
||||
.busy_placement = &sys_placement_flags
|
||||
};
|
||||
|
||||
struct ttm_placement vmw_vram_ne_placement = {
|
||||
.fpfn = 0,
|
||||
.lpfn = 0,
|
||||
|
@ -172,6 +181,18 @@ static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vmw_move_notify(struct ttm_buffer_object *bo,
|
||||
struct ttm_mem_reg *new_mem)
|
||||
{
|
||||
if (new_mem->mem_type != TTM_PL_SYSTEM)
|
||||
vmw_dmabuf_gmr_unbind(bo);
|
||||
}
|
||||
|
||||
static void vmw_swap_notify(struct ttm_buffer_object *bo)
|
||||
{
|
||||
vmw_dmabuf_gmr_unbind(bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: We're using the old vmware polling method to sync.
|
||||
* Do this with fences instead.
|
||||
|
@ -225,5 +246,7 @@ struct ttm_bo_driver vmw_bo_driver = {
|
|||
.sync_obj_wait = vmw_sync_obj_wait,
|
||||
.sync_obj_flush = vmw_sync_obj_flush,
|
||||
.sync_obj_unref = vmw_sync_obj_unref,
|
||||
.sync_obj_ref = vmw_sync_obj_ref
|
||||
.sync_obj_ref = vmw_sync_obj_ref,
|
||||
.move_notify = vmw_move_notify,
|
||||
.swap_notify = vmw_swap_notify
|
||||
};
|
||||
|
|
|
@ -147,6 +147,8 @@ static char *vmw_devname = "vmwgfx";
|
|||
|
||||
static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
|
||||
static void vmw_master_init(struct vmw_master *);
|
||||
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *ptr);
|
||||
|
||||
static void vmw_print_capabilities(uint32_t capabilities)
|
||||
{
|
||||
|
@ -217,6 +219,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
|||
|
||||
dev_priv->dev = dev;
|
||||
dev_priv->vmw_chipset = chipset;
|
||||
dev_priv->last_read_sequence = (uint32_t) -100;
|
||||
mutex_init(&dev_priv->hw_mutex);
|
||||
mutex_init(&dev_priv->cmdbuf_mutex);
|
||||
rwlock_init(&dev_priv->resource_lock);
|
||||
|
@ -351,6 +354,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
|||
vmw_fb_init(dev_priv);
|
||||
}
|
||||
|
||||
dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
|
||||
register_pm_notifier(&dev_priv->pm_nb);
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_device:
|
||||
|
@ -385,6 +391,8 @@ static int vmw_driver_unload(struct drm_device *dev)
|
|||
|
||||
DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
|
||||
|
||||
unregister_pm_notifier(&dev_priv->pm_nb);
|
||||
|
||||
if (!dev_priv->stealth) {
|
||||
vmw_fb_close(dev_priv);
|
||||
vmw_kms_close(dev_priv);
|
||||
|
@ -650,6 +658,57 @@ static void vmw_remove(struct pci_dev *pdev)
|
|||
drm_put_dev(dev);
|
||||
}
|
||||
|
||||
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *ptr)
|
||||
{
|
||||
struct vmw_private *dev_priv =
|
||||
container_of(nb, struct vmw_private, pm_nb);
|
||||
struct vmw_master *vmaster = dev_priv->active_master;
|
||||
|
||||
switch (val) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
ttm_suspend_lock(&vmaster->lock);
|
||||
|
||||
/**
|
||||
* This empties VRAM and unbinds all GMR bindings.
|
||||
* Buffer contents is moved to swappable memory.
|
||||
*/
|
||||
ttm_bo_swapout_all(&dev_priv->bdev);
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_SUSPEND:
|
||||
ttm_suspend_unlock(&vmaster->lock);
|
||||
break;
|
||||
case PM_RESTORE_PREPARE:
|
||||
break;
|
||||
case PM_POST_RESTORE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* These might not be needed with the virtual SVGA device.
|
||||
*/
|
||||
|
||||
int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmw_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
return pci_enable_device(pdev);
|
||||
}
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
|
||||
DRIVER_MODESET,
|
||||
|
@ -689,7 +748,9 @@ static struct drm_driver driver = {
|
|||
.name = VMWGFX_DRIVER_NAME,
|
||||
.id_table = vmw_pci_id_list,
|
||||
.probe = vmw_probe,
|
||||
.remove = vmw_remove
|
||||
.remove = vmw_remove,
|
||||
.suspend = vmw_pci_suspend,
|
||||
.resume = vmw_pci_resume
|
||||
},
|
||||
.name = VMWGFX_DRIVER_NAME,
|
||||
.desc = VMWGFX_DRIVER_DESC,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "drmP.h"
|
||||
#include "vmwgfx_drm.h"
|
||||
#include "drm_hashtab.h"
|
||||
#include "linux/suspend.h"
|
||||
#include "ttm/ttm_bo_driver.h"
|
||||
#include "ttm/ttm_object.h"
|
||||
#include "ttm/ttm_lock.h"
|
||||
|
@ -258,6 +259,7 @@ struct vmw_private {
|
|||
|
||||
struct vmw_master *active_master;
|
||||
struct vmw_master fbdev_master;
|
||||
struct notifier_block pm_nb;
|
||||
};
|
||||
|
||||
static inline struct vmw_private *vmw_priv(struct drm_device *dev)
|
||||
|
@ -353,6 +355,7 @@ extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
|
|||
struct vmw_dma_buffer *bo);
|
||||
extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
|
||||
struct vmw_dma_buffer *bo);
|
||||
extern void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo);
|
||||
extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
|
||||
|
@ -401,6 +404,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
|
|||
|
||||
extern struct ttm_placement vmw_vram_placement;
|
||||
extern struct ttm_placement vmw_vram_ne_placement;
|
||||
extern struct ttm_placement vmw_vram_sys_placement;
|
||||
extern struct ttm_placement vmw_sys_placement;
|
||||
extern struct ttm_bo_driver vmw_bo_driver;
|
||||
extern int vmw_dma_quiescent(struct drm_device *dev);
|
||||
|
|
|
@ -487,6 +487,21 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
|
||||
return 0;
|
||||
|
||||
/**
|
||||
* Put BO in VRAM, only if there is space.
|
||||
*/
|
||||
|
||||
ret = ttm_bo_validate(bo, &vmw_vram_sys_placement, true, false);
|
||||
if (unlikely(ret == -ERESTARTSYS))
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* Otherwise, set it up as GMR.
|
||||
*/
|
||||
|
||||
if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
|
||||
return 0;
|
||||
|
||||
|
@ -494,6 +509,10 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
|
|||
if (likely(ret == 0 || ret == -ERESTARTSYS))
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* If that failed, try VRAM again, this time evicting
|
||||
* previous contents.
|
||||
*/
|
||||
|
||||
ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false);
|
||||
return ret;
|
||||
|
|
|
@ -649,14 +649,6 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
|
|||
if (unlikely(ret != 0))
|
||||
goto err_unlock;
|
||||
|
||||
if (vmw_bo->gmr_bound) {
|
||||
vmw_gmr_unbind(vmw_priv, vmw_bo->gmr_id);
|
||||
spin_lock(&bo->glob->lru_lock);
|
||||
ida_remove(&vmw_priv->gmr_ida, vmw_bo->gmr_id);
|
||||
spin_unlock(&bo->glob->lru_lock);
|
||||
vmw_bo->gmr_bound = NULL;
|
||||
}
|
||||
|
||||
ret = ttm_bo_validate(bo, &ne_placement, false, false);
|
||||
ttm_bo_unreserve(bo);
|
||||
err_unlock:
|
||||
|
|
|
@ -98,8 +98,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
|||
(unsigned int) min,
|
||||
(unsigned int) fifo->capabilities);
|
||||
|
||||
dev_priv->fence_seq = (uint32_t) -100;
|
||||
dev_priv->last_read_sequence = (uint32_t) -100;
|
||||
dev_priv->fence_seq = dev_priv->last_read_sequence;
|
||||
iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
|
||||
|
||||
return vmw_fifo_send_fence(dev_priv, &dummy);
|
||||
|
|
|
@ -553,9 +553,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
|
|||
} *cmd;
|
||||
int i, increment = 1;
|
||||
|
||||
if (!num_clips ||
|
||||
!(dev_priv->fifo.capabilities &
|
||||
SVGA_FIFO_CAP_SCREEN_OBJECT)) {
|
||||
if (!num_clips) {
|
||||
num_clips = 1;
|
||||
clips = &norect;
|
||||
norect.x1 = norect.y1 = 0;
|
||||
|
@ -574,10 +572,10 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
|
|||
|
||||
for (i = 0; i < num_clips; i++, clips += increment) {
|
||||
cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
|
||||
cmd[i].body.x = cpu_to_le32(clips[i].x1);
|
||||
cmd[i].body.y = cpu_to_le32(clips[i].y1);
|
||||
cmd[i].body.width = cpu_to_le32(clips[i].x2 - clips[i].x1);
|
||||
cmd[i].body.height = cpu_to_le32(clips[i].y2 - clips[i].y1);
|
||||
cmd[i].body.x = cpu_to_le32(clips->x1);
|
||||
cmd[i].body.y = cpu_to_le32(clips->y1);
|
||||
cmd[i].body.width = cpu_to_le32(clips->x2 - clips->x1);
|
||||
cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
|
||||
}
|
||||
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
|
||||
|
|
|
@ -104,7 +104,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
|
|||
bool pin, bool interruptible)
|
||||
{
|
||||
struct ttm_buffer_object *bo = &buf->base;
|
||||
struct ttm_bo_global *glob = bo->glob;
|
||||
struct ttm_placement *overlay_placement = &vmw_vram_placement;
|
||||
int ret;
|
||||
|
||||
|
@ -116,14 +115,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
|
|||
if (unlikely(ret != 0))
|
||||
goto err;
|
||||
|
||||
if (buf->gmr_bound) {
|
||||
vmw_gmr_unbind(dev_priv, buf->gmr_id);
|
||||
spin_lock(&glob->lru_lock);
|
||||
ida_remove(&dev_priv->gmr_ida, buf->gmr_id);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
buf->gmr_bound = NULL;
|
||||
}
|
||||
|
||||
if (pin)
|
||||
overlay_placement = &vmw_vram_ne_placement;
|
||||
|
||||
|
|
|
@ -599,6 +599,27 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
|
|||
if (unlikely(ret != 0))
|
||||
goto out_err1;
|
||||
|
||||
|
||||
if (srf->flags & (1 << 9) &&
|
||||
srf->num_sizes == 1 &&
|
||||
srf->sizes[0].width == 64 &&
|
||||
srf->sizes[0].height == 64 &&
|
||||
srf->format == SVGA3D_A8R8G8B8) {
|
||||
|
||||
srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
|
||||
/* clear the image */
|
||||
if (srf->snooper.image) {
|
||||
memset(srf->snooper.image, 0x00, 64 * 64 * 4);
|
||||
} else {
|
||||
DRM_ERROR("Failed to allocate cursor_image\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_err1;
|
||||
}
|
||||
} else {
|
||||
srf->snooper.image = NULL;
|
||||
}
|
||||
srf->snooper.crtc = NULL;
|
||||
|
||||
user_srf->base.shareable = false;
|
||||
user_srf->base.tfile = NULL;
|
||||
|
||||
|
@ -622,24 +643,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (srf->flags & (1 << 9) &&
|
||||
srf->num_sizes == 1 &&
|
||||
srf->sizes[0].width == 64 &&
|
||||
srf->sizes[0].height == 64 &&
|
||||
srf->format == SVGA3D_A8R8G8B8) {
|
||||
|
||||
srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
|
||||
/* clear the image */
|
||||
if (srf->snooper.image)
|
||||
memset(srf->snooper.image, 0x00, 64 * 64 * 4);
|
||||
else
|
||||
DRM_ERROR("Failed to allocate cursor_image\n");
|
||||
|
||||
} else {
|
||||
srf->snooper.image = NULL;
|
||||
}
|
||||
srf->snooper.crtc = NULL;
|
||||
|
||||
rep->sid = user_srf->base.hash.key;
|
||||
if (rep->sid == SVGA3D_INVALID_ID)
|
||||
DRM_ERROR("Created bad Surface ID.\n");
|
||||
|
@ -754,20 +757,29 @@ static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob,
|
|||
return bo_user_size + page_array_size;
|
||||
}
|
||||
|
||||
void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
|
||||
void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
|
||||
struct ttm_bo_global *glob = bo->glob;
|
||||
struct vmw_private *dev_priv =
|
||||
container_of(bo->bdev, struct vmw_private, bdev);
|
||||
|
||||
ttm_mem_global_free(glob->mem_glob, bo->acc_size);
|
||||
if (vmw_bo->gmr_bound) {
|
||||
vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
|
||||
spin_lock(&glob->lru_lock);
|
||||
ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
vmw_bo->gmr_bound = false;
|
||||
}
|
||||
}
|
||||
|
||||
void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
|
||||
struct ttm_bo_global *glob = bo->glob;
|
||||
|
||||
vmw_dmabuf_gmr_unbind(bo);
|
||||
ttm_mem_global_free(glob->mem_glob, bo->acc_size);
|
||||
kfree(vmw_bo);
|
||||
}
|
||||
|
||||
|
@ -813,18 +825,10 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
|
|||
static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
|
||||
struct vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma;
|
||||
struct ttm_bo_global *glob = bo->glob;
|
||||
struct vmw_private *dev_priv =
|
||||
container_of(bo->bdev, struct vmw_private, bdev);
|
||||
|
||||
vmw_dmabuf_gmr_unbind(bo);
|
||||
ttm_mem_global_free(glob->mem_glob, bo->acc_size);
|
||||
if (vmw_bo->gmr_bound) {
|
||||
vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
|
||||
spin_lock(&glob->lru_lock);
|
||||
ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
}
|
||||
kfree(vmw_user_bo);
|
||||
}
|
||||
|
||||
|
@ -868,7 +872,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
|
|||
}
|
||||
|
||||
ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
|
||||
&vmw_vram_placement, true,
|
||||
&vmw_vram_sys_placement, true,
|
||||
&vmw_user_dmabuf_destroy);
|
||||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
|
|
|
@ -353,6 +353,11 @@ struct ttm_bo_driver {
|
|||
/* notify the driver we are taking a fault on this BO
|
||||
* and have reserved it */
|
||||
void (*fault_reserve_notify)(struct ttm_buffer_object *bo);
|
||||
|
||||
/**
|
||||
* notify the driver that we're about to swap out this bo
|
||||
*/
|
||||
void (*swap_notify) (struct ttm_buffer_object *bo);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue