Commit 2cde4afa authored by Len Brown's avatar Len Brown
Browse files

Pull sony-2.6.24 into release branch

parents e67c5d8d fd1caaed
Loading
Loading
Loading
Loading
+148 −56
Original line number Diff line number Diff line
@@ -1173,7 +1173,8 @@ static struct acpi_driver sony_nc_driver = {
#define SONYPI_TYPE3_OFFSET	0x12

struct sony_pic_ioport {
	struct acpi_resource_io	io;
	struct acpi_resource_io	io1;
	struct acpi_resource_io	io2;
	struct list_head	list;
};

@@ -1443,11 +1444,11 @@ static u8 sony_pic_call1(u8 dev)
{
	u8 v1, v2;

	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
			ITERATIONS_LONG);
	outb(dev, spic_dev.cur_ioport->io.minimum + 4);
	v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4);
	v2 = inb_p(spic_dev.cur_ioport->io.minimum);
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
	v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
	dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
	return v2;
}
@@ -1456,13 +1457,13 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
{
	u8 v1;

	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
			ITERATIONS_LONG);
	outb(dev, spic_dev.cur_ioport->io.minimum + 4);
	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
			ITERATIONS_LONG);
	outb(fn, spic_dev.cur_ioport->io.minimum);
	v1 = inb_p(spic_dev.cur_ioport->io.minimum);
	outb(fn, spic_dev.cur_ioport->io1.minimum);
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
	dprintk("sony_pic_call2: 0x%.4x\n", v1);
	return v1;
}
@@ -1471,13 +1472,13 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
{
	u8 v1;

	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
	outb(dev, spic_dev.cur_ioport->io.minimum + 4);
	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
	outb(fn, spic_dev.cur_ioport->io.minimum);
	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
	outb(v, spic_dev.cur_ioport->io.minimum);
	v1 = inb_p(spic_dev.cur_ioport->io.minimum);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
	outb(fn, spic_dev.cur_ioport->io1.minimum);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
	outb(v, spic_dev.cur_ioport->io1.minimum);
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
	dprintk("sony_pic_call3: 0x%.4x\n", v1);
	return v1;
}
@@ -2074,7 +2075,18 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)

	switch (resource->type) {
	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
		{
			/* start IO enumeration */
			struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
			if (!ioport)
				return AE_ERROR;

			list_add(&ioport->list, &dev->ioports);
			return AE_OK;
		}

	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/* end IO enumeration */
		return AE_OK;

	case ACPI_RESOURCE_TYPE_IRQ:
@@ -2101,7 +2113,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
				if (!interrupt)
					return AE_ERROR;

				list_add_tail(&interrupt->list, &dev->interrupts);
				list_add(&interrupt->list, &dev->interrupts);
				interrupt->irq.triggering = p->triggering;
				interrupt->irq.polarity = p->polarity;
				interrupt->irq.sharable = p->sharable;
@@ -2113,18 +2125,27 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
	case ACPI_RESOURCE_TYPE_IO:
		{
			struct acpi_resource_io *io = &resource->data.io;
			struct sony_pic_ioport *ioport = NULL;
			struct sony_pic_ioport *ioport =
				list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
			if (!io) {
				dprintk("Blank IO resource\n");
				return AE_OK;
			}

			ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
			if (!ioport)
			if (!ioport->io1.minimum) {
				memcpy(&ioport->io1, io, sizeof(*io));
				dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
						ioport->io1.address_length);
			}
			else if (!ioport->io2.minimum) {
				memcpy(&ioport->io2, io, sizeof(*io));
				dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
						ioport->io2.address_length);
			}
			else {
				printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
				return AE_ERROR;

			list_add_tail(&ioport->list, &dev->ioports);
			memcpy(&ioport->io, io, sizeof(*io));
			}
			return AE_OK;
		}
	default:
