Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1067b6c2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -389,7 +389,7 @@
      </para>
      </para>
      <para>
      <para>
	If your driver supports memory management (it should!), you'll
	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.
	it depends on which memory manager you're using, TTM or GEM.
      </para>
      </para>
      <sect3>
      <sect3>
@@ -399,7 +399,7 @@
	  aperture space for graphics devices. TTM supports both UMA devices
	  aperture space for graphics devices. TTM supports both UMA devices
	  and devices with dedicated video RAM (VRAM), i.e. most discrete
	  and devices with dedicated video RAM (VRAM), i.e. most discrete
	  graphics devices.  If your device has dedicated RAM, supporting
	  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 specific buffer execution function.  See the radeon
	  driver for examples.
	  driver for examples.
	</para>
	</para>
@@ -443,7 +443,7 @@
	  likely eventually calling ttm_bo_global_init and
	  likely eventually calling ttm_bo_global_init and
	  ttm_bo_global_release, respectively.  Also like the previous
	  ttm_bo_global_release, respectively.  Also like the previous
	  object, ttm_global_item_ref is used to create an initial reference
	  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>
	</para>
      </sect3>
      </sect3>
      <sect3>
      <sect3>
@@ -557,7 +557,7 @@ void intel_crt_init(struct drm_device *dev)
	  CRT connector and encoder combination is created.  A device
	  CRT connector and encoder combination is created.  A device
	  specific i2c bus is also created, for fetching EDID data and
	  specific i2c bus is also created, for fetching EDID data and
	  performing monitor detection.  Once the process is complete,
	  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.
	  properties available to applications.
	</para>
	</para>
	<sect4>
	<sect4>
@@ -581,12 +581,12 @@ void intel_crt_init(struct drm_device *dev)
	<para>
	<para>
	  For each encoder, CRTC and connector, several functions must
	  For each encoder, CRTC and connector, several functions must
	  be provided, depending on the object type.  Encoder objects
	  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),
	  (for converting requested modes into native hardware timings),
	  and prepare, set and commit functions for use by the core DRM
	  and prepare, set and commit functions for use by the core DRM
	  helper functions.  Connector helpers need to provide mode fetch and
	  helper functions.  Connector helpers need to provide mode fetch and
	  validity functions as well as an encoder matching function for
	  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)
	  connector functions include a DPMS callback, (deprecated)
	  save/restore routines, detection, mode probing, property handling,
	  save/restore routines, detection, mode probing, property handling,
	  and cleanup functions.
	  and cleanup functions.
+22 −6
Original line number Original line Diff line number Diff line
@@ -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;
	bool poll = false;
	struct drm_connector *connector;
	int ret;
	int ret;


	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
		if (connector->polled)
		if (connector->polled)
			poll = true;
			poll = true;
	}
	}
	slow_work_register_user(THIS_MODULE);
	delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
			       &output_poll_ops);


	if (poll) {
	if (poll) {
		ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD);
		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);
			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);
EXPORT_SYMBOL(drm_kms_helper_poll_init);


void drm_kms_helper_poll_fini(struct drm_device *dev)
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);
	slow_work_unregister_user(THIS_MODULE);
}
}
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
+3 −1
Original line number Original line Diff line number Diff line
@@ -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);
	struct drm_device *dev = pci_get_drvdata(pdev);
	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
	if (state == VGA_SWITCHEROO_ON) {
	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 */
		/* i915 resume handler doesn't set to D0 */
		pci_set_power_state(dev->pdev, PCI_D0);
		pci_set_power_state(dev->pdev, PCI_D0);
		i915_resume(dev);
		i915_resume(dev);
		drm_kms_helper_poll_enable(dev);
	} else {
	} else {
		printk(KERN_ERR "i915: switched off\n");
		printk(KERN_ERR "i915: switched off\n");
		drm_kms_helper_poll_disable(dev);
		i915_suspend(dev, pmm);
		i915_suspend(dev, pmm);
	}
	}
}
}
+63 −8
Original line number Original line Diff line number Diff line
@@ -34,7 +34,7 @@
static struct nouveau_dsm_priv {
static struct nouveau_dsm_priv {
	bool dsm_detected;
	bool dsm_detected;
	acpi_handle dhandle;
	acpi_handle dhandle;
	acpi_handle dsm_handle;
	acpi_handle rom_handle;
} nouveau_dsm_priv;
} nouveau_dsm_priv;


