Commit 1067b6c2 authored by Linus Torvalds's avatar Linus Torvalds

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: (41 commits)
  drm/radeon/kms: make sure display hw is disabled when suspending
  drm/vmwgfx: Allow userspace to change default layout. Bump minor.
  drm/vmwgfx: Fix framebuffer modesetting
  drm/vmwgfx: Fix vga save / restore with display topology.
  vgaarb: use MIT license
  vgaarb: convert pr_devel() to pr_debug()
  drm: fix typos in Linux DRM Developer's Guide
  drm/radeon/kms/pm: voltage fixes
  drm/radeon/kms/pm: radeon_set_power_state fixes
  drm/radeon/kms/pm: patch default power state with default clocks/voltages on r6xx+
  drm/radeon/kms/pm: enable SetVoltage on r7xx/evergreen
  drm/radeon/kms/pm: add support for SetVoltage cmd table (V2)
  drm/radeon/kms/evergreen: add initial CS parser
  drm/kms: disable/enable poll around switcheroo on/off
  drm/nouveau: fixup confusion over which handle the DSM is hanging off.
  drm/nouveau: attempt to get bios from ACPI v3
  drm/nv50: cast IGP memory location to u64 before shifting
  drm/ttm: Fix ttm_page_alloc.c
  drm/ttm: Fix cached TTM page allocation.
  drm/vmwgfx: Remove some leftover debug messages.
  ...