@@ -2199,10 +2220,22 @@ static int sony_pic_enable(struct acpi_device *device,
{
	acpi_status status;
	int result = 0;
	/* Type 1 resource layout is:
	 *    IO
	 *    IO
	 *    IRQNoFlags
	 *    End
	 *
	 * Type 2 and 3 resource layout is:
	 *    IO
	 *    IRQNoFlags
	 *    End
	 */
	struct {
		struct acpi_resource io_res;
		struct acpi_resource irq_res;
		struct acpi_resource end;
		struct acpi_resource res1;
		struct acpi_resource res2;
		struct acpi_resource res3;
		struct acpi_resource res4;
	} *resource;
	struct acpi_buffer buffer = { 0, NULL };

@@ -2217,21 +2250,49 @@ static int sony_pic_enable(struct acpi_device *device,
	buffer.length = sizeof(*resource) + 1;
	buffer.pointer = resource;

	/* setup Type 1 resources */
	if (spic_dev.model == SONYPI_DEVICE_TYPE1) {

		/* setup io resources */
		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
		resource->res1.length = sizeof(struct acpi_resource);
		memcpy(&resource->res1.data.io, &ioport->io1,
				sizeof(struct acpi_resource_io));

		resource->res2.type = ACPI_RESOURCE_TYPE_IO;
		resource->res2.length = sizeof(struct acpi_resource);
		memcpy(&resource->res2.data.io, &ioport->io2,
				sizeof(struct acpi_resource_io));

		/* setup irq resource */
		resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
		resource->res3.length = sizeof(struct acpi_resource);
		memcpy(&resource->res3.data.irq, &irq->irq,
				sizeof(struct acpi_resource_irq));
		/* we requested a shared irq */
		resource->res3.data.irq.sharable = ACPI_SHARED;

		resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;

	}
	/* setup Type 2/3 resources */
	else {
		/* setup io resource */
	resource->io_res.type = ACPI_RESOURCE_TYPE_IO;
	resource->io_res.length = sizeof(struct acpi_resource);
	memcpy(&resource->io_res.data.io, &ioport->io,
		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
		resource->res1.length = sizeof(struct acpi_resource);
		memcpy(&resource->res1.data.io, &ioport->io1,
				sizeof(struct acpi_resource_io));

		/* setup irq resource */
	resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ;
	resource->irq_res.length = sizeof(struct acpi_resource);
	memcpy(&resource->irq_res.data.irq, &irq->irq,
		resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
		resource->res2.length = sizeof(struct acpi_resource);
		memcpy(&resource->res2.data.irq, &irq->irq,
				sizeof(struct acpi_resource_irq));
		/* we requested a shared irq */
	resource->irq_res.data.irq.sharable = ACPI_SHARED;
		resource->res2.data.irq.sharable = ACPI_SHARED;

	resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
		resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
	}

	/* Attempt to set the resource */
	dprintk("Evaluating _SRS\n");
@@ -2239,7 +2300,7 @@ static int sony_pic_enable(struct acpi_device *device,

	/* check for total failure */
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR DRV_PFX "Error evaluating _SRS");
		printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
		result = -ENODEV;
		goto end;
	}
@@ -2268,11 +2329,14 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)

	struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;

	ev = inb_p(dev->cur_ioport->io.minimum);
	data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset);
	ev = inb_p(dev->cur_ioport->io1.minimum);
	if (dev->cur_ioport->io2.minimum)
		data_mask = inb_p(dev->cur_ioport->io2.minimum);
	else
		data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset);

	dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
			ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset);
			ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset);

	if (ev == 0x00 || ev == 0xff)
		return IRQ_HANDLED;
@@ -2323,8 +2387,11 @@ static int sony_pic_remove(struct acpi_device *device, int type)
	}

	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
	release_region(spic_dev.cur_ioport->io.minimum,
			spic_dev.cur_ioport->io.address_length);
	release_region(spic_dev.cur_ioport->io1.minimum,
			spic_dev.cur_ioport->io1.address_length);
	if (spic_dev.cur_ioport->io2.minimum)
		release_region(spic_dev.cur_ioport->io2.minimum,
				spic_dev.cur_ioport->io2.address_length);

	sonypi_compat_exit();

@@ -2397,16 +2464,38 @@ static int sony_pic_add(struct acpi_device *device)
		goto err_remove_input;

	/* request io port */
	list_for_each_entry(io, &spic_dev.ioports, list) {
		if (request_region(io->io.minimum, io->io.address_length,
	list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
		if (request_region(io->io1.minimum, io->io1.address_length,
					"Sony Programable I/O Device")) {
			dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
					io->io1.minimum, io->io1.maximum,
					io->io1.address_length);
			/* Type 1 have 2 ioports */
			if (io->io2.minimum) {
				if (request_region(io->io2.minimum,
						io->io2.address_length,
						"Sony Programable I/O Device")) {
			dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n",
					io->io.minimum, io->io.maximum,
					io->io.address_length);
					dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
							io->io2.minimum, io->io2.maximum,
							io->io2.address_length);
					spic_dev.cur_ioport = io;
					break;
				}
				else {
					dprintk("Unable to get I/O port2: "
							"0x%.4x (0x%.4x) + 0x%.2x\n",
							io->io2.minimum, io->io2.maximum,
							io->io2.address_length);
					release_region(io->io1.minimum,
							io->io1.address_length);
				}
			}
			else {
				spic_dev.cur_ioport = io;
				break;
			}
		}
	}
	if (!spic_dev.cur_ioport) {
		printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
		result = -ENODEV;
@@ -2414,7 +2503,7 @@ static int sony_pic_add(struct acpi_device *device)
	}

	/* request IRQ */
	list_for_each_entry(irq, &spic_dev.interrupts, list) {
	list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
		if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
					IRQF_SHARED, "sony-laptop", &spic_dev)) {
			dprintk("IRQ: %d - triggering: %d - "
@@ -2462,8 +2551,11 @@ err_free_irq:
	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);

err_release_region:
	release_region(spic_dev.cur_ioport->io.minimum,
			spic_dev.cur_ioport->io.address_length);
	release_region(spic_dev.cur_ioport->io1.minimum,
			spic_dev.cur_ioport->io1.address_length);
	if (spic_dev.cur_ioport->io2.minimum)
		release_region(spic_dev.cur_ioport->io2.minimum,
				spic_dev.cur_ioport->io2.address_length);

err_remove_compat:
	sonypi_compat_exit();