[alsa-devel] [PATCH] ALSA: hda: option to enable arbitrary buffer/period sizes
Takashi Iwai
tiwai at suse.de
Thu Aug 4 17:46:16 CEST 2011
At Thu, 4 Aug 2011 10:12:56 -0500,
Pierre-Louis Bossart wrote:
>
> Add new parameter to disable rounding of buffer/period sizes to
> multiples of 128 bytes. This is more efficient in terms of memory
> access but isn't required by the HDA spec and prevents users from
> specifying exact period/buffer sizes. For example for 44.1kHz, a
> period size set to 20ms will be rounded to 19.59ms.
>
> Tested and enabled on Intel HDA controllers. Option is disabled by
> default for other controllers.
>
> Tested-by: Wu Fengguang <fengguang.wu at intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
Thanks, applied now.
Takashi
> ---
> Documentation/sound/alsa/ALSA-Configuration.txt | 5 ++
> sound/pci/hda/hda_intel.c | 68 ++++++++++++++++++-----
> 2 files changed, 58 insertions(+), 15 deletions(-)
>
> diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
> index 8975701..27126c4 100644
> --- a/Documentation/sound/alsa/ALSA-Configuration.txt
> +++ b/Documentation/sound/alsa/ALSA-Configuration.txt
> @@ -886,6 +886,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
> disable)
> power_save_controller - Reset HD-audio controller in power-saving mode
> (default = on)
> + align_buffer_size - Force rounding of buffer/period sizes to multiples
> + of 128 bytes. This is more efficient in terms of memory
> + access but isn't required by the HDA spec and prevents
> + users from specifying exact period/buffer sizes.
> + (default = on)
>
> This module supports multiple cards and autoprobe.
>
> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index be69822..2a8bed9 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -116,6 +116,11 @@ module_param(power_save_controller, bool, 0644);
> MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
> #endif
>
> +static int align_buffer_size = 1;
> +module_param(align_buffer_size, bool, 0644);
> +MODULE_PARM_DESC(align_buffer_size,
> + "Force buffer and period sizes to be multiple of 128 bytes.");
> +
> MODULE_LICENSE("GPL");
> MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
> "{Intel, ICH6M},"
> @@ -481,6 +486,7 @@ enum {
> #define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
> #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
> #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
> +#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */
>
> /* quirks for ATI SB / AMD Hudson */
> #define AZX_DCAPS_PRESET_ATI_SB \
> @@ -1599,6 +1605,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
> struct snd_pcm_runtime *runtime = substream->runtime;
> unsigned long flags;
> int err;
> + int buff_step;
>
> mutex_lock(&chip->open_mutex);
> azx_dev = azx_assign_device(chip, substream);
> @@ -1613,10 +1620,25 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
> runtime->hw.rates = hinfo->rates;
> snd_pcm_limit_hw_rates(runtime);
> snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
> + if (align_buffer_size)
> + /* constrain buffer sizes to be multiple of 128
> + bytes. This is more efficient in terms of memory
> + access but isn't required by the HDA spec and
> + prevents users from specifying exact period/buffer
> + sizes. For example for 44.1kHz, a period size set
> + to 20ms will be rounded to 19.59ms. */
> + buff_step = 128;
> + else
> + /* Don't enforce steps on buffer sizes, still need to
> + be multiple of 4 bytes (HDA spec). Tested on Intel
> + HDA controllers, may not work on all devices where
> + option needs to be disabled */
> + buff_step = 4;
> +
> snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
> - 128);
> + buff_step);
> snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
> - 128);
> + buff_step);
> snd_hda_power_up(apcm->codec);
> err = hinfo->ops.open(hinfo, apcm->codec, substream);
> if (err < 0) {
> @@ -2616,6 +2638,10 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
> gcap &= ~ICH6_GCAP_64OK;
> }
>
> + /* disable buffer size rounding to 128-byte multiples if supported */
> + if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
> + align_buffer_size = 0;
> +
> /* allow 64bit DMA address if supported by H/W */
> if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
> pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
> @@ -2817,37 +2843,49 @@ static void __devexit azx_remove(struct pci_dev *pci)
> static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
> /* CPT */
> { PCI_DEVICE(0x8086, 0x1c20),
> - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
> + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
> + AZX_DCAPS_BUFSIZE },
> /* PBG */
> { PCI_DEVICE(0x8086, 0x1d20),
> - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
> + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
> + AZX_DCAPS_BUFSIZE},
> /* Panther Point */
> { PCI_DEVICE(0x8086, 0x1e20),
> - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
> + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
> + AZX_DCAPS_BUFSIZE},
> /* SCH */
> { PCI_DEVICE(0x8086, 0x811b),
> - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP },
> + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
> + AZX_DCAPS_BUFSIZE},
> { PCI_DEVICE(0x8086, 0x2668),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH6 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH6 */
> { PCI_DEVICE(0x8086, 0x27d8),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH7 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH7 */
> { PCI_DEVICE(0x8086, 0x269a),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ESB2 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ESB2 */
> { PCI_DEVICE(0x8086, 0x284b),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH8 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH8 */
> { PCI_DEVICE(0x8086, 0x293e),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH9 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH9 */
> { PCI_DEVICE(0x8086, 0x293f),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH9 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH9 */
> { PCI_DEVICE(0x8086, 0x3a3e),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH10 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH10 */
> { PCI_DEVICE(0x8086, 0x3a6e),
> - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH10 */
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
> + AZX_DCAPS_BUFSIZE }, /* ICH10 */
> /* Generic Intel */
> { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
> .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
> .class_mask = 0xffffff,
> - .driver_data = AZX_DRIVER_ICH },
> + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_BUFSIZE },
> /* ATI SB 450/600/700/800/900 */
> { PCI_DEVICE(0x1002, 0x437b),
> .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
> --
> 1.7.6
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
More information about the Alsa-devel
mailing list