aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/uninorth-agp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/agp/uninorth-agp.c')
-rw-r--r--drivers/char/agp/uninorth-agp.c52
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 @@
26static int uninorth_rev; 27static int uninorth_rev;
27static int is_u3; 28static int is_u3;
28 29
30
29static int uninorth_fetch_size(void) 31static 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
281static 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 */
289static 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
330static int agp_uninorth_resume(struct pci_dev *pdev) 345static 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
336static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) 365static 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
631static int __init agp_uninorth_init(void) 667static int __init agp_uninorth_init(void)