Skip to content

Commit

Permalink
Merge tag 'asoc-fix-v6.3' of https://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/broonie/sound into for-linus

ASoC: Fixes for v6.3

Almost all of this is driver specific fixes and new IDs that have come
in during the merge window.  A good chunk of them are simple ones from
me which came about due to a bunch of Mediatek Chromebooks being enabled
in KernelCI, there's more where that came from.

We do have one small feature added to the PCM core by Claudiu Beznea in
order to allow the sequencing required to resolve a noise issue with the
Microchip PDMC driver.
  • Loading branch information
Takashi Iwai committed Mar 3, 2023
2 parents 26ed1d2 + b56ec29 commit fb2e5fc
Show file tree
Hide file tree
Showing 21 changed files with 260 additions and 147 deletions.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/sound/apple,mca.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ properties:
- enum:
- apple,t6000-mca
- apple,t8103-mca
- apple,t8112-mca
- const: apple,mca

reg:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ properties:
maxItems: 4
uniqueItems: true

microchip,startup-delay-us:
description: |
Specifies the delay in microseconds that needs to be applied after
enabling the PDMC microphones to avoid unwanted noise due to microphones
not being ready.
required:
- compatible
- reg
Expand Down
2 changes: 2 additions & 0 deletions include/sound/soc-component.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ struct snd_soc_component_driver {
bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */
int be_pcm_base; /* base device ID for all BE PCMs */

unsigned int start_dma_last;

#ifdef CONFIG_DEBUG_FS
const char *debugfs_prefix;
#endif
Expand Down
14 changes: 14 additions & 0 deletions sound/soc/amd/yc/acp6x-mach.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
DMI_MATCH(DMI_BOARD_NAME, "8A43"),
}
},
{}
};

Expand Down
31 changes: 23 additions & 8 deletions sound/soc/apple/mca.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@
#define SERDES_CONF_UNK3 BIT(14)
#define SERDES_CONF_NO_DATA_FEEDBACK BIT(15)
#define SERDES_CONF_SYNC_SEL GENMASK(18, 16)
#define SERDES_CONF_SOME_RST BIT(19)
#define REG_TX_SERDES_BITSTART 0x08
#define REG_RX_SERDES_BITSTART 0x0c
#define REG_TX_SERDES_SLOTMASK 0x0c
Expand Down Expand Up @@ -203,15 +202,24 @@ static void mca_fe_early_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
FIELD_PREP(SERDES_CONF_SYNC_SEL, 7));
mca_modify(cl, serdes_unit + REG_SERDES_STATUS,
SERDES_STATUS_EN | SERDES_STATUS_RST,
SERDES_STATUS_RST);
mca_modify(cl, serdes_conf, SERDES_CONF_SOME_RST,
SERDES_CONF_SOME_RST);
readl_relaxed(cl->base + serdes_conf);
mca_modify(cl, serdes_conf, SERDES_STATUS_RST, 0);
WARN_ON(readl_relaxed(cl->base + REG_SERDES_STATUS) &
/*
* Experiments suggest that it takes at most ~1 us
* for the bit to clear, so wait 2 us for good measure.
*/
udelay(2);
WARN_ON(readl_relaxed(cl->base + serdes_unit + REG_SERDES_STATUS) &
SERDES_STATUS_RST);
mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
FIELD_PREP(SERDES_CONF_SYNC_SEL, cl->no + 1));
break;
default:
break;
Expand Down Expand Up @@ -942,10 +950,17 @@ static int mca_pcm_new(struct snd_soc_component *component,
chan = mca_request_dma_channel(cl, i);

if (IS_ERR_OR_NULL(chan)) {
mca_pcm_free(component, rtd->pcm);

if (chan && PTR_ERR(chan) == -EPROBE_DEFER)
return PTR_ERR(chan);

dev_err(component->dev, "unable to obtain DMA channel (stream %d cluster %d): %pe\n",
i, cl->no, chan);
mca_pcm_free(component, rtd->pcm);
return -EINVAL;

if (!chan)
return -EINVAL;
return PTR_ERR(chan);
}

cl->dma_chans[i] = chan;
Expand Down
53 changes: 48 additions & 5 deletions sound/soc/atmel/mchp-pdmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ struct mchp_pdmc {
struct clk *gclk;
u32 pdmcen;
u32 suspend_irq;
u32 startup_delay_us;
int mic_no;
int sinc_order;
bool audio_filter_en;
Expand Down Expand Up @@ -425,6 +426,7 @@ static const struct snd_soc_component_driver mchp_pdmc_dai_component = {
.open = &mchp_pdmc_open,
.close = &mchp_pdmc_close,
.legacy_dai_naming = 1,
.start_dma_last = 1,
};

static const unsigned int mchp_pdmc_1mic[] = {1};
Expand Down Expand Up @@ -632,6 +634,29 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
return 0;
}

static void mchp_pdmc_noise_filter_workaround(struct mchp_pdmc *dd)
{
u32 tmp, steps = 16;

/*
* PDMC doesn't wait for microphones' startup time thus the acquisition
* may start before the microphones are ready leading to poc noises at
* the beginning of capture. To avoid this, we need to wait 50ms (in
* normal startup procedure) or 150 ms (worst case after resume from sleep
* states) after microphones are enabled and then clear the FIFOs (by
* reading the RHR 16 times) and possible interrupts before continuing.
* Also, for this to work the DMA needs to be started after interrupts
* are enabled.
*/
usleep_range(dd->startup_delay_us, dd->startup_delay_us + 5);

while (steps--)
regmap_read(dd->regmap, MCHP_PDMC_RHR, &tmp);

/* Clear interrupts. */
regmap_read(dd->regmap, MCHP_PDMC_ISR, &tmp);
}

static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
Expand All @@ -644,15 +669,17 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
/* Enable overrun and underrun error interrupts */
regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq |
MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR);
dd->suspend_irq = 0;
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_soc_component_update_bits(cpu, MCHP_PDMC_MR,
MCHP_PDMC_MR_PDMCEN_MASK,
dd->pdmcen);

mchp_pdmc_noise_filter_workaround(dd);

/* Enable interrupts. */
regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq |
MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR);
dd->suspend_irq = 0;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
regmap_read(dd->regmap, MCHP_PDMC_IMR, &dd->suspend_irq);
Expand Down Expand Up @@ -796,6 +823,7 @@ static bool mchp_pdmc_readable_reg(struct device *dev, unsigned int reg)
case MCHP_PDMC_CFGR:
case MCHP_PDMC_IMR:
case MCHP_PDMC_ISR:
case MCHP_PDMC_RHR:
case MCHP_PDMC_VER:
return true;
default:
Expand All @@ -817,6 +845,17 @@ static bool mchp_pdmc_writeable_reg(struct device *dev, unsigned int reg)
}
}

static bool mchp_pdmc_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case MCHP_PDMC_ISR:
case MCHP_PDMC_RHR:
return true;
default:
return false;
}
}

static bool mchp_pdmc_precious_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
Expand All @@ -836,6 +875,7 @@ static const struct regmap_config mchp_pdmc_regmap_config = {
.readable_reg = mchp_pdmc_readable_reg,
.writeable_reg = mchp_pdmc_writeable_reg,
.precious_reg = mchp_pdmc_precious_reg,
.volatile_reg = mchp_pdmc_volatile_reg,
.cache_type = REGCACHE_FLAT,
};

Expand Down Expand Up @@ -918,6 +958,9 @@ static int mchp_pdmc_dt_init(struct mchp_pdmc *dd)
dd->channel_mic_map[i].clk_edge = edge;
}

dd->startup_delay_us = 150000;
of_property_read_u32(np, "microchip,startup-delay-us", &dd->startup_delay_us);

return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions sound/soc/atmel/sam9g20_wm8731.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = {
.init = at91sam9g20ek_wm8731_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBP_CFP,
#ifndef ENABLE_MIC_INPUT
.playback_only = true,
#endif
SND_SOC_DAILINK_REG(pcm),
};

Expand Down
1 change: 1 addition & 0 deletions sound/soc/codecs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2103,6 +2103,7 @@ config SND_SOC_WSA883X
config SND_SOC_ZL38060
tristate "Microsemi ZL38060 Connected Home Audio Processor"
depends on SPI_MASTER
depends on GPIOLIB
select REGMAP
help
Support for ZL38060 Connected Home Audio Processor from Microsemi,
Expand Down
19 changes: 1 addition & 18 deletions sound/soc/codecs/adau7118.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,22 +444,6 @@ static const struct snd_soc_component_driver adau7118_component_driver = {
.endianness = 1,
};

static void adau7118_regulator_disable(void *data)
{
struct adau7118_data *st = data;
int ret;
/*
* If we fail to disable DVDD, don't bother in trying IOVDD. We
* actually don't want to be left in the situation where DVDD
* is enabled and IOVDD is disabled.
*/
ret = regulator_disable(st->dvdd);
if (ret)
return;

regulator_disable(st->iovdd);
}

static int adau7118_regulator_setup(struct adau7118_data *st)
{
st->iovdd = devm_regulator_get(st->dev, "iovdd");
Expand All @@ -481,8 +465,7 @@ static int adau7118_regulator_setup(struct adau7118_data *st)
regcache_cache_only(st->map, true);
}

return devm_add_action_or_reset(st->dev, adau7118_regulator_disable,
st);
return 0;
}

static int adau7118_parset_dt(const struct adau7118_data *st)
Expand Down
41 changes: 34 additions & 7 deletions sound/soc/codecs/da7219-aad.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,26 +339,49 @@ static void da7219_aad_hptest_work(struct work_struct *work)
SND_JACK_HEADSET | SND_JACK_LINEOUT);
}

static void da7219_aad_jack_det_work(struct work_struct *work)
{
struct da7219_aad_priv *da7219_aad =
container_of(work, struct da7219_aad_priv, jack_det_work);
struct snd_soc_component *component = da7219_aad->component;
u8 srm_st;

mutex_lock(&da7219_aad->jack_det_mutex);

srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK;
msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4);
/* Enable ground switch */
snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);

mutex_unlock(&da7219_aad->jack_det_mutex);
}


/*
* IRQ
*/

static irqreturn_t da7219_aad_pre_irq_thread(int irq, void *data)
{

struct da7219_aad_priv *da7219_aad = data;

if (!da7219_aad->jack_inserted)
schedule_work(&da7219_aad->jack_det_work);

return IRQ_WAKE_THREAD;
}

static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
{
struct da7219_aad_priv *da7219_aad = data;
struct snd_soc_component *component = da7219_aad->component;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
u8 events[DA7219_AAD_IRQ_REG_MAX];
u8 statusa, srm_st;
u8 statusa;
int i, report = 0, mask = 0;

srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK;
msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4);
/* Enable ground switch */
snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);

/* Read current IRQ events */
regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
events, DA7219_AAD_IRQ_REG_MAX);
Expand All @@ -377,6 +400,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B],
statusa);

if (!da7219_aad->jack_inserted)
cancel_work_sync(&da7219_aad->jack_det_work);

if (statusa & DA7219_JACK_INSERTION_STS_MASK) {
/* Jack Insertion */
if (events[DA7219_AAD_IRQ_REG_A] &
Expand Down Expand Up @@ -940,8 +966,9 @@ int da7219_aad_init(struct snd_soc_component *component)

INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work);
INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work);

ret = request_threaded_irq(da7219_aad->irq, NULL,
ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread,
da7219_aad_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"da7219-aad", da7219_aad);
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/codecs/da7219-aad.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define __DA7219_AAD_H

#include <linux/timer.h>
#include <linux/mutex.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include <sound/da7219-aad.h>
Expand Down Expand Up @@ -196,6 +197,9 @@ struct da7219_aad_priv {

struct work_struct btn_det_work;
struct work_struct hptest_work;
struct work_struct jack_det_work;

struct mutex jack_det_mutex;

struct snd_soc_jack *jack;
bool micbias_resume_enable;
Expand Down
Loading

0 comments on commit fb2e5fc

Please sign in to comment.