Skip to content

Commit

Permalink
ALSA: hda: option to enable arbitrary buffer/period sizes
Browse files Browse the repository at this point in the history
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@intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Pierre-Louis Bossart authored and Takashi Iwai committed Aug 4, 2011
1 parent d66fee5 commit 2ae66c2
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 15 deletions.
5 changes: 5 additions & 0 deletions Documentation/sound/alsa/ALSA-Configuration.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
68 changes: 53 additions & 15 deletions sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},"
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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 },
Expand Down

0 comments on commit 2ae66c2

Please sign in to comment.