ALSA: hda: option to enable arbitrary buffer/period sizes
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>
This commit is contained in:
Родитель
d66fee5d65
Коммит
2ae66c2655
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
Загрузка…
Ссылка в новой задаче