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

Commit a80c47da authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "Again less intensive changes in this rc: you can find only a few
  HD-audio fixes (noise fixes for Intel Broxton chip and a few Thinkpad
  models, quirks for Alienware 17 and Packard Bell DOTS) in addition to
  a long-standing rme96 bug fix"

* tag 'sound-4.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda/ca0132 - quirk for Alienware 17 2015
  ALSA: hda - Fix noise problems on Thinkpad T440s
  ALSA: hda - Fixing speaker noise on the two latest thinkpad models
  ALSA: hda - Add inverted dmic for Packard Bell DOTS
  ALSA: hda - Fix playback noise with 24/32 bit sample size on BXT
  ALSA: rme96: Fix unexpected volume reset after rate changes
parents 6764e5eb 5328e1ea
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -93,6 +93,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_HSW_EM4			0x100c
#define AZX_REG_HSW_EM4			0x100c
#define AZX_REG_HSW_EM5			0x1010
#define AZX_REG_HSW_EM5			0x1010


/* Skylake/Broxton display HD-A controller Extended Mode registers */
#define AZX_REG_SKL_EM4L		0x1040

/* PCI space */
/* PCI space */
#define AZX_PCIREG_TCSEL		0x44
#define AZX_PCIREG_TCSEL		0x44


+23 −0
Original line number Original line Diff line number Diff line
@@ -355,6 +355,8 @@ enum {
					((pci)->device == 0x0d0c) || \
					((pci)->device == 0x0d0c) || \
					((pci)->device == 0x160c))
					((pci)->device == 0x160c))


#define IS_BROXTON(pci)	((pci)->device == 0x5a98)

static char *driver_short_names[] = {
static char *driver_short_names[] = {
	[AZX_DRIVER_ICH] = "HDA Intel",
	[AZX_DRIVER_ICH] = "HDA Intel",
	[AZX_DRIVER_PCH] = "HDA Intel PCH",
	[AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -506,15 +508,36 @@ static void azx_init_pci(struct azx *chip)
        }
        }
}
}


/*
 * In BXT-P A0, HD-Audio DMA requests is later than expected,
 * and makes an audio stream sensitive to system latencies when
 * 24/32 bits are playing.
 * Adjusting threshold of DMA fifo to force the DMA request
 * sooner to improve latency tolerance at the expense of power.
 */
static void bxt_reduce_dma_latency(struct azx *chip)
{
	u32 val;

	val = azx_readl(chip, SKL_EM4L);
	val &= (0x3 << 20);
	azx_writel(chip, SKL_EM4L, val);
}

static void hda_intel_init_chip(struct azx *chip, bool full_reset)
static void hda_intel_init_chip(struct azx *chip, bool full_reset)
{
{
	struct hdac_bus *bus = azx_bus(chip);
	struct hdac_bus *bus = azx_bus(chip);
	struct pci_dev *pci = chip->pci;


	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
		snd_hdac_set_codec_wakeup(bus, true);
		snd_hdac_set_codec_wakeup(bus, true);
	azx_init_chip(chip, full_reset);
	azx_init_chip(chip, full_reset);
	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
		snd_hdac_set_codec_wakeup(bus, false);
		snd_hdac_set_codec_wakeup(bus, false);

	/* reduce dma latency to avoid noise */
	if (IS_BROXTON(pci))
		bxt_reduce_dma_latency(chip);
}
}


/* calculate runtime delay from LPIB */
/* calculate runtime delay from LPIB */
+2 −1
Original line number Original line Diff line number Diff line
@@ -778,7 +778,8 @@ static const struct hda_pintbl alienware_pincfgs[] = {
};
};


static const struct snd_pci_quirk ca0132_quirks[] = {
static const struct snd_pci_quirk ca0132_quirks[] = {
	SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE),
	SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
	SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
	{}
	{}
};
};


+31 −1
Original line number Original line Diff line number Diff line
@@ -4204,6 +4204,18 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
	}
	}
}
}


/* additional fixup for Thinkpad T440s noise problem */
static void alc_fixup_tpt440(struct hda_codec *codec,
				  const struct hda_fixup *fix, int action)
{
	struct alc_spec *spec = codec->spec;

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->shutup = alc_no_shutup; /* reduce click noise */
		spec->gen.mixer_nid = 0; /* reduce background noise */
	}
}

static void alc_shutup_dell_xps13(struct hda_codec *codec)
static void alc_shutup_dell_xps13(struct hda_codec *codec)
{
{
	struct alc_spec *spec = codec->spec;
	struct alc_spec *spec = codec->spec;
@@ -4578,6 +4590,7 @@ enum {
	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
	ALC292_FIXUP_TPT440_DOCK,
	ALC292_FIXUP_TPT440_DOCK,
	ALC292_FIXUP_TPT440,
	ALC283_FIXUP_BXBT2807_MIC,
	ALC283_FIXUP_BXBT2807_MIC,
	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
	ALC282_FIXUP_ASPIRE_V5_PINS,
	ALC282_FIXUP_ASPIRE_V5_PINS,
@@ -4596,6 +4609,7 @@ enum {
	ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
	ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
	ALC275_FIXUP_DELL_XPS,
	ALC275_FIXUP_DELL_XPS,
	ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
	ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
	ALC293_FIXUP_LENOVO_SPK_NOISE,
};
};


static const struct hda_fixup alc269_fixups[] = {
static const struct hda_fixup alc269_fixups[] = {
@@ -5050,6 +5064,12 @@ static const struct hda_fixup alc269_fixups[] = {
		.chained = true,
		.chained = true,
		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
	},
	},
	[ALC292_FIXUP_TPT440] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = alc_fixup_tpt440,
		.chained = true,
		.chain_id = ALC292_FIXUP_TPT440_DOCK,
	},
	[ALC283_FIXUP_BXBT2807_MIC] = {
	[ALC283_FIXUP_BXBT2807_MIC] = {
		.type = HDA_FIXUP_PINS,
		.type = HDA_FIXUP_PINS,
		.v.pins = (const struct hda_pintbl[]) {
		.v.pins = (const struct hda_pintbl[]) {
@@ -5187,6 +5207,12 @@ static const struct hda_fixup alc269_fixups[] = {
		.chained = true,
		.chained = true,
		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
	},
	},
	[ALC293_FIXUP_LENOVO_SPK_NOISE] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = alc_fixup_disable_aamix,
		.chained = true,
		.chain_id = ALC269_FIXUP_THINKPAD_ACPI
	},
};
};


static const struct snd_pci_quirk alc269_fixup_tbl[] = {
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5325,7 +5351,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440),
	SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
@@ -5334,6 +5360,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
	SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
	SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
	SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
	SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
	SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
	SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
	SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
	SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5343,6 +5370,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
	SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -5423,6 +5451,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
	{.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
	{.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
	{.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
	{.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
	{.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
	{.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
	{.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
	{}
	{}
};
};


@@ -6409,6 +6438,7 @@ static const struct hda_fixup alc662_fixups[] = {
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
	SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
	SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
	SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
	SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
	SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
+26 −15
Original line number Original line Diff line number Diff line
@@ -741,11 +741,12 @@ snd_rme96_playback_setrate(struct rme96 *rme96,
	{
	{
		/* change to/from double-speed: reset the DAC (if available) */
		/* change to/from double-speed: reset the DAC (if available) */
		snd_rme96_reset_dac(rme96);
		snd_rme96_reset_dac(rme96);
		return 1; /* need to restore volume */
	} else {
	} else {
		writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
		writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
	}
		return 0;
		return 0;
	}
	}
}


static int
static int
snd_rme96_capture_analog_setrate(struct rme96 *rme96,
snd_rme96_capture_analog_setrate(struct rme96 *rme96,
@@ -980,6 +981,7 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
	struct rme96 *rme96 = snd_pcm_substream_chip(substream);
	struct rme96 *rme96 = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_pcm_runtime *runtime = substream->runtime;
	int err, rate, dummy;
	int err, rate, dummy;
	bool apply_dac_volume = false;


	runtime->dma_area = (void __force *)(rme96->iobase +
	runtime->dma_area = (void __force *)(rme96->iobase +
					     RME96_IO_PLAY_BUFFER);
					     RME96_IO_PLAY_BUFFER);
@@ -993,24 +995,26 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
	{
	{
                /* slave clock */
                /* slave clock */
                if ((int)params_rate(params) != rate) {
                if ((int)params_rate(params) != rate) {
			spin_unlock_irq(&rme96->lock);
			err = -EIO;
			return -EIO;                    
			goto error;
		}
		}
	} else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {
	} else {
		spin_unlock_irq(&rme96->lock);
		err = snd_rme96_playback_setrate(rme96, params_rate(params));
		return err;
		if (err < 0)
	}
			goto error;
	if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {
		apply_dac_volume = err > 0; /* need to restore volume later? */
		spin_unlock_irq(&rme96->lock);
		return err;
	}
	}

	err = snd_rme96_playback_setformat(rme96, params_format(params));
	if (err < 0)
		goto error;
	snd_rme96_setframelog(rme96, params_channels(params), 1);
	snd_rme96_setframelog(rme96, params_channels(params), 1);
	if (rme96->capture_periodsize != 0) {
	if (rme96->capture_periodsize != 0) {
		if (params_period_size(params) << rme96->playback_frlog !=
		if (params_period_size(params) << rme96->playback_frlog !=
		    rme96->capture_periodsize)
		    rme96->capture_periodsize)
		{
		{
			spin_unlock_irq(&rme96->lock);
			err = -EBUSY;
			return -EBUSY;
			goto error;
		}
		}
	}
	}
	rme96->playback_periodsize =
	rme96->playback_periodsize =
@@ -1021,9 +1025,16 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
		rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
		rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
		writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
		writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
	}
	}

	err = 0;
 error:
	spin_unlock_irq(&rme96->lock);
	spin_unlock_irq(&rme96->lock);
	if (apply_dac_volume) {
		usleep_range(3000, 10000);
		snd_rme96_apply_dac_volume(rme96);
	}


	return 0;
	return err;
}
}


static int
static int