diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-11-17 11:26:09 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:28:55 -0500 |
commit | 5fe76e4dc60a2c3ff9b1143f5275a953db685e26 (patch) | |
tree | f54acdb029f429bf8c0068ed964a1216fbe614d3 /Documentation/sound/alsa/DocBook | |
parent | a4efc230c60ad15584e723755316e67b3c708d67 (diff) |
[ALSA] document - Update PM support
Modules: Documentation
Update the description about the PCI PM support.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'Documentation/sound/alsa/DocBook')
-rw-r--r-- | Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 185 |
1 files changed, 146 insertions, 39 deletions
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index f2e59fe802bd..4963d83d1511 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | |||
@@ -18,8 +18,8 @@ | |||
18 | </affiliation> | 18 | </affiliation> |
19 | </author> | 19 | </author> |
20 | 20 | ||
21 | <date>October 6, 2005</date> | 21 | <date>November 17, 2005</date> |
22 | <edition>0.3.5</edition> | 22 | <edition>0.3.6</edition> |
23 | 23 | ||
24 | <abstract> | 24 | <abstract> |
25 | <para> | 25 | <para> |
@@ -2329,9 +2329,14 @@ struct _snd_pcm_runtime { | |||
2329 | <constant>PAUSE</constant> bit means that the pcm supports the | 2329 | <constant>PAUSE</constant> bit means that the pcm supports the |
2330 | <quote>pause</quote> operation, while the | 2330 | <quote>pause</quote> operation, while the |
2331 | <constant>RESUME</constant> bit means that the pcm supports | 2331 | <constant>RESUME</constant> bit means that the pcm supports |
2332 | the <quote>suspend/resume</quote> operation. If these flags | 2332 | the full <quote>suspend/resume</quote> operation. |
2333 | are set, the <structfield>trigger</structfield> callback below | 2333 | If <constant>PAUSE</constant> flag is set, |
2334 | must handle the corresponding commands. | 2334 | the <structfield>trigger</structfield> callback below |
2335 | must handle the corresponding (pause push/release) commands. | ||
2336 | The suspend/resume trigger commands can be defined even without | ||
2337 | <constant>RESUME</constant> flag. See <link | ||
2338 | linkend="power-management"><citetitle> | ||
2339 | Power Management</citetitle></link> section for details. | ||
2335 | </para> | 2340 | </para> |
2336 | 2341 | ||
2337 | <para> | 2342 | <para> |
@@ -2903,8 +2908,8 @@ struct _snd_pcm_runtime { | |||
2903 | </para> | 2908 | </para> |
2904 | 2909 | ||
2905 | <para> | 2910 | <para> |
2906 | When the pcm supports the suspend/resume operation | 2911 | When the pcm supports the suspend/resume operation, |
2907 | (i.e. <constant>SNDRV_PCM_INFO_RESUME</constant> flag is set), | 2912 | regardless of full or partial suspend/resume support, |
2908 | <constant>SUSPEND</constant> and <constant>RESUME</constant> | 2913 | <constant>SUSPEND</constant> and <constant>RESUME</constant> |
2909 | commands must be handled, too. | 2914 | commands must be handled, too. |
2910 | These commands are issued when the power-management status is | 2915 | These commands are issued when the power-management status is |
@@ -2913,6 +2918,8 @@ struct _snd_pcm_runtime { | |||
2913 | do suspend and resume of the pcm substream, and usually, they | 2918 | do suspend and resume of the pcm substream, and usually, they |
2914 | are identical with <constant>STOP</constant> and | 2919 | are identical with <constant>STOP</constant> and |
2915 | <constant>START</constant> commands, respectively. | 2920 | <constant>START</constant> commands, respectively. |
2921 | See <link linkend="power-management"><citetitle> | ||
2922 | Power Management</citetitle></link> section for details. | ||
2916 | </para> | 2923 | </para> |
2917 | 2924 | ||
2918 | <para> | 2925 | <para> |
@@ -5483,22 +5490,60 @@ struct _snd_pcm_runtime { | |||
5483 | <constant>CONFIG_PM</constant>. | 5490 | <constant>CONFIG_PM</constant>. |
5484 | </para> | 5491 | </para> |
5485 | 5492 | ||
5493 | <para> | ||
5494 | If the driver supports the suspend/resume | ||
5495 | <emphasis>fully</emphasis>, that is, the device can be | ||
5496 | properly resumed to the status at the suspend is called, | ||
5497 | you can set <constant>SNDRV_PCM_INFO_RESUME</constant> flag | ||
5498 | to pcm info field. Usually, this is possible when the | ||
5499 | registers of ths chip can be safely saved and restored to the | ||
5500 | RAM. If this is set, the trigger callback is called with | ||
5501 | <constant>SNDRV_PCM_TRIGGER_RESUME</constant> after resume | ||
5502 | callback is finished. | ||
5503 | </para> | ||
5504 | |||
5505 | <para> | ||
5506 | Even if the driver doesn't support PM fully but only the | ||
5507 | partial suspend/resume is possible, it's still worthy to | ||
5508 | implement suspend/resume callbacks. In such a case, applications | ||
5509 | would reset the status by calling | ||
5510 | <function>snd_pcm_prepare()</function> and restart the stream | ||
5511 | appropriately. Hence, you can define suspend/resume callbacks | ||
5512 | below but don't set <constant>SNDRV_PCM_INFO_RESUME</constant> | ||
5513 | info flag to the PCM. | ||
5514 | </para> | ||
5515 | |||
5516 | <para> | ||
5517 | Note that the trigger with SUSPEND can be always called when | ||
5518 | <function>snd_pcm_suspend_all</function> is called, | ||
5519 | regardless of <constant>SNDRV_PCM_INFO_RESUME</constant> flag. | ||
5520 | The <constant>RESUME</constant> flag affects only the behavior | ||
5521 | of <function>snd_pcm_resume()</function>. | ||
5522 | (Thus, in theory, | ||
5523 | <constant>SNDRV_PCM_TRIGGER_RESUME</constant> isn't needed | ||
5524 | to be handled in the trigger callback when no | ||
5525 | <constant>SNDRV_PCM_INFO_RESUME</constant> flag is set. But, | ||
5526 | it's better to keep it for compatibility reason.) | ||
5527 | </para> | ||
5486 | <para> | 5528 | <para> |
5487 | ALSA provides the common power-management layer. Each card driver | 5529 | In the earlier version of ALSA drivers, a common |
5488 | needs to have only low-level suspend and resume callbacks. | 5530 | power-management layer was provided, but it has been removed. |
5531 | The driver needs to define the suspend/resume hooks according to | ||
5532 | the bus the device is assigned. In the case of PCI driver, the | ||
5533 | callbacks look like below: | ||
5489 | 5534 | ||
5490 | <informalexample> | 5535 | <informalexample> |
5491 | <programlisting> | 5536 | <programlisting> |
5492 | <![CDATA[ | 5537 | <![CDATA[ |
5493 | #ifdef CONFIG_PM | 5538 | #ifdef CONFIG_PM |
5494 | static int snd_my_suspend(struct snd_card *card, pm_message_t state) | 5539 | static int snd_my_suspend(struct pci_dev *pci, pm_message_t state) |
5495 | { | 5540 | { |
5496 | .... // do things for suspsend | 5541 | .... /* do things for suspsend */ |
5497 | return 0; | 5542 | return 0; |
5498 | } | 5543 | } |
5499 | static int snd_my_resume(struct snd_card *card) | 5544 | static int snd_my_resume(struct pci_dev *pci) |
5500 | { | 5545 | { |
5501 | .... // do things for suspsend | 5546 | .... /* do things for suspsend */ |
5502 | return 0; | 5547 | return 0; |
5503 | } | 5548 | } |
5504 | #endif | 5549 | #endif |
@@ -5511,11 +5556,18 @@ struct _snd_pcm_runtime { | |||
5511 | The scheme of the real suspend job is as following. | 5556 | The scheme of the real suspend job is as following. |
5512 | 5557 | ||
5513 | <orderedlist> | 5558 | <orderedlist> |
5514 | <listitem><para>Retrieve the chip data from pm_private_data field.</para></listitem> | 5559 | <listitem><para>Retrieve the card and the chip data.</para></listitem> |
5560 | <listitem><para>Call <function>snd_power_change_state()</function> with | ||
5561 | <constant>SNDRV_CTL_POWER_D3hot</constant> to change the | ||
5562 | power status.</para></listitem> | ||
5515 | <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem> | 5563 | <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem> |
5564 | <listitem><para>If AC97 codecs are used, call | ||
5565 | <function>snd_ac97_resume()</function> for each codec.</para></listitem> | ||
5516 | <listitem><para>Save the register values if necessary.</para></listitem> | 5566 | <listitem><para>Save the register values if necessary.</para></listitem> |
5517 | <listitem><para>Stop the hardware if necessary.</para></listitem> | 5567 | <listitem><para>Stop the hardware if necessary.</para></listitem> |
5518 | <listitem><para>Disable the PCI device by calling <function>pci_disable_device()</function>.</para></listitem> | 5568 | <listitem><para>Disable the PCI device by calling |
5569 | <function>pci_disable_device()</function>. Then, call | ||
5570 | <function>pci_save_state()</function> at last.</para></listitem> | ||
5519 | </orderedlist> | 5571 | </orderedlist> |
5520 | </para> | 5572 | </para> |
5521 | 5573 | ||
@@ -5525,18 +5577,24 @@ struct _snd_pcm_runtime { | |||
5525 | <informalexample> | 5577 | <informalexample> |
5526 | <programlisting> | 5578 | <programlisting> |
5527 | <![CDATA[ | 5579 | <![CDATA[ |
5528 | static int mychip_suspend(struct snd_card *card, pm_message_t state) | 5580 | static int mychip_suspend(strut pci_dev *pci, pm_message_t state) |
5529 | { | 5581 | { |
5530 | /* (1) */ | 5582 | /* (1) */ |
5531 | struct mychip *chip = card->pm_private_data; | 5583 | struct snd_card *card = pci_get_drvdata(pci); |
5584 | struct mychip *chip = card->private_data; | ||
5532 | /* (2) */ | 5585 | /* (2) */ |
5533 | snd_pcm_suspend_all(chip->pcm); | 5586 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
5534 | /* (3) */ | 5587 | /* (3) */ |
5535 | snd_mychip_save_registers(chip); | 5588 | snd_pcm_suspend_all(chip->pcm); |
5536 | /* (4) */ | 5589 | /* (4) */ |
5537 | snd_mychip_stop_hardware(chip); | 5590 | snd_ac97_suspend(chip->ac97); |
5538 | /* (5) */ | 5591 | /* (5) */ |
5539 | pci_disable_device(chip->pci); | 5592 | snd_mychip_save_registers(chip); |
5593 | /* (6) */ | ||
5594 | snd_mychip_stop_hardware(chip); | ||
5595 | /* (7) */ | ||
5596 | pci_disable_device(pci); | ||
5597 | pci_save_state(pci); | ||
5540 | return 0; | 5598 | return 0; |
5541 | } | 5599 | } |
5542 | ]]> | 5600 | ]]> |
@@ -5548,14 +5606,17 @@ struct _snd_pcm_runtime { | |||
5548 | The scheme of the real resume job is as following. | 5606 | The scheme of the real resume job is as following. |
5549 | 5607 | ||
5550 | <orderedlist> | 5608 | <orderedlist> |
5551 | <listitem><para>Retrieve the chip data from pm_private_data field.</para></listitem> | 5609 | <listitem><para>Retrieve the card and the chip data.</para></listitem> |
5552 | <listitem><para>Enable the pci device again by calling | 5610 | <listitem><para>Set up PCI. First, call <function>pci_restore_state()</function>. |
5553 | <function>pci_enable_device()</function>.</para></listitem> | 5611 | Then enable the pci device again by calling <function>pci_enable_device()</function>. |
5612 | Call <function>pci_set_master()</function> if necessary, too.</para></listitem> | ||
5554 | <listitem><para>Re-initialize the chip.</para></listitem> | 5613 | <listitem><para>Re-initialize the chip.</para></listitem> |
5555 | <listitem><para>Restore the saved registers if necessary.</para></listitem> | 5614 | <listitem><para>Restore the saved registers if necessary.</para></listitem> |
5556 | <listitem><para>Resume the mixer, e.g. calling | 5615 | <listitem><para>Resume the mixer, e.g. calling |
5557 | <function>snd_ac97_resume()</function>.</para></listitem> | 5616 | <function>snd_ac97_resume()</function>.</para></listitem> |
5558 | <listitem><para>Restart the hardware (if any).</para></listitem> | 5617 | <listitem><para>Restart the hardware (if any).</para></listitem> |
5618 | <listitem><para>Call <function>snd_power_change_state()</function> with | ||
5619 | <constant>SNDRV_CTL_POWER_D0</constant> to notify the processes.</para></listitem> | ||
5559 | </orderedlist> | 5620 | </orderedlist> |
5560 | </para> | 5621 | </para> |
5561 | 5622 | ||
@@ -5565,12 +5626,15 @@ struct _snd_pcm_runtime { | |||
5565 | <informalexample> | 5626 | <informalexample> |
5566 | <programlisting> | 5627 | <programlisting> |
5567 | <![CDATA[ | 5628 | <![CDATA[ |
5568 | static void mychip_resume(struct mychip *chip) | 5629 | static int mychip_resume(struct pci_dev *pci) |
5569 | { | 5630 | { |
5570 | /* (1) */ | 5631 | /* (1) */ |
5571 | struct mychip *chip = card->pm_private_data; | 5632 | struct snd_card *card = pci_get_drvdata(pci); |
5633 | struct mychip *chip = card->private_data; | ||
5572 | /* (2) */ | 5634 | /* (2) */ |
5573 | pci_enable_device(chip->pci); | 5635 | pci_restore_state(pci); |
5636 | pci_enable_device(pci); | ||
5637 | pci_set_master(pci); | ||
5574 | /* (3) */ | 5638 | /* (3) */ |
5575 | snd_mychip_reinit_chip(chip); | 5639 | snd_mychip_reinit_chip(chip); |
5576 | /* (4) */ | 5640 | /* (4) */ |
@@ -5579,6 +5643,8 @@ struct _snd_pcm_runtime { | |||
5579 | snd_ac97_resume(chip->ac97); | 5643 | snd_ac97_resume(chip->ac97); |
5580 | /* (6) */ | 5644 | /* (6) */ |
5581 | snd_mychip_restart_chip(chip); | 5645 | snd_mychip_restart_chip(chip); |
5646 | /* (7) */ | ||
5647 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
5582 | return 0; | 5648 | return 0; |
5583 | } | 5649 | } |
5584 | ]]> | 5650 | ]]> |
@@ -5587,8 +5653,48 @@ struct _snd_pcm_runtime { | |||
5587 | </para> | 5653 | </para> |
5588 | 5654 | ||
5589 | <para> | 5655 | <para> |
5590 | OK, we have all callbacks now. Let's set up them now. In the | 5656 | As shown in the above, it's better to save registers after |
5591 | initialization of the card, add the following: | 5657 | suspending the PCM operations via |
5658 | <function>snd_pcm_suspend_all()</function> or | ||
5659 | <function>snd_pcm_suspend()</function>. It means that the PCM | ||
5660 | streams are already stoppped when the register snapshot is | ||
5661 | taken. But, remind that you don't have to restart the PCM | ||
5662 | stream in the resume callback. It'll be restarted via | ||
5663 | trigger call with <constant>SNDRV_PCM_TRIGGER_RESUME</constant> | ||
5664 | when necessary. | ||
5665 | </para> | ||
5666 | |||
5667 | <para> | ||
5668 | OK, we have all callbacks now. Let's set them up. In the | ||
5669 | initialization of the card, make sure that you can get the chip | ||
5670 | data from the card instance, typically via | ||
5671 | <structfield>private_data</structfield> field, in case you | ||
5672 | created the chip data individually. | ||
5673 | |||
5674 | <informalexample> | ||
5675 | <programlisting> | ||
5676 | <![CDATA[ | ||
5677 | static int __devinit snd_mychip_probe(struct pci_dev *pci, | ||
5678 | const struct pci_device_id *pci_id) | ||
5679 | { | ||
5680 | .... | ||
5681 | struct snd_card *card; | ||
5682 | struct mychip *chip; | ||
5683 | .... | ||
5684 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL); | ||
5685 | .... | ||
5686 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
5687 | .... | ||
5688 | card->private_data = chip; | ||
5689 | .... | ||
5690 | } | ||
5691 | ]]> | ||
5692 | </programlisting> | ||
5693 | </informalexample> | ||
5694 | |||
5695 | When you created the chip data with | ||
5696 | <function>snd_card_new()</function>, it's anyway accessible | ||
5697 | via <structfield>private_data</structfield> field. | ||
5592 | 5698 | ||
5593 | <informalexample> | 5699 | <informalexample> |
5594 | <programlisting> | 5700 | <programlisting> |
@@ -5600,30 +5706,28 @@ struct _snd_pcm_runtime { | |||
5600 | struct snd_card *card; | 5706 | struct snd_card *card; |
5601 | struct mychip *chip; | 5707 | struct mychip *chip; |
5602 | .... | 5708 | .... |
5603 | snd_card_set_pm_callback(card, snd_my_suspend, snd_my_resume, chip); | 5709 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, |
5710 | sizeof(struct mychip)); | ||
5711 | .... | ||
5712 | chip = card->private_data; | ||
5604 | .... | 5713 | .... |
5605 | } | 5714 | } |
5606 | ]]> | 5715 | ]]> |
5607 | </programlisting> | 5716 | </programlisting> |
5608 | </informalexample> | 5717 | </informalexample> |
5609 | 5718 | ||
5610 | Here you don't have to put ifdef CONFIG_PM around, since it's already | ||
5611 | checked in the header and expanded to empty if not needed. | ||
5612 | </para> | 5719 | </para> |
5613 | 5720 | ||
5614 | <para> | 5721 | <para> |
5615 | If you need a space for saving the registers, you'll need to | 5722 | If you need a space for saving the registers, allocate the |
5616 | allocate the buffer for it here, too, since it would be fatal | 5723 | buffer for it here, too, since it would be fatal |
5617 | if you cannot allocate a memory in the suspend phase. | 5724 | if you cannot allocate a memory in the suspend phase. |
5618 | The allocated buffer should be released in the corresponding | 5725 | The allocated buffer should be released in the corresponding |
5619 | destructor. | 5726 | destructor. |
5620 | </para> | 5727 | </para> |
5621 | 5728 | ||
5622 | <para> | 5729 | <para> |
5623 | And next, set suspend/resume callbacks to the pci_driver, | 5730 | And next, set suspend/resume callbacks to the pci_driver. |
5624 | This can be done by passing a macro SND_PCI_PM_CALLBACKS | ||
5625 | in the pci_driver struct. This macro is expanded to the correct | ||
5626 | (global) callbacks if CONFIG_PM is set. | ||
5627 | 5731 | ||
5628 | <informalexample> | 5732 | <informalexample> |
5629 | <programlisting> | 5733 | <programlisting> |
@@ -5633,7 +5737,10 @@ struct _snd_pcm_runtime { | |||
5633 | .id_table = snd_my_ids, | 5737 | .id_table = snd_my_ids, |
5634 | .probe = snd_my_probe, | 5738 | .probe = snd_my_probe, |
5635 | .remove = __devexit_p(snd_my_remove), | 5739 | .remove = __devexit_p(snd_my_remove), |
5636 | SND_PCI_PM_CALLBACKS | 5740 | #ifdef CONFIG_PM |
5741 | .suspend = snd_my_suspend, | ||
5742 | .resume = snd_my_resume, | ||
5743 | #endif | ||
5637 | }; | 5744 | }; |
5638 | ]]> | 5745 | ]]> |
5639 | </programlisting> | 5746 | </programlisting> |