diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/uninorth-agp.c | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 0f248239b4ba..a673971f2a90 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <asm/uninorth.h> | 10 | #include <asm/uninorth.h> |
11 | #include <asm/pci-bridge.h> | 11 | #include <asm/pci-bridge.h> |
12 | #include <asm/prom.h> | 12 | #include <asm/prom.h> |
13 | #include <asm/pmac_feature.h> | ||
13 | #include "agp.h" | 14 | #include "agp.h" |
14 | 15 | ||
15 | /* | 16 | /* |
@@ -26,6 +27,7 @@ | |||
26 | static int uninorth_rev; | 27 | static int uninorth_rev; |
27 | static int is_u3; | 28 | static int is_u3; |
28 | 29 | ||
30 | |||
29 | static int uninorth_fetch_size(void) | 31 | static int uninorth_fetch_size(void) |
30 | { | 32 | { |
31 | int i; | 33 | int i; |
@@ -264,7 +266,8 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode) | |||
264 | &scratch); | 266 | &scratch); |
265 | } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000); | 267 | } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000); |
266 | if ((scratch & PCI_AGP_COMMAND_AGP) == 0) | 268 | if ((scratch & PCI_AGP_COMMAND_AGP) == 0) |
267 | printk(KERN_ERR PFX "failed to write UniNorth AGP command reg\n"); | 269 | printk(KERN_ERR PFX "failed to write UniNorth AGP" |
270 | " command register\n"); | ||
268 | 271 | ||
269 | if (uninorth_rev >= 0x30) { | 272 | if (uninorth_rev >= 0x30) { |
270 | /* This is an AGP V3 */ | 273 | /* This is an AGP V3 */ |
@@ -278,13 +281,24 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode) | |||
278 | } | 281 | } |
279 | 282 | ||
280 | #ifdef CONFIG_PM | 283 | #ifdef CONFIG_PM |
281 | static int agp_uninorth_suspend(struct pci_dev *pdev, pm_message_t state) | 284 | /* |
285 | * These Power Management routines are _not_ called by the normal PCI PM layer, | ||
286 | * but directly by the video driver through function pointers in the device | ||
287 | * tree. | ||
288 | */ | ||
289 | static int agp_uninorth_suspend(struct pci_dev *pdev) | ||
282 | { | 290 | { |
291 | struct agp_bridge_data *bridge; | ||
283 | u32 cmd; | 292 | u32 cmd; |
284 | u8 agp; | 293 | u8 agp; |
285 | struct pci_dev *device = NULL; | 294 | struct pci_dev *device = NULL; |
286 | 295 | ||
287 | if (state != PMSG_SUSPEND) | 296 | bridge = agp_find_bridge(pdev); |
297 | if (bridge == NULL) | ||
298 | return -ENODEV; | ||
299 | |||
300 | /* Only one suspend supported */ | ||
301 | if (bridge->dev_private_data) | ||
288 | return 0; | 302 | return 0; |
289 | 303 | ||
290 | /* turn off AGP on the video chip, if it was enabled */ | 304 | /* turn off AGP on the video chip, if it was enabled */ |
@@ -315,6 +329,7 @@ static int agp_uninorth_suspend(struct pci_dev *pdev, pm_message_t state) | |||
315 | /* turn off AGP on the bridge */ | 329 | /* turn off AGP on the bridge */ |
316 | agp = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 330 | agp = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
317 | pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd); | 331 | pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd); |
332 | bridge->dev_private_data = (void *)cmd; | ||
318 | if (cmd & PCI_AGP_COMMAND_AGP) { | 333 | if (cmd & PCI_AGP_COMMAND_AGP) { |
319 | printk("uninorth-agp: disabling AGP on bridge %s\n", | 334 | printk("uninorth-agp: disabling AGP on bridge %s\n", |
320 | pci_name(pdev)); | 335 | pci_name(pdev)); |
@@ -329,9 +344,23 @@ static int agp_uninorth_suspend(struct pci_dev *pdev, pm_message_t state) | |||
329 | 344 | ||
330 | static int agp_uninorth_resume(struct pci_dev *pdev) | 345 | static int agp_uninorth_resume(struct pci_dev *pdev) |
331 | { | 346 | { |
347 | struct agp_bridge_data *bridge; | ||
348 | u32 command; | ||
349 | |||
350 | bridge = agp_find_bridge(pdev); | ||
351 | if (bridge == NULL) | ||
352 | return -ENODEV; | ||
353 | |||
354 | command = (u32)bridge->dev_private_data; | ||
355 | bridge->dev_private_data = NULL; | ||
356 | if (!(command & PCI_AGP_COMMAND_AGP)) | ||
357 | return 0; | ||
358 | |||
359 | uninorth_agp_enable(bridge, command); | ||
360 | |||
332 | return 0; | 361 | return 0; |
333 | } | 362 | } |
334 | #endif | 363 | #endif /* CONFIG_PM */ |
335 | 364 | ||
336 | static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) | 365 | static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) |
337 | { | 366 | { |
@@ -575,6 +604,12 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, | |||
575 | of_node_put(uninorth_node); | 604 | of_node_put(uninorth_node); |
576 | } | 605 | } |
577 | 606 | ||
607 | #ifdef CONFIG_PM | ||
608 | /* Inform platform of our suspend/resume caps */ | ||
609 | pmac_register_agp_pm(pdev, agp_uninorth_suspend, agp_uninorth_resume); | ||
610 | #endif | ||
611 | |||
612 | /* Allocate & setup our driver */ | ||
578 | bridge = agp_alloc_bridge(); | 613 | bridge = agp_alloc_bridge(); |
579 | if (!bridge) | 614 | if (!bridge) |
580 | return -ENOMEM; | 615 | return -ENOMEM; |
@@ -599,6 +634,11 @@ static void __devexit agp_uninorth_remove(struct pci_dev *pdev) | |||
599 | { | 634 | { |
600 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 635 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
601 | 636 | ||
637 | #ifdef CONFIG_PM | ||
638 | /* Inform platform of our suspend/resume caps */ | ||
639 | pmac_register_agp_pm(pdev, NULL, NULL); | ||
640 | #endif | ||
641 | |||
602 | agp_remove_bridge(bridge); | 642 | agp_remove_bridge(bridge); |
603 | agp_put_bridge(bridge); | 643 | agp_put_bridge(bridge); |
604 | } | 644 | } |
@@ -622,10 +662,6 @@ static struct pci_driver agp_uninorth_pci_driver = { | |||
622 | .id_table = agp_uninorth_pci_table, | 662 | .id_table = agp_uninorth_pci_table, |
623 | .probe = agp_uninorth_probe, | 663 | .probe = agp_uninorth_probe, |
624 | .remove = agp_uninorth_remove, | 664 | .remove = agp_uninorth_remove, |
625 | #ifdef CONFIG_PM | ||
626 | .suspend = agp_uninorth_suspend, | ||
627 | .resume = agp_uninorth_resume, | ||
628 | #endif | ||
629 | }; | 665 | }; |
630 | 666 | ||
631 | static int __init agp_uninorth_init(void) | 667 | static int __init agp_uninorth_init(void) |