static const char nouveau_dsm_muid[] = {
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)
static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
{
{
	if (id == VGA_SWITCHEROO_IGD)
	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
	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,
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)
	if (id == VGA_SWITCHEROO_IGD)
		return 0;
		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)
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);
	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
	if (!dhandle)
	if (!dhandle)
		return false;
		return false;

	status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
	status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
	if (ACPI_FAILURE(status)) {
	if (ACPI_FAILURE(status)) {
		return false;
		return false;
	}
	}


	ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED,
	ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
			  NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
			  NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
	if (ret < 0)
	if (ret < 0)
		return false;
		return false;


	nouveau_dsm_priv.dhandle = dhandle;
	nouveau_dsm_priv.dhandle = dhandle;
	nouveau_dsm_priv.dsm_handle = nvidia_handle;
	return true;
	return true;
}
}


@@ -173,6 +173,7 @@ static bool nouveau_dsm_detect(void)
	struct pci_dev *pdev = NULL;
	struct pci_dev *pdev = NULL;
	int has_dsm = 0;
	int has_dsm = 0;
	int vga_count = 0;
	int vga_count = 0;

	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
		vga_count++;
		vga_count++;


@@ -180,7 +181,7 @@ static bool nouveau_dsm_detect(void)
	}
	}


	if (vga_count == 2 && has_dsm) {
	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",
		printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
		       acpi_method_name);
		       acpi_method_name);
		nouveau_dsm_priv.dsm_detected = true;
		nouveau_dsm_priv.dsm_detected = true;
@@ -204,3 +205,57 @@ void nouveau_unregister_dsm_handler(void)
{
{
	vga_switcheroo_unregister_handler();
	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);
}
+60 −11
Original line number Original line Diff line number Diff line
@@ -178,6 +178,25 @@ static void load_vbios_pci(struct drm_device *dev, uint8_t *data)
	pci_disable_rom(dev->pdev);
	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 {
struct methods {
	const char desc[8];
	const char desc[8];
	void (*loadbios)(struct drm_device *, uint8_t *);
	void (*loadbios)(struct drm_device *, uint8_t *);
@@ -191,6 +210,7 @@ static struct methods nv04_methods[] = {
};
};


static struct methods nv50_methods[] = {
static struct methods nv50_methods[] = {
	{ "ACPI", load_vbios_acpi, true },
	{ "PRAMIN", load_vbios_pramin, true },
	{ "PRAMIN", load_vbios_pramin, true },
	{ "PROM", load_vbios_prom, false },
	{ "PROM", load_vbios_prom, false },
	{ "PCIROM", load_vbios_pci, true },
	{ "PCIROM", load_vbios_pci, true },
@@ -2807,6 +2827,9 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)


		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);


		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);
			nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);


		/* The NVIDIA binary driver doesn't appear to actually do
		/* The NVIDIA binary driver doesn't appear to actually do
@@ -5533,12 +5556,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
	entry->bus = (conn >> 16) & 0xf;
	entry->bus = (conn >> 16) & 0xf;
	entry->location = (conn >> 20) & 0x3;
	entry->location = (conn >> 20) & 0x3;
	entry->or = (conn >> 24) & 0xf;
	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) {
	switch (entry->type) {
	case OUTPUT_ANALOG:
	case OUTPUT_ANALOG:
@@ -5622,6 +5639,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
		break;
		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? */
	/* unsure what DCB version introduces this, 3.0? */
	if (conf & 0x100000)
	if (conf & 0x100000)
		entry->i2c_upper_default = true;
		entry->i2c_upper_default = true;
@@ -6205,6 +6232,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
		nouveau_i2c_fini(dev, entry);
		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
int
nouveau_bios_init(struct drm_device *dev)
nouveau_bios_init(struct drm_device *dev)
{
{
@@ -6239,11 +6290,9 @@ nouveau_bios_init(struct drm_device *dev)
	bios->execute = false;
	bios->execute = false;


	/* ... unless card isn't POSTed already */
	/* ... unless card isn't POSTed already */
	if (dev_priv->card_type >= NV_10 &&
	if (!nouveau_bios_posted(dev)) {
	    NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
	    NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
		NV_INFO(dev, "Adaptor not initialised\n");
		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");
			NV_ERROR(dev, "Unable to POST this chipset\n");
			return -ENODEV;
			return -ENODEV;
		}
		}
Loading