diff options
author | Pierre Ossman <drzeus-list@drzeus.cx> | 2005-11-29 03:09:32 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:31:30 -0500 |
commit | 68094e3251a664ee1389fcf179497237cbf78331 (patch) | |
tree | 1f38ff587622bab4b1063c19447832f6cbff8a6f /drivers/pnp | |
parent | 4c98cfef2efa6b6662ac28c4f0069964bbd9fdf9 (diff) |
[ALSA] [PATCH] alsa: Improved PnP suspend support
Also use the PnP functions to start/stop the devices during the suspend so
that drivers will not have to duplicate this code.
Cc: Adam Belay <ambx1@neo.rr.com>
Cc: Jaroslav Kysela <perex@suse.cz>
Cc: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'drivers/pnp')
-rw-r--r-- | drivers/pnp/driver.c | 37 | ||||
-rw-r--r-- | drivers/pnp/manager.c | 78 |
2 files changed, 91 insertions, 24 deletions
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index ea2cb9a8b21d..15fb758a9e52 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
@@ -150,19 +150,46 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state) | |||
150 | { | 150 | { |
151 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); | 151 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); |
152 | struct pnp_driver * pnp_drv = pnp_dev->driver; | 152 | struct pnp_driver * pnp_drv = pnp_dev->driver; |
153 | int error; | ||
154 | |||
155 | if (!pnp_drv) | ||
156 | return 0; | ||
157 | |||
158 | if (pnp_drv->suspend) { | ||
159 | error = pnp_drv->suspend(pnp_dev, state); | ||
160 | if (error) | ||
161 | return error; | ||
162 | } | ||
163 | |||
164 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) && | ||
165 | pnp_can_disable(pnp_dev)) { | ||
166 | error = pnp_stop_dev(pnp_dev); | ||
167 | if (error) | ||
168 | return error; | ||
169 | } | ||
153 | 170 | ||
154 | if (pnp_drv && pnp_drv->suspend) | ||
155 | return pnp_drv->suspend(pnp_dev, state); | ||
156 | return 0; | 171 | return 0; |
157 | } | 172 | } |
158 | 173 | ||
159 | static void pnp_bus_resume(struct device *dev) | 174 | static int pnp_bus_resume(struct device *dev) |
160 | { | 175 | { |
161 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); | 176 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); |
162 | struct pnp_driver * pnp_drv = pnp_dev->driver; | 177 | struct pnp_driver * pnp_drv = pnp_dev->driver; |
178 | int error; | ||
179 | |||
180 | if (!pnp_drv) | ||
181 | return 0; | ||
182 | |||
183 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { | ||
184 | error = pnp_start_dev(pnp_dev); | ||
185 | if (error) | ||
186 | return error; | ||
187 | } | ||
163 | 188 | ||
164 | if (pnp_drv && pnp_drv->resume) | 189 | if (pnp_drv->resume) |
165 | pnp_drv->resume(pnp_dev); | 190 | return pnp_drv->resume(pnp_dev); |
191 | |||
192 | return 0; | ||
166 | } | 193 | } |
167 | 194 | ||
168 | struct bus_type pnp_bus_type = { | 195 | struct bus_type pnp_bus_type = { |
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 261668618b2d..c4256aa32bcb 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -470,6 +470,53 @@ int pnp_auto_config_dev(struct pnp_dev *dev) | |||
470 | } | 470 | } |
471 | 471 | ||
472 | /** | 472 | /** |
473 | * pnp_start_dev - low-level start of the PnP device | ||
474 | * @dev: pointer to the desired device | ||
475 | * | ||
476 | * assumes that resources have alread been allocated | ||
477 | */ | ||
478 | |||
479 | int pnp_start_dev(struct pnp_dev *dev) | ||
480 | { | ||
481 | if (!pnp_can_write(dev)) { | ||
482 | pnp_info("Device %s does not supported activation.", dev->dev.bus_id); | ||
483 | return -EINVAL; | ||
484 | } | ||
485 | |||
486 | if (dev->protocol->set(dev, &dev->res)<0) { | ||
487 | pnp_err("Failed to activate device %s.", dev->dev.bus_id); | ||
488 | return -EIO; | ||
489 | } | ||
490 | |||
491 | pnp_info("Device %s activated.", dev->dev.bus_id); | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * pnp_stop_dev - low-level disable of the PnP device | ||
498 | * @dev: pointer to the desired device | ||
499 | * | ||
500 | * does not free resources | ||
501 | */ | ||
502 | |||
503 | int pnp_stop_dev(struct pnp_dev *dev) | ||
504 | { | ||
505 | if (!pnp_can_disable(dev)) { | ||
506 | pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); | ||
507 | return -EINVAL; | ||
508 | } | ||
509 | if (dev->protocol->disable(dev)<0) { | ||
510 | pnp_err("Failed to disable device %s.", dev->dev.bus_id); | ||
511 | return -EIO; | ||
512 | } | ||
513 | |||
514 | pnp_info("Device %s disabled.", dev->dev.bus_id); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | /** | ||
473 | * pnp_activate_dev - activates a PnP device for use | 520 | * pnp_activate_dev - activates a PnP device for use |
474 | * @dev: pointer to the desired device | 521 | * @dev: pointer to the desired device |
475 | * | 522 | * |
@@ -477,6 +524,8 @@ int pnp_auto_config_dev(struct pnp_dev *dev) | |||
477 | */ | 524 | */ |
478 | int pnp_activate_dev(struct pnp_dev *dev) | 525 | int pnp_activate_dev(struct pnp_dev *dev) |
479 | { | 526 | { |
527 | int error; | ||
528 | |||
480 | if (!dev) | 529 | if (!dev) |
481 | return -EINVAL; | 530 | return -EINVAL; |
482 | if (dev->active) { | 531 | if (dev->active) { |
@@ -487,18 +536,11 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
487 | if (pnp_auto_config_dev(dev)) | 536 | if (pnp_auto_config_dev(dev)) |
488 | return -EBUSY; | 537 | return -EBUSY; |
489 | 538 | ||
490 | if (!pnp_can_write(dev)) { | 539 | error = pnp_start_dev(dev); |
491 | pnp_info("Device %s does not supported activation.", dev->dev.bus_id); | 540 | if (error) |
492 | return -EINVAL; | 541 | return error; |
493 | } | ||
494 | |||
495 | if (dev->protocol->set(dev, &dev->res)<0) { | ||
496 | pnp_err("Failed to activate device %s.", dev->dev.bus_id); | ||
497 | return -EIO; | ||
498 | } | ||
499 | 542 | ||
500 | dev->active = 1; | 543 | dev->active = 1; |
501 | pnp_info("Device %s activated.", dev->dev.bus_id); | ||
502 | 544 | ||
503 | return 1; | 545 | return 1; |
504 | } | 546 | } |
@@ -511,23 +553,19 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
511 | */ | 553 | */ |
512 | int pnp_disable_dev(struct pnp_dev *dev) | 554 | int pnp_disable_dev(struct pnp_dev *dev) |
513 | { | 555 | { |
556 | int error; | ||
557 | |||
514 | if (!dev) | 558 | if (!dev) |
515 | return -EINVAL; | 559 | return -EINVAL; |
516 | if (!dev->active) { | 560 | if (!dev->active) { |
517 | return 0; /* the device is already disabled */ | 561 | return 0; /* the device is already disabled */ |
518 | } | 562 | } |
519 | 563 | ||
520 | if (!pnp_can_disable(dev)) { | 564 | error = pnp_stop_dev(dev); |
521 | pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); | 565 | if (error) |
522 | return -EINVAL; | 566 | return error; |
523 | } | ||
524 | if (dev->protocol->disable(dev)<0) { | ||
525 | pnp_err("Failed to disable device %s.", dev->dev.bus_id); | ||
526 | return -EIO; | ||
527 | } | ||
528 | 567 | ||
529 | dev->active = 0; | 568 | dev->active = 0; |
530 | pnp_info("Device %s disabled.", dev->dev.bus_id); | ||
531 | 569 | ||
532 | /* release the resources so that other devices can use them */ | 570 | /* release the resources so that other devices can use them */ |
533 | down(&pnp_res_mutex); | 571 | down(&pnp_res_mutex); |
@@ -558,6 +596,8 @@ EXPORT_SYMBOL(pnp_manual_config_dev); | |||
558 | #if 0 | 596 | #if 0 |
559 | EXPORT_SYMBOL(pnp_auto_config_dev); | 597 | EXPORT_SYMBOL(pnp_auto_config_dev); |
560 | #endif | 598 | #endif |
599 | EXPORT_SYMBOL(pnp_start_dev); | ||
600 | EXPORT_SYMBOL(pnp_stop_dev); | ||
561 | EXPORT_SYMBOL(pnp_activate_dev); | 601 | EXPORT_SYMBOL(pnp_activate_dev); |
562 | EXPORT_SYMBOL(pnp_disable_dev); | 602 | EXPORT_SYMBOL(pnp_disable_dev); |
563 | EXPORT_SYMBOL(pnp_resource_change); | 603 | EXPORT_SYMBOL(pnp_resource_change); |