Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ae66c26 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Takashi Iwai
Browse files

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: default avatarWu Fengguang <fengguang.wu@intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent d66fee5d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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.
    
+53 −15
Original line number Diff line number Diff line
@@ -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 },