parents a652883a d8dcaa1d
......@@ -389,7 +389,7 @@
</para>
<para>
If your driver supports memory management (it should!), you'll
need to set that up at load time as well. How you intialize
need to set that up at load time as well. How you initialize
it depends on which memory manager you're using, TTM or GEM.
</para>
<sect3>
......@@ -399,7 +399,7 @@
aperture space for graphics devices. TTM supports both UMA devices
and devices with dedicated video RAM (VRAM), i.e. most discrete
graphics devices. If your device has dedicated RAM, supporting
TTM is desireable. TTM also integrates tightly with your
TTM is desirable. TTM also integrates tightly with your
driver specific buffer execution function. See the radeon
driver for examples.
</para>
......@@ -443,7 +443,7 @@
likely eventually calling ttm_bo_global_init and
ttm_bo_global_release, respectively. Also like the previous
object, ttm_global_item_ref is used to create an initial reference
count for the TTM, which will call your initalization function.
count for the TTM, which will call your initialization function.
</para>
</sect3>
<sect3>
......@@ -557,7 +557,7 @@ void intel_crt_init(struct drm_device *dev)
CRT connector and encoder combination is created. A device
specific i2c bus is also created, for fetching EDID data and
performing monitor detection. Once the process is complete,
the new connector is regsitered with sysfs, to make its
the new connector is registered with sysfs, to make its
properties available to applications.
</para>
<sect4>
......@@ -581,12 +581,12 @@ void intel_crt_init(struct drm_device *dev)
<para>
For each encoder, CRTC and connector, several functions must
be provided, depending on the object type. Encoder objects
need should provide a DPMS (basically on/off) function, mode fixup
need to provide a DPMS (basically on/off) function, mode fixup
(for converting requested modes into native hardware timings),
and prepare, set and commit functions for use by the core DRM
helper functions. Connector helpers need to provide mode fetch and
validity functions as well as an encoder matching function for
returing an ideal encoder for a given connector. The core
returning an ideal encoder for a given connector. The core
connector functions include a DPMS callback, (deprecated)
save/restore routines, detection, mode probing, property handling,
and cleanup functions.
......
......@@ -860,19 +860,24 @@ static void output_poll_execute(struct slow_work *work)
}
}
void drm_kms_helper_poll_init(struct drm_device *dev)
void drm_kms_helper_poll_disable(struct drm_device *dev)
{
if (!dev->mode_config.poll_enabled)
return;
delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
}
EXPORT_SYMBOL(drm_kms_helper_poll_disable);
void drm_kms_helper_poll_enable(struct drm_device *dev)
{
struct drm_connector *connector;
bool poll = false;
struct drm_connector *connector;
int ret;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->polled)
poll = true;
}
slow_work_register_user(THIS_MODULE);
delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
&output_poll_ops);
if (poll) {
ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD);
......@@ -880,11 +885,22 @@ void drm_kms_helper_poll_init(struct drm_device *dev)
DRM_ERROR("delayed enqueue failed %d\n", ret);
}
}
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
void drm_kms_helper_poll_init(struct drm_device *dev)
{
slow_work_register_user(THIS_MODULE);
delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
&output_poll_ops);
dev->mode_config.poll_enabled = true;
drm_kms_helper_poll_enable(dev);
}
EXPORT_SYMBOL(drm_kms_helper_poll_init);
void drm_kms_helper_poll_fini(struct drm_device *dev)
{
delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
drm_kms_helper_poll_disable(dev);
slow_work_unregister_user(THIS_MODULE);
}
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
......
......@@ -1320,12 +1320,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
struct drm_device *dev = pci_get_drvdata(pdev);
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
if (state == VGA_SWITCHEROO_ON) {
printk(KERN_INFO "i915: switched off\n");
printk(KERN_INFO "i915: switched on\n");
/* i915 resume handler doesn't set to D0 */
pci_set_power_state(dev->pdev, PCI_D0);
i915_resume(dev);
drm_kms_helper_poll_enable(dev);
} else {
printk(KERN_ERR "i915: switched off\n");
drm_kms_helper_poll_disable(dev);
i915_suspend(dev, pmm);
}
}
......
......@@ -34,7 +34,7 @@
static struct nouveau_dsm_priv {
bool dsm_detected;
acpi_handle dhandle;
acpi_handle dsm_handle;
acpi_handle rom_handle;
} nouveau_dsm_priv;
static const char nouveau_dsm_muid[] = {
......@@ -107,9 +107,9 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
{
if (id == VGA_SWITCHEROO_IGD)
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_STAMINA);
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
else
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_SPEED);
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
}
static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
......@@ -118,7 +118,7 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
if (id == VGA_SWITCHEROO_IGD)
return 0;
return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dsm_handle, state);
return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
}
static int nouveau_dsm_init(void)
......@@ -151,18 +151,18 @@ static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return false;
status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
if (ACPI_FAILURE(status)) {
return false;
}
ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED,
NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
if (ret < 0)
return false;
nouveau_dsm_priv.dhandle = dhandle;
nouveau_dsm_priv.dsm_handle = nvidia_handle;
return true;
}
......@@ -173,6 +173,7 @@ static bool nouveau_dsm_detect(void)
struct pci_dev *pdev = NULL;
int has_dsm = 0;
int vga_count = 0;
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
vga_count++;
......@@ -180,7 +181,7 @@ static bool nouveau_dsm_detect(void)
}
if (vga_count == 2 && has_dsm) {
acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer);
acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
acpi_method_name);
nouveau_dsm_priv.dsm_detected = true;
......@@ -204,3 +205,57 @@ void nouveau_unregister_dsm_handler(void)
{
vga_switcheroo_unregister_handler();
}
/* retrieve the ROM in 4k blocks */
static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
int offset, int len)
{
acpi_status status;
union acpi_object rom_arg_elements[2], *obj;
struct acpi_object_list rom_arg;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
rom_arg.count = 2;
rom_arg.pointer = &rom_arg_elements[0];
rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
rom_arg_elements[0].integer.value = offset;
rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
rom_arg_elements[1].integer.value = len;
status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
return -ENODEV;
}
obj = (union acpi_object *)buffer.pointer;
memcpy(bios+offset, obj->buffer.pointer, len);
kfree(buffer.pointer);
return len;
}
bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
{
acpi_status status;
acpi_handle dhandle, rom_handle;
if (!nouveau_dsm_priv.dsm_detected)
return false;
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return false;
status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
if (ACPI_FAILURE(status))
return false;
nouveau_dsm_priv.rom_handle = rom_handle;
return true;
}
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
{
return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
}
......@@ -178,6 +178,25 @@ static void load_vbios_pci(struct drm_device *dev, uint8_t *data)
pci_disable_rom(dev->pdev);
}
static void load_vbios_acpi(struct drm_device *dev, uint8_t *data)
{
int i;
int ret;
int size = 64 * 1024;
if (!nouveau_acpi_rom_supported(dev->pdev))
return;
for (i = 0; i < (size / ROM_BIOS_PAGE); i++) {
ret = nouveau_acpi_get_bios_chunk(data,
(i * ROM_BIOS_PAGE),
ROM_BIOS_PAGE);
if (ret <= 0)
break;
}
return;
}
struct methods {
const char desc[8];
void (*loadbios)(struct drm_device *, uint8_t *);
......@@ -191,6 +210,7 @@ static struct methods nv04_methods[] = {
};
static struct methods nv50_methods[] = {
{ "ACPI", load_vbios_acpi, true },
{ "PRAMIN", load_vbios_pramin, true },
{ "PROM", load_vbios_prom, false },
{ "PCIROM", load_vbios_pci, true },
......@@ -2807,7 +2827,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
offset, gpio->tag, gpio->state_default);
if (bios->execute)
nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
/* The NVIDIA binary driver doesn't appear to actually do
* any of this, my VBIOS does however.
......@@ -5533,12 +5556,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
entry->bus = (conn >> 16) & 0xf;
entry->location = (conn >> 20) & 0x3;
entry->or = (conn >> 24) & 0xf;
/*
* Normal entries consist of a single bit, but dual link has the
* next most significant bit set too
*/
entry->duallink_possible =
((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
switch (entry->type) {
case OUTPUT_ANALOG:
......@@ -5622,6 +5639,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
break;
}
if (dcb->version < 0x40) {
/* Normal entries consist of a single bit, but dual link has
* the next most significant bit set too
*/
entry->duallink_possible =
((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
} else {
entry->duallink_possible = (entry->sorconf.link == 3);
}
/* unsure what DCB version introduces this, 3.0? */
if (conf & 0x100000)
entry->i2c_upper_default = true;
......@@ -6205,6 +6232,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
nouveau_i2c_fini(dev, entry);
}
static bool
nouveau_bios_posted(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
bool was_locked;
unsigned htotal;
if (dev_priv->chipset >= NV_50) {
if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
NVReadVgaCrtc(dev, 0, 0x1a) == 0)
return false;
return true;
}
was_locked = NVLockVgaCrtcs(dev, false);
htotal = NVReadVgaCrtc(dev, 0, 0x06);
htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
NVLockVgaCrtcs(dev, was_locked);
return (htotal != 0);
}
int
nouveau_bios_init(struct drm_device *dev)
{
......@@ -6239,11 +6290,9 @@ nouveau_bios_init(struct drm_device *dev)
bios->execute = false;
/* ... unless card isn't POSTed already */
if (dev_priv->card_type >= NV_10 &&
NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
if (!nouveau_bios_posted(dev)) {
NV_INFO(dev, "Adaptor not initialised\n");
if (dev_priv->card_type < NV_50) {
if (dev_priv->card_type < NV_40) {
NV_ERROR(dev, "Unable to POST this chipset\n");
return -ENODEV;
}
......
......@@ -432,24 +432,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
}
static struct drm_display_mode *
nouveau_connector_native_mode(struct nouveau_connector *connector)
nouveau_connector_native_mode(struct drm_connector *connector)
{
struct drm_device *dev = connector->base.dev;
struct drm_connector_helper_funcs *helper = connector->helper_private;
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode, *largest = NULL;
int high_w = 0, high_h = 0, high_v = 0;
/* Use preferred mode if there is one.. */
list_for_each_entry(mode, &connector->base.probed_modes, head) {
list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
if (helper->mode_valid(connector, mode) != MODE_OK)
continue;
/* Use preferred mode if there is one.. */
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
NV_DEBUG_KMS(dev, "native mode from preferred\n");
return drm_mode_duplicate(dev, mode);
}
}
/* Otherwise, take the resolution with the largest width, then height,
* then vertical refresh
*/
list_for_each_entry(mode, &connector->base.probed_modes, head) {
/* Otherwise, take the resolution with the largest width, then
* height, then vertical refresh
*/
if (mode->hdisplay < high_w)
continue;
......@@ -553,7 +556,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
*/
if (!nv_connector->native_mode)
nv_connector->native_mode =
nouveau_connector_native_mode(nv_connector);
nouveau_connector_native_mode(connector);
if (ret == 0 && nv_connector->native_mode) {
struct drm_display_mode *mode;
......@@ -584,9 +587,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
switch (nv_encoder->dcb->type) {
case OUTPUT_LVDS:
BUG_ON(!nv_connector->native_mode);
if (mode->hdisplay > nv_connector->native_mode->hdisplay ||
mode->vdisplay > nv_connector->native_mode->vdisplay)
if (nv_connector->native_mode &&
(mode->hdisplay > nv_connector->native_mode->hdisplay ||
mode->vdisplay > nv_connector->native_mode->vdisplay))
return MODE_PANEL;
min_clock = 0;
......@@ -594,8 +597,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
break;
case OUTPUT_TMDS:
if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
(dev_priv->card_type < NV_50 &&
!nv_encoder->dcb->duallink_possible))
!nv_encoder->dcb->duallink_possible)
max_clock = 165000;
else
max_clock = 330000;
......@@ -729,7 +731,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
if (ret == 0)
goto out;
nv_connector->detected_encoder = nv_encoder;
nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
nv_connector->native_mode = nouveau_connector_native_mode(connector);
list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
drm_mode_remove(connector, mode);
......
......@@ -40,6 +40,8 @@ struct nouveau_crtc {
int sharpness;
int last_dpms;
int cursor_saved_x, cursor_saved_y;
struct {
int cpp;
bool blanked;
......
......@@ -175,6 +175,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
nouveau_bo_unpin(nouveau_fb->nvbo);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
}
NV_INFO(dev, "Evicting buffers...\n");
ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
......@@ -314,12 +321,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
int ret;
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
if (!ret)
ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
if (ret)
NV_ERROR(dev, "Could not pin/map cursor.\n");
}
if (dev_priv->card_type < NV_50) {
nv04_display_restore(dev);
NVLockVgaCrtcs(dev, false);
} else
nv50_display_init(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
nv_crtc->cursor.set_offset(nv_crtc,
nv_crtc->cursor.nvbo->bo.offset -
dev_priv->vm_vram_base);
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
nv_crtc->cursor_saved_y);
}
/* Force CLUT to get re-loaded during modeset */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
......
......@@ -851,12 +851,17 @@ extern int nouveau_dma_init(struct nouveau_channel *);
extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
/* nouveau_acpi.c */
#define ROM_BIOS_PAGE 4096
#if defined(CONFIG_ACPI)
void nouveau_register_dsm_handler(void);
void nouveau_unregister_dsm_handler(void);
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
#else
static inline void nouveau_register_dsm_handler(void) {}
static inline void nouveau_unregister_dsm_handler(void) {}
static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
#endif
/* nouveau_backlight.c */
......
......@@ -540,7 +540,8 @@ nouveau_mem_detect(struct drm_device *dev)
dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
dev_priv->vram_sys_base <<= 12;
}
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
......
......@@ -376,12 +376,15 @@ nouveau_card_init_channel(struct drm_device *dev)
static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
enum vga_switcheroo_state state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
if (state == VGA_SWITCHEROO_ON) {
printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
nouveau_pci_resume(pdev);
drm_kms_helper_poll_enable(dev);
} else {
printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
drm_kms_helper_poll_disable(dev);
nouveau_pci_suspend(pdev, pmm);
}
}
......@@ -913,6 +916,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
case NOUVEAU_GETPARAM_VM_VRAM_BASE:
getparam->value = dev_priv->vm_vram_base;
break;
case NOUVEAU_GETPARAM_PTIMER_TIME:
getparam->value = dev_priv->engine.timer.read(dev);
break;
case NOUVEAU_GETPARAM_GRAPH_UNITS:
/* NV40 and NV50 versions are quite different, but register
* address is the same. User is supposed to know the card
......
......@@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
static void
nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
{
nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
NV_PRAMDAC_CU_START_POS,
XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
......
......@@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
{
struct drm_device *dev = nv_crtc->base.dev;
nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
((y & 0xFFFF) << 16) | (x & 0xFFFF));
/* Needed to make the cursor move. */
......
......@@ -274,7 +274,6 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
int
nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_encoder *nv_encoder = NULL;
struct drm_encoder *encoder;
bool dum;
......@@ -324,11 +323,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
uint32_t tmp;
if (dev_priv->chipset < 0x90 ||
dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
else
tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
switch ((tmp & 0x00000f00) >> 8) {
case 8:
......
......@@ -33,6 +33,9 @@ $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
$(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
$(call if_changed,mkregtable)
$(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
$(call if_changed,mkregtable)
$(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
$(obj)/r200.o: $(obj)/r200_reg_safe.h
......@@ -47,6 +50,8 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
$(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
radeon_irq.o r300_cmdbuf.o r600_cp.o
# add KMS driver
......@@ -60,7 +65,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
evergreen.o
evergreen.o evergreen_cs.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
......
......@@ -41,7 +41,12 @@ void evergreen_fini(struct radeon_device *rdev);
void evergreen_pm_misc(struct radeon_device *rdev)
{
int requested_index = rdev->pm.requested_power_state_index;
struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
if ((voltage->type == VOLTAGE_SW) && voltage->voltage)
radeon_atom_set_voltage(rdev, voltage->voltage);
}
void evergreen_pm_prepare(struct radeon_device *rdev)
......
This diff is collapsed.
......@@ -151,6 +151,9 @@
#define EVERGREEN_DATA_FORMAT 0x6b00
# define EVERGREEN_INTERLEAVE_EN (1 << 0)
#define EVERGREEN_DESKTOP_HEIGHT 0x6b04
#define EVERGREEN_VLINE_START_END 0x6b08
#define EVERGREEN_VLINE_STATUS 0x6bb8
# define EVERGREEN_VLINE_STAT (1 << 12)
#define EVERGREEN_VIEWPORT_START 0x6d70
#define EVERGREEN_VIEWPORT_SIZE 0x6d74
......
This diff is collapsed.
......@@ -475,6 +475,12 @@ void r600_pm_init_profile(struct radeon_device *rdev)
void r600_pm_misc(struct radeon_device *rdev)
{
int requested_index = rdev->pm.requested_power_state_index;
struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
if ((voltage->type == VOLTAGE_SW) && voltage->voltage)
radeon_atom_set_voltage(rdev, voltage->voltage);
}
......
......@@ -176,6 +176,7 @@ void radeon_pm_suspend(struct radeon_device *rdev);
void radeon_pm_resume(struct radeon_device *rdev);
void radeon_combios_get_power_modes(struct radeon_device *rdev);
void radeon_atombios_get_power_modes(struct radeon_device *rdev);
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
/*
* Fences.
......
......@@ -724,8 +724,8 @@ static struct radeon_asic evergreen_asic = {
.irq_set = &evergreen_irq_set,
.irq_process = &evergreen_irq_process,
.get_vblank_counter = &evergreen_get_vblank_counter,
.fence_ring_emit = NULL,
.cs_parse = NULL,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
.copy_blit = NULL,
.copy_dma = NULL,
.copy = NULL,
......
......@@ -314,6 +314,7 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
int evergreen_irq_set(struct radeon_device *rdev);
int evergreen_irq_process(struct radeon_device *rdev);
extern int evergreen_cs_parse(struct radeon_cs_parser *p);
extern void evergreen_pm_misc(struct radeon_device *rdev);
extern void evergreen_pm_prepare(struct radeon_device *rdev);
extern void evergreen_pm_finish(struct radeon_device *rdev);
......
......@@ -1538,7 +1538,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state[state_index].pcie_lanes =
power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
(misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
VOLTAGE_GPIO;
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
......@@ -1605,7 +1606,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
(misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
VOLTAGE_GPIO;
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
......@@ -1679,7 +1681,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
(misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
VOLTAGE_GPIO;
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
......@@ -1755,9 +1758,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state[state_index].misc2 = 0;
}
} else {
int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
uint8_t fw_frev, fw_crev;
uint16_t fw_data_offset, vddc = 0;
union firmware_info *firmware_info;
ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
&fw_frev, &fw_crev, &fw_data_offset)) {
firmware_info =
(union firmware_info *)(mode_info->atom_context->bios +
fw_data_offset);
vddc = firmware_info->info_14.usBootUpVDDCVoltage;
}
/* add the i2c bus for thermal/fan chip */
/* no support for internal controller yet */
ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
if (controller->ucType > 0) {
if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
(controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
......@@ -1904,6 +1920,16 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
/* patch the table values with the default slck/mclk from firmware info */
for (j = 0; j < mode_index; j++) {
rdev->pm.power_state[state_index].clock_info[j].mclk =
rdev->clock.default_mclk;
rdev->pm.power_state[state_index].clock_info[j].sclk =
rdev->clock.default_sclk;
if (vddc)
rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
vddc;
}
}
state_index++;
}
......@@ -1998,6 +2024,42 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev,
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
union set_voltage {
struct _SET_VOLTAGE_PS_ALLOCATION alloc;
struct _SET_VOLTAGE_PARAMETERS v1;
struct _SET_VOLTAGE_PARAMETERS_V2 v2;
};
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
{
union set_voltage args;
int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
u8 frev, crev, volt_index = level;
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
switch (crev) {
case 1:
args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
args.v1.ucVoltageIndex = volt_index;
break;
case 2:
args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
args.v2.usVoltageLevel = cpu_to_le16(level);
break;
default:
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
return;
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
......
......@@ -2454,7 +2454,12 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
if ((state_index > 0) &&
(rdev->pm.power_state[0].clock_info[0].voltage.type = VOLTAGE_GPIO))
rdev->pm.power_state[state_index].clock_info[0].voltage =
rdev->pm.power_state[0].clock_info[0].voltage;
else
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
rdev->pm.power_state[state_index].pcie_lanes = 16;
rdev->pm.power_state[state_index].flags = 0;
rdev->pm.default_power_state_index = state_index;
......
......@@ -546,8 +546,10 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
/* don't suspend or resume card normally */
rdev->powered_down = false;
radeon_resume_kms(dev);
drm_kms_helper_poll_enable(dev);
} else {
printk(KERN_INFO "radeon: switched off\n");
drm_kms_helper_poll_disable(dev);
radeon_suspend_kms(dev, pmm);
/* don't suspend or resume card normally */
rdev->powered_down = true;
......@@ -711,6 +713,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
{
struct radeon_device *rdev;
struct drm_crtc *crtc;
struct drm_connector *connector;
int r;
if (dev == NULL || dev->dev_private == NULL) {
......@@ -723,6 +726,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
if (rdev->powered_down)
return 0;
/* turn off display hw */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
}
/* unpin the front buffers */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
......
......@@ -151,6 +151,7 @@ static void radeon_sync_with_vblank(struct radeon_device *rdev)
static void radeon_set_power_state(struct radeon_device *rdev)
{
u32 sclk, mclk;
bool misc_after = false;
if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
......@@ -167,55 +168,47 @@ static void radeon_set_power_state(struct radeon_device *rdev)
if (mclk > rdev->clock.default_mclk)
mclk = rdev->clock.default_mclk;
/* voltage, pcie lanes, etc.*/
radeon_pm_misc(rdev);
/* upvolt before raising clocks, downvolt after lowering clocks */
if (sclk < rdev->pm.current_sclk)
misc_after = true;
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
radeon_sync_with_vblank(rdev);
radeon_sync_with_vblank(rdev);
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
if (!radeon_pm_in_vbl(rdev))
return;
}
radeon_pm_prepare(rdev);
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_engine_clock(rdev, sclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_sclk = sclk;
DRM_DEBUG("Setting: e: %d\n", sclk);
}
radeon_pm_prepare(rdev);
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_memory_clock(rdev, mclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_mclk = mclk;
DRM_DEBUG("Setting: m: %d\n", mclk);
}
radeon_pm_finish(rdev);
} else {
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_sync_with_vblank(rdev);
radeon_pm_prepare(rdev);
radeon_set_engine_clock(rdev, sclk);
radeon_pm_finish(rdev);
rdev->pm.current_sclk = sclk;
DRM_DEBUG("Setting: e: %d\n", sclk);
}
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_sync_with_vblank(rdev);
radeon_pm_prepare(rdev);
radeon_set_memory_clock(rdev, mclk);
radeon_pm_finish(rdev);
rdev->pm.current_mclk = mclk;
DRM_DEBUG("Setting: m: %d\n", mclk);
}
if (!misc_after)
/* voltage, pcie lanes, etc.*/
radeon_pm_misc(rdev);
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_engine_clock(rdev, sclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_sclk = sclk;
DRM_DEBUG("Setting: e: %d\n", sclk);
}
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_memory_clock(rdev, mclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_mclk = mclk;
DRM_DEBUG("Setting: m: %d\n", mclk);
}
if (misc_after)
/* voltage, pcie lanes, etc.*/
radeon_pm_misc(rdev);
radeon_pm_finish(rdev);
rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
} else
......
This diff is collapsed.
......@@ -74,7 +74,8 @@ void rs600_pm_misc(struct radeon_device *rdev)
if (voltage->delay)
udelay(voltage->delay);
}
}
} else if (voltage->type == VOLTAGE_VDDC)
radeon_atom_set_voltage(rdev, voltage->vddc_id);
dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
......
......@@ -44,7 +44,12 @@ void rv770_fini(struct radeon_device *rdev);
void rv770_pm_misc(struct radeon_device *rdev)
{
int requested_index = rdev->pm.requested_power_state_index;
struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
if ((voltage->type == VOLTAGE_SW) && voltage->voltage)
radeon_atom_set_voltage(rdev, voltage->voltage);
}
/*
......
......@@ -77,7 +77,7 @@ struct ttm_page_pool {
/**
* Limits for the pool. They are handled without locks because only place where
* they may change is in sysfs store. They won't have immediate effect anyway
* so forcing serialiazation to access them is pointless.
* so forcing serialization to access them is pointless.
*/
struct ttm_pool_opts {
......@@ -165,16 +165,18 @@ static ssize_t ttm_pool_store(struct kobject *kobj,
m->options.small = val;
else if (attr == &ttm_page_pool_alloc_size) {
if (val > NUM_PAGES_TO_ALLOC*8) {
printk(KERN_ERR "[ttm] Setting allocation size to %lu "
"is not allowed. Recomended size is "
"%lu\n",
NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
printk(KERN_ERR TTM_PFX
"Setting allocation size to %lu "
"is not allowed. Recommended size is "
"%lu\n",
NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
return size;
} else if (val > NUM_PAGES_TO_ALLOC) {
printk(KERN_WARNING "[ttm] Setting allocation size to "
"larger than %lu is not recomended.\n",
NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
printk(KERN_WARNING TTM_PFX
"Setting allocation size to "
"larger than %lu is not recommended.\n",
NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
}
m->options.alloc_size = val;
}
......@@ -277,7 +279,7 @@ static void ttm_pages_put(struct page *pages[], unsigned npages)
{
unsigned i;
if (set_pages_array_wb(pages, npages))
printk(KERN_ERR "[ttm] Failed to set %d pages to wb!\n",
printk(KERN_ERR TTM_PFX "Failed to set %d pages to wb!\n",
npages);
for (i = 0; i < npages; ++i)
__free_page(pages[i]);
......@@ -313,7 +315,8 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
GFP_KERNEL);
if (!pages_to_free) {
printk(KERN_ERR "Failed to allocate memory for pool free operation.\n");
printk(KERN_ERR TTM_PFX
"Failed to allocate memory for pool free operation.\n");
return 0;
}
......@@ -390,7 +393,7 @@ static int ttm_pool_get_num_unused_pages(void)
}
/**
* Calback for mm to request pool to reduce number of page held.
* Callback for mm to request pool to reduce number of page held.
*/
static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
{
......@@ -433,14 +436,16 @@ static int ttm_set_pages_caching(struct page **pages,
case tt_uncached:
r = set_pages_array_uc(pages, cpages);
if (r)
printk(KERN_ERR "[ttm] Failed to set %d pages to uc!\n",
cpages);
printk(KERN_ERR TTM_PFX
"Failed to set %d pages to uc!\n",
cpages);
break;
case tt_wc:
r = set_pages_array_wc(pages, cpages);
if (r)
printk(KERN_ERR "[ttm] Failed to set %d pages to wc!\n",
cpages);
printk(KERN_ERR TTM_PFX
"Failed to set %d pages to wc!\n",
cpages);
break;
default:
break;
......@@ -458,7 +463,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages,
struct page **failed_pages, unsigned cpages)
{
unsigned i;
/* Failed pages has to be reed */
/* Failed pages have to be freed */
for (i = 0; i < cpages; ++i) {
list_del(&failed_pages[i]->lru);
__free_page(failed_pages[i]);
......@@ -485,7 +490,8 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
if (!caching_array) {
printk(KERN_ERR "[ttm] unable to allocate table for new pages.");
printk(KERN_ERR TTM_PFX
"Unable to allocate table for new pages.");
return -ENOMEM;
}
......@@ -493,12 +499,13 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
p = alloc_page(gfp_flags);
if (!p) {
printk(KERN_ERR "[ttm] unable to get page %u\n", i);
printk(KERN_ERR TTM_PFX "Unable to get page %u.\n", i);
/* store already allocated pages in the pool after
* setting the caching state */
if (cpages) {
r = ttm_set_pages_caching(caching_array, cstate, cpages);
r = ttm_set_pages_caching(caching_array,
cstate, cpages);
if (r)
ttm_handle_caching_state_failure(pages,
ttm_flags, cstate,
......@@ -590,7 +597,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
++pool->nrefills;
pool->npages += alloc_size;
} else {
printk(KERN_ERR "[ttm] Failed to fill pool (%p).", pool);
printk(KERN_ERR TTM_PFX
"Failed to fill pool (%p).", pool);
/* If we have any pages left put them to the pool. */
list_for_each_entry(p, &pool->list, lru) {
++cpages;
......@@ -671,13 +679,14 @@ int ttm_get_pages(struct list_head *pages, int flags,
if (flags & TTM_PAGE_FLAG_DMA32)
gfp_flags |= GFP_DMA32;
else
gfp_flags |= __GFP_HIGHMEM;
gfp_flags |= GFP_HIGHUSER;
for (r = 0; r < count; ++r) {
p = alloc_page(gfp_flags);
if (!p) {
printk(KERN_ERR "[ttm] unable to allocate page.");
printk(KERN_ERR TTM_PFX
"Unable to allocate page.");
return -ENOMEM;
}
......@@ -709,8 +718,9 @@ int ttm_get_pages(struct list_head *pages, int flags,
if (r) {
/* If there is any pages in the list put them back to
* the pool. */
printk(KERN_ERR "[ttm] Failed to allocate extra pages "
"for large request.");
printk(KERN_ERR TTM_PFX
"Failed to allocate extra pages "
"for large request.");
ttm_put_pages(pages, 0, flags, cstate);
return r;
}
......@@ -778,7 +788,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
if (atomic_add_return(1, &_manager.page_alloc_inited) > 1)
return 0;
printk(KERN_INFO "[ttm] Initializing pool allocator.\n");
printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n");
ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc");
......@@ -813,7 +823,7 @@ void ttm_page_alloc_fini()
if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0)
return;
printk(KERN_INFO "[ttm] Finilizing pool allocator.\n");
printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n");
ttm_pool_mm_shrink_fini(&_manager);
for (i = 0; i < NUM_POOLS; ++i)
......
......@@ -4,6 +4,6 @@ ccflags-y := -Iinclude/drm
vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
vmwgfx_overlay.o
vmwgfx_overlay.o vmwgfx_fence.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
......@@ -88,6 +88,9 @@
#define DRM_IOCTL_VMW_FENCE_WAIT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \
struct drm_vmw_fence_wait_arg)
#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
struct drm_vmw_update_layout_arg)
/**
......@@ -135,7 +138,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
DRM_AUTH | DRM_UNLOCKED)
DRM_AUTH | DRM_UNLOCKED),
VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
};
static struct pci_device_id vmw_pci_id_list[] = {
......@@ -318,6 +323,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
goto out_err3;
}
/* Need mmio memory to check for fifo pitchlock cap. */
if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
!(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
!vmw_fifo_have_pitchlock(dev_priv)) {
ret = -ENOSYS;
DRM_ERROR("Hardware has no pitchlock\n");
goto out_err4;
}
dev_priv->tdev = ttm_object_device_init
(dev_priv->mem_global_ref.object, 12);
......@@ -399,8 +413,6 @@ static int vmw_driver_unload(struct drm_device *dev)
{
struct vmw_private *dev_priv = vmw_priv(dev);
DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
unregister_pm_notifier(&dev_priv->pm_nb);
vmw_fb_close(dev_priv);
......@@ -546,7 +558,6 @@ static int vmw_master_create(struct drm_device *dev,
{
struct vmw_master *vmaster;
DRM_INFO("Master create.\n");
vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
if (unlikely(vmaster == NULL))
return -ENOMEM;
......@@ -563,7 +574,6 @@ static void vmw_master_destroy(struct drm_device *dev,
{
struct vmw_master *vmaster = vmw_master(master);
DRM_INFO("Master destroy.\n");
master->driver_priv = NULL;
kfree(vmaster);
}
......@@ -579,8 +589,6 @@ static int vmw_master_set(struct drm_device *dev,
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret = 0;
DRM_INFO("Master set.\n");
if (active) {
BUG_ON(active != &dev_priv->fbdev_master);
ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
......@@ -622,8 +630,6 @@ static void vmw_master_drop(struct drm_device *dev,
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret;
DRM_INFO("Master drop.\n");
/**
* Make sure the master doesn't disappear while we have
* it locked.
......
......@@ -41,12 +41,13 @@
#define VMWGFX_DRIVER_DATE "20100209"
#define VMWGFX_DRIVER_MAJOR 1
#define VMWGFX_DRIVER_MINOR 0
#define VMWGFX_DRIVER_MINOR 2
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
#define VMWGFX_MAX_GMRS 2048
#define VMWGFX_MAX_DISPLAYS 16
struct vmw_fpriv {
struct drm_master *locked_master;
......@@ -102,6 +103,13 @@ struct vmw_surface {
struct vmw_cursor_snooper snooper;
};
struct vmw_fence_queue {
struct list_head head;
struct timespec lag;
struct timespec lag_time;
spinlock_t lock;
};
struct vmw_fifo_state {
unsigned long reserved_size;
__le32 *dynamic_buffer;
......@@ -115,6 +123,7 @@ struct vmw_fifo_state {
uint32_t capabilities;
struct mutex fifo_mutex;
struct rw_semaphore rwsem;
struct vmw_fence_queue fence_queue;
};
struct vmw_relocation {
......@@ -144,6 +153,14 @@ struct vmw_master {
struct ttm_lock lock;
};
struct vmw_vga_topology_state {
uint32_t width;
uint32_t height;
uint32_t primary;
uint32_t pos_x;
uint32_t pos_y;
};
struct vmw_private {
struct ttm_bo_device bdev;
struct ttm_bo_global_ref bo_global_ref;
......@@ -171,14 +188,19 @@ struct vmw_private {
* VGA registers.
*/
struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
uint32_t vga_width;
uint32_t vga_height;
uint32_t vga_depth;
uint32_t vga_bpp;
uint32_t vga_pseudo;
uint32_t vga_red_mask;
uint32_t vga_blue_mask;
uint32_t vga_green_mask;
uint32_t vga_blue_mask;
uint32_t vga_bpl;
uint32_t vga_pitchlock;
uint32_t num_displays;
/*
* Framebuffer info.
......@@ -393,6 +415,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
/**
* TTM glue - vmwgfx_ttm_glue.c
......@@ -441,6 +464,23 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv,
uint32_t sequence,
bool interruptible,
unsigned long timeout);
extern void vmw_update_sequence(struct vmw_private *dev_priv,
struct vmw_fifo_state *fifo_state);
/**
* Rudimentary fence objects currently used only for throttling -
* vmwgfx_fence.c
*/
extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
extern int vmw_fence_push(struct vmw_fence_queue *queue,
uint32_t sequence);
extern int vmw_fence_pull(struct vmw_fence_queue *queue,
uint32_t signaled_sequence);
extern int vmw_wait_lag(struct vmw_private *dev_priv,
struct vmw_fence_queue *queue, uint32_t us);
/**
* Kernel framebuffer - vmwgfx_fb.c
......@@ -466,6 +506,11 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
struct ttm_object_file *tfile,
struct ttm_buffer_object *bo,
SVGA3dCmdHeader *header);
void vmw_kms_write_svga(struct vmw_private *vmw_priv,
unsigned width, unsigned height, unsigned pitch,
unsigned bbp, unsigned depth);
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
/**
* Overlay control - vmwgfx_overlay.c
......
......@@ -669,6 +669,15 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
goto out_err;
vmw_apply_relocations(sw_context);
if (arg->throttle_us) {
ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
arg->throttle_us);
if (unlikely(ret != 0))
goto out_err;
}
vmw_fifo_commit(dev_priv, arg->command_size);
ret = vmw_fifo_send_fence(dev_priv, &sequence);
......
......@@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
/* without multimon its hard to resize */
if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
(var->xres != par->max_width ||
var->yres != par->max_height)) {
DRM_ERROR("Tried to resize, but we don't have multimon\n");
if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
(var->xoffset != 0 || var->yoffset != 0)) {
DRM_ERROR("Can not handle panning without display topology\n");
return -EINVAL;
}
if (var->xres > par->max_width ||
var->yres > par->max_height) {
if ((var->xoffset + var->xres) > par->max_width ||
(var->yoffset + var->yres) > par->max_height) {
DRM_ERROR("Requested geom can not fit in framebuffer\n");
return -EINVAL;
}
......@@ -154,27 +152,11 @@ static int vmw_fb_set_par(struct fb_info *info)
struct vmw_fb_par *par = info->par;
struct vmw_private *vmw_priv = par->vmw_priv;
if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
info->fix.line_length,
par->bpp, par->depth);
if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
/* TODO check if pitch and offset changes */
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
......@@ -183,13 +165,13 @@ static int vmw_fb_set_par(struct fb_info *info)
vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
} else {
vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
/* TODO check if pitch and offset changes */
}
/* This is really helpful since if this fails the user
* can probably not see anything on the screen.
*/
WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
return 0;
}
......@@ -416,48 +398,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
int ret;
/* XXX These shouldn't be hardcoded. */
initial_width = 800;
initial_height = 600;
fb_bbp = 32;
fb_depth = 24;
if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
} else {
fb_width = min(vmw_priv->fb_max_width, initial_width);
fb_height = min(vmw_priv->fb_max_height, initial_height);
}
/* XXX As shouldn't these be as well. */
fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
initial_width = min(fb_width, initial_width);
initial_height = min(fb_height, initial_height);
vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
fb_pitch = fb_width * fb_bbp / 8;
fb_size = fb_pitch * fb_height;
fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
DRM_DEBUG("bpp %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
DRM_DEBUG("depth %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
DRM_DEBUG("bpl %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
DRM_DEBUG("fb_pitch %u\n", fb_pitch);
DRM_DEBUG("fb_size %u kiB\n", fb_size / 1024);
info = framebuffer_alloc(sizeof(*par), device);
if (!info)
......@@ -659,6 +616,10 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
goto err_unlock;
ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
/* Could probably bug on */
WARN_ON(bo->offset != 0);
ttm_bo_unreserve(bo);
err_unlock:
ttm_write_unlock(&vmw_priv->active_master->lock);
......
/**************************************************************************
*
* Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "vmwgfx_drv.h"
struct vmw_fence {
struct list_head head;
uint32_t sequence;
struct timespec submitted;
};
void vmw_fence_queue_init(struct vmw_fence_queue *queue)
{
INIT_LIST_HEAD(&queue->head);
queue->lag = ns_to_timespec(0);
getrawmonotonic(&queue->lag_time);
spin_lock_init(&queue->lock);
}
void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
{
struct vmw_fence *fence, *next;
spin_lock(&queue->lock);
list_for_each_entry_safe(fence, next, &queue->head, head) {
kfree(fence);
}
spin_unlock(&queue->lock);
}
int vmw_fence_push(struct vmw_fence_queue *queue,
uint32_t sequence)
{
struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
if (unlikely(!fence))
return -ENOMEM;
fence->sequence = sequence;
getrawmonotonic(&fence->submitted);
spin_lock(&queue->lock);
list_add_tail(&fence->head, &queue->head);
spin_unlock(&queue->lock);
return 0;
}
int vmw_fence_pull(struct vmw_fence_queue *queue,
uint32_t signaled_sequence)
{
struct vmw_fence *fence, *next;
struct timespec now;
bool updated = false;
spin_lock(&queue->lock);
getrawmonotonic(&now);
if (list_empty(&queue->head)) {
queue->lag = ns_to_timespec(0);
queue->lag_time = now;
updated = true;
goto out_unlock;
}
list_for_each_entry_safe(fence, next, &queue->head, head) {
if (signaled_sequence - fence->sequence > (1 << 30))
continue;
queue->lag = timespec_sub(now, fence->submitted);
queue->lag_time = now;
updated = true;
list_del(&fence->head);
kfree(fence);
}
out_unlock:
spin_unlock(&queue->lock);
return (updated) ? 0 : -EBUSY;
}
static struct timespec vmw_timespec_add(struct timespec t1,
struct timespec t2)
{
t1.tv_sec += t2.tv_sec;
t1.tv_nsec += t2.tv_nsec;
if (t1.tv_nsec >= 1000000000L) {
t1.tv_sec += 1;
t1.tv_nsec -= 1000000000L;
}
return t1;
}
static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
{
struct timespec now;
spin_lock(&queue->lock);
getrawmonotonic(&now);
queue->lag = vmw_timespec_add(queue->lag,
timespec_sub(now, queue->lag_time));
queue->lag_time = now;
spin_unlock(&queue->lock);
return queue->lag;
}
static bool vmw_lag_lt(struct vmw_fence_queue *queue,
uint32_t us)
{
struct timespec lag, cond;
cond = ns_to_timespec((s64) us * 1000);
lag = vmw_fifo_lag(queue);
return (timespec_compare(&lag, &cond) < 1);
}
int vmw_wait_lag(struct vmw_private *dev_priv,
struct vmw_fence_queue *queue, uint32_t us)
{
struct vmw_fence *fence;
uint32_t sequence;
int ret;
while (!vmw_lag_lt(queue, us)) {
spin_lock(&queue->lock);
if (list_empty(&queue->head))
sequence = atomic_read(&dev_priv->fence_seq);
else {
fence = list_first_entry(&queue->head,
struct vmw_fence, head);
sequence = fence->sequence;
}
spin_unlock(&queue->lock);
ret = vmw_wait_fence(dev_priv, false, sequence, true,
3*HZ);
if (unlikely(ret != 0))
return ret;
(void) vmw_fence_pull(queue, sequence);
}
return 0;
}
......@@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
uint32_t fifo_min, hwversion;
if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
return false;
fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
return false;
......@@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
return true;
}
bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
{
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
uint32_t caps;
if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
return false;
caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
if (caps & SVGA_FIFO_CAP_PITCHLOCK)
return true;
return false;
}
int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
{
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
......@@ -120,7 +138,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
vmw_fence_queue_init(&fifo->fence_queue);
return vmw_fifo_send_fence(dev_priv, &dummy);
out_err:
vfree(fifo->static_buffer);
......@@ -159,6 +177,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
dev_priv->enable_state);
mutex_unlock(&dev_priv->hw_mutex);
vmw_fence_queue_takedown(&fifo->fence_queue);
if (likely(fifo->last_buffer != NULL)) {
vfree(fifo->last_buffer);
......@@ -484,6 +503,8 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
fifo_state->last_buffer_add = true;
vmw_fifo_commit(dev_priv, bytes);
fifo_state->last_buffer_add = false;
(void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
vmw_update_sequence(dev_priv, fifo_state);
out_err:
return ret;
......
......@@ -64,22 +64,33 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
return (busy == 0);
}
void vmw_update_sequence(struct vmw_private *dev_priv,
struct vmw_fifo_state *fifo_state)
{
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
if (dev_priv->last_read_sequence != sequence) {
dev_priv->last_read_sequence = sequence;
vmw_fence_pull(&fifo_state->fence_queue, sequence);
}
}
bool vmw_fence_signaled(struct vmw_private *dev_priv,
uint32_t sequence)
{
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
struct vmw_fifo_state *fifo_state;
bool ret;
if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
return true;
dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
fifo_state = &dev_priv->fifo;
vmw_update_sequence(dev_priv, fifo_state);
if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
return true;
fifo_state = &dev_priv->fifo;
if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
vmw_fifo_idle(dev_priv, sequence))
return true;
......
This diff is collapsed.
......@@ -94,9 +94,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
/*
* Legacy display unit functions - vmwgfx_ldu.h
* Legacy display unit functions - vmwgfx_ldu.c
*/
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
struct drm_vmw_rect *rects);
#endif
......@@ -38,6 +38,7 @@ struct vmw_legacy_display {
struct list_head active;
unsigned num_active;
unsigned last_num_active;
struct vmw_framebuffer *fb;
};
......@@ -48,9 +49,12 @@ struct vmw_legacy_display {
struct vmw_legacy_display_unit {
struct vmw_display_unit base;
struct list_head active;
unsigned pref_width;
unsigned pref_height;
bool pref_active;
struct drm_display_mode *pref_mode;
unsigned unit;
struct list_head active;
};
static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
......@@ -88,23 +92,44 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
{
struct vmw_legacy_display *lds = dev_priv->ldu_priv;
struct vmw_legacy_display_unit *entry;
struct drm_crtc *crtc;
struct drm_framebuffer *fb = NULL;
struct drm_crtc *crtc = NULL;
int i = 0;
/* to stop the screen from changing size on resize */
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
for (i = 0; i < lds->num_active; i++) {
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
/* If there is no display topology the host just assumes
* that the guest will set the same layout as the host.
*/
if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
int w = 0, h = 0;
list_for_each_entry(entry, &lds->active, active) {
crtc = &entry->base.crtc;
w = max(w, crtc->x + crtc->mode.hdisplay);
h = max(h, crtc->y + crtc->mode.vdisplay);
i++;
}
if (crtc == NULL)
return 0;
fb = entry->base.crtc.fb;
vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
fb->bits_per_pixel, fb->depth);
return 0;
}
/* Now set the mode */
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
if (!list_empty(&lds->active)) {
entry = list_entry(lds->active.next, typeof(*entry), active);
fb = entry->base.crtc.fb;
vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
fb->bits_per_pixel, fb->depth);
}
/* Make sure we always show something. */
vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS,
lds->num_active ? lds->num_active : 1);
i = 0;
list_for_each_entry(entry, &lds->active, active) {
crtc = &entry->base.crtc;
......@@ -120,6 +145,10 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
i++;
}
BUG_ON(i != lds->num_active);
lds->last_num_active = lds->num_active;
return 0;
}
......@@ -130,6 +159,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
if (list_empty(&ldu->active))
return 0;
/* Must init otherwise list_empty(&ldu->active) will not work. */
list_del_init(&ldu->active);
if (--(ld->num_active) == 0) {
BUG_ON(!ld->fb);
......@@ -149,24 +179,29 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
struct vmw_legacy_display_unit *entry;
struct list_head *at;
BUG_ON(!ld->num_active && ld->fb);
if (vfb != ld->fb) {
if (ld->fb && ld->fb->unpin)
ld->fb->unpin(ld->fb);
if (vfb->pin)
vfb->pin(vfb);
ld->fb = vfb;
}
if (!list_empty(&ldu->active))
return 0;
at = &ld->active;
list_for_each_entry(entry, &ld->active, active) {
if (entry->unit > ldu->unit)
if (entry->base.unit > ldu->base.unit)
break;
at = &entry->active;
}
list_add(&ldu->active, at);
if (ld->num_active++ == 0) {
BUG_ON(ld->fb);
if (vfb->pin)
vfb->pin(vfb);
ld->fb = vfb;
}
ld->num_active++;
return 0;
}
......@@ -208,6 +243,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
/* ldu only supports one fb active at the time */
if (dev_priv->ldu_priv->fb && vfb &&
!(dev_priv->ldu_priv->num_active == 1 &&
!list_empty(&ldu->active)) &&
dev_priv->ldu_priv->fb != vfb) {
DRM_ERROR("Multiple framebuffers not supported\n");
return -EINVAL;
......@@ -300,8 +337,7 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
static enum drm_connector_status
vmw_ldu_connector_detect(struct drm_connector *connector)
{
/* XXX vmwctrl should control connection status */
if (vmw_connector_to_ldu(connector)->base.unit == 0)
if (vmw_connector_to_ldu(connector)->pref_active)
return connector_status_connected;
return connector_status_disconnected;
}
......@@ -312,10 +348,9 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
752, 800, 0, 480, 489, 492, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 800x600@60Hz */
{ DRM_MODE("800x600",
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1024x768@60Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
1184, 1344, 0, 768, 771, 777, 806, 0,
......@@ -387,10 +422,34 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height)
{
struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode = NULL;
struct drm_display_mode prefmode = { DRM_MODE("preferred",
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
};
int i;
/* Add preferred mode */
{
mode = drm_mode_duplicate(dev, &prefmode);
if (!mode)
return 0;
mode->hdisplay = ldu->pref_width;
mode->vdisplay = ldu->pref_height;
mode->vrefresh = drm_mode_vrefresh(mode);
drm_mode_probed_add(connector, mode);
if (ldu->pref_mode) {
list_del_init(&ldu->pref_mode->head);
drm_mode_destroy(dev, ldu->pref_mode);
}
ldu->pref_mode = mode;
}
for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
vmw_ldu_connector_builtin[i].vdisplay > max_height)
......@@ -443,18 +502,21 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
if (!ldu)
return -ENOMEM;
ldu->unit = unit;
ldu->base.unit = unit;
crtc = &ldu->base.crtc;
encoder = &ldu->base.encoder;
connector = &ldu->base.connector;
INIT_LIST_HEAD(&ldu->active);
ldu->pref_active = (unit == 0);
ldu->pref_width = 800;
ldu->pref_height = 600;
ldu->pref_mode = NULL;
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
/* Initial status */
if (unit == 0)
connector->status = connector_status_connected;
else
connector->status = connector_status_disconnected;
connector->status = vmw_ldu_connector_detect(connector);
drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
DRM_MODE_ENCODER_LVDS);
......@@ -462,8 +524,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0;
INIT_LIST_HEAD(&ldu->active);
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
drm_connector_attach_property(connector,
......@@ -487,18 +547,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
dev_priv->ldu_priv->num_active = 0;
dev_priv->ldu_priv->last_num_active = 0;
dev_priv->ldu_priv->fb = NULL;
drm_mode_create_dirty_info_property(dev_priv->dev);
vmw_ldu_init(dev_priv, 0);
vmw_ldu_init(dev_priv, 1);
vmw_ldu_init(dev_priv, 2);
vmw_ldu_init(dev_priv, 3);
vmw_ldu_init(dev_priv, 4);
vmw_ldu_init(dev_priv, 5);
vmw_ldu_init(dev_priv, 6);
vmw_ldu_init(dev_priv, 7);
/* for old hardware without multimon only enable one display */
if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
vmw_ldu_init(dev_priv, 1);
vmw_ldu_init(dev_priv, 2);
vmw_ldu_init(dev_priv, 3);
vmw_ldu_init(dev_priv, 4);
vmw_ldu_init(dev_priv, 5);
vmw_ldu_init(dev_priv, 6);
vmw_ldu_init(dev_priv, 7);
}
return 0;
}
......@@ -514,3 +578,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
return 0;
}
int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
struct drm_vmw_rect *rects)
{
struct drm_device *dev = dev_priv->dev;
struct vmw_legacy_display_unit *ldu;
struct drm_connector *con;
int i;
mutex_lock(&dev->mode_config.mutex);
#if 0
DRM_INFO("%s: new layout ", __func__);
for (i = 0; i < (int)num; i++)
DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
rects[i].w, rects[i].h);
DRM_INFO("\n");
#else
(void)i;
#endif
list_for_each_entry(con, &dev->mode_config.connector_list, head) {
ldu = vmw_connector_to_ldu(con);
if (num > ldu->base.unit) {
ldu->pref_width = rects[ldu->base.unit].w;
ldu->pref_height = rects[ldu->base.unit].h;
ldu->pref_active = true;
} else {
ldu->pref_width = 800;
ldu->pref_height = 600;
ldu->pref_active = false;
}
con->status = vmw_ldu_connector_detect(con);
}
mutex_unlock(&dev->mode_config.mutex);
return 0;
}
......@@ -358,6 +358,8 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
if (stream->buf != buf)
stream->buf = vmw_dmabuf_reference(buf);
stream->saved = *arg;
/* stream is no longer stopped/paused */
stream->paused = false;
return 0;
}
......
/*
* vgaarb.c
* vgaarb.c: Implements the VGA arbitration. For details refer to
* Documentation/vgaarbiter.txt
*
*
* (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
* (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
*
* Implements the VGA arbitration. For details refer to
* Documentation/vgaarbiter.txt
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS
* IN THE SOFTWARE.
*
*/
#include <linux/module.h>
......@@ -155,8 +175,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
(vgadev->decodes & VGA_RSRC_LEGACY_MEM))
rsrc |= VGA_RSRC_LEGACY_MEM;
pr_devel("%s: %d\n", __func__, rsrc);
pr_devel("%s: owns: %d\n", __func__, vgadev->owns);
pr_debug("%s: %d\n", __func__, rsrc);
pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
/* Check what resources we need to acquire */
wants = rsrc & ~vgadev->owns;
......@@ -268,7 +288,7 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
{
unsigned int old_locks = vgadev->locks;
pr_devel("%s\n", __func__);
pr_debug("%s\n", __func__);
/* Update our counters, and account for equivalent legacy resources
* if we decode them
......@@ -575,6 +595,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
else
vga_decode_count--;
}
pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
}
void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
......@@ -831,7 +852,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
curr_pos += 5;
remaining -= 5;
pr_devel("client 0x%p called 'lock'\n", priv);
pr_debug("client 0x%p called 'lock'\n", priv);
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
ret_val = -EPROTO;
......@@ -867,7 +888,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
curr_pos += 7;
remaining -= 7;
pr_devel("client 0x%p called 'unlock'\n", priv);
pr_debug("client 0x%p called 'unlock'\n", priv);
if (strncmp(curr_pos, "all", 3) == 0)
io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
......@@ -917,7 +938,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
curr_pos += 8;
remaining -= 8;
pr_devel("client 0x%p called 'trylock'\n", priv);
pr_debug("client 0x%p called 'trylock'\n", priv);
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
ret_val = -EPROTO;
......@@ -961,7 +982,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
curr_pos += 7;
remaining -= 7;
pr_devel("client 0x%p called 'target'\n", priv);
pr_debug("client 0x%p called 'target'\n", priv);
/* if target is default */
if (!strncmp(curr_pos, "default", 7))
pdev = pci_dev_get(vga_default_device());
......@@ -971,11 +992,11 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
ret_val = -EPROTO;
goto done;
}
pr_devel("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
pbus = pci_find_bus(domain, bus);
pr_devel("vgaarb: pbus %p\n", pbus);
pr_debug("vgaarb: pbus %p\n", pbus);
if (pbus == NULL) {
pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
domain, bus);
......@@ -983,7 +1004,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
goto done;
}
pdev = pci_get_slot(pbus, devfn);
pr_devel("vgaarb: pdev %p\n", pdev);
pr_debug("vgaarb: pdev %p\n", pdev);
if (!pdev) {
pr_err("vgaarb: invalid PCI address %x:%x\n",
bus, devfn);
......@@ -993,7 +1014,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
}
vgadev = vgadev_find(pdev);
pr_devel("vgaarb: vgadev %p\n", vgadev);
pr_debug("vgaarb: vgadev %p\n", vgadev);
if (vgadev == NULL) {
pr_err("vgaarb: this pci device is not a vga device\n");
pci_dev_put(pdev);
......@@ -1029,7 +1050,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
} else if (strncmp(curr_pos, "decodes ", 8) == 0) {
curr_pos += 8;
remaining -= 8;
pr_devel("vgaarb: client 0x%p called 'decodes'\n", priv);
pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
ret_val = -EPROTO;
......@@ -1058,7 +1079,7 @@ static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait)
{
struct vga_arb_private *priv = file->private_data;
pr_devel("%s\n", __func__);
pr_debug("%s\n", __func__);
if (priv == NULL)
return -ENODEV;
......@@ -1071,7 +1092,7 @@ static int vga_arb_open(struct inode *inode, struct file *file)
struct vga_arb_private *priv;
unsigned long flags;
pr_devel("%s\n", __func__);
pr_debug("%s\n", __func__);
priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
if (priv == NULL)
......@@ -1101,7 +1122,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
unsigned long flags;
int i;
pr_devel("%s\n", __func__);
pr_debug("%s\n", __func__);
if (priv == NULL)
return -ENODEV;
......@@ -1112,7 +1133,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
uc = &priv->cards[i];
if (uc->pdev == NULL)
continue;
pr_devel("uc->io_cnt == %d, uc->mem_cnt == %d\n",
pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
uc->io_cnt, uc->mem_cnt);
while (uc->io_cnt--)
vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
......@@ -1165,7 +1186,7 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
struct pci_dev *pdev = to_pci_dev(dev);
bool notify = false;
pr_devel("%s\n", __func__);
pr_debug("%s\n", __func__);
/* For now we're only intereted in devices added and removed. I didn't
* test this thing here, so someone needs to double check for the
......
......@@ -130,4 +130,7 @@ extern int drm_helper_resume_force_mode(struct drm_device *dev);
extern void drm_kms_helper_poll_init(struct drm_device *dev);
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
extern void drm_helper_hpd_irq_event(struct drm_device *dev);
extern void drm_kms_helper_poll_disable(struct drm_device *dev);
extern void drm_kms_helper_poll_enable(struct drm_device *dev);
#endif
......@@ -79,6 +79,7 @@ struct drm_nouveau_gpuobj_free {
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12
#define NOUVEAU_GETPARAM_GRAPH_UNITS 13
#define NOUVEAU_GETPARAM_PTIMER_TIME 14
struct drm_nouveau_getparam {
uint64_t param;
uint64_t value;
......
......@@ -50,6 +50,8 @@
#define DRM_VMW_EXECBUF 12
#define DRM_VMW_FIFO_DEBUG 13
#define DRM_VMW_FENCE_WAIT 14
/* guarded by minor version >= 2 */
#define DRM_VMW_UPDATE_LAYOUT 15
/*************************************************************************/
......@@ -585,4 +587,28 @@ struct drm_vmw_stream_arg {
* sure that the stream has been stopped.
*/
/*************************************************************************/
/**
* DRM_VMW_UPDATE_LAYOUT - Update layout
*
* Updates the prefered modes and connection status for connectors. The
* command conisits of one drm_vmw_update_layout_arg pointing out a array
* of num_outputs drm_vmw_rect's.
*/
/**
* struct drm_vmw_update_layout_arg
*
* @num_outputs: number of active
* @rects: pointer to array of drm_vmw_rect
*
* Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
*/
struct drm_vmw_update_layout_arg {
uint32_t num_outputs;
uint32_t pad64;
uint64_t rects;
};
#endif
......@@ -5,6 +5,27 @@
* (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
* (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS
* IN THE SOFTWARE.
*
*/
#ifndef LINUX_VGA_H
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment