Video PM Methods

Peter Jones pjones at redhat.com
Wed May 17 08:03:22 PDT 2006


On Wed, 2006-05-17 at 13:26 +0200, Stefan Seyfried wrote:
> On Wed, May 17, 2006 at 10:35:02AM +0100, Richard Hughes wrote:
> > On Tue, 2006-05-16 at 15:15 -0400, Peter Jones wrote:
> 
> > I figure if the video card is a *specific* device:subdevice from a
> > specific vendor, then the pm resume tweaks would be the same between
> > laptop vendors, or is that not a valid assumption?
> 
> I don't think so. I have seen ATI Radeon RV250 in ThinkPads just working
> fine with /proc/sys/kernel/acpi_video_flags=3, but in a Dell D600 they
> need VBE_POST|VBE_SAVE and may not use a framebuffer. I am not sure that
> they have the exact same PCI id, but it clearly depends on the BIOS more
> than on the chip.

I'm pretty sure those have a different subvendor:subdevice -- the R250
Lf in my thinkpad has 1014:0531 (IBM:somedev).  I think that getting
this right is actually the very common case.

In fact, I suspect we want something very close to what the kernel has
-- a table of devices keyed on the full [vendor id, device id, subvendor
id, subdevice id], with sentinels PCI_VENDOR_ANY and PCI_DEVICE_ANY
which match any value, and then (possibly) another table of "quirks"
keyed the same way.  I'm not actually sure we need the quirks table yet.

So the code I'm thinking of might turn out to look something like:

typedef enum {
	S3_BIOS			= 0x1,
	S3_MODE 		= 0x2,
	SUSPEND_VGAMODE_3	= 0x4,
	SUSPEND_DPMS_SUSPEND	= 0x8,
	...
	RESUME_VBESTATE_RESTORE	= 0x100,
	RESUME_VBEMODE_RESTORE	= 0x101,
	RESUME_VBE_POST		= 0x102,
	RESUME_DPMS_ON		= 0x104,
	...
} suspend_resume_flags;

#define PCI_VENDOR_ANY 0x10000
#define PCI_VENDOR_NOT 0x20000
#define PCI_TABLE_END 0x40000
#define PCI_DEVICE_ANY PCI_VENDOR_ANY
#define PCI_DEVICE_NOT PCI_VENDOR_NOT

struct pci_device_table {
	u32 vendor_id;
	u32 device_id;
	u32 subvendor_id;
	u32 subdevice_id;
	u32 flags;
} pci_devices[] = {
	{ PCI_VENDOR_ATI, PCI_DEVICE_ANY,
	  PCI_VENDOR_IBM, PCI_DEVICE_ANY | PCI_DEVICE_NOT | PCI_DEVICE_IBM_BADDEV,
	  SUSPEND_DPMS_SUSPEND },
	{ PCI_VENDOR_ATI, PCI_DEVICE_ANY,
	  PCI_VENDOR_IBM, PCI_DEVICE_IBM_BADDEV,
	  some other set of flags },
	{ PCI_VENDOR_INTEL, PCI_DEVICE_I915,
	  PCI_VENDOR_ANY, PCI_DEVICE_ANY,
	  S3_BIOS | S3_MODE },
	{ .vendor_id = PCI_TABLE_END }
};

static inline get_device_flags(struct pci_dev *dev) {
	struct pci_device_table *cur;

	for (cur = pci_devices ; cur->vendor_id != PCI_TABLE_END ; cur++) {
		if (cur->vendor_id != PCI_VENDOR_ANY) {
			if (dev->vendor_id != (cur->vendor_id & 0xffff) ||
			    (cur->vendor_id & PCI_VENDOR_NOT))
				continue;
		}
		if (cur->device_id != PCI_DEVICE_ANY) {
			if (dev->device_id != (cur->device_id & 0xffff) ||
			    (cur->device_id & PCI_DEVICE_NOT))
				continue;
		}
		if (cur->subvendor_id != PCI_VENDOR_ANY) {
			if (dev->subvendor_id != (cur->subvendor_id & 0xffff) ||
			    (cur->subvendor_id & PCI_VENDOR_NOT))
				continue;
		}
		if (cur->subdevice_id != PCI_DEVICE_ANY) {
			if (dev->subdevice_id != (cur->subdevice_id & 0xffff) ||
			    (cur->subdevice_id & PCI_DEVICE_NOT))
				continue;
		}
		return cur->flags;
	}
	return 0;
}

> What we could do is a 2 stage setup:
> - match the machines we know and do what is configured for them.
> - if we do not know them, match on the chip and do a "best practice"
>   for the chip. E.g. most i915 i have seen worked happily with
>   acpi_video_flags=3, many new ATIs do not work with framebuffer, but
>   need VBE_POST|VBE_SAVE, so we could "guess" what will work. If this
>   guessed value is used, issue a loud honking warning into syslog before
>   suspend and tell the users how to check their machine and where to
>   report success. That is how the s2ram whitelist grows every day.

See above -- it really doesn't need to be two stages, it's just a table.
Also, it's easily expressed in e.g. xml if we want to go that route
(which I bet most people do).  And it's easy to override things, should
you want to, in those XML documents.

-- 
  Peter



More information about the hal mailing list