From afcfbcb39fe539ff9a24ca9187bb49e09a14abe5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:12 +0100 Subject: ALSA: core: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-1-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/core/control.c | 4 ++-- sound/core/seq/seq_memory.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/control.c b/sound/core/control.c index 3b44378b9dec..1571c7f7c43b 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -836,7 +836,7 @@ static void fill_remaining_elem_value(struct snd_ctl_elem_value *control, { size_t offset = value_sizes[info->type] * info->count; - offset = (offset + sizeof(u32) - 1) / sizeof(u32); + offset = DIV_ROUND_UP(offset, sizeof(u32)); memset32((u32 *)control->value.bytes.data + offset, pattern, sizeof(control->value) / sizeof(u32) - offset); } @@ -928,7 +928,7 @@ static int sanity_check_elem_value(struct snd_card *card, /* check whether the remaining area kept untouched */ offset = value_sizes[info->type] * info->count; - offset = (offset + sizeof(u32) - 1) / sizeof(u32); + offset = DIV_ROUND_UP(offset, sizeof(u32)); p = (u32 *)control->value.bytes.data + offset; for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) { if (*p != pattern) { diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 65db1a7c77b7..e245bb6ba533 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -290,7 +290,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event, extlen = 0; if (snd_seq_ev_is_variable(event)) { extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK; - ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event); + ncells = DIV_ROUND_UP(extlen, sizeof(struct snd_seq_event)); } if (ncells >= pool->total_elements) return -ENOMEM; -- cgit v1.2.3 From 7ef74bdc0d974bed3e2d3fdd806e4d30796833d0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:13 +0100 Subject: ALSA: aloop: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-2-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/drivers/aloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 702f91b9c60f..8a24e5ae7cef 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -219,7 +219,7 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm) dpcm->period_update_pending = 1; } tick = dpcm->period_size_frac - dpcm->irq_pos; - tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; + tick = DIV_ROUND_UP(tick, dpcm->pcm_bps); mod_timer(&dpcm->timer, jiffies + tick); return 0; -- cgit v1.2.3 From af787b2e837fb6003886c151f8cea0484fcd381d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:14 +0100 Subject: ALSA: asihpi: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-3-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpidebug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c index f37856ab05f8..9570d9a44fe8 100644 --- a/sound/pci/asihpi/hpidebug.c +++ b/sound/pci/asihpi/hpidebug.c @@ -52,7 +52,7 @@ void hpi_debug_data(u16 *pdata, u32 len) int lines; int cols = 8; - lines = (len + cols - 1) / cols; + lines = DIV_ROUND_UP(len, cols); if (lines > 8) lines = 8; -- cgit v1.2.3 From e02e198e88f4c3bd9a56b031d46895a191919c4e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:15 +0100 Subject: ALSA: bt87x: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @r1@ expression x; constant C1; constant C2; @@ (x + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ try: if int(C1) != int(C2) - 1: cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_UP(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-4-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/bt87x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 54cb223caa2f..cf9f8d80a0b6 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -327,7 +327,8 @@ static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id) current_block = chip->current_line * 16 / chip->lines; irq_block = status >> INT_RISCS_SHIFT; if (current_block != irq_block) - chip->current_line = (irq_block * chip->lines + 15) / 16; + chip->current_line = DIV_ROUND_UP(irq_block * chip->lines, + 16); snd_pcm_period_elapsed(chip->substream); } -- cgit v1.2.3 From 636c46c51cfcb82859be3e4a903ebe5b790e1ac0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:16 +0100 Subject: ALSA: cx46xx: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-5-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/cs46xx/cs46xx_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 4490dd7469d9..37f516e6a5c2 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -813,7 +813,7 @@ static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned correctionPerGOF = tmp1 / GOF_PER_SEC; tmp1 -= correctionPerGOF * GOF_PER_SEC; correctionPerSec = tmp1; - initialDelay = ((48000 * 24) + rate - 1) / rate; + initialDelay = DIV_ROUND_UP(48000 * 24, rate); /* * Fill in the VariDecimate control block. -- cgit v1.2.3 From 7ca4282ade77de53b6e9ffa2695566e5d35dab1e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:17 +0100 Subject: ALSA: ctxfi: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-6-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/ctresource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c index 61e51e35ba16..6d0a01b189e1 100644 --- a/sound/pci/ctxfi/ctresource.c +++ b/sound/pci/ctxfi/ctresource.c @@ -209,7 +209,7 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, mgr->type = NUM_RSCTYP; - mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL); + mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL); if (!mgr->rscs) return -ENOMEM; -- cgit v1.2.3 From 7095be6d2cc2870299c9e6c6c2df3148be410c4a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:18 +0100 Subject: ALSA: dummy: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-7-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/drivers/dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index b5486de08b97..316c9afadefe 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -236,7 +236,7 @@ struct dummy_systimer_pcm { static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) { mod_timer(&dpcm->timer, jiffies + - (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate); + DIV_ROUND_UP(dpcm->frac_period_rest, dpcm->rate)); } static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) -- cgit v1.2.3 From 483548a26f1aa65caf16eb99413e5003b3cfc81b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:19 +0100 Subject: ALSA: emu10k1: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-8-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 94b8d5b08225..288e0fd2e47d 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -375,7 +375,7 @@ int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size, struct snd_dma_buffer *dmab) { if (emu->iommu_workaround) { - size_t npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + size_t npages = DIV_ROUND_UP(size, PAGE_SIZE); size_t size_real = npages * PAGE_SIZE; /* -- cgit v1.2.3 From 81d0ec4349ec53e990e018ad0ce553046aab0fa3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:20 +0100 Subject: ALSA: hda: Use DIV_ROUND_UP()/roundup() instead of open-coding it Use DIV_ROUND_UP() and roundup() instead of open-coding them. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -((((x) + (y) - 1) / (y)) * y) +roundup(x, y) @r1@ expression x; constant C1; constant C2; @@ (x + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ print C1, C2 try: if int(C1) != int(C2) - 1: cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_UP(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-9-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/hda/hdac_stream.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index abe7a1b16fe1..a6ed3dc35f7e 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -435,12 +435,11 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev) pos_adj = bus->bdl_pos_adj; if (!azx_dev->no_period_wakeup && pos_adj > 0) { pos_align = pos_adj; - pos_adj = (pos_adj * runtime->rate + 47999) / 48000; + pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000); if (!pos_adj) pos_adj = pos_align; else - pos_adj = ((pos_adj + pos_align - 1) / pos_align) * - pos_align; + pos_adj = roundup(pos_adj, pos_align); pos_adj = frames_to_bytes(runtime, pos_adj); if (pos_adj >= period_bytes) { dev_warn(bus->dev, "Too big adjustment %d\n", -- cgit v1.2.3 From a434713bfefa4058e6b500f8cb6f8350acdce08b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:21 +0100 Subject: ALSA: lola: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @r1@ expression x; constant C1; constant C2; @@ (x + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ try: if int(C1) != int(C2) - 1: cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_UP(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-10-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/lola/lola_clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c index fdb85f256ed5..cafd30e30913 100644 --- a/sound/pci/lola/lola_clock.c +++ b/sound/pci/lola/lola_clock.c @@ -135,7 +135,7 @@ int lola_init_clock_widget(struct lola *chip, int nid) } nitems = chip->clock.items; - nb_verbs = (nitems + 3) / 4; + nb_verbs = DIV_ROUND_UP(nitems, 4); idx = 0; idx_list = 0; for (i = 0; i < nb_verbs; i++) { -- cgit v1.2.3 From e4d8aef21403a48c8cf43b2f98b9a27b990fae5b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:22 +0100 Subject: ALSA: usb: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -(((x) + (y) - 1) / (y)) +DIV_ROUND_UP(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-11-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 12b15ed59eaa..412fcd817ecc 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -254,7 +254,7 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val) if (val < cval->min) return 0; else if (val >= cval->max) - return (cval->max - cval->min + cval->res - 1) / cval->res; + return DIV_ROUND_UP(cval->max - cval->min, cval->res); else return (val - cval->min) / cval->res; } @@ -1338,7 +1338,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, } uinfo->value.integer.min = 0; uinfo->value.integer.max = - (cval->max - cval->min + cval->res - 1) / cval->res; + DIV_ROUND_UP(cval->max - cval->min, cval->res); } return 0; } -- cgit v1.2.3 From af102a88ade2aca4b5c38843fbdc05d9f85b7723 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:23 +0100 Subject: ALSA: vx: Use roundup() instead of open-coding it Use roundup() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -((((x) + (y) - 1) / (y)) * y) +roundup(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-12-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/drivers/vx/vx_pcm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 3d2e3bcafca8..daffda99b4f7 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -1154,8 +1154,7 @@ static int vx_init_audio_io(struct vx_core *chip) chip->ibl.size = 0; vx_set_ibl(chip, &chip->ibl); /* query the info */ if (preferred > 0) { - chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / - chip->ibl.granularity) * chip->ibl.granularity; + chip->ibl.size = roundup(preferred, chip->ibl.granularity); if (chip->ibl.size > chip->ibl.max_size) chip->ibl.size = chip->ibl.max_size; } else -- cgit v1.2.3 From 6b5edf1dcc6005feb0151e3b6c8465770593d5f8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:24 +0100 Subject: ALSA: oss: Use DIV_ROUND_CLOSEST() instead of open-coding it Use DIV_ROUND_CLOSEST() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -((x) + ((y) / 2)) / (y) +DIV_ROUND_CLOSEST(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-13-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/core/oss/mixer_oss.c | 2 +- sound/core/oss/rate.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index f702c96a7478..af5de08f9819 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -418,7 +418,7 @@ static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long n if (orange == 0) return 0; - return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin; + return DIV_ROUND_CLOSEST(nrange * (val - omin), orange) + nmin; } /* convert from alsa native to oss values (0-100) */ diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index d381f4c967c9..98269119347f 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c @@ -193,7 +193,7 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_ if (plugin->src_format.rate < plugin->dst_format.rate) { res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); } else { - res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); + res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch); } if (data->old_src_frames > 0) { snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames; @@ -224,7 +224,7 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_ return 0; data = (struct rate_priv *)plugin->extra_data; if (plugin->src_format.rate < plugin->dst_format.rate) { - res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); + res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch); } else { res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); } -- cgit v1.2.3 From 4743feb9f43b896b22af93e20307eb62fa1299d3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:25 +0100 Subject: ALSA: sonicvibes: Use DIV_ROUND_CLOSEST() instead of open-coding it Use DIV_ROUND_CLOSEST() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -((x) + ((y) / 2)) / (y) +DIV_ROUND_CLOSEST(x, y) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-14-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/sonicvibes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index ecdd54d7a4e1..bd805e416e12 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -570,7 +570,7 @@ static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int unsigned int div; unsigned long flags; - div = (rate * 65536 + SV_FULLRATE / 2) / SV_FULLRATE; + div = DIV_ROUND_CLOSEST(rate * 65536, SV_FULLRATE); if (div > 65535) div = 65535; spin_lock_irqsave(&sonic->reg_lock, flags); -- cgit v1.2.3 From a8667a3f1588bf61f73ac76f8caff3d9dfcf272e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:26 +0100 Subject: ALSA: trident: Use DIV_ROUND_CLOSEST() instead of open-coding it Use DIV_ROUND_CLOSEST() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @@ expression x, y; @@ -((x) + ((y) / 2)) / (y) +DIV_ROUND_CLOSEST(x, y) @r1@ expression x; constant C1; constant C2; @@ ((x) + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ try: if int(C1) * 2 != int(C2): cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_CLOSEST(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-15-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/trident/trident_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 6e50376163a2..8d0d0d8335ec 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -678,7 +678,7 @@ static unsigned int snd_trident_convert_rate(unsigned int rate) else if (rate == 48000) delta = 0x1000; else - delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff; + delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff; return delta; } @@ -1034,7 +1034,7 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream) ESO_bytes++; // Set channel sample rate, 4.12 format - val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate; + val = DIV_ROUND_CLOSEST(48000U << 12, runtime->rate); outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R)); // Set channel interrupt blk length -- cgit v1.2.3 From db43394690d00508464da724e9d2f54c0ef13ea3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:27 +0100 Subject: ALSA: ens1370: Use DIV_ROUND_CLOSEST() instead of open-coding it Use DIV_ROUND_CLOSEST() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @r1@ expression x; constant C1; constant C2; @@ ((x) + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ try: if int(C1) * 2 != int(C2): cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_CLOSEST(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-16-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/ens1370.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index d9acef0826a9..93c4fd313311 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -752,7 +752,7 @@ static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) unsigned int freq, r; mutex_lock(&ensoniq->src_mutex); - freq = ((rate << 15) + 1500) / 3000; + freq = DIV_ROUND_CLOSEST(rate << 15, 3000); r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | ES_1371_DIS_P1; @@ -773,7 +773,7 @@ static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) unsigned int freq, r; mutex_lock(&ensoniq->src_mutex); - freq = ((rate << 15) + 1500) / 3000; + freq = DIV_ROUND_CLOSEST(rate << 15, 3000); r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | ES_1371_DIS_P2; -- cgit v1.2.3 From e08eaf4003e2afbab98b8a1172b5b17323962543 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:28 +0100 Subject: ALSA: sis7019: Use DIV_ROUND_CLOSEST() instead of open-coding it Use DIV_ROUND_CLOSEST() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @r1@ expression x; constant C1; constant C2; @@ ((x) + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ try: if int(C1) * 2 != int(C2): cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_CLOSEST(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-17-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/sis7019.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 7bf6059d50fb..8ffa2f53c0b5 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -363,7 +363,7 @@ static u32 sis_rate_to_delta(unsigned int rate) else if (rate == 48000) delta = 0x1000; else - delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff; + delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff; return delta; } -- cgit v1.2.3 From 64062869f0d63d118560c15f671376b43f71b102 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 23 Dec 2020 18:22:29 +0100 Subject: ALSA: maestro: Use DIV_ROUND_CLOSEST() instead of open-coding it Use DIV_ROUND_CLOSEST() instead of open-coding it. This documents intent and makes it more clear what is going on for the casual reviewer. Generated using the following the Coccinelle semantic patch. // @r1@ expression x; constant C1; constant C2; @@ ((x) + C1) / C2 @script:python@ C1 << r1.C1; C2 << r1.C2; @@ try: if int(C1) * 2 != int(C2): cocci.include_match(False) except: cocci.include_match(False) @@ expression r1.x; constant r1.C1; constant r1.C2; @@ -(((x) + C1) / C2) +DIV_ROUND_CLOSEST(x, C2) // Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20201223172229.781-18-lars@metafoo.de Signed-off-by: Takashi Iwai --- sound/pci/maestro3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 40232a278b1a..f622c2a6f746 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1245,7 +1245,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s, snd_pcm_format_width(runtime->format) == 16 ? 0 : 1); /* set up dac/adc rate */ - freq = ((runtime->rate << 15) + 24000 ) / 48000; + freq = DIV_ROUND_CLOSEST(runtime->rate << 15, 48000); if (freq) freq--; -- cgit v1.2.3 From a9830fc388817c90282925694474fae005fec990 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Dec 2020 19:21:38 +0200 Subject: catpt: Switch to use list_entry_is_head() helper Since we got list_entry_is_head() helper in the generic header, we may switch catpt to use it. It removes the need in additional variable. Signed-off-by: Andy Shevchenko Reviewed-by: Cezary Rojewski Link: https://lore.kernel.org/r/20201214172138.44267-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/catpt/pcm.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c index e5d54bb1c42a..9d304b3a817f 100644 --- a/sound/soc/intel/catpt/pcm.c +++ b/sound/soc/intel/catpt/pcm.c @@ -331,7 +331,7 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, { struct catpt_dev *cdev = dev_get_drvdata(dai->dev); struct snd_soc_component *component = dai->component; - struct snd_kcontrol *pos, *kctl = NULL; + struct snd_kcontrol *pos; const char *name; int ret; u32 id = stream->info.stream_hw_id; @@ -356,17 +356,15 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, list_for_each_entry(pos, &component->card->snd_card->controls, list) { if (pos->private_data == component && - !strncmp(name, pos->id.name, sizeof(pos->id.name))) { - kctl = pos; + !strncmp(name, pos->id.name, sizeof(pos->id.name))) break; - } } - if (!kctl) + if (list_entry_is_head(pos, &component->card->snd_card->controls, list)) return -ENOENT; if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK) - return catpt_set_dspvol(cdev, id, (long *)kctl->private_value); - ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value); + return catpt_set_dspvol(cdev, id, (long *)pos->private_value); + ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)pos->private_value); if (ret) return CATPT_IPC_ERROR(ret); return 0; -- cgit v1.2.3 From 7726e49837af634accaec317c8d246d1d90d8fc5 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 16 Dec 2020 11:25:12 +0000 Subject: ASoC: wm_adsp: Improve handling of raw byte streams As the register map is 16-bit or 32-bit big-endian, the 24-bit DSP words appear padded and with the bytes swapped. When reading a raw stream of bytes, the pad bytes must be removed and the data bytes swapped back to their original order. The previous implementation of this assumed that the be32_to_cpu() in wm_adsp_read_data_block() would swap back to little-endian. But this is obviously only true on a little-endian CPU. It also made two walks through the data, once to endian-swap and again to strip the pad bytes. This patch re-works the code so that the endian-swap and unpad are done together in a single walk, and it is not dependent on the endianness of the CPU. The data_word_size argument to wm_adsp_remove_padding() has been dropped because currently this is always 3. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20201216112512.26503-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 55 +++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index dec8716aa8ef..5b7d81a91df3 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -3664,12 +3664,12 @@ int wm_adsp_compr_get_caps(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); -static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, - unsigned int mem_addr, - unsigned int num_words, u32 *data) +static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type, + unsigned int mem_addr, + unsigned int num_words, __be32 *data) { struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); - unsigned int i, reg; + unsigned int reg; int ret; if (!mem) @@ -3682,16 +3682,22 @@ static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, if (ret < 0) return ret; - for (i = 0; i < num_words; ++i) - data[i] = be32_to_cpu(data[i]) & 0x00ffffffu; - return 0; } static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, unsigned int mem_addr, u32 *data) { - return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data); + __be32 raw; + int ret; + + ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw); + if (ret) + return ret; + + *data = be32_to_cpu(raw) & 0x00ffffffu; + + return 0; } static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, @@ -3724,18 +3730,22 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, buf->host_buf_ptr + field_offset, data); } -static void wm_adsp_remove_padding(u32 *buf, int nwords, int data_word_size) +static void wm_adsp_remove_padding(u32 *buf, int nwords) { - u8 *pack_in = (u8 *)buf; + const __be32 *pack_in = (__be32 *)buf; u8 *pack_out = (u8 *)buf; - int i, j; + int i; - /* Remove the padding bytes from the data read from the DSP */ + /* + * DSP words from the register map have pad bytes and the data bytes + * are in swapped order. This swaps back to the original little-endian + * order and strips the pad bytes. + */ for (i = 0; i < nwords; i++) { - for (j = 0; j < data_word_size; j++) - *pack_out++ = *pack_in++; - - pack_in += sizeof(*buf) - data_word_size; + u32 word = be32_to_cpu(*pack_in++); + *pack_out++ = (u8)word; + *pack_out++ = (u8)(word >> 8); + *pack_out++ = (u8)(word >> 16); } } @@ -3919,12 +3929,7 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) return -EINVAL; } - for (i = 0; i < ARRAY_SIZE(coeff_v1.name); i++) - coeff_v1.name[i] = be32_to_cpu(coeff_v1.name[i]); - - wm_adsp_remove_padding((u32 *)&coeff_v1.name, - ARRAY_SIZE(coeff_v1.name), - WM_ADSP_DATA_WORD_SIZE); + wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name)); buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part, (char *)&coeff_v1.name); @@ -4263,12 +4268,12 @@ static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) return 0; /* Read data from DSP */ - ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, - nwords, compr->raw_buf); + ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr, + nwords, compr->raw_buf); if (ret < 0) return ret; - wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE); + wm_adsp_remove_padding(compr->raw_buf, nwords); /* update read index to account for words read */ buf->read_index += nwords; -- cgit v1.2.3 From 6bdd75a1f6f552ecfb0afd6f544b022b2d34c56a Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Tue, 22 Dec 2020 03:15:24 +0000 Subject: ASoC: rt1015: modify calibration sequence for better performance New calibration sequence to fix power issue in idle state. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/ec66399502514edbb1de3cf9bff08b1d@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 32e6bcf763d1..5fdf7bbfd375 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -497,40 +497,20 @@ static void rt1015_calibrate(struct rt1015_priv *rt1015) snd_soc_dapm_mutex_lock(&component->dapm); regcache_cache_bypass(regmap, true); - regmap_write(regmap, RT1015_PWR9, 0xAA60); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0089); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008A); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008C); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008D); - regmap_write(regmap, RT1015_PWR4, 0x80B2); - regmap_write(regmap, RT1015_CLASSD_SEQ, 0x5797); - regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2100); - regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0100); - regmap_write(regmap, RT1015_PWR5, 0x2175); - regmap_write(regmap, RT1015_MIXER1, 0x005D); - regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1); - regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12F7); - regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x1205); - msleep(200); - regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2000); - regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0180); - regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1); - regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x0A05); - msleep(200); + regmap_write(regmap, RT1015_CLK_DET, 0x0000); regmap_write(regmap, RT1015_PWR4, 0x00B2); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0009); + msleep(100); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000A); + msleep(100); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000C); + msleep(100); regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2028); regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140); - regmap_write(regmap, RT1015_PWR5, 0x0175); - regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x1721); - regmap_write(regmap, RT1015_CLASSD_SEQ, 0x570E); - regmap_write(regmap, RT1015_MIXER1, 0x203D); - regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5A01); - regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12FF); - regmap_write(regmap, RT1015_GAT_BOOST, 0x0eFE); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008E); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0088); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000D); + msleep(300); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008); regmap_write(regmap, RT1015_SYS_RST1, 0x05F5); - regmap_write(regmap, RT1015_SYS_RST2, 0x0b9a); regcache_cache_bypass(regmap, false); regcache_mark_dirty(regmap); -- cgit v1.2.3 From 57fc2bbc62ef9d505e8732acbae0d6b5c59836cd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 8 Dec 2020 13:18:05 +0200 Subject: ASoC: sprd: Switch to use list_entry_is_head() helper Since we got list_entry_is_head() helper in the generic header, we may switch driver to use it. This eliminates the need in additional variable. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20201208111805.6989-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sprd/sprd-mcdt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index f439e5503a3c..34b2ce733b54 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c @@ -866,23 +866,23 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable); struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, enum sprd_mcdt_channel_type type) { - struct sprd_mcdt_chan *temp, *chan = NULL; + struct sprd_mcdt_chan *temp; mutex_lock(&sprd_mcdt_list_mutex); list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { if (temp->type == type && temp->id == channel) { - chan = temp; + list_del_init(&temp->list); break; } } - if (chan) - list_del(&chan->list); + if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list)) + temp = NULL; mutex_unlock(&sprd_mcdt_list_mutex); - return chan; + return temp; } EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan); -- cgit v1.2.3 From e05cde84eabccc0441f837f0661cd4c6f4820513 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 18 Dec 2020 16:45:44 +0100 Subject: ASoC: meson: Use managed DMA buffer allocation Using a managed buffer will pre-allocate the buffer using snd_pcm_lib_preallocate_pages() and automatically free it when the PCM is destroyed. In addition it will call snd_pcm_lib_malloc_pages() before the driver's hw_params() callback and snd_pcm_lib_free_pages() after the driver's hw_free() callback. This slightly reduces the boilerplate code of the driver. Signed-off-by: Lars-Peter Clausen Reviewed-by: Jerome Brunet Tested-by: Jerome Brunet Link: https://lore.kernel.org/r/20201218154544.25513-1-lars@metafoo.de Signed-off-by: Mark Brown --- sound/soc/meson/aiu-fifo-i2s.c | 1 - sound/soc/meson/aiu-fifo-spdif.c | 1 - sound/soc/meson/aiu-fifo.c | 18 ++---------------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c index d91b0d874342..2388a2d0b3a6 100644 --- a/sound/soc/meson/aiu-fifo-i2s.c +++ b/sound/soc/meson/aiu-fifo-i2s.c @@ -124,7 +124,6 @@ const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops = { .trigger = aiu_fifo_i2s_trigger, .prepare = aiu_fifo_i2s_prepare, .hw_params = aiu_fifo_i2s_hw_params, - .hw_free = aiu_fifo_hw_free, .startup = aiu_fifo_startup, .shutdown = aiu_fifo_shutdown, }; diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c index 44eb6faacf44..2fb30f89bf7a 100644 --- a/sound/soc/meson/aiu-fifo-spdif.c +++ b/sound/soc/meson/aiu-fifo-spdif.c @@ -158,7 +158,6 @@ const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops = { .trigger = fifo_spdif_trigger, .prepare = fifo_spdif_prepare, .hw_params = fifo_spdif_hw_params, - .hw_free = aiu_fifo_hw_free, .startup = aiu_fifo_startup, .shutdown = aiu_fifo_shutdown, }; diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c index aa88aae8e517..4ad23267cace 100644 --- a/sound/soc/meson/aiu-fifo.c +++ b/sound/soc/meson/aiu-fifo.c @@ -99,11 +99,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct aiu_fifo *fifo = dai->playback_dma_data; dma_addr_t end; - int ret; - - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (ret < 0) - return ret; /* Setup the fifo boundaries */ end = runtime->dma_addr + runtime->dma_bytes - fifo->fifo_block; @@ -124,12 +119,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream, return 0; } -int aiu_fifo_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - return snd_pcm_lib_free_pages(substream); -} - static irqreturn_t aiu_fifo_isr(int irq, void *dev_id) { struct snd_pcm_substream *playback = dev_id; @@ -187,15 +176,12 @@ void aiu_fifo_shutdown(struct snd_pcm_substream *substream, int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { - struct snd_pcm_substream *substream = - rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; struct snd_card *card = rtd->card->snd_card; struct aiu_fifo *fifo = dai->playback_dma_data; size_t size = fifo->pcm->buffer_bytes_max; - snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - card->dev, size, size); + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); return 0; } -- cgit v1.2.3 From 49d411f2c93aae48dd379c77db887aa282e9fb51 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 29 Dec 2020 09:51:03 +0100 Subject: ASoC: Intel: common: Fix some typos s/apci/acpi/ Turn an ICL into a TGL because it is likely a cut'n'paste error Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20201229085103.192715-1-christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-ehl-match.c | 2 +- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index badafc1d54d2..5c7a1214403d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration. + * soc-acpi-intel-ehl-match.c - tables and support for EHL ACPI enumeration. * * Copyright (c) 2019, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 98196e9fad62..4933184df5f5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration. + * soc-acpi-intel-tgl-match.c - tables and support for TGL ACPI enumeration. * * Copyright (c) 2019, Intel Corporation. * -- cgit v1.2.3 From 4ac275eda0d7bf6f222ad0093ffbdfd2f4228eaa Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 24 Dec 2020 18:06:03 +0800 Subject: ASoC: rt1015: sort header inclusions Sorts header inclusions. ASCII value of 'r' is less than 's'. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201224100607.3006171-2-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 5fdf7bbfd375..e78364f54451 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -24,10 +24,10 @@ #include #include #include +#include #include #include #include -#include #include "rl6231.h" #include "rt1015.h" -- cgit v1.2.3 From bf1eb056ac15a058fb5e254307f14f45efbe79d8 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 24 Dec 2020 18:06:04 +0800 Subject: ASoC: rt1015: save boost_mode only if valid Saves boost_mode only if valid. Also returns -EINVAL if it is invalid. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201224100607.3006171-3-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index e78364f54451..3b9db3a1a3bc 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -444,10 +444,9 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol, snd_soc_kcontrol_component(kcontrol); struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); + int boost_mode = ucontrol->value.integer.value[0]; - rt1015->boost_mode = ucontrol->value.integer.value[0]; - - switch (rt1015->boost_mode) { + switch (boost_mode) { case BYPASS: snd_soc_component_update_bits(component, RT1015_SMART_BST_CTRL1, RT1015_ABST_AUTO_EN_MASK | @@ -471,8 +470,11 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol, break; default: dev_err(component->dev, "Unknown boost control.\n"); + return -EINVAL; } + rt1015->boost_mode = boost_mode; + return 0; } -- cgit v1.2.3 From e48b41e903a102744827661080acd500b7bbef26 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 24 Dec 2020 18:06:05 +0800 Subject: ASoC: rt1015: return error if any when setting bypass_boost Returns -EBUSY if DAC is using when setting bypass_boost. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201224100607.3006171-4-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 3b9db3a1a3bc..aab5c1b0ece5 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -528,17 +528,19 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - if (!rt1015->dac_is_used) { - rt1015->bypass_boost = ucontrol->value.integer.value[0]; - if (rt1015->bypass_boost == RT1015_Bypass_Boost && + if (rt1015->dac_is_used) { + dev_err(component->dev, "DAC is being used!\n"); + return -EBUSY; + } + + rt1015->bypass_boost = ucontrol->value.integer.value[0]; + if (rt1015->bypass_boost == RT1015_Bypass_Boost && !rt1015->cali_done) { - rt1015_calibrate(rt1015); - rt1015->cali_done = 1; + rt1015_calibrate(rt1015); + rt1015->cali_done = 1; - regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010); - } - } else - dev_err(component->dev, "DAC is being used!\n"); + regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010); + } return 0; } -- cgit v1.2.3 From 3128f1c3b53d73e35e1069663736284358fcdd01 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 24 Dec 2020 18:06:06 +0800 Subject: ASoC: rt1015: refactor retry loop and rt1015_priv allocation Refactors retry loop in flush DAC work. It is more clear to use a for-loop here. Uses !rt1015 to check if NULL. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201224100607.3006171-5-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index aab5c1b0ece5..cc57529ea877 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -550,15 +550,14 @@ static void rt1015_flush_work(struct work_struct *work) struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv, flush_work.work); struct snd_soc_component *component = rt1015->component; - unsigned int val, i = 0, count = 200; + unsigned int val, i; - while (i < count) { + for (i = 0; i < 200; ++i) { usleep_range(1000, 1500); dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i); regmap_read(rt1015->regmap, RT1015_CLK_DET, &val); if (val & 0x800) break; - i++; } regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); @@ -1167,9 +1166,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c, int ret; unsigned int val; - rt1015 = devm_kzalloc(&i2c->dev, sizeof(struct rt1015_priv), - GFP_KERNEL); - if (rt1015 == NULL) + rt1015 = devm_kzalloc(&i2c->dev, sizeof(*rt1015), GFP_KERNEL); + if (!rt1015) return -ENOMEM; i2c_set_clientdata(i2c, rt1015); -- cgit v1.2.3 From a5db2ca51367eeafb0c4013d3a6fc58932612c03 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 24 Dec 2020 18:06:07 +0800 Subject: ASoC: rt1015: remove unneeded variables in rt1015_priv - `lrck' is only used in .hw_params callback so that it can be local. - `bclk' is unused. - `id' is unused. - `amp_ver' is unused. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201224100607.3006171-6-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 9 ++++----- sound/soc/codecs/rt1015.h | 4 ---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index cc57529ea877..bf452cc0096f 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -704,11 +704,11 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - int pre_div, bclk_ms, frame_size; + int pre_div, bclk_ms, frame_size, lrck; unsigned int val_len = 0; - rt1015->lrck = params_rate(params); - pre_div = rl6231_get_clk_info(rt1015->sysclk, rt1015->lrck); + lrck = params_rate(params); + pre_div = rl6231_get_clk_info(rt1015->sysclk, lrck); if (pre_div < 0) { dev_err(component->dev, "Unsupported clock rate\n"); return -EINVAL; @@ -722,13 +722,12 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream, } bclk_ms = frame_size > 32; - rt1015->bclk = rt1015->lrck * (32 << bclk_ms); dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", bclk_ms, pre_div, dai->id); dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", - rt1015->lrck, pre_div, dai->id); + lrck, pre_div, dai->id); switch (params_width(params)) { case 16: diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index b6ea753014e1..e9b498a754e0 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -427,16 +427,12 @@ struct rt1015_priv { struct regmap *regmap; int sysclk; int sysclk_src; - int lrck; - int bclk; int bclk_ratio; - int id; int pll_src; int pll_in; int pll_out; int boost_mode; int bypass_boost; - int amp_ver; int dac_is_used; int cali_done; int hw_config; -- cgit v1.2.3 From e9141c1aaa72782b9de7b224cd184a809aa4a87f Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Wed, 30 Dec 2020 16:02:35 +0800 Subject: ASoC: rt5645: Remove the redundant delay time This patch removes the redundant delay time to speed up from the cold start of headphone playback. Signed-off-by: Oder Chiou Link: https://lore.kernel.org/r/20201230080235.12698-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 420003d062c7..1c9e61abda30 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -435,7 +435,6 @@ struct rt5645_priv { int jack_type; bool en_button_func; - bool hp_on; int v_id; }; @@ -1645,6 +1644,7 @@ static void hp_amp_power(struct snd_soc_component *component, int on) { static int hp_amp_power_count; struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); + int i, val; if (on) { if (hp_amp_power_count <= 0) { @@ -1655,7 +1655,13 @@ static void hp_amp_power(struct snd_soc_component *component, int on) snd_soc_component_write(component, RT5645_DEPOP_M1, 0x000d); regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_HP_DCC_INT1, 0x9f01); - msleep(20); + for (i = 0; i < 20; i++) { + usleep_range(1000, 1500); + regmap_read(rt5645->regmap, RT5645_PR_BASE + + RT5645_HP_DCC_INT1, &val); + if (!(val & 0x8000)) + break; + } snd_soc_component_update_bits(component, RT5645_DEPOP_M1, RT5645_HP_CO_MASK, RT5645_HP_CO_EN); regmap_write(rt5645->regmap, RT5645_PR_BASE + @@ -1665,7 +1671,6 @@ static void hp_amp_power(struct snd_soc_component *component, int on) RT5645_MAMP_INT_REG2, 0xfc00); snd_soc_component_write(component, RT5645_DEPOP_M2, 0x1140); msleep(90); - rt5645->hp_on = true; } else { /* depop parameters */ snd_soc_component_update_bits(component, RT5645_DEPOP_M2, @@ -1885,27 +1890,6 @@ static int rt5645_bst2_event(struct snd_soc_dapm_widget *w, return 0; } -static int rt5650_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - if (rt5645->hp_on) { - msleep(100); - rt5645->hp_on = false; - } - break; - - default: - return 0; - } - - return 0; -} - static int rt5645_set_micbias1_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { @@ -2242,7 +2226,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("PDM1R"), SND_SOC_DAPM_OUTPUT("SPOL"), SND_SOC_DAPM_OUTPUT("SPOR"), - SND_SOC_DAPM_POST("DAPM_POST", rt5650_hp_event), }; static const struct snd_soc_dapm_widget rt5645_specific_dapm_widgets[] = { -- cgit v1.2.3 From a0b653e89a3afd2a833f23589a83488fac842ddb Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 30 Dec 2020 17:24:26 +0000 Subject: ASoC: wm_adsp: Only use __be32 for big-endian data This fixes some minor cases where u32 or unsigned int types were used to store big-endian data, and __be32 types used to store both big-endian and cpu-endian data. This was producing sparse warnings. Most cases resulted from using the same variable to hold the big-endian value and its converted cpu-endian value. These can be simply fixed by introducing another local variable, or avoiding storing the intermediate value back into the original variable. One special case is the raw_buf used in the compressed streams to transfer data from DSP to user-side. The endian conversion happens in-place (as there's no point introducing another buffer) so a cast to (__be32 *) is added when passing it to wm_adsp_read_raw_data_block(). Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20201230172427.13865-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 5b7d81a91df3..8cfa8ac1b8c4 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -980,7 +980,7 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl, unsigned int event_id) { struct wm_adsp *dsp = ctl->dsp; - u32 val = cpu_to_be32(event_id); + __be32 val = cpu_to_be32(event_id); unsigned int reg; int i, ret; @@ -3704,6 +3704,7 @@ static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, unsigned int mem_addr, u32 data) { struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); + __be32 val = cpu_to_be32(data & 0x00ffffffu); unsigned int reg; if (!mem) @@ -3711,9 +3712,7 @@ static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, reg = dsp->ops->region_to_reg(mem, mem_addr); - data = cpu_to_be32(data & 0x00ffffffu); - - return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); + return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); } static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, @@ -3870,7 +3869,8 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) { struct wm_adsp_host_buf_coeff_v1 coeff_v1; struct wm_adsp_compr_buf *buf; - unsigned int val, reg; + unsigned int reg, version; + __be32 bufp; int ret, i; ret = wm_coeff_base_reg(ctl, ®); @@ -3878,17 +3878,17 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) return ret; for (i = 0; i < 5; ++i) { - ret = regmap_raw_read(ctl->dsp->regmap, reg, &val, sizeof(val)); + ret = regmap_raw_read(ctl->dsp->regmap, reg, &bufp, sizeof(bufp)); if (ret < 0) return ret; - if (val) + if (bufp) break; usleep_range(1000, 2000); } - if (!val) { + if (!bufp) { adsp_err(ctl->dsp, "Failed to acquire host buffer\n"); return -EIO; } @@ -3898,7 +3898,7 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) return -ENOMEM; buf->host_buf_mem_type = ctl->alg_region.type; - buf->host_buf_ptr = be32_to_cpu(val); + buf->host_buf_ptr = be32_to_cpu(bufp); ret = wm_adsp_buffer_populate(buf); if (ret < 0) @@ -3918,14 +3918,13 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) if (ret < 0) return ret; - coeff_v1.versions = be32_to_cpu(coeff_v1.versions); - val = coeff_v1.versions & HOST_BUF_COEFF_COMPAT_VER_MASK; - val >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT; + version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK; + version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT; - if (val > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) { + if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) { adsp_err(ctl->dsp, "Host buffer coeff ver %u > supported version %u\n", - val, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER); + version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER); return -EINVAL; } @@ -3935,9 +3934,9 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) (char *)&coeff_v1.name); compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n", - buf->host_buf_ptr, val); + buf->host_buf_ptr, version); - return val; + return version; } static int wm_adsp_buffer_init(struct wm_adsp *dsp) @@ -4269,7 +4268,7 @@ static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) /* Read data from DSP */ ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr, - nwords, compr->raw_buf); + nwords, (__be32 *)compr->raw_buf); if (ret < 0) return ret; -- cgit v1.2.3 From f6212e0ab3ff28d4e2e53a520496a052c241df39 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 30 Dec 2020 17:24:27 +0000 Subject: ASoC: wm_adsp: Use snd_ctl_elem_type_t for control types Sparse will complain about trying to convert between values declared as snd_ctl_elem_type_t and other types. This patch converts to consistently use snd_ctl_elem_type_t for control type values. A __force cast is needed in a couple of cases where the control type value is parsed out of a DSP data block. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20201230172427.13865-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 12 +++++++----- sound/soc/codecs/wmfw.h | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 8cfa8ac1b8c4..f8ad768364c2 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -619,7 +619,7 @@ struct wm_coeff_ctl { unsigned int set:1; struct soc_bytes_ext bytes_ext; unsigned int flags; - unsigned int type; + snd_ctl_elem_type_t type; }; static const char *wm_adsp_mem_region_name(unsigned int type) @@ -1420,7 +1420,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, const struct wm_adsp_alg_region *alg_region, unsigned int offset, unsigned int len, const char *subname, unsigned int subname_len, - unsigned int flags, unsigned int type) + unsigned int flags, snd_ctl_elem_type_t type) { struct wm_coeff_ctl *ctl; struct wmfw_ctl_work *ctl_work; @@ -1554,7 +1554,7 @@ struct wm_coeff_parsed_coeff { int mem_type; const u8 *name; int name_len; - int ctl_type; + snd_ctl_elem_type_t ctl_type; int flags; int len; }; @@ -1649,7 +1649,7 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, blk->mem_type = le16_to_cpu(raw->hdr.type); blk->name = raw->name; blk->name_len = strlen(raw->name); - blk->ctl_type = le16_to_cpu(raw->ctl_type); + blk->ctl_type = (__force snd_ctl_elem_type_t)le16_to_cpu(raw->ctl_type); blk->flags = le16_to_cpu(raw->flags); blk->len = le32_to_cpu(raw->len); break; @@ -1662,7 +1662,9 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, &blk->name); wm_coeff_parse_string(sizeof(u8), &tmp, NULL); wm_coeff_parse_string(sizeof(u16), &tmp, NULL); - blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); + blk->ctl_type = + (__force snd_ctl_elem_type_t)wm_coeff_parse_int(sizeof(raw->ctl_type), + &tmp); blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h index 7423272c30e9..f3d51602f85c 100644 --- a/sound/soc/codecs/wmfw.h +++ b/sound/soc/codecs/wmfw.h @@ -24,9 +24,9 @@ #define WMFW_CTL_FLAG_READABLE 0x0001 /* Non-ALSA coefficient types start at 0x1000 */ -#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */ -#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */ -#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */ +#define WMFW_CTL_TYPE_ACKED ((__force snd_ctl_elem_type_t)0x1000) /* acked control */ +#define WMFW_CTL_TYPE_HOSTEVENT ((__force snd_ctl_elem_type_t)0x1001) /* event control */ +#define WMFW_CTL_TYPE_HOST_BUFFER ((__force snd_ctl_elem_type_t)0x1002) /* host buffer pointer */ struct wmfw_header { char magic[4]; -- cgit v1.2.3 From c1cbbea9c4db41eb69a831d8b07da52e05b1d1e8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Dec 2020 16:43:34 +0100 Subject: ASoC: mediatek: add MTK_PMIC_WRAP dependency Randconfig builds often show harmless warnings like WARNING: unmet direct dependencies detected for SND_SOC_MT6359 Depends on [n]: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && MTK_PMIC_WRAP [=n] Selected by [y]: - SND_SOC_MT8192_MT6359_RT1015_RT5682 [=y] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && I2C [=y] && SND_SOC_MT8192 [=y] Add a dependency to avoid that. Signed-off-by: Arnd Bergmann Acked-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201230154345.639122-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/mediatek/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 8d3dcfb6a580..effdb76369e4 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -172,7 +172,7 @@ config SND_SOC_MT8192 config SND_SOC_MT8192_MT6359_RT1015_RT5682 tristate "ASoC Audio driver for MT8192 with MT6359 RT1015 RT5682 codec" depends on I2C - depends on SND_SOC_MT8192 + depends on SND_SOC_MT8192 && MTK_PMIC_WRAP select SND_SOC_MT6359 select SND_SOC_RT1015 select SND_SOC_RT1015P -- cgit v1.2.3 From e33c93b2206fedee35df756940e07af7b1f29768 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 17 Dec 2020 10:27:40 -0600 Subject: ASoC: wm8962: Add optional mclk device tree binding The driver can request an optional clock for mclk. Update the txt file to reflect this. Suggested-by: Geert Uytterhoeven Signed-off-by: Adam Ford Acked-by: Charles Keepax Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/20201217162740.1452000-1-aford173@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/wm8962.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/wm8962.txt b/Documentation/devicetree/bindings/sound/wm8962.txt index dcfa9a3369fd..c36c649ddfd0 100644 --- a/Documentation/devicetree/bindings/sound/wm8962.txt +++ b/Documentation/devicetree/bindings/sound/wm8962.txt @@ -9,6 +9,9 @@ Required properties: - reg : the I2C address of the device. Optional properties: + + - clocks : The clock source of the mclk + - spk-mono: This is a boolean property. If present, the SPK_MONO bit of R51 (Class D Control 2) gets set, indicating that the speaker is in mono mode. @@ -27,6 +30,7 @@ Example: wm8962: codec@1a { compatible = "wlf,wm8962"; reg = <0x1a>; + clocks = <&clks IMX6QDL_CLK_CKO>; gpio-cfg = < 0x0000 /* 0:Default */ -- cgit v1.2.3 From a1f31cc4e98e1833f53fd2c6e9a218d6b86f5388 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 3 Jan 2021 14:53:17 +0100 Subject: ASoC: fsl_aud2htx: select SND_SOC_IMX_PCM_DMA The newly added driver requires DMA support and fails to build when that is disabled: aarch64-linux-ld: sound/soc/fsl/fsl_aud2htx.o: in function `fsl_aud2htx_probe': fsl_aud2htx.c:(.text+0x3e0): undefined reference to `imx_pcm_dma_init' Fixes: 8a24c834c053 ("ASoC: fsl_aud2htx: Add aud2htx module driver") Signed-off-by: Arnd Bergmann Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20210103135327.3630973-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 84db0b7b9d59..d7f30036d434 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -108,6 +108,7 @@ config SND_SOC_FSL_XCVR config SND_SOC_FSL_AUD2HTX tristate "AUDIO TO HDMI TX module support" depends on ARCH_MXC || COMPILE_TEST + select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n help Say Y if you want to add AUDIO TO HDMI TX support for NXP. -- cgit v1.2.3 From d750570e048165c54a99703729438b2a4ccf379b Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Fri, 25 Dec 2020 11:08:45 +0800 Subject: ASoC: rt1015: re-calibrate again when resuming Assuming the calibration state gets lost after system suspend. Re-calibrates again when resuming. The rt1015_priv is alloced by kzalloc. No need to initialize cali_done to 0 in component probe callback. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201225030845.4138497-1-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index bf452cc0096f..145724a5f389 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -1035,7 +1035,6 @@ static int rt1015_probe(struct snd_soc_component *component) rt1015->component = component; rt1015->bclk_ratio = 0; - rt1015->cali_done = 0; INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work); @@ -1093,6 +1092,10 @@ static int rt1015_resume(struct snd_soc_component *component) regcache_cache_only(rt1015->regmap, false); regcache_sync(rt1015->regmap); + + if (rt1015->cali_done) + rt1015_calibrate(rt1015); + return 0; } #else -- cgit v1.2.3 From 81a6320da73ca23f44155715ec3d9e92bea4e35a Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 24 Dec 2020 18:18:54 +0800 Subject: ASoC: rt1015: remove bclk_ratio bclk_ratio is unused. Removes bclk_ratio and .set_bclk_ratio callback. Removes snd_soc_dai_set_bclk_ratio() in a few machine drivers which are obviously using rt1015. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20201224101854.3024823-1-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/amd/acp3x-rt5682-max9836.c | 4 +--- sound/soc/codecs/rt1015.c | 28 ---------------------- sound/soc/codecs/rt1015.h | 1 - sound/soc/intel/boards/sof_rt5682.c | 7 ------ sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 6 ----- .../mt8183/mt8183-mt6358-ts3a227-max98357.c | 6 ----- .../mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 6 ----- 7 files changed, 1 insertion(+), 57 deletions(-) diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index 1a4e8ca0f99c..cea320ad0e1c 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -140,9 +140,7 @@ static int acp3x_1015_hw_params(struct snd_pcm_substream *substream, for_each_rtd_codec_dais(rtd, i, codec_dai) { if (strcmp(codec_dai->name, "rt1015-aif")) continue; - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret < 0) - return ret; + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 64 * srate, 256 * srate); if (ret < 0) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 145724a5f389..37b5795b00d1 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -864,14 +864,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, freq_out == rt1015->pll_out) return 0; - if (source == RT1015_PLL_S_BCLK) { - if (rt1015->bclk_ratio == 0) { - dev_err(component->dev, - "Can not support bclk ratio as 0.\n"); - return -EINVAL; - } - } - switch (source) { case RT1015_PLL_S_MCLK: snd_soc_component_update_bits(component, RT1015_CLK2, @@ -911,23 +903,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, return 0; } -static int rt1015_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) -{ - struct snd_soc_component *component = dai->component; - struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - - dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio); - - rt1015->bclk_ratio = ratio; - - if (ratio == 50) { - dev_dbg(component->dev, "Unsupport bclk ratio\n"); - return -EINVAL; - } - - return 0; -} - static int rt1015_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { @@ -1034,8 +1009,6 @@ static int rt1015_probe(struct snd_soc_component *component) snd_soc_component_get_drvdata(component); rt1015->component = component; - rt1015->bclk_ratio = 0; - INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work); return 0; @@ -1056,7 +1029,6 @@ static void rt1015_remove(struct snd_soc_component *component) static struct snd_soc_dai_ops rt1015_aif_dai_ops = { .hw_params = rt1015_hw_params, .set_fmt = rt1015_set_dai_fmt, - .set_bclk_ratio = rt1015_set_bclk_ratio, .set_tdm_slot = rt1015_set_tdm_slot, }; diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index e9b498a754e0..2aeaf65ba793 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -427,7 +427,6 @@ struct rt1015_priv { struct regmap *regmap; int sysclk; int sysclk_src; - int bclk_ratio; int pll_src; int pll_in; int pll_out; diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 8b1ca2da9bb9..55505e207bc0 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -323,13 +323,6 @@ static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, fs = 64; for_each_rtd_codec_dais(rtd, i, codec_dai) { - /* Set tdm/i2s1 master bclk ratio */ - ret = snd_soc_dai_set_bclk_ratio(codec_dai, fs); - if (ret < 0) { - dev_err(card->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, params_rate(params) * fs, params_rate(params) * 256); diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 078e58f1ad0b..870cdfd17fff 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -125,12 +125,6 @@ mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, for_each_rtd_codec_dais(rtd, i, codec_dai) { if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) || !strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) { - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret) { - dev_err(rtd->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, rate * 64, rate * 256); diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 8c8340854859..0e4892245035 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -68,12 +68,6 @@ mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, int ret, i; for_each_rtd_codec_dais(rtd, i, codec_dai) { - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret < 0) { - dev_err(card->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, rate * 64, rate * 256); if (ret < 0) { diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 716fbb4126b5..a988ce1e58de 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -46,12 +46,6 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, int ret, i; for_each_rtd_codec_dais(rtd, i, codec_dai) { - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret) { - dev_err(card->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, params_rate(params) * 64, -- cgit v1.2.3 From a8644292ea46064f990e4a3c4585bdb294c0d89a Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Tue, 5 Jan 2021 15:02:55 +0100 Subject: ASoC: txx9: Remove driver CPU support for TX49xx is getting removed, so remove sound support for it. Signed-off-by: Thomas Bogendoerfer Link: https://lore.kernel.org/r/20210105140305.141401-11-tsbogend@alpha.franken.de Signed-off-by: Mark Brown --- sound/soc/Kconfig | 1 - sound/soc/Makefile | 1 - sound/soc/txx9/Kconfig | 30 --- sound/soc/txx9/Makefile | 12 -- sound/soc/txx9/txx9aclc-ac97.c | 230 --------------------- sound/soc/txx9/txx9aclc-generic.c | 88 -------- sound/soc/txx9/txx9aclc.c | 422 -------------------------------------- sound/soc/txx9/txx9aclc.h | 71 ------- 8 files changed, 855 deletions(-) delete mode 100644 sound/soc/txx9/Kconfig delete mode 100644 sound/soc/txx9/Makefile delete mode 100644 sound/soc/txx9/txx9aclc-ac97.c delete mode 100644 sound/soc/txx9/txx9aclc-generic.c delete mode 100644 sound/soc/txx9/txx9aclc.c delete mode 100644 sound/soc/txx9/txx9aclc.h diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 71a6fe87d1a1..47da9ce17693 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -71,7 +71,6 @@ source "sound/soc/stm/Kconfig" source "sound/soc/sunxi/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/ti/Kconfig" -source "sound/soc/txx9/Kconfig" source "sound/soc/uniphier/Kconfig" source "sound/soc/ux500/Kconfig" source "sound/soc/xilinx/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index ddbac3a2169f..508dbaa1814e 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_SND_SOC) += stm/ obj-$(CONFIG_SND_SOC) += sunxi/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += ti/ -obj-$(CONFIG_SND_SOC) += txx9/ obj-$(CONFIG_SND_SOC) += uniphier/ obj-$(CONFIG_SND_SOC) += ux500/ obj-$(CONFIG_SND_SOC) += xilinx/ diff --git a/sound/soc/txx9/Kconfig b/sound/soc/txx9/Kconfig deleted file mode 100644 index d928edf9f5a9..000000000000 --- a/sound/soc/txx9/Kconfig +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -## -## TXx9 ACLC -## -config SND_SOC_TXX9ACLC - tristate "SoC Audio for TXx9" - depends on HAS_TXX9_ACLC && TXX9_DMAC - help - This option enables support for the AC Link Controllers in TXx9 SoC. - -config HAS_TXX9_ACLC - bool - -config SND_SOC_TXX9ACLC_AC97 - tristate - select AC97_BUS - select SND_AC97_CODEC - select SND_SOC_AC97_BUS - - -## -## Boards -## -config SND_SOC_TXX9ACLC_GENERIC - tristate "Generic TXx9 ACLC sound machine" - depends on SND_SOC_TXX9ACLC - select SND_SOC_TXX9ACLC_AC97 - select SND_SOC_AC97_CODEC - help - This is a generic AC97 sound machine for use in TXx9 based systems. diff --git a/sound/soc/txx9/Makefile b/sound/soc/txx9/Makefile deleted file mode 100644 index 37ad833eb329..000000000000 --- a/sound/soc/txx9/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Platform -snd-soc-txx9aclc-objs := txx9aclc.o -snd-soc-txx9aclc-ac97-objs := txx9aclc-ac97.o - -obj-$(CONFIG_SND_SOC_TXX9ACLC) += snd-soc-txx9aclc.o -obj-$(CONFIG_SND_SOC_TXX9ACLC_AC97) += snd-soc-txx9aclc-ac97.o - -# Machine -snd-soc-txx9aclc-generic-objs := txx9aclc-generic.o - -obj-$(CONFIG_SND_SOC_TXX9ACLC_GENERIC) += snd-soc-txx9aclc-generic.o diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c deleted file mode 100644 index d9e348444bd0..000000000000 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * TXx9 ACLC AC97 driver - * - * Copyright (C) 2009 Atsushi Nemoto - * - * Based on RBTX49xx patch from CELF patch archive. - * (C) Copyright TOSHIBA CORPORATION 2004-2006 - */ - -#include -#include -#include -#include -#include -#include -#include /* for TXX9_DIRECTMAP_BASE */ -#include -#include -#include -#include "txx9aclc.h" - -#define AC97_DIR \ - (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) - -#define AC97_RATES \ - SNDRV_PCM_RATE_8000_48000 - -#ifdef __BIG_ENDIAN -#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_BE -#else -#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_LE -#endif - -static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); - -/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ -static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; - -static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata) -{ - return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; -} - -/* AC97 controller reads codec register */ -static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - u32 dat; - - if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num))) - return 0xffff; - reg |= ac97->num << 7; - dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; - __raw_writel(dat, base + ACREGACC); - __raw_writel(ACINT_REGACCRDY, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { - __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); - printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg); - dat = 0xffff; - goto done; - } - dat = __raw_readl(base + ACREGACC); - if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { - printk(KERN_ERR "reg mismatch %x with %x\n", - dat, reg); - dat = 0xffff; - goto done; - } - dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff; -done: - __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); - return dat; -} - -/* AC97 controller writes to codec register */ -static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - - __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | - (val << ACREGACC_DAT_SHIFT), - base + ACREGACC); - __raw_writel(ACINT_REGACCRDY, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { - printk(KERN_ERR - "ac97 write timeout (reg %#x)\n", reg); - } - __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); -} - -static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; - - __raw_writel(ACCTL_ENLINK, base + ACCTLDIS); - udelay(1); - __raw_writel(ACCTL_ENLINK, base + ACCTLEN); - /* wait for primary codec ready status */ - __raw_writel(ready, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, - (__raw_readl(base + ACINTSTS) & ready) == ready, - HZ)) { - dev_err(&ac97->dev, "primary codec is not ready " - "(status %#x)\n", - __raw_readl(base + ACINTSTS)); - } - __raw_writel(ACINT_REGACCRDY, base + ACINTSTS); - __raw_writel(ready, base + ACINTDIS); -} - -/* AC97 controller operations */ -static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { - .read = txx9aclc_ac97_read, - .write = txx9aclc_ac97_write, - .reset = txx9aclc_ac97_cold_reset, -}; - -static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) -{ - struct txx9aclc_plat_drvdata *drvdata = dev_id; - void __iomem *base = drvdata->base; - - __raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS); - wake_up(&ac97_waitq); - return IRQ_HANDLED; -} - -static int txx9aclc_ac97_probe(struct snd_soc_dai *dai) -{ - txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai); - return 0; -} - -static int txx9aclc_ac97_remove(struct snd_soc_dai *dai) -{ - struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai); - - /* disable AC-link */ - __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); - txx9aclc_drvdata = NULL; - return 0; -} - -static struct snd_soc_dai_driver txx9aclc_ac97_dai = { - .probe = txx9aclc_ac97_probe, - .remove = txx9aclc_ac97_remove, - .playback = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .capture = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, -}; - -static const struct snd_soc_component_driver txx9aclc_ac97_component = { - .name = "txx9aclc-ac97", -}; - -static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) -{ - struct txx9aclc_plat_drvdata *drvdata; - struct resource *r; - int err; - int irq; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->base = devm_ioremap_resource(&pdev->dev, r); - if (IS_ERR(drvdata->base)) - return PTR_ERR(drvdata->base); - - platform_set_drvdata(pdev, drvdata); - drvdata->physbase = r->start; - if (sizeof(drvdata->physbase) > sizeof(r->start) && - r->start >= TXX9_DIRECTMAP_BASE && - r->start < TXX9_DIRECTMAP_BASE + 0x400000) - drvdata->physbase |= 0xf00000000ull; - err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, - 0, dev_name(&pdev->dev), drvdata); - if (err < 0) - return err; - - err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops); - if (err < 0) - return err; - - return devm_snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, - &txx9aclc_ac97_dai, 1); -} - -static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) -{ - snd_soc_set_ac97_ops(NULL); - return 0; -} - -static struct platform_driver txx9aclc_ac97_driver = { - .probe = txx9aclc_ac97_dev_probe, - .remove = txx9aclc_ac97_dev_remove, - .driver = { - .name = "txx9aclc-ac97", - }, -}; - -module_platform_driver(txx9aclc_ac97_driver); - -MODULE_AUTHOR("Atsushi Nemoto "); -MODULE_DESCRIPTION("TXx9 ACLC AC97 driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:txx9aclc-ac97"); diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c deleted file mode 100644 index d6893721ba1d..000000000000 --- a/sound/soc/txx9/txx9aclc-generic.c +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Generic TXx9 ACLC machine driver - * - * Copyright (C) 2009 Atsushi Nemoto - * - * Based on RBTX49xx patch from CELF patch archive. - * (C) Copyright TOSHIBA CORPORATION 2004-2006 - * - * This is a very generic AC97 sound machine driver for boards which - * have (AC97) audio at ACLC (e.g. RBTX49XX boards). - */ - -#include -#include -#include -#include -#include -#include "txx9aclc.h" - -SND_SOC_DAILINK_DEFS(hifi, - DAILINK_COMP_ARRAY(COMP_CPU("txx9aclc-ac97")), - DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("txx9aclc-pcm-audio"))); - -static struct snd_soc_dai_link txx9aclc_generic_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - SND_SOC_DAILINK_REG(hifi), -}; - -static struct snd_soc_card txx9aclc_generic_card = { - .name = "Generic TXx9 ACLC Audio", - .owner = THIS_MODULE, - .dai_link = &txx9aclc_generic_dai, - .num_links = 1, -}; - -static struct platform_device *soc_pdev; - -static int __init txx9aclc_generic_probe(struct platform_device *pdev) -{ - int ret; - - soc_pdev = platform_device_alloc("soc-audio", -1); - if (!soc_pdev) - return -ENOMEM; - platform_set_drvdata(soc_pdev, &txx9aclc_generic_card); - ret = platform_device_add(soc_pdev); - if (ret) { - platform_device_put(soc_pdev); - return ret; - } - - return 0; -} - -static int __exit txx9aclc_generic_remove(struct platform_device *pdev) -{ - platform_device_unregister(soc_pdev); - return 0; -} - -static struct platform_driver txx9aclc_generic_driver = { - .remove = __exit_p(txx9aclc_generic_remove), - .driver = { - .name = "txx9aclc-generic", - }, -}; - -static int __init txx9aclc_generic_init(void) -{ - return platform_driver_probe(&txx9aclc_generic_driver, - txx9aclc_generic_probe); -} - -static void __exit txx9aclc_generic_exit(void) -{ - platform_driver_unregister(&txx9aclc_generic_driver); -} - -module_init(txx9aclc_generic_init); -module_exit(txx9aclc_generic_exit); - -MODULE_AUTHOR("Atsushi Nemoto "); -MODULE_DESCRIPTION("Generic TXx9 ACLC ALSA SoC audio driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:txx9aclc-generic"); diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c deleted file mode 100644 index 1d2d0d9b57b0..000000000000 --- a/sound/soc/txx9/txx9aclc.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Generic TXx9 ACLC platform driver - * - * Copyright (C) 2009 Atsushi Nemoto - * - * Based on RBTX49xx patch from CELF patch archive. - * (C) Copyright TOSHIBA CORPORATION 2004-2006 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "txx9aclc.h" - -#define DRV_NAME "txx9aclc" - -static struct txx9aclc_soc_device { - struct txx9aclc_dmadata dmadata[2]; -} txx9aclc_soc_device; - -/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ -static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; - -static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, - struct txx9aclc_dmadata *dmadata); - -static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { - /* - * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID - * needs more works for noncoherent MIPS. - */ - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_PAUSE, - .period_bytes_min = 1024, - .period_bytes_max = 8 * 1024, - .periods_min = 2, - .periods_max = 4096, - .buffer_bytes_max = 32 * 1024, -}; - -static int txx9aclc_pcm_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct txx9aclc_dmadata *dmadata = runtime->private_data; - - dev_dbg(component->dev, - "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " - "runtime->min_align %ld\n", - (unsigned long)runtime->dma_area, - (unsigned long)runtime->dma_addr, runtime->dma_bytes, - runtime->min_align); - dev_dbg(component->dev, - "periods %d period_bytes %d stream %d\n", - params_periods(params), params_period_bytes(params), - substream->stream); - - dmadata->substream = substream; - dmadata->pos = 0; - return 0; -} - -static int txx9aclc_pcm_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct txx9aclc_dmadata *dmadata = runtime->private_data; - - dmadata->dma_addr = runtime->dma_addr; - dmadata->buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - dmadata->period_bytes = snd_pcm_lib_period_bytes(substream); - - if (dmadata->buffer_bytes == dmadata->period_bytes) { - dmadata->frag_bytes = dmadata->period_bytes >> 1; - dmadata->frags = 2; - } else { - dmadata->frag_bytes = dmadata->period_bytes; - dmadata->frags = dmadata->buffer_bytes / dmadata->period_bytes; - } - dmadata->frag_count = 0; - dmadata->pos = 0; - return 0; -} - -static void txx9aclc_dma_complete(void *arg) -{ - struct txx9aclc_dmadata *dmadata = arg; - unsigned long flags; - - /* dma completion handler cannot submit new operations */ - spin_lock_irqsave(&dmadata->dma_lock, flags); - if (dmadata->frag_count >= 0) { - dmadata->dmacount--; - if (!WARN_ON(dmadata->dmacount < 0)) - queue_work(system_highpri_wq, &dmadata->work); - } - spin_unlock_irqrestore(&dmadata->dma_lock, flags); -} - -static struct dma_async_tx_descriptor * -txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr) -{ - struct dma_chan *chan = dmadata->dma_chan; - struct dma_async_tx_descriptor *desc; - struct scatterlist sg; - - sg_init_table(&sg, 1); - sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf_dma_addr)), - dmadata->frag_bytes, buf_dma_addr & (PAGE_SIZE - 1)); - sg_dma_address(&sg) = buf_dma_addr; - desc = dmaengine_prep_slave_sg(chan, &sg, 1, - dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - dev_err(&chan->dev->device, "cannot prepare slave dma\n"); - return NULL; - } - desc->callback = txx9aclc_dma_complete; - desc->callback_param = dmadata; - dmaengine_submit(desc); - return desc; -} - -#define NR_DMA_CHAIN 2 - -static void txx9aclc_dma_work(struct work_struct *work) -{ - struct txx9aclc_dmadata *dmadata = - container_of(work, struct txx9aclc_dmadata, work); - struct dma_chan *chan = dmadata->dma_chan; - struct dma_async_tx_descriptor *desc; - struct snd_pcm_substream *substream = dmadata->substream; - u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - ACCTL_AUDODMA : ACCTL_AUDIDMA; - int i; - unsigned long flags; - - spin_lock_irqsave(&dmadata->dma_lock, flags); - if (dmadata->frag_count < 0) { - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - dmaengine_terminate_all(chan); - /* first time */ - for (i = 0; i < NR_DMA_CHAIN; i++) { - desc = txx9aclc_dma_submit(dmadata, - dmadata->dma_addr + i * dmadata->frag_bytes); - if (!desc) - return; - } - dmadata->dmacount = NR_DMA_CHAIN; - dma_async_issue_pending(chan); - spin_lock_irqsave(&dmadata->dma_lock, flags); - __raw_writel(ctlbit, base + ACCTLEN); - dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags; - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - return; - } - if (WARN_ON(dmadata->dmacount >= NR_DMA_CHAIN)) { - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - return; - } - while (dmadata->dmacount < NR_DMA_CHAIN) { - dmadata->dmacount++; - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - desc = txx9aclc_dma_submit(dmadata, - dmadata->dma_addr + - dmadata->frag_count * dmadata->frag_bytes); - if (!desc) - return; - dma_async_issue_pending(chan); - - spin_lock_irqsave(&dmadata->dma_lock, flags); - dmadata->frag_count++; - dmadata->frag_count %= dmadata->frags; - dmadata->pos += dmadata->frag_bytes; - dmadata->pos %= dmadata->buffer_bytes; - if ((dmadata->frag_count * dmadata->frag_bytes) % - dmadata->period_bytes == 0) - snd_pcm_period_elapsed(substream); - } - spin_unlock_irqrestore(&dmadata->dma_lock, flags); -} - -static int txx9aclc_pcm_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, int cmd) -{ - struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - unsigned long flags; - int ret = 0; - u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - ACCTL_AUDODMA : ACCTL_AUDIDMA; - - spin_lock_irqsave(&dmadata->dma_lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - dmadata->frag_count = -1; - queue_work(system_highpri_wq, &dmadata->work); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - __raw_writel(ctlbit, base + ACCTLDIS); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - __raw_writel(ctlbit, base + ACCTLEN); - break; - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - return ret; -} - -static snd_pcm_uframes_t -txx9aclc_pcm_pointer(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - - return bytes_to_frames(substream->runtime, dmadata->pos); -} - -static int txx9aclc_pcm_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct txx9aclc_soc_device *dev = &txx9aclc_soc_device; - struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; - int ret; - - ret = snd_soc_set_runtime_hwparams(substream, &txx9aclc_pcm_hardware); - if (ret) - return ret; - /* ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; - substream->runtime->private_data = dmadata; - return 0; -} - -static int txx9aclc_pcm_close(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - struct dma_chan *chan = dmadata->dma_chan; - - dmadata->frag_count = -1; - dmaengine_terminate_all(chan); - return 0; -} - -static int txx9aclc_pcm_new(struct snd_soc_component *component, - struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); - struct snd_pcm *pcm = rtd->pcm; - struct platform_device *pdev = to_platform_device(component->dev); - struct txx9aclc_soc_device *dev; - struct resource *r; - int i; - int ret; - - /* at this point onwards the AC97 component has probed and this will be valid */ - dev = snd_soc_dai_get_drvdata(dai); - - dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; - dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; - for (i = 0; i < 2; i++) { - r = platform_get_resource(pdev, IORESOURCE_DMA, i); - if (!r) { - ret = -EBUSY; - goto exit; - } - dev->dmadata[i].dma_res = r; - ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); - if (ret) - goto exit; - } - - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, - card->dev, 64 * 1024, 4 * 1024 * 1024); - return 0; - -exit: - for (i = 0; i < 2; i++) { - if (dev->dmadata[i].dma_chan) - dma_release_channel(dev->dmadata[i].dma_chan); - dev->dmadata[i].dma_chan = NULL; - } - return ret; -} - -static bool filter(struct dma_chan *chan, void *param) -{ - struct txx9aclc_dmadata *dmadata = param; - char *devname; - bool found = false; - - devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name, - (int)dmadata->dma_res->start); - if (strcmp(dev_name(chan->device->dev), devname) == 0) { - chan->private = &dmadata->dma_slave; - found = true; - } - kfree(devname); - return found; -} - -static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, - struct txx9aclc_dmadata *dmadata) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - struct txx9dmac_slave *ds = &dmadata->dma_slave; - dma_cap_mask_t mask; - - spin_lock_init(&dmadata->dma_lock); - - ds->reg_width = sizeof(u32); - if (dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ds->tx_reg = drvdata->physbase + ACAUDODAT; - ds->rx_reg = 0; - } else { - ds->tx_reg = 0; - ds->rx_reg = drvdata->physbase + ACAUDIDAT; - } - - /* Try to grab a DMA channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); - if (!dmadata->dma_chan) { - printk(KERN_ERR - "DMA channel for %s is not available\n", - dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? - "playback" : "capture"); - return -EBUSY; - } - INIT_WORK(&dmadata->work, txx9aclc_dma_work); - return 0; -} - -static int txx9aclc_pcm_probe(struct snd_soc_component *component) -{ - snd_soc_component_set_drvdata(component, &txx9aclc_soc_device); - return 0; -} - -static void txx9aclc_pcm_remove(struct snd_soc_component *component) -{ - struct txx9aclc_soc_device *dev = snd_soc_component_get_drvdata(component); - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - int i; - - /* disable all FIFO DMAs */ - __raw_writel(ACCTL_AUDODMA | ACCTL_AUDIDMA, base + ACCTLDIS); - /* dummy R/W to clear pending DMAREQ if any */ - __raw_writel(__raw_readl(base + ACAUDIDAT), base + ACAUDODAT); - - for (i = 0; i < 2; i++) { - struct txx9aclc_dmadata *dmadata = &dev->dmadata[i]; - struct dma_chan *chan = dmadata->dma_chan; - - if (chan) { - dmadata->frag_count = -1; - dmaengine_terminate_all(chan); - dma_release_channel(chan); - } - dev->dmadata[i].dma_chan = NULL; - } -} - -static const struct snd_soc_component_driver txx9aclc_soc_component = { - .name = DRV_NAME, - .probe = txx9aclc_pcm_probe, - .remove = txx9aclc_pcm_remove, - .open = txx9aclc_pcm_open, - .close = txx9aclc_pcm_close, - .hw_params = txx9aclc_pcm_hw_params, - .prepare = txx9aclc_pcm_prepare, - .trigger = txx9aclc_pcm_trigger, - .pointer = txx9aclc_pcm_pointer, - .pcm_construct = txx9aclc_pcm_new, -}; - -static int txx9aclc_soc_platform_probe(struct platform_device *pdev) -{ - return devm_snd_soc_register_component(&pdev->dev, - &txx9aclc_soc_component, NULL, 0); -} - -static struct platform_driver txx9aclc_pcm_driver = { - .driver = { - .name = "txx9aclc-pcm-audio", - }, - - .probe = txx9aclc_soc_platform_probe, -}; - -module_platform_driver(txx9aclc_pcm_driver); - -MODULE_AUTHOR("Atsushi Nemoto "); -MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h deleted file mode 100644 index 37c691ba56ed..000000000000 --- a/sound/soc/txx9/txx9aclc.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * TXx9 SoC AC Link Controller - */ - -#ifndef __TXX9ACLC_H -#define __TXX9ACLC_H - -#include -#include - -#define ACCTLEN 0x00 /* control enable */ -#define ACCTLDIS 0x04 /* control disable */ -#define ACCTL_ENLINK 0x00000001 /* enable/disable AC-link */ -#define ACCTL_AUDODMA 0x00000100 /* AUDODMA enable/disable */ -#define ACCTL_AUDIDMA 0x00001000 /* AUDIDMA enable/disable */ -#define ACCTL_AUDOEHLT 0x00010000 /* AUDO error halt - enable/disable */ -#define ACCTL_AUDIEHLT 0x00100000 /* AUDI error halt - enable/disable */ -#define ACREGACC 0x08 /* codec register access */ -#define ACREGACC_DAT_SHIFT 0 /* data field */ -#define ACREGACC_REG_SHIFT 16 /* address field */ -#define ACREGACC_CODECID_SHIFT 24 /* CODEC ID field */ -#define ACREGACC_READ 0x80000000 /* CODEC read */ -#define ACREGACC_WRITE 0x00000000 /* CODEC write */ -#define ACINTSTS 0x10 /* interrupt status */ -#define ACINTMSTS 0x14 /* interrupt masked status */ -#define ACINTEN 0x18 /* interrupt enable */ -#define ACINTDIS 0x1c /* interrupt disable */ -#define ACINT_CODECRDY(n) (0x00000001 << (n)) /* CODECn ready */ -#define ACINT_REGACCRDY 0x00000010 /* ACREGACC ready */ -#define ACINT_AUDOERR 0x00000100 /* AUDO underrun error */ -#define ACINT_AUDIERR 0x00001000 /* AUDI overrun error */ -#define ACDMASTS 0x80 /* DMA request status */ -#define ACDMA_AUDO 0x00000001 /* AUDODMA pending */ -#define ACDMA_AUDI 0x00000010 /* AUDIDMA pending */ -#define ACAUDODAT 0xa0 /* audio out data */ -#define ACAUDIDAT 0xb0 /* audio in data */ -#define ACREVID 0xfc /* revision ID */ - -struct txx9aclc_dmadata { - struct resource *dma_res; - struct txx9dmac_slave dma_slave; - struct dma_chan *dma_chan; - struct work_struct work; - spinlock_t dma_lock; - int stream; /* SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE */ - struct snd_pcm_substream *substream; - unsigned long pos; - dma_addr_t dma_addr; - unsigned long buffer_bytes; - unsigned long period_bytes; - unsigned long frag_bytes; - int frags; - int frag_count; - int dmacount; -}; - -struct txx9aclc_plat_drvdata { - void __iomem *base; - u64 physbase; -}; - -static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( - struct snd_soc_dai *dai) -{ - return dev_get_drvdata(dai->dev); -} - -#endif /* __TXX9ACLC_H */ -- cgit v1.2.3 From aac568269bd80a510758ec5d5744b1a2eea3f049 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 7 Jan 2021 13:07:57 +0100 Subject: ASoC: Intel: bytcht_es8316: Remove comment about SSP0 being untested Remove a stale comment about SSP0 being untested, the bytcht_es8316 has supported SSP0 for a while now and this has been successfully tested on a GP electrinic T701 tablet. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210107120757.12051-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcht_es8316.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 892cf684216e..06df2d46d910 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -331,9 +331,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { /* back ends */ { - /* Only SSP2 has been tested here, so BYT-CR platforms that - * require SSP0 will not work. - */ .name = "SSP2-Codec", .id = 0, .no_pcm = 1, -- cgit v1.2.3 From 2c1382840c194533399818d0ed39dfc94f906187 Mon Sep 17 00:00:00 2001 From: 朱灿灿 Date: Fri, 25 Dec 2020 16:42:46 +0800 Subject: ASoC: soc-pcm: disconnect BEs if the FE is not ready FE is connected to two BEs, BE1 is active, BE2 is deactive. When closing BE1, FE/BE1 is in HW_FREE state, then BE2 is startup by mixer runtime update. For FE is in HW_FREE state, dpcm_run_update_startup() will skip BE2's startup because FE's state is HW_FREE, BE2 stays in FE's be_clients list. During FE's closed, the dpcm_fe_dai_close() will close all related BEs, BE2 will be closed. This will lead to BE2's dpcm[stream].users mismatch. We need disconnet all pending BEs in the corner case. Signed-off-by: zhucancan Link: https://lore.kernel.org/r/AAoArwDfDnoefyxzy2wyiaqm.1.1608885766936.Hmail.zhucancan@vivo.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ee51dc7fd893..481a4a25acb0 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2440,8 +2440,11 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) /* Only start the BE if the FE is ready */ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE || - fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) - return -EINVAL; + fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) { + dev_err(fe->dev, "ASoC: FE %s is not ready %d\n", + fe->dai_link->name, fe->dpcm[stream].state); + goto disconnect; + } /* startup must always be called for new BEs */ ret = dpcm_be_dai_startup(fe, stream); @@ -2502,12 +2505,18 @@ hw_free: close: dpcm_be_dai_shutdown(fe, stream); disconnect: - /* disconnect any closed BEs */ + /* disconnect any pending BEs */ spin_lock_irqsave(&fe->card->dpcm_lock, flags); for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) - dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; + + /* is this op for this BE ? */ + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + continue; + + if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE || + be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW) + dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; } spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); -- cgit v1.2.3 From 75b1a8f9d62e50f05d0e4e9f3c8bcde32527ffc1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 4 Jan 2021 09:17:34 -0800 Subject: ALSA: Convert strlcpy to strscpy when return value is unused strlcpy is deprecated. see: Documentation/process/deprecated.rst Change the calls that do not use the strlcpy return value to the preferred strscpy. Done with cocci script: @@ expression e1, e2, e3; @@ - strlcpy( + strscpy( e1, e2, e3); This cocci script leaves the instances where the return value is used unchanged. After this patch, sound/ has 3 uses of strlcpy() that need to be manually inspected for conversion and changed one day. $ git grep -w strlcpy sound/ sound/usb/card.c: len = strlcpy(card->longname, s, sizeof(card->longname)); sound/usb/mixer.c: return strlcpy(buf, p->name, buflen); sound/usb/mixer.c: return strlcpy(buf, p->names[index], buflen); Miscellenea: o Remove trailing whitespace in conversion of sound/core/hwdep.c Link: https://lore.kernel.org/lkml/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Joe Perches Acked-by: Mark Brown Link: https://lore.kernel.org/r/22b393d1790bb268769d0bab7bacf0866dcb0c14.camel@perches.com Signed-off-by: Takashi Iwai --- sound/aoa/codecs/onyx.c | 2 +- sound/aoa/codecs/tas.c | 2 +- sound/aoa/codecs/toonie.c | 2 +- sound/aoa/core/alsa.c | 8 ++++---- sound/aoa/fabrics/layout.c | 6 +++--- sound/aoa/soundbus/sysfs.c | 2 +- sound/arm/aaci.c | 6 +++--- sound/arm/pxa2xx-ac97.c | 2 +- sound/core/compress_offload.c | 2 +- sound/core/control.c | 16 ++++++++-------- sound/core/ctljack.c | 2 +- sound/core/hwdep.c | 6 +++--- sound/core/init.c | 4 ++-- sound/core/oss/mixer_oss.c | 12 ++++++------ sound/core/pcm.c | 2 +- sound/core/pcm_native.c | 6 +++--- sound/core/rawmidi.c | 2 +- sound/core/seq/oss/seq_oss_midi.c | 4 ++-- sound/core/seq/oss/seq_oss_synth.c | 6 +++--- sound/core/seq/seq_clientmgr.c | 2 +- sound/core/seq/seq_ports.c | 6 +++--- sound/core/timer.c | 10 +++++----- sound/core/timer_compat.c | 4 ++-- sound/drivers/opl3/opl3_oss.c | 2 +- sound/drivers/opl3/opl3_synth.c | 2 +- sound/firewire/bebob/bebob_hwdep.c | 2 +- sound/firewire/dice/dice-hwdep.c | 2 +- sound/firewire/digi00x/digi00x-hwdep.c | 2 +- sound/firewire/fireface/ff-hwdep.c | 2 +- sound/firewire/fireworks/fireworks_hwdep.c | 2 +- sound/firewire/motu/motu-hwdep.c | 2 +- sound/firewire/oxfw/oxfw-hwdep.c | 2 +- sound/firewire/tascam/tascam-hwdep.c | 2 +- sound/i2c/i2c.c | 4 ++-- sound/isa/ad1848/ad1848.c | 4 ++-- sound/isa/cs423x/cs4231.c | 4 ++-- sound/isa/cs423x/cs4236.c | 4 ++-- sound/isa/es1688/es1688.c | 4 ++-- sound/isa/sb/sb16_csp.c | 2 +- sound/isa/sb/sb_mixer.c | 2 +- sound/oss/dmasound/dmasound_core.c | 4 ++-- sound/pci/cs5535audio/cs5535audio_olpc.c | 4 ++-- sound/pci/ctxfi/ctpcm.c | 2 +- sound/pci/emu10k1/emu10k1.c | 4 ++-- sound/pci/emu10k1/emu10k1_main.c | 2 +- sound/pci/emu10k1/emufx.c | 6 +++--- sound/pci/es1968.c | 2 +- sound/pci/fm801.c | 2 +- sound/pci/hda/hda_auto_parser.c | 2 +- sound/pci/hda/hda_codec.c | 2 +- sound/pci/hda/hda_controller.c | 2 +- sound/pci/hda/hda_eld.c | 2 +- sound/pci/hda/hda_generic.c | 2 +- sound/pci/hda/hda_intel.c | 2 +- sound/pci/hda/hda_jack.c | 2 +- sound/pci/ice1712/juli.c | 2 +- sound/pci/ice1712/psc724.c | 4 ++-- sound/pci/ice1712/quartet.c | 2 +- sound/pci/ice1712/wm8776.c | 2 +- sound/pci/lola/lola.c | 2 +- sound/pci/lola/lola_pcm.c | 2 +- sound/pci/rme9652/hdspm.c | 2 +- sound/ppc/keywest.c | 2 +- sound/soc/qcom/qdsp6/q6afe.c | 2 +- sound/soc/sh/rcar/core.c | 2 +- sound/usb/bcd2000/bcd2000.c | 2 +- sound/usb/caiaq/audio.c | 2 +- sound/usb/caiaq/device.c | 6 +++--- sound/usb/caiaq/midi.c | 2 +- sound/usb/card.c | 4 ++-- sound/usb/hiface/chip.c | 6 +++--- sound/usb/hiface/pcm.c | 2 +- sound/usb/mixer.c | 12 ++++++------ sound/usb/mixer_quirks.c | 2 +- sound/usb/mixer_scarlett.c | 2 +- sound/usb/mixer_scarlett_gen2.c | 2 +- sound/usb/mixer_us16x08.c | 2 +- sound/x86/intel_hdmi_audio.c | 2 +- sound/xen/xen_snd_front_cfg.c | 2 +- 79 files changed, 134 insertions(+), 134 deletions(-) diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 12028b3e2eee..1abee841cc45 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -1013,7 +1013,7 @@ static int onyx_i2c_probe(struct i2c_client *client, goto fail; } - strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); + strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); onyx->codec.owner = THIS_MODULE; onyx->codec.init = onyx_init_codec; onyx->codec.exit = onyx_exit_codec; diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index d3e37577b529..ac246dd3ab49 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -894,7 +894,7 @@ static int tas_i2c_probe(struct i2c_client *client, /* seems that half is a saner default */ tas->drc_range = TAS3004_DRC_MAX / 2; - strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); + strscpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); tas->codec.owner = THIS_MODULE; tas->codec.init = tas_init_codec; tas->codec.exit = tas_exit_codec; diff --git a/sound/aoa/codecs/toonie.c b/sound/aoa/codecs/toonie.c index c2d014486c33..0da5af129492 100644 --- a/sound/aoa/codecs/toonie.c +++ b/sound/aoa/codecs/toonie.c @@ -126,7 +126,7 @@ static int __init toonie_init(void) if (!toonie) return -ENOMEM; - strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); + strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); toonie->codec.owner = THIS_MODULE; toonie->codec.init = toonie_init_codec; toonie->codec.exit = toonie_exit_codec; diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c index b61081342266..7fce8581ddbd 100644 --- a/sound/aoa/core/alsa.c +++ b/sound/aoa/core/alsa.c @@ -28,10 +28,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev) return err; aoa_card = alsa_card->private_data; aoa_card->alsa_card = alsa_card; - strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); - strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); - strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); - strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); + strscpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); + strscpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); + strscpy(alsa_card->longname, name, sizeof(alsa_card->longname)); + strscpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); err = snd_card_register(aoa_card->alsa_card); if (err < 0) { printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index d2e85b83f7ed..ec4ef18555bc 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -948,7 +948,7 @@ static void layout_attached_codec(struct aoa_codec *codec) ldev->gpio.methods->set_lineout(codec->gpio, 1); ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, + strscpy(ctl->id.name, "Headphone Switch", sizeof(ctl->id.name)); ldev->lineout_ctrl = ctl; aoa_snd_ctl_add(ctl); @@ -962,14 +962,14 @@ static void layout_attached_codec(struct aoa_codec *codec) ctl = snd_ctl_new1(&lineout_detect_choice, ldev); if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, + strscpy(ctl->id.name, "Headphone Detect Autoswitch", sizeof(ctl->id.name)); aoa_snd_ctl_add(ctl); ctl = snd_ctl_new1(&lineout_detected, ldev); if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, + strscpy(ctl->id.name, "Headphone Detected", sizeof(ctl->id.name)); ldev->lineout_detected_ctrl = ctl; diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c index a2d55e15afbb..dead3105689b 100644 --- a/sound/aoa/soundbus/sysfs.c +++ b/sound/aoa/soundbus/sysfs.c @@ -13,7 +13,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, int length; if (*sdev->modalias) { - strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); + strscpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); strcat(buf, "\n"); length = strlen(buf); } else { diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index a0996c47e58f..f02a91bdaa97 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -890,8 +890,8 @@ static struct aaci *aaci_init_card(struct amba_device *dev) card->private_free = aaci_free_card; - strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); - strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); + strscpy(card->driver, DRIVER_NAME, sizeof(card->driver)); + strscpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s PL%03x rev%u at 0x%08llx, irq %d", card->shortname, amba_part(dev), amba_rev(dev), @@ -921,7 +921,7 @@ static int aaci_init_pcm(struct aaci *aaci) pcm->private_data = aaci; pcm->info_flags = 0; - strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); + strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index ea8e233150c8..6322e6392594 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -235,7 +235,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev) if (ret < 0) goto err; - strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver)); + strscpy(card->driver, dev->dev.driver->name, sizeof(card->driver)); ret = pxa2xx_ac97_pcm_new(card); if (ret) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index debc30fcf5b3..21ce4c056a92 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -1132,7 +1132,7 @@ static void snd_compress_proc_done(struct snd_compr *compr) static inline void snd_compress_set_id(struct snd_compr *compr, const char *id) { - strlcpy(compr->id, id, sizeof(compr->id)); + strscpy(compr->id, id, sizeof(compr->id)); } #else static inline int snd_compress_proc_init(struct snd_compr *compr) diff --git a/sound/core/control.c b/sound/core/control.c index 1571c7f7c43b..5165741a8400 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -261,7 +261,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, kctl->id.device = ncontrol->device; kctl->id.subdevice = ncontrol->subdevice; if (ncontrol->name) { - strlcpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name)); + strscpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name)); if (strcmp(ncontrol->name, kctl->id.name) != 0) pr_warn("ALSA: Control name '%s' truncated to '%s'\n", ncontrol->name, kctl->id.name); @@ -701,12 +701,12 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, return -ENOMEM; down_read(&snd_ioctl_rwsem); info->card = card->number; - strlcpy(info->id, card->id, sizeof(info->id)); - strlcpy(info->driver, card->driver, sizeof(info->driver)); - strlcpy(info->name, card->shortname, sizeof(info->name)); - strlcpy(info->longname, card->longname, sizeof(info->longname)); - strlcpy(info->mixername, card->mixername, sizeof(info->mixername)); - strlcpy(info->components, card->components, sizeof(info->components)); + strscpy(info->id, card->id, sizeof(info->id)); + strscpy(info->driver, card->driver, sizeof(info->driver)); + strscpy(info->name, card->shortname, sizeof(info->name)); + strscpy(info->longname, card->longname, sizeof(info->longname)); + strscpy(info->mixername, card->mixername, sizeof(info->mixername)); + strscpy(info->components, card->components, sizeof(info->components)); up_read(&snd_ioctl_rwsem); if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) { kfree(info); @@ -2137,7 +2137,7 @@ int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels, WARN(strlen(names[info->value.enumerated.item]) >= sizeof(info->value.enumerated.name), "ALSA: too long item name '%s'\n", names[info->value.enumerated.item]); - strlcpy(info->value.enumerated.name, + strscpy(info->value.enumerated.name, names[info->value.enumerated.item], sizeof(info->value.enumerated.name)); return 0; diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c index 9be4e282f2e0..709b1a9c2caa 100644 --- a/sound/core/ctljack.c +++ b/sound/core/ctljack.c @@ -35,7 +35,7 @@ static int get_available_index(struct snd_card *card, const char *name) sid.index = 0; sid.iface = SNDRV_CTL_ELEM_IFACE_CARD; - strlcpy(sid.name, name, sizeof(sid.name)); + strscpy(sid.name, name, sizeof(sid.name)); while (snd_ctl_find_id(card, &sid)) { sid.index++; diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 0c029892880a..264b8ea64bc2 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -177,8 +177,8 @@ static int snd_hwdep_info(struct snd_hwdep *hw, memset(&info, 0, sizeof(info)); info.card = hw->card->number; - strlcpy(info.id, hw->id, sizeof(info.id)); - strlcpy(info.name, hw->name, sizeof(info.name)); + strscpy(info.id, hw->id, sizeof(info.id)); + strscpy(info.name, hw->name, sizeof(info.name)); info.iface = hw->iface; if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -379,7 +379,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, hwdep->card = card; hwdep->device = device; if (id) - strlcpy(hwdep->id, id, sizeof(hwdep->id)); + strscpy(hwdep->id, id, sizeof(hwdep->id)); snd_device_initialize(&hwdep->dev, card); hwdep->dev.release = release_hwdep_device; diff --git a/sound/core/init.c b/sound/core/init.c index 75aec71c48a8..56834febc7a4 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -174,7 +174,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid, if (extra_size > 0) card->private_data = (char *)card + sizeof(struct snd_card); if (xid) - strlcpy(card->id, xid, sizeof(card->id)); + strscpy(card->id, xid, sizeof(card->id)); err = 0; mutex_lock(&snd_card_mutex); if (idx < 0) /* first check the matching module-name slot */ @@ -623,7 +623,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, /* last resort... */ dev_err(card->dev, "unable to set card id (%s)\n", id); if (card->proc_root->name) - strlcpy(card->id, card->proc_root->name, sizeof(card->id)); + strscpy(card->id, card->proc_root->name, sizeof(card->id)); } /** diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index af5de08f9819..bec928327478 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -87,8 +87,8 @@ static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer, struct mixer_info info; memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); - strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); + strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); + strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); info.modify_counter = card->mixer_oss_change_count; if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -103,8 +103,8 @@ static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer, _old_mixer_info info; memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); - strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); + strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); + strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; return 0; @@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strlcpy(id.name, name, sizeof(id.name)); + strscpy(id.name, name, sizeof(id.name)); id.index = index; return snd_ctl_find_id(card, &id); } @@ -1355,7 +1355,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) mixer->oss_dev_alloc = 1; mixer->card = card; if (*card->mixername) - strlcpy(mixer->name, card->mixername, sizeof(mixer->name)); + strscpy(mixer->name, card->mixername, sizeof(mixer->name)); else snprintf(mixer->name, sizeof(mixer->name), "mixer%i", card->number); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index be5714f1bb58..e5947281e5fc 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -729,7 +729,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device, init_waitqueue_head(&pcm->open_wait); INIT_LIST_HEAD(&pcm->list); if (id) - strlcpy(pcm->id, id, sizeof(pcm->id)); + strscpy(pcm->id, id, sizeof(pcm->id)); err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 9f3f8e953ff0..66ae1e248103 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -209,13 +209,13 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) info->device = pcm->device; info->stream = substream->stream; info->subdevice = substream->number; - strlcpy(info->id, pcm->id, sizeof(info->id)); - strlcpy(info->name, pcm->name, sizeof(info->name)); + strscpy(info->id, pcm->id, sizeof(info->id)); + strscpy(info->name, pcm->name, sizeof(info->name)); info->dev_class = pcm->dev_class; info->dev_subclass = pcm->dev_subclass; info->subdevices_count = pstr->substream_count; info->subdevices_avail = pstr->substream_count - pstr->substream_opened; - strlcpy(info->subname, substream->name, sizeof(info->subname)); + strscpy(info->subname, substream->name, sizeof(info->subname)); return 0; } diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 257ad5206240..aca00af93afe 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1686,7 +1686,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams); if (id != NULL) - strlcpy(rmidi->id, id, sizeof(rmidi->id)); + strscpy(rmidi->id, id, sizeof(rmidi->id)); snd_device_initialize(&rmidi->dev, card); rmidi->dev.release = release_rawmidi_device; diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 2ddfe2226651..3f82c196de46 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -173,7 +173,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) snd_use_lock_init(&mdev->use_lock); /* copy and truncate the name of synth device */ - strlcpy(mdev->name, pinfo->name, sizeof(mdev->name)); + strscpy(mdev->name, pinfo->name, sizeof(mdev->name)); /* create MIDI coder */ if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) { @@ -647,7 +647,7 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info inf->device = dev; inf->dev_type = 0; /* FIXME: ?? */ inf->capabilities = 0; /* FIXME: ?? */ - strlcpy(inf->name, mdev->name, sizeof(inf->name)); + strscpy(inf->name, mdev->name, sizeof(inf->name)); snd_use_lock_free(&mdev->use_lock); return 0; } diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 11554d0412f0..136dc663887a 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -107,7 +107,7 @@ snd_seq_oss_synth_probe(struct device *_dev) snd_use_lock_init(&rec->use_lock); /* copy and truncate the name of synth device */ - strlcpy(rec->name, dev->name, sizeof(rec->name)); + strscpy(rec->name, dev->name, sizeof(rec->name)); /* registration */ spin_lock_irqsave(®ister_lock, flags); @@ -616,7 +616,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in inf->synth_subtype = 0; inf->nr_voices = 16; inf->device = dev; - strlcpy(inf->name, minf.name, sizeof(inf->name)); + strscpy(inf->name, minf.name, sizeof(inf->name)); } else { if ((rec = get_synthdev(dp, dev)) == NULL) return -ENXIO; @@ -624,7 +624,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in inf->synth_subtype = rec->synth_subtype; inf->nr_voices = rec->nr_voices; inf->device = dev; - strlcpy(inf->name, rec->name, sizeof(inf->name)); + strscpy(inf->name, rec->name, sizeof(inf->name)); snd_use_lock_free(&rec->use_lock); } return 0; diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index f9f2fea58b32..b6a24fb5e76b 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1584,7 +1584,7 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, info->queue = q->queue; info->owner = q->owner; info->locked = q->locked; - strlcpy(info->name, q->name, sizeof(info->name)); + strscpy(info->name, q->name, sizeof(info->name)); queuefree(q); return 0; diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 83be6b982a87..b9c2ce2b8d5a 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -327,7 +327,7 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port, /* set port name */ if (info->name[0]) - strlcpy(port->name, info->name, sizeof(port->name)); + strscpy(port->name, info->name, sizeof(port->name)); /* set capabilities */ port->capability = info->capability; @@ -356,7 +356,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port, return -EINVAL; /* get port name */ - strlcpy(info->name, port->name, sizeof(info->name)); + strscpy(info->name, port->name, sizeof(info->name)); /* get capabilities */ info->capability = port->capability; @@ -654,7 +654,7 @@ int snd_seq_event_port_attach(int client, /* Set up the port */ memset(&portinfo, 0, sizeof(portinfo)); portinfo.addr.client = client; - strlcpy(portinfo.name, portname ? portname : "Unnamed port", + strscpy(portinfo.name, portname ? portname : "Unnamed port", sizeof(portinfo.name)); portinfo.capability = cap; diff --git a/sound/core/timer.c b/sound/core/timer.c index 765ea66665a8..6898b1ac0d7f 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -959,7 +959,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, timer->tmr_device = tid->device; timer->tmr_subdevice = tid->subdevice; if (id) - strlcpy(timer->id, id, sizeof(timer->id)); + strscpy(timer->id, id, sizeof(timer->id)); timer->sticks = 1; INIT_LIST_HEAD(&timer->device_list); INIT_LIST_HEAD(&timer->open_list_head); @@ -1659,8 +1659,8 @@ static int snd_timer_user_ginfo(struct file *file, ginfo->card = t->card ? t->card->number : -1; if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(ginfo->id, t->id, sizeof(ginfo->id)); - strlcpy(ginfo->name, t->name, sizeof(ginfo->name)); + strscpy(ginfo->id, t->id, sizeof(ginfo->id)); + strscpy(ginfo->name, t->name, sizeof(ginfo->name)); ginfo->resolution = t->hw.resolution; if (t->hw.resolution_min > 0) { ginfo->resolution_min = t->hw.resolution_min; @@ -1814,8 +1814,8 @@ static int snd_timer_user_info(struct file *file, info->card = t->card ? t->card->number : -1; if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) info->flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(info->id, t->id, sizeof(info->id)); - strlcpy(info->name, t->name, sizeof(info->name)); + strscpy(info->id, t->id, sizeof(info->id)); + strscpy(info->name, t->name, sizeof(info->name)); info->resolution = t->hw.resolution; if (copy_to_user(_info, info, sizeof(*_info))) err = -EFAULT; diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 0103d16f6f9f..ee973b7b8044 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -61,8 +61,8 @@ static int snd_timer_user_info_compat(struct file *file, info.card = t->card ? t->card->number : -1; if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) info.flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(info.id, t->id, sizeof(info.id)); - strlcpy(info.name, t->name, sizeof(info.name)); + strscpy(info.id, t->id, sizeof(info.id)); + strscpy(info.name, t->name, sizeof(info.name)); info.resolution = t->hw.resolution; if (copy_to_user(_info, &info, sizeof(*_info))) return -EFAULT; diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 7bf0d5f3fedd..c82c7c1c0714 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -97,7 +97,7 @@ void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name) return; opl3->oss_seq_dev = dev; - strlcpy(dev->name, name, sizeof(dev->name)); + strscpy(dev->name, name, sizeof(dev->name)); arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); arg->type = SYNTH_TYPE_FM; if (opl3->hardware < OPL3_HW_OPL3) { diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 08c10ac9d6c8..97d30a833ac8 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -290,7 +290,7 @@ int snd_opl3_load_patch(struct snd_opl3 *opl3, } if (name) - strlcpy(patch->name, name, sizeof(patch->name)); + strscpy(patch->name, name, sizeof(patch->name)); return 0; } diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c index c362eb38ab90..8677e3ec8d14 100644 --- a/sound/firewire/bebob/bebob_hwdep.c +++ b/sound/firewire/bebob/bebob_hwdep.c @@ -80,7 +80,7 @@ hwdep_get_info(struct snd_bebob *bebob, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/dice/dice-hwdep.c b/sound/firewire/dice/dice-hwdep.c index f69f7996762f..ffc0b97782d6 100644 --- a/sound/firewire/dice/dice-hwdep.c +++ b/sound/firewire/dice/dice-hwdep.c @@ -79,7 +79,7 @@ static int hwdep_get_info(struct snd_dice *dice, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/digi00x/digi00x-hwdep.c b/sound/firewire/digi00x/digi00x-hwdep.c index 41c5857c612e..aadf7d724856 100644 --- a/sound/firewire/digi00x/digi00x-hwdep.c +++ b/sound/firewire/digi00x/digi00x-hwdep.c @@ -87,7 +87,7 @@ static int hwdep_get_info(struct snd_dg00x *dg00x, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/fireface/ff-hwdep.c b/sound/firewire/fireface/ff-hwdep.c index e73e8d2865a5..4b2e0dff5ddb 100644 --- a/sound/firewire/fireface/ff-hwdep.c +++ b/sound/firewire/fireface/ff-hwdep.c @@ -79,7 +79,7 @@ static int hwdep_get_info(struct snd_ff *ff, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c index e93eb4616c5f..626c0c34b0b6 100644 --- a/sound/firewire/fireworks/fireworks_hwdep.c +++ b/sound/firewire/fireworks/fireworks_hwdep.c @@ -212,7 +212,7 @@ hwdep_get_info(struct snd_efw *efw, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/motu/motu-hwdep.c b/sound/firewire/motu/motu-hwdep.c index 0764a477052a..b5ced5d27758 100644 --- a/sound/firewire/motu/motu-hwdep.c +++ b/sound/firewire/motu/motu-hwdep.c @@ -86,7 +86,7 @@ static int hwdep_get_info(struct snd_motu *motu, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/oxfw/oxfw-hwdep.c b/sound/firewire/oxfw/oxfw-hwdep.c index eba33d050060..9e1b3e151bad 100644 --- a/sound/firewire/oxfw/oxfw-hwdep.c +++ b/sound/firewire/oxfw/oxfw-hwdep.c @@ -79,7 +79,7 @@ static int hwdep_get_info(struct snd_oxfw *oxfw, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 6f38335fe10b..74eed9505665 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -154,7 +154,7 @@ static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index a684faa771ef..847e3b6ca601 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c @@ -84,7 +84,7 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name, list_add_tail(&bus->buses, &master->buses); bus->master = master; } - strlcpy(bus->name, name, sizeof(bus->name)); + strscpy(bus->name, name, sizeof(bus->name)); err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops); if (err < 0) { snd_i2c_bus_free(bus); @@ -108,7 +108,7 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, if (device == NULL) return -ENOMEM; device->addr = addr; - strlcpy(device->name, name, sizeof(device->name)); + strscpy(device->name, name, sizeof(device->name)); list_add_tail(&device->list, &bus->devices); device->bus = bus; *rdevice = device; diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 593c6e959afe..47bffe623105 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -95,8 +95,8 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n) if (error < 0) goto out; - strlcpy(card->driver, "AD1848", sizeof(card->driver)); - strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); + strscpy(card->driver, "AD1848", sizeof(card->driver)); + strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); if (!thinkpad[n]) snprintf(card->longname, sizeof(card->longname), diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index 2135963eba78..bcbea6962d7e 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -95,8 +95,8 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n) if (error < 0) goto out; - strlcpy(card->driver, "CS4231", sizeof(card->driver)); - strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); + strscpy(card->driver, "CS4231", sizeof(card->driver)); + strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); if (dma2[n] < 0) snprintf(card->longname, sizeof(card->longname), diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index fa3c39cff5f8..fb9d8a4b7084 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -405,8 +405,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) if (err < 0) return err; } - strlcpy(card->driver, chip->pcm->name, sizeof(card->driver)); - strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); + strscpy(card->driver, chip->pcm->name, sizeof(card->driver)); + strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); if (dma2[dev] < 0) snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx, irq %i, dma %i", diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 64610571a5e1..766ab43aaf77 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -133,8 +133,8 @@ static int snd_es1688_probe(struct snd_card *card, unsigned int n) if (error < 0) return error; - strlcpy(card->driver, "ES1688", sizeof(card->driver)); - strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); + strscpy(card->driver, "ES1688", sizeof(card->driver)); + strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port, chip->irq, chip->dma8); diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 270af863e198..8635a2b6b36b 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -388,7 +388,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, return err; /* fill in codec header */ - strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name)); + strscpy(p->codec_name, info.codec_name, sizeof(p->codec_name)); p->func_nr = func_nr; p->mode = le16_to_cpu(funcdesc_h.flags_play_rec); switch (le16_to_cpu(funcdesc_h.VOC_type)) { diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 3f703b4a304d..5de5506e7e60 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -482,7 +482,7 @@ int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int ty ctl = snd_ctl_new1(&newctls[type], chip); if (! ctl) return -ENOMEM; - strlcpy(ctl->id.name, name, sizeof(ctl->id.name)); + strscpy(ctl->id.name, name, sizeof(ctl->id.name)); ctl->id.index = index; ctl->private_value = value; if ((err = snd_ctl_add(chip->card, ctl)) < 0) diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index 38f25e97538f..49679aa8631d 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -355,8 +355,8 @@ static int mixer_ioctl(struct file *file, u_int cmd, u_long arg) { mixer_info info; memset(&info, 0, sizeof(info)); - strlcpy(info.id, dmasound.mach.name2, sizeof(info.id)); - strlcpy(info.name, dmasound.mach.name2, sizeof(info.name)); + strscpy(info.id, dmasound.mach.name2, sizeof(info.id)); + strscpy(info.name, dmasound.mach.name2, sizeof(info.name)); info.modify_counter = mixer.modify_counter; if (copy_to_user((void __user *)arg, &info, sizeof(info))) return -EFAULT; diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c index 4e295303b041..110d3209441b 100644 --- a/sound/pci/cs5535audio/cs5535audio_olpc.c +++ b/sound/pci/cs5535audio/cs5535audio_olpc.c @@ -158,13 +158,13 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) /* drop the original AD1888 HPF control */ memset(&elem, 0, sizeof(elem)); elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strlcpy(elem.name, "High Pass Filter Enable", sizeof(elem.name)); + strscpy(elem.name, "High Pass Filter Enable", sizeof(elem.name)); snd_ctl_remove_id(card, &elem); /* drop the original V_REFOUT control */ memset(&elem, 0, sizeof(elem)); elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strlcpy(elem.name, "V_REFOUT Enable", sizeof(elem.name)); + strscpy(elem.name, "V_REFOUT Enable", sizeof(elem.name)); snd_ctl_remove_id(card, &elem); /* add the OLPC-specific controls */ diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 3f48ad0e27e7..81dfc6a76b18 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -433,7 +433,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc, pcm->private_data = atc; pcm->info_flags = 0; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strlcpy(pcm->name, device_name, sizeof(pcm->name)); + strscpy(pcm->name, device_name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops); diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 29b7720d7961..353934c88cbd 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -168,9 +168,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, } #endif - strlcpy(card->driver, emu->card_capabilities->driver, + strscpy(card->driver, emu->card_capabilities->driver, sizeof(card->driver)); - strlcpy(card->shortname, emu->card_capabilities->name, + strscpy(card->shortname, emu->card_capabilities->name, sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index bd70e112ffd7..24a2fd706d69 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1869,7 +1869,7 @@ int snd_emu10k1_create(struct snd_card *card, emu->serial); if (!*card->id && c->id) - strlcpy(card->id, c->id, sizeof(card->id)); + strscpy(card->id, c->id, sizeof(card->id)); is_audigy = emu->audigy = c->emu10k2_chip; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 4e76ed0e91d5..80ef62a4a7c0 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -940,7 +940,7 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, memset(gctl, 0, sizeof(*gctl)); id = &ctl->kcontrol->id; gctl->id.iface = (__force int)id->iface; - strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name)); + strscpy(gctl->id.name, id->name, sizeof(gctl->id.name)); gctl->id.index = id->index; gctl->id.device = id->device; gctl->id.subdevice = id->subdevice; @@ -976,7 +976,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, err = snd_emu10k1_verify_controls(emu, icode, in_kernel); if (err < 0) goto __error; - strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); + strscpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); /* stop FX processor - this may be dangerous, but it's better to miss some samples than generate wrong ones - [jk] */ if (emu->audigy) @@ -1015,7 +1015,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, int err; mutex_lock(&emu->fx8010.lock); - strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); + strscpy(icode->name, emu->fx8010.name, sizeof(icode->name)); /* ok, do the main job */ err = snd_emu10k1_gpr_peek(emu, icode); if (err >= 0) diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 34332d008b27..c6be14c4f311 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2768,7 +2768,7 @@ static int snd_es1968_create(struct snd_card *card, if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) { dev_info(card->dev, "detected TEA575x radio type %s\n", get_tea575x_gpio(chip)->name); - strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name, + strscpy(chip->tea.card, get_tea575x_gpio(chip)->name, sizeof(chip->tea.card)); break; } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 0a95032fd297..c6ad6235a669 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1300,7 +1300,7 @@ static int snd_fm801_create(struct snd_card *card, chip->tea575x_tuner |= tuner_only; } if (!(chip->tea575x_tuner & TUNER_DISABLED)) { - strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name, + strscpy(chip->tea.card, get_tea575x_gpio(chip)->name, sizeof(chip->tea.card)); } #endif diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 4dc01647753c..1a001ecf7f63 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -764,7 +764,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, } if (!name) return 0; - strlcpy(label, name, maxlen); + strscpy(label, name, maxlen); return 1; } EXPORT_SYMBOL_GPL(snd_hda_get_pin_label); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 687216e74526..bc3b51eb8390 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4009,7 +4009,7 @@ int snd_hda_add_imux_item(struct hda_codec *codec, sizeof(imux->items[imux->num_items].label), "%s %d", label, label_idx); else - strlcpy(imux->items[imux->num_items].label, label, + strscpy(imux->items[imux->num_items].label, label, sizeof(imux->items[imux->num_items].label)); imux->items[imux->num_items].index = index; imux->num_items++; diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 80016b7b6849..9087981cd1f7 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -735,7 +735,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, &pcm); if (err < 0) return err; - strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); + strscpy(pcm->name, cpcm->name, sizeof(pcm->name)); apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); if (apcm == NULL) { snd_device_free(chip->card, pcm); diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 136477ed46ae..9e97443795f8 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -260,7 +260,7 @@ int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, codec_info(codec, "HDMI: out of range MNL %d\n", mnl); goto out_fail; } else - strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); + strscpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); for (i = 0; i < e->sad_count; i++) { if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 8060cc86dfea..5e40944e7342 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -5721,7 +5721,7 @@ static void fill_pcm_stream_name(char *str, size_t len, const char *sfx, if (*str) return; - strlcpy(str, chip_name, len); + strscpy(str, chip_name, len); /* drop non-alnum chars after a space */ for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) { diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 770ad25f1907..694d95e3a46e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2037,7 +2037,7 @@ static int azx_first_init(struct azx *chip) return -EBUSY; strcpy(card->driver, "HDA-Intel"); - strlcpy(card->shortname, driver_short_names[chip->driver_type], + strscpy(card->shortname, driver_short_names[chip->driver_type], sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 588059428d8f..b8b568046592 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -530,7 +530,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, !is_jack_detectable(codec, nid); if (base_name) - strlcpy(name, base_name, sizeof(name)); + strscpy(name, base_name, sizeof(name)); else snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL); if (phantom_jack) diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index e57a55cebc5a..f0f8324b08b6 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -413,7 +413,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card, { struct snd_ctl_elem_id sid = {0}; - strlcpy(sid.name, name, sizeof(sid.name)); + strscpy(sid.name, name, sizeof(sid.name)); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; return snd_ctl_find_id(card, &sid); } diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c index 7aa3f92040d0..82cf365cda10 100644 --- a/sound/pci/ice1712/psc724.c +++ b/sound/pci/ice1712/psc724.c @@ -189,12 +189,12 @@ static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected) /* notify about master speaker mute change */ memset(&elem_id, 0, sizeof(elem_id)); elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strlcpy(elem_id.name, "Master Speakers Playback Switch", + strscpy(elem_id.name, "Master Speakers Playback Switch", sizeof(elem_id.name)); kctl = snd_ctl_find_id(ice->card, &elem_id); snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); /* and headphone mute change */ - strlcpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name, + strscpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name, sizeof(elem_id.name)); kctl = snd_ctl_find_id(ice->card, &elem_id); snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index 0e3e04aa9faf..0dfa093f7dca 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c @@ -771,7 +771,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card, { struct snd_ctl_elem_id sid = {0}; - strlcpy(sid.name, name, sizeof(sid.name)); + strscpy(sid.name, name, sizeof(sid.name)); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; return snd_ctl_find_id(card, &sid); } diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c index d96008df880d..6eda86119dff 100644 --- a/sound/pci/ice1712/wm8776.c +++ b/sound/pci/ice1712/wm8776.c @@ -38,7 +38,7 @@ static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm, unsigned int index_offset; memset(&elem_id, 0, sizeof(elem_id)); - strlcpy(elem_id.name, ctl_name, sizeof(elem_id.name)); + strscpy(elem_id.name, ctl_name, sizeof(elem_id.name)); elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; kctl = snd_ctl_find_id(card, &elem_id); if (!kctl) diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index cdd8db79bcfa..491c90f83fbc 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -669,7 +669,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, } strcpy(card->driver, "Lola"); - strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname)); + strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", card->shortname, chip->bar[0].addr, chip->irq); diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index f647c7ed00c4..684faaf40f31 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c @@ -601,7 +601,7 @@ int lola_create_pcm(struct lola *chip) &pcm); if (err < 0) return err; - strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name)); + strscpy(pcm->name, "Digigram Lola", sizeof(pcm->name)); pcm->private_data = chip; for (i = 0; i < 2; i++) { if (chip->pcm[i].num_streams) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 04e878a0f773..b66711574b1a 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6329,7 +6329,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, memset(&hdspm_version, 0, sizeof(hdspm_version)); hdspm_version.card_type = hdspm->io_type; - strlcpy(hdspm_version.cardname, hdspm->card_name, + strscpy(hdspm_version.cardname, hdspm->card_name, sizeof(hdspm_version.cardname)); hdspm_version.serial = hdspm->serial; hdspm_version.firmware_rev = hdspm->firmware_rev; diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 9554a0c506af..a6c1905039de 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -49,7 +49,7 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) return -EINVAL; /* ignored */ memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "keywest", I2C_NAME_SIZE); + strscpy(info.type, "keywest", I2C_NAME_SIZE); info.addr = keywest_ctx->addr; client = i2c_new_client_device(adapter, &info); if (IS_ERR(client)) diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index daa58b5f941e..cad1cd1bfdf0 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -1707,7 +1707,7 @@ int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, pkt->hdr.token = hw_block_id; pkt->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST; vote_cfg->hw_block_id = hw_block_id; - strlcpy(vote_cfg->client_name, client_name, + strscpy(vote_cfg->client_name, client_name, sizeof(vote_cfg->client_name)); ret = afe_apr_send_pkt(afe, pkt, NULL, diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 6e670b3e92a0..6dd5659db44c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1472,7 +1472,7 @@ static int rsnd_kctrl_info(struct snd_kcontrol *kctrl, uinfo->value.enumerated.items = cfg->max; if (uinfo->value.enumerated.item >= cfg->max) uinfo->value.enumerated.item = cfg->max - 1; - strlcpy(uinfo->value.enumerated.name, + strscpy(uinfo->value.enumerated.name, cfg->texts[uinfo->value.enumerated.item], sizeof(uinfo->value.enumerated.name)); } else { diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c index 010976d9ceb2..cd4a0bc6d278 100644 --- a/sound/usb/bcd2000/bcd2000.c +++ b/sound/usb/bcd2000/bcd2000.c @@ -300,7 +300,7 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k) if (ret < 0) return ret; - strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name)); + strscpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name)); rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; rmidi->private_data = bcd2k; diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 3b6bb2cbe886..4981753652a7 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -804,7 +804,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) } cdev->pcm->private_data = cdev; - strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name)); + strscpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name)); memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 2af3b7eb0a88..e03481caf7f6 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -477,9 +477,9 @@ static int init_card(struct snd_usb_caiaqdev *cdev) usb_string(usb_dev, usb_dev->descriptor.iProduct, cdev->product_name, CAIAQ_USB_STR_LEN); - strlcpy(card->driver, MODNAME, sizeof(card->driver)); - strlcpy(card->shortname, cdev->product_name, sizeof(card->shortname)); - strlcpy(card->mixername, cdev->product_name, sizeof(card->mixername)); + strscpy(card->driver, MODNAME, sizeof(card->driver)); + strscpy(card->shortname, cdev->product_name, sizeof(card->shortname)); + strscpy(card->mixername, cdev->product_name, sizeof(card->mixername)); /* if the id was not passed as module option, fill it with a shortened * version of the product string which does not contain any diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c index 512fbb3ee604..c656d0162432 100644 --- a/sound/usb/caiaq/midi.c +++ b/sound/usb/caiaq/midi.c @@ -125,7 +125,7 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) if (ret < 0) return ret; - strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name)); + strscpy(rmidi->name, device->product_name, sizeof(rmidi->name)); rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; rmidi->private_data = device; diff --git a/sound/usb/card.c b/sound/usb/card.c index d731ca62d599..85e79b9ecb08 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -474,7 +474,7 @@ static void usb_audio_make_shortname(struct usb_device *dev, else if (quirk && quirk->product_name) s = quirk->product_name; if (s && *s) { - strlcpy(card->shortname, s, sizeof(card->shortname)); + strscpy(card->shortname, s, sizeof(card->shortname)); return; } @@ -506,7 +506,7 @@ static void usb_audio_make_longname(struct usb_device *dev, if (preset && preset->profile_name) s = preset->profile_name; if (s && *s) { - strlcpy(card->longname, s, sizeof(card->longname)); + strscpy(card->longname, s, sizeof(card->longname)); return; } diff --git a/sound/usb/hiface/chip.c b/sound/usb/hiface/chip.c index b2d9623e9934..c2824188d142 100644 --- a/sound/usb/hiface/chip.c +++ b/sound/usb/hiface/chip.c @@ -80,12 +80,12 @@ static int hiface_chip_create(struct usb_interface *intf, return ret; } - strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); + strscpy(card->driver, DRIVER_NAME, sizeof(card->driver)); if (quirk && quirk->device_name) - strlcpy(card->shortname, quirk->device_name, sizeof(card->shortname)); + strscpy(card->shortname, quirk->device_name, sizeof(card->shortname)); else - strlcpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname)); + strscpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname)); strlcat(card->longname, card->shortname, sizeof(card->longname)); len = strlcat(card->longname, " at ", sizeof(card->longname)); diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index d942179ca095..71f17f02f341 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -594,7 +594,7 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq) pcm->private_data = rt; pcm->private_free = hiface_pcm_free; - strlcpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name)); + strscpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 412fcd817ecc..85fed017710e 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1556,7 +1556,7 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, if (!found) return; - strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name)); + strscpy(kctl->id.name, "Headphone", sizeof(kctl->id.name)); } static const struct usb_feature_control_info *get_feature_control_info(int control) @@ -1691,7 +1691,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer, break; default: if (!len) - strlcpy(kctl->id.name, audio_feature_info[control-1].name, + strscpy(kctl->id.name, audio_feature_info[control-1].name, sizeof(kctl->id.name)); break; } @@ -1770,7 +1770,7 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer, int name_len = get_term_name(mixer->chip, term, name, name_size, 0); if (name_len == 0) - strlcpy(name, "Unknown", name_size); + strscpy(name, "Unknown", name_size); /* * sound/core/ctljack.c has a convention of naming jack controls @@ -2490,7 +2490,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) { /* nothing */ ; } else if (info->name) { - strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); + strscpy(kctl->id.name, info->name, sizeof(kctl->id.name)); } else { if (extension_unit) nameid = uac_extension_unit_iExtension(desc, state->mixer->protocol); @@ -2503,7 +2503,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, kctl->id.name, sizeof(kctl->id.name)); if (!len) - strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); + strscpy(kctl->id.name, name, sizeof(kctl->id.name)); } append_ctl_name(kctl, " "); append_ctl_name(kctl, valinfo->suffix); @@ -2743,7 +2743,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, kctl->id.name, sizeof(kctl->id.name), 0); /* ... or use the fixed string "USB" as the last resort */ if (!len) - strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); + strscpy(kctl->id.name, "USB", sizeof(kctl->id.name)); /* and add the proper suffix */ if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR || diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index df036a359f2f..abad1d61a536 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2725,7 +2725,7 @@ static int snd_pioneer_djm_controls_info(struct snd_kcontrol *kctl, struct snd_c if (info->value.enumerated.item >= count) info->value.enumerated.item = count - 1; name = group->options[info->value.enumerated.item].name; - strlcpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name)); + strscpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name)); info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; info->count = 1; info->value.enumerated.items = count; diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c index 49fcd2505443..691b95466d0f 100644 --- a/sound/usb/mixer_scarlett.c +++ b/sound/usb/mixer_scarlett.c @@ -569,7 +569,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer, } kctl->private_free = snd_usb_mixer_elem_free; - strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); + strscpy(kctl->id.name, name, sizeof(kctl->id.name)); err = snd_usb_mixer_add_control(&elem->head, kctl); if (err < 0) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 4bbec56c7df3..560c2ade829d 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -961,7 +961,7 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, } kctl->private_free = snd_usb_mixer_elem_free; - strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); + strscpy(kctl->id.name, name, sizeof(kctl->id.name)); err = snd_usb_mixer_add_control(&elem->head, kctl); if (err < 0) diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index bd63a9ce6a70..b7b6f3834ed5 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -1076,7 +1076,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer, else kctl->private_free = snd_usb_mixer_elem_free; - strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); + strscpy(kctl->id.name, name, sizeof(kctl->id.name)); err = snd_usb_mixer_add_control(&elem->head, kctl); if (err < 0) diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 9f9fcd2749f2..5b351f4ca543 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1790,7 +1790,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) /* setup private data which can be retrieved when required */ pcm->private_data = ctx; pcm->info_flags = 0; - strlcpy(pcm->name, card->shortname, strlen(card->shortname)); + strscpy(pcm->name, card->shortname, strlen(card->shortname)); /* setup the ops for playabck */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); diff --git a/sound/xen/xen_snd_front_cfg.c b/sound/xen/xen_snd_front_cfg.c index eda077c8087a..63b0398c3276 100644 --- a/sound/xen/xen_snd_front_cfg.c +++ b/sound/xen/xen_snd_front_cfg.c @@ -398,7 +398,7 @@ static int cfg_device(struct xen_snd_front_info *front_info, str = xenbus_read(XBT_NIL, device_path, XENSND_FIELD_DEVICE_NAME, NULL); if (!IS_ERR(str)) { - strlcpy(pcm_instance->name, str, sizeof(pcm_instance->name)); + strscpy(pcm_instance->name, str, sizeof(pcm_instance->name)); kfree(str); } -- cgit v1.2.3 From 31c51a424f5163ee6f14fcc251f81078457123e1 Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Fri, 8 Jan 2021 08:58:34 +0000 Subject: ASoC: es8328: Remove redundant null check before clk_disable_unprepare Because clk_disable_unprepare() already checked NULL clock parameter, so the additional check is unnecessary, just remove it. Signed-off-by: Xu Wang Link: https://lore.kernel.org/r/20210108085834.7168-1-vulab@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/codecs/es8328.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 7e26231a596a..b537300d0ce8 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -809,8 +809,7 @@ static void es8328_remove(struct snd_soc_component *component) es8328 = snd_soc_component_get_drvdata(component); - if (es8328->clk) - clk_disable_unprepare(es8328->clk); + clk_disable_unprepare(es8328->clk); regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), es8328->supplies); -- cgit v1.2.3 From 11b943c06a1c1baafb0325896e666d77f5ac78b8 Mon Sep 17 00:00:00 2001 From: Michael Sit Wei Hong Date: Fri, 8 Jan 2021 11:12:48 +0800 Subject: ASoC: Intel: KMB: Enable DMA transfer mode Enable DMA transfer mode for Intel Keem Bay ASoC platform driver. The driver will search the device tree for DMA resources at boot time to enable DMA transfer mode, and will proceed to use DMA transfer if the resource is available, otherwise the default PIO mode will be used. Signed-off-by: Michael Sit Wei Hong Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210108031248.20520-6-michael.wei.hong.sit@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 2 + sound/soc/intel/keembay/kmb_platform.c | 157 +++++++++++++++++++++++++++++---- sound/soc/intel/keembay/kmb_platform.h | 9 ++ 3 files changed, 153 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 0c6404fc12b3..f3a4a907b29d 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -203,6 +203,8 @@ config SND_SOC_INTEL_KEEMBAY tristate "Keembay Platforms" depends on ARCH_KEEMBAY || COMPILE_TEST depends on COMMON_CLK + select SND_DMAENGINE_PCM + select SND_SOC_GENERIC_DMAENGINE_PCM help If you have a Intel Keembay platform then enable this option by saying Y or m. diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 1c3748f33136..4961ba89c110 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -6,10 +6,12 @@ // #include +#include #include #include #include #include +#include #include #include #include @@ -343,6 +345,53 @@ static const struct snd_soc_component_driver kmb_component = { .pointer = kmb_pcm_pointer, }; +static const struct snd_soc_component_driver kmb_component_dma = { + .name = "kmb", +}; + +static int kmb_probe(struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + + if (kmb_i2s->use_pio) + return 0; + + snd_soc_dai_init_dma_data(cpu_dai, &kmb_i2s->play_dma_data, + &kmb_i2s->capture_dma_data); + + return 0; +} + +static inline void kmb_i2s_enable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream) +{ + u32 dma_reg; + + dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR); + /* Enable DMA handshake for stream */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_reg |= I2S_DMAEN_TXBLOCK; + else + dma_reg |= I2S_DMAEN_RXBLOCK; + + writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR); +} + +static inline void kmb_i2s_disable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream) +{ + u32 dma_reg; + + dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR); + /* Disable DMA handshake for stream */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_reg &= ~I2S_DMAEN_TXBLOCK; + writel(1, kmb_i2s->i2s_base + I2S_RTXDMA); + } else { + dma_reg &= ~I2S_DMAEN_RXBLOCK; + writel(1, kmb_i2s->i2s_base + I2S_RRXDMA); + } + writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR); +} + static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s, struct snd_pcm_substream *substream) { @@ -356,7 +405,11 @@ static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s, else writel(1, kmb_i2s->i2s_base + IRER); - kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true); + if (kmb_i2s->use_pio) + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, + config->chan_nr, true); + else + kmb_i2s_enable_dma(kmb_i2s, substream->stream); if (kmb_i2s->clock_provider) writel(1, kmb_i2s->i2s_base + CER); @@ -434,7 +487,8 @@ static int kmb_dai_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_STOP: kmb_i2s->active--; - kmb_i2s_stop(kmb_i2s, substream); + if (kmb_i2s->use_pio) + kmb_i2s_stop(kmb_i2s, substream); break; default: return -EINVAL; @@ -485,16 +539,22 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, config->data_width = 16; kmb_i2s->ccr = 0x00; kmb_i2s->xfer_resolution = 0x02; + kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case SNDRV_PCM_FORMAT_S24_LE: config->data_width = 32; kmb_i2s->ccr = 0x14; kmb_i2s->xfer_resolution = 0x05; + kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; kmb_i2s->ccr = 0x10; kmb_i2s->xfer_resolution = 0x05; + kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; default: dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt"); @@ -572,9 +632,56 @@ static int kmb_dai_prepare(struct snd_pcm_substream *substream, return 0; } +static int kmb_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + struct snd_dmaengine_dai_dma_data *dma_data; + + if (kmb_i2s->use_pio) + return 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_data = &kmb_i2s->play_dma_data; + else + dma_data = &kmb_i2s->capture_dma_data; + + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); + + return 0; +} + +static int kmb_dai_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */ + if (kmb_i2s->use_pio) + kmb_i2s_clear_irqs(kmb_i2s, substream->stream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(0, kmb_i2s->i2s_base + ITER); + else + writel(0, kmb_i2s->i2s_base + IRER); + + if (kmb_i2s->use_pio) + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false); + else + kmb_i2s_disable_dma(kmb_i2s, substream->stream); + + if (!kmb_i2s->active) { + writel(0, kmb_i2s->i2s_base + CER); + writel(0, kmb_i2s->i2s_base + IER); + } + + return 0; +} + static struct snd_soc_dai_ops kmb_dai_ops = { + .startup = kmb_dai_startup, .trigger = kmb_dai_trigger, .hw_params = kmb_dai_hw_params, + .hw_free = kmb_dai_hw_free, .prepare = kmb_dai_prepare, .set_fmt = kmb_set_dai_fmt, }; @@ -607,6 +714,7 @@ static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = { SNDRV_PCM_FMTBIT_S16_LE), }, .ops = &kmb_dai_ops, + .probe = kmb_probe, }, }; @@ -626,6 +734,7 @@ static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = { SNDRV_PCM_FMTBIT_S16_LE), }, .ops = &kmb_dai_ops, + .probe = kmb_probe, }, }; @@ -637,10 +746,12 @@ static const struct of_device_id kmb_plat_of_match[] = { static int kmb_plat_dai_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct snd_soc_dai_driver *kmb_i2s_dai; const struct of_device_id *match; struct device *dev = &pdev->dev; struct kmb_i2s_info *kmb_i2s; + struct resource *res; int ret, irq; u32 comp1_reg; @@ -682,7 +793,7 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) return PTR_ERR(kmb_i2s->clk_i2s); } - kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0); + kmb_i2s->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(kmb_i2s->i2s_base)) return PTR_ERR(kmb_i2s->i2s_base); @@ -692,22 +803,38 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) kmb_i2s->dev = &pdev->dev; - irq = platform_get_irq_optional(pdev, 0); - if (irq > 0) { - ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0, - pdev->name, kmb_i2s); - if (ret < 0) { - dev_err(dev, "failed to request irq\n"); - return ret; - } - } - comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1); kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2; - ret = devm_snd_soc_register_component(dev, &kmb_component, - kmb_i2s_dai, 1); + kmb_i2s->use_pio = !(of_property_read_bool(np, "dmas")); + + if (kmb_i2s->use_pio) { + irq = platform_get_irq_optional(pdev, 0); + if (irq > 0) { + ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0, + pdev->name, kmb_i2s); + if (ret < 0) { + dev_err(dev, "failed to request irq\n"); + return ret; + } + } + ret = devm_snd_soc_register_component(dev, &kmb_component, + kmb_i2s_dai, 1); + } else { + kmb_i2s->play_dma_data.addr = res->start + I2S_TXDMA; + kmb_i2s->capture_dma_data.addr = res->start + I2S_RXDMA; + ret = snd_dmaengine_pcm_register(&pdev->dev, + NULL, 0); + if (ret) { + dev_err(&pdev->dev, "could not register dmaengine: %d\n", + ret); + return ret; + } + ret = devm_snd_soc_register_component(dev, &kmb_component_dma, + kmb_i2s_dai, 1); + } + if (ret) { dev_err(dev, "not able to register dai\n"); return ret; diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h index 0c393e5916b6..67234caee814 100644 --- a/sound/soc/intel/keembay/kmb_platform.h +++ b/sound/soc/intel/keembay/kmb_platform.h @@ -12,6 +12,7 @@ #include #include #include +#include /* Register values with reference to KMB databook v1.1 */ /* common register for all channel */ @@ -103,7 +104,12 @@ #define DW_I2S_PROVIDER BIT(3) #define I2S_RXDMA 0x01C0 +#define I2S_RRXDMA 0x01C4 #define I2S_TXDMA 0x01C8 +#define I2S_RTXDMA 0x01CC +#define I2S_DMACR 0x0200 +#define I2S_DMAEN_RXBLOCK (1 << 16) +#define I2S_DMAEN_TXBLOCK (1 << 17) /* * struct i2s_clk_config_data - represent i2s clk configuration data @@ -131,6 +137,9 @@ struct kmb_i2s_info { u32 xfer_resolution; u32 fifo_th; bool clock_provider; + /* data related to DMA transfers b/w i2s and DMAC */ + struct snd_dmaengine_dai_dma_data play_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; struct i2s_clk_config_data config; int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); -- cgit v1.2.3 From 9ddaa1e6181b3d33080f2ed7c27cb0bba819e562 Mon Sep 17 00:00:00 2001 From: Michael Sit Wei Hong Date: Fri, 8 Jan 2021 11:12:47 +0800 Subject: ASoC: intel, keembay-i2s: Add info for device to use DMA Add descriptions for entries needed for audio device to use DMA channels for audio playback and capture. Signed-off-by: Michael Sit Wei Hong Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210108031248.20520-5-michael.wei.hong.sit@intel.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/intel,keembay-i2s.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index d346e61ab708..e0658f122cbb 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -45,6 +45,18 @@ properties: - const: osc - const: apb_clk + dmas: + items: + - description: DMA controller phandle and DMA channel + for TX and RX + + dma-names: + items: + - description: "tx" for the transmit channel + "rx" for the receive channel + - const: tx + - const: rx + required: - compatible - "#sound-dai-cells" @@ -70,4 +82,6 @@ examples: interrupts = ; clock-names = "osc", "apb_clk"; clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>; + dmas = <&axi_dma0 29 &axi_dma0 33>; + dma-names = "tx", "rx"; }; -- cgit v1.2.3 From 21f603482a6bdc4e7481f5a8e0e4b654d8d6e3a3 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Mon, 11 Jan 2021 13:41:38 +0800 Subject: ASoC: rt5645: Introduce mapping for ACPI-defined GPIO On at least one laptop (ECS EF20EA) the 'hp-detect' GPIO is defined in the DSDT table by the ACPI GpioIo resources in _CRS. The GPIO related information should be mapped to the rt5645 driver to enable the jack detection also on non-DT platforms. Signed-off-by: Chris Chiu Link: https://lore.kernel.org/r/20210111054141.4668-2-chiu@endlessos.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 1c9e61abda30..33f277678223 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -42,6 +42,8 @@ static unsigned int quirk = -1; module_param(quirk, uint, 0444); MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override"); +static const struct acpi_gpio_mapping *cht_rt5645_gpios; + #define RT5645_DEVICE_ID 0x6308 #define RT5650_DEVICE_ID 0x6419 @@ -3831,6 +3833,10 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk); } + if (cht_rt5645_gpios && has_acpi_companion(&i2c->dev)) + if (devm_acpi_dev_add_driver_gpios(&i2c->dev, cht_rt5645_gpios)) + dev_dbg(&i2c->dev, "Failed to add driver gpios\n"); + rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", GPIOD_IN); -- cgit v1.2.3 From a4dae468cfdd90cdb08d96161482c23739dd636a Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Mon, 11 Jan 2021 13:41:39 +0800 Subject: ASoC: rt5645: Add ACPI-defined GPIO for ECS EF20 series Add the hp-detect gpio for ECS EF20 series laptops based on the _CRS defined in DSDT table. Method (_CRS, 0, NotSerialized) { Name (SBUF, ResourceTemplate () { I2cSerialBusV2 (0x001A, ControllerInitiated, 0x00061A80, AddressingMode7Bit, "\\_SB.PCI0.I2C2", 0x00, ResourceConsumer, , Exclusive, ) GpioInt (Edge, ActiveBoth, SharedAndWake, PullNone, 0x0000, "\\_SB.GPO3", 0x00, ResourceConsumer, , ) { // Pin list 0x004F } GpioIo (Shared, PullDefault, 0x0000, 0x0000, IoRestrictionInputOnly, "\\_SB.GPO3", 0x00, ResourceConsumer, , ) { // Pin list 0x004F } }) Return (SBUF) /* \_SB_.PCI0.I2C2.RTK2._CRS.SBUF */ } Signed-off-by: Chris Chiu Link: https://lore.kernel.org/r/20210111054141.4668-3-chiu@endlessos.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 33f277678223..f830a463f9b9 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3636,6 +3636,19 @@ static const struct rt5645_platform_data kahlee_platform_data = { .jd_mode = 3, }; +static const struct acpi_gpio_params ef20_hp_detect = { 1, 0, false }; + +static const struct acpi_gpio_mapping cht_rt5645_ef20_gpios[] = { + { "hp-detect-gpios", &ef20_hp_detect, 1 }, + { }, +}; + +static int cht_rt5645_ef20_quirk_cb(const struct dmi_system_id *id) +{ + cht_rt5645_gpios = cht_rt5645_ef20_gpios; + return 1; +} + static const struct dmi_system_id dmi_platform_data[] = { { .ident = "Chrome Buddy", @@ -3765,6 +3778,20 @@ static const struct dmi_system_id dmi_platform_data[] = { }, .driver_data = (void *)&intel_braswell_platform_data, }, + { + .ident = "EF20", + .callback = cht_rt5645_ef20_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20"), + }, + }, + { + .ident = "EF20EA", + .callback = cht_rt5645_ef20_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), + }, + }, { } }; -- cgit v1.2.3 From 28c988492cf65626d06ae32d7f20f1596c080667 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Mon, 11 Jan 2021 13:41:40 +0800 Subject: ASoC: rt5645: add inv_hp_det flag The ECS EF20EA laptop use gpio for jack detection instead of rt5645 rt5645 JD. However, the GPIO polarity is inverse for hp-detect based on the _DSD property of the RTK2 device. Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () {"hp-detect-gpio", Package() {^RTK2, 0, 0, 1 }}, } }) This flag will invert the hp-detect gpio polarity. Signed-off-by: Chris Chiu Link: https://lore.kernel.org/r/20210111054141.4668-4-chiu@endlessos.org Signed-off-by: Mark Brown --- include/sound/rt5645.h | 2 ++ sound/soc/codecs/rt5645.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index 39a77c7cea36..710c95be5509 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h @@ -22,6 +22,8 @@ struct rt5645_platform_data { bool level_trigger_irq; /* Invert JD1_1 status polarity */ bool inv_jd1_1; + /* Invert HP detect status polarity */ + bool inv_hp_pol; /* Value to asign to snd_soc_card.long_name */ const char *long_name; diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index f830a463f9b9..aaeb10c59334 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -34,6 +34,7 @@ #define QUIRK_INV_JD1_1(q) ((q) & 1) #define QUIRK_LEVEL_IRQ(q) (((q) >> 1) & 1) #define QUIRK_IN2_DIFF(q) (((q) >> 2) & 1) +#define QUIRK_INV_HP_POL(q) (((q) >> 3) & 1) #define QUIRK_JD_MODE(q) (((q) >> 4) & 7) #define QUIRK_DMIC1_DATA_PIN(q) (((q) >> 8) & 3) #define QUIRK_DMIC2_DATA_PIN(q) (((q) >> 12) & 3) @@ -3246,6 +3247,8 @@ static void rt5645_jack_detect_work(struct work_struct *work) case 0: /* Not using rt5645 JD */ if (rt5645->gpiod_hp_det) { gpio_state = gpiod_get_value(rt5645->gpiod_hp_det); + if (rt5645->pdata.inv_hp_pol) + gpio_state ^= 1; dev_dbg(rt5645->component->dev, "gpio_state = %d\n", gpio_state); report = rt5645_jack_detect(rt5645->component, gpio_state); @@ -3855,6 +3858,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk); rt5645->pdata.level_trigger_irq = QUIRK_LEVEL_IRQ(quirk); rt5645->pdata.inv_jd1_1 = QUIRK_INV_JD1_1(quirk); + rt5645->pdata.inv_hp_pol = QUIRK_INV_HP_POL(quirk); rt5645->pdata.jd_mode = QUIRK_JD_MODE(quirk); rt5645->pdata.dmic1_data_pin = QUIRK_DMIC1_DATA_PIN(quirk); rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk); -- cgit v1.2.3 From 3ac2bfd52b7de6206b1e694a4e79a39d6106c961 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Mon, 11 Jan 2021 13:41:41 +0800 Subject: ASoC: rt5645: Enable internal microphone and JD on ECS EF20 On ECS EF20 series laptops, the internal mic is on DMIC2/IN2P. And they need the inv_hp_det to make jack detection to work as exoected. Signed-off-by: Chris Chiu Link: https://lore.kernel.org/r/20210111054141.4668-5-chiu@endlessos.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index aaeb10c59334..63a7e052eaa0 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3639,6 +3639,12 @@ static const struct rt5645_platform_data kahlee_platform_data = { .jd_mode = 3, }; +static const struct rt5645_platform_data ecs_ef20_platform_data = { + .dmic1_data_pin = RT5645_DMIC1_DISABLE, + .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, + .inv_hp_pol = 1, +}; + static const struct acpi_gpio_params ef20_hp_detect = { 1, 0, false }; static const struct acpi_gpio_mapping cht_rt5645_ef20_gpios[] = { @@ -3787,6 +3793,7 @@ static const struct dmi_system_id dmi_platform_data[] = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "EF20"), }, + .driver_data = (void *)&ecs_ef20_platform_data, }, { .ident = "EF20EA", @@ -3794,6 +3801,7 @@ static const struct dmi_system_id dmi_platform_data[] = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), }, + .driver_data = (void *)&ecs_ef20_platform_data, }, { } }; -- cgit v1.2.3 From 867f8d18df4f5ccd6c2daf4441a6adeca0b9725b Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Mon, 11 Jan 2021 17:27:40 +0800 Subject: ASoC: rt5682: fix getting the wrong device id when the suspend_stress_test This patch will be the workaround to fix getting the wrong device ID on the rare chance. It seems like something unstable when the system resumes. e.g. the bus clock This patch tries to read the device ID to check several times. After the test, the driver will get the correct device ID the second time. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210111092740.9128-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 4d707e854875..69f046bba67a 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -375,18 +375,12 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap, static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - int ret = 0; + int ret = 0, loop = 10; unsigned int val; if (rt5682->hw_init) return 0; - regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); - if (val != DEVICE_ID) { - dev_err(dev, "Device with ID register %x is not rt5682\n", val); - return -ENODEV; - } - /* * PM runtime is only enabled when a Slave reports as Attached */ @@ -406,6 +400,19 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) pm_runtime_get_noresume(&slave->dev); + while (loop > 0) { + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val == DEVICE_ID) + break; + dev_warn(dev, "Device with ID register %x is not rt5682\n", val); + usleep_range(30000, 30005); + loop--; + } + if (val != DEVICE_ID) { + dev_err(dev, "Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + if (rt5682->first_hw_init) { regcache_cache_only(rt5682->regmap, false); regcache_cache_bypass(rt5682->regmap, true); -- cgit v1.2.3 From 5a15cd7fce20b1fd4aece6a0240e2b58cd6a225d Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Mon, 11 Jan 2021 17:25:44 +0800 Subject: ASoC: rt5682: enable fast discharge for headset unplugging To avoid the pop noise, this patch enables the feature of fast discharge. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210111092544.9064-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 4d865edadd7e..42ad5bea86b5 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -953,6 +953,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) case 0x1: case 0x2: rt5682->jack_type = SND_JACK_HEADSET; + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_EN); rt5682_enable_push_button_irq(component, true); break; default: @@ -982,6 +984,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) snd_soc_component_update_bits(component, RT5682_MICBIAS_2, RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, RT5682_PWR_CLK25M_PD | RT5682_PWR_CLK1M_PD); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_DIS); rt5682->jack_type = 0; } @@ -1011,11 +1015,13 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, if (!rt5682->is_sdw) { switch (rt5682->pdata.jd_src) { case RT5682_JD1: + snd_soc_component_update_bits(component, + RT5682_CBJ_CTRL_5, 0x0700, 0x0600); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2, RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); snd_soc_component_write(component, RT5682_CBJ_CTRL_1, - 0xd042); + 0xd142); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_3, RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); -- cgit v1.2.3 From 4eeed5f40354735c4e68e71904db528ed19c9cbb Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Sat, 9 Jan 2021 09:15:01 +0530 Subject: ASoC: soc-pcm: return correct -ERRNO in failure path Kernel test robot throws below error -> sound/soc/soc-pcm.c:2523 dpcm_run_update_startup() error: uninitialized symbol 'ret'. Initializing ret = 0 and returning correct -ERRNO in failure path. Reported-by: kernel test robot Signed-off-by: Souptick Joarder Link: https://lore.kernel.org/r/1610163901-5523-1-git-send-email-jrdr.linux@gmail.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 481a4a25acb0..29328ce39904 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2432,7 +2432,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) snd_soc_dpcm_get_substream(fe, stream); struct snd_soc_dpcm *dpcm; enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; - int ret; + int ret = 0; unsigned long flags; dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n", @@ -2441,6 +2441,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) /* Only start the BE if the FE is ready */ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE || fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) { + ret = -EINVAL; dev_err(fe->dev, "ASoC: FE %s is not ready %d\n", fe->dai_link->name, fe->dpcm[stream].state); goto disconnect; -- cgit v1.2.3 From fe9989fb25b0cea6414e72e0514c70ed8b158c28 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 11 Jan 2021 13:38:25 +0000 Subject: ASoC: wm_adsp: Fix uninitialized variable warnings wm_adsp_read_data_word() used if (ret) to check for an error from wm_adsp_read_raw_data_block(). While this is perfectly valid, wm_adsp_read_raw_data_block() itself uses if (ret < 0) and three calls to wm_adsp_read_data_word() also use if (ret < 0). This creates an error check chain like this: 1st) if (ret < 0) return ret; 2nd) if (ret) return ret; 3rd) if (ret < 0) ... This can confuse the compiler into thinking that there are possible returns > 0 from the middle if() that are not handled by the final if(). If this was true it would lead to using uninitialized variables later in the outer function. Fix this by changing the test in wm_adsp_read_data_word() to be if (ret < 0). Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20210111133825.8758-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f8ad768364c2..1fc7bc1970ea 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -3694,7 +3694,7 @@ static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, int ret; ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw); - if (ret) + if (ret < 0) return ret; *data = be32_to_cpu(raw) & 0x00ffffffu; -- cgit v1.2.3 From e91b65b36fde0690f1c694f17dd1b549295464a7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 11 Jan 2021 12:50:21 +0300 Subject: ASoC: soc-pcm: Fix an uninitialized error code The error path here doesn't set "ret" so it returns uninitialized data instead of a negative error code. Fixes: 2c1382840c19 ("ASoC: soc-pcm: disconnect BEs if the FE is not ready") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/X/wfXQFxeMLvpO+1@mwanda Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 29328ce39904..a253c9f918e1 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2444,6 +2444,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) ret = -EINVAL; dev_err(fe->dev, "ASoC: FE %s is not ready %d\n", fe->dai_link->name, fe->dpcm[stream].state); + ret = -EINVAL; goto disconnect; } -- cgit v1.2.3 From 1851ccf9e155b2a6f6cca1a7bd49325f5efbd5d2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 9 Jan 2021 22:01:17 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add new BYT_RT5640_NO_SPEAKERS quirk-flag Some devices, like mini PCs/media/top-set boxes do not have any speakers at all, an example of the is the Mele PCG03 Mini PC. Add a new BYT_RT5640_NO_SPEAKERS quirk-flag which when sets does not add speaker routes and modifies the components and the (optional) long_name strings to reflect that there are no speakers. Cc: Rasmus Porsager Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210109210119.159032-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 5520d7c80019..dce2df30d4c5 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -71,6 +71,7 @@ enum { #define BYT_RT5640_SSP0_AIF2 BIT(21) #define BYT_RT5640_MCLK_EN BIT(22) #define BYT_RT5640_MCLK_25MHZ BIT(23) +#define BYT_RT5640_NO_SPEAKERS BIT(24) #define BYTCR_INPUT_DEFAULTS \ (BYT_RT5640_IN3_MAP | \ @@ -132,6 +133,8 @@ static void log_quirks(struct device *dev) dev_info(dev, "quirk JD_NOT_INV enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) dev_info(dev, "quirk MONO_SPEAKER enabled\n"); + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) + dev_info(dev, "quirk NO_SPEAKERS enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) dev_info(dev, "quirk DIFF_MIC enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { @@ -946,7 +949,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_mono_spk_map, ARRAY_SIZE(byt_rt5640_mono_spk_map)); - } else { + } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_stereo_spk_map, ARRAY_SIZE(byt_rt5640_stereo_spk_map)); @@ -1188,6 +1191,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; + __maybe_unused const char *spk_type; const struct dmi_system_id *dmi_id; struct byt_rt5640_private *priv; struct snd_soc_acpi_mach *mach; @@ -1196,7 +1200,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) bool sof_parent; int ret_val = 0; int dai_index = 0; - int i; + int i, cfg_spk; is_bytcr = false; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -1335,16 +1339,24 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) } } + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { + cfg_spk = 0; + spk_type = "none"; + } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { + cfg_spk = 1; + spk_type = "mono"; + } else { + cfg_spk = 2; + spk_type = "stereo"; + } + snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), - "cfg-spk:%s cfg-mic:%s", - (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? "1" : "2", + "cfg-spk:%d cfg-mic:%s", cfg_spk, map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); byt_rt5640_card.components = byt_rt5640_components; #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), - "bytcr-rt5640-%s-spk-%s-mic", - (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? - "mono" : "stereo", + "bytcr-rt5640-%s-spk-%s-mic", spk_type, map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); byt_rt5640_card.long_name = byt_rt5640_long_name; #endif -- cgit v1.2.3 From 46466ab68e752d054b4b7aece1bfadc9f9bbf272 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 9 Jan 2021 22:01:18 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add new BYT_RT5640_NO_INTERNAL_MIC_MAP input-mapping Some devices, like mini PCs/media/top-set boxes do not have an internal microphone at all, an example of the is the Mele PCG03 Mini PC. Add a new BYT_RT5640_NO_INTERNAL_MIC_MAP input-mapping for this, which does not add any internal-mic routes and modifies the components and the (optional) long_name strings to reflect this. Cc: Rasmus Porsager Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210109210119.159032-3-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index dce2df30d4c5..48d781faded1 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -35,6 +35,7 @@ enum { BYT_RT5640_DMIC2_MAP, BYT_RT5640_IN1_MAP, BYT_RT5640_IN3_MAP, + BYT_RT5640_NO_INTERNAL_MIC_MAP, }; enum { @@ -117,6 +118,9 @@ static void log_quirks(struct device *dev) case BYT_RT5640_IN3_MAP: dev_info(dev, "quirk IN3_MAP enabled\n"); break; + case BYT_RT5640_NO_INTERNAL_MIC_MAP: + dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n"); + break; default: dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); break; @@ -876,8 +880,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_card *card = runtime->card; struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; - const struct snd_soc_dapm_route *custom_map; - int num_routes; + const struct snd_soc_dapm_route *custom_map = NULL; + int num_routes = 0; int ret; card->dapm.idle_bias_off = true; @@ -912,13 +916,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) custom_map = byt_rt5640_intmic_in3_map; num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); break; + case BYT_RT5640_DMIC1_MAP: + custom_map = byt_rt5640_intmic_dmic1_map; + num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); + break; case BYT_RT5640_DMIC2_MAP: custom_map = byt_rt5640_intmic_dmic2_map; num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); break; - default: - custom_map = byt_rt5640_intmic_dmic1_map; - num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); } ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); @@ -1190,7 +1195,7 @@ struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; + static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" }; __maybe_unused const char *spk_type; const struct dmi_system_id *dmi_id; struct byt_rt5640_private *priv; -- cgit v1.2.3 From df33032146baefb29d7e61193738f39e454917e3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 9 Jan 2021 22:01:19 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Mele PCG03 Mini PC Add a quirk for the Mele PCG03 Mini PC, being a Mini PC this device has no speakers and no internal microphone. To make matters worse the speaker output pins are shorted (to gnd or to each other?) and SPKVDD is provided. So trying to output sound on the speakers leads to shorting SPKVDD, this leads to a power dip after which the codec is an unknown state. Sometimes it drops of the i2c bus, sometimes it does still respond to i2c transfers, but is otherwise not functional. TL;DR: trying to use the speaker outputs on this model is BAD. Besides not having speakers / an internal mic, this is a Bay Trail CR device without a CHAN package in ACPI, so we default to SSP0-AIF2 as codec connection. But the device is actually using SSP0-AIF1, so we need to quirk that too. Cc: Rasmus Porsager Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210109210119.159032-4-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 48d781faded1..2dee84578b90 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -620,6 +620,15 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { /* Mele PCG03 Mini PC */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"), + }, + .driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP | + BYT_RT5640_NO_SPEAKERS | + BYT_RT5640_SSP0_AIF1), + }, { /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"), -- cgit v1.2.3 From 780b1a02c1795b58f217aabfd0688d616408bb89 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 7 Jan 2021 12:53:24 +0100 Subject: ASoC: Intel: cht_bsw_nau8824: Move snd_soc_dai_set_tdm_slot call to cht_codec_fixup Move the snd_soc_dai_set_tdm_slot() call from cht_codec_init() to cht_codec_fixup(). There are 2 reasons for doing this: 1. This aligns the cht_bsw_nau8824 with all the other BYT/CHT machine drivers which also do this from their codec_fixup function. 2. When using the SOF driver, things like the TDM info is set from the topology file. Moving the call to the codec_fixup function, which gets skipped when using the SOF driver avoids the call interfering with the settings when using the SOF driver. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210107115324.11602-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_nau8824.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index fd5e25ca05f7..da5a5cbc8759 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -100,13 +100,6 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_component *component = codec_dai->component; int ret, jack_type; - /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xf, 0x1, 4, 24); - if (ret < 0) { - dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret); - return ret; - } - /* NAU88L24 supports 4 butons headset detection * KEY_PLAYPAUSE * KEY_VOICECOMMAND @@ -141,6 +134,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + int ret; /* The DSP will covert the FE rate to 48k, stereo, 24bits */ rate->min = rate->max = 48000; @@ -150,6 +144,13 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xf, 0x1, 4, 24); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); + return ret; + } + return 0; } -- cgit v1.2.3 From 554a1b00957ec1033994a2d03b5b8eac59a24f3c Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Fri, 8 Jan 2021 08:44:56 +0000 Subject: ASoC: adau17x1: Remove redundant null check before clk_disable_unprepare Because clk_disable_unprepare() already checked NULL clock parameter, so the additional check is unnecessary, just remove it. Signed-off-by: Xu Wang Link: https://lore.kernel.org/r/20210108084456.6603-1-vulab@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/codecs/adau17x1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 30e072c80ac1..546ee8178038 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -1095,8 +1095,7 @@ void adau17x1_remove(struct device *dev) { struct adau *adau = dev_get_drvdata(dev); - if (adau->mclk) - clk_disable_unprepare(adau->mclk); + clk_disable_unprepare(adau->mclk); } EXPORT_SYMBOL_GPL(adau17x1_remove); -- cgit v1.2.3 From f2973a1de9d9890b6ac712fb1825d3449ee9cc93 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 12 Jan 2021 11:17:25 +0100 Subject: ASoC: es8316: Fix possible NULL pointer deref in es8316_disable_jack_detect() sound/soc/soc-core.c: soc_remove_component() unconditionally calls snd_soc_component_set_jack(component, NULL, NULL); on any components being removed. This means that on machines where the machine-driver does not provide a jack through snd_soc_component_set_jack() es8316_disable_jack_detect() will still get called and at this time es8316->jack will be NULL and the es8316->jack->status check in es8316_disable_jack_detect() will lead to a NULL pointer deref. Fix this by checking for es8316->jack bein NULL at the start of es8316_disable_jack_detect() and turn the function into a no-op in that case. Cc: russianneuromancer Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210112101725.44200-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index f9ec5cf82599..1ce84f12a4cf 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -681,6 +681,9 @@ static void es8316_disable_jack_detect(struct snd_soc_component *component) { struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); + if (!es8316->jack) + return; /* Already disabled (or never enabled) */ + disable_irq(es8316->irq); mutex_lock(&es8316->lock); -- cgit v1.2.3 From 8b66d7c58c11cf3b1a1cea738582367a96cdaaf8 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 5 Jan 2021 17:56:40 +0200 Subject: ASoC: SOF: add mutex to protect the dsp_power_state access There could be more than one thread read/write the dsp_power_state simultaneously (e.g. hda_dsp_d0i3_work and sof_ipc_tx_message), add a mutex power_state_access to make sure the access to it is mutually exclusive. Signed-off-by: Keyon Jie Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Reviewed-by: Guennadi Liakhovetski Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210105155640.3725238-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 1 + sound/soc/sof/ops.h | 11 ++++++++--- sound/soc/sof/sof-priv.h | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index adc7c37145d6..2b85ef5d6092 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -316,6 +316,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) INIT_LIST_HEAD(&sdev->route_list); spin_lock_init(&sdev->ipc_lock); spin_lock_init(&sdev->hw_lock); + mutex_init(&sdev->power_state_access); if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) INIT_WORK(&sdev->probe_work, sof_probe_work); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 95e748b36903..4c1f9daaa6e8 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -208,11 +208,16 @@ static inline int snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, const struct sof_dsp_power_state *target_state) { + int ret = 0; + + mutex_lock(&sdev->power_state_access); + if (sof_ops(sdev)->set_power_state) - return sof_ops(sdev)->set_power_state(sdev, target_state); + ret = sof_ops(sdev)->set_power_state(sdev, target_state); - /* D0 substate is not supported, do nothing here. */ - return 0; + mutex_unlock(&sdev->power_state_access); + + return ret; } /* debug */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 68da8f797403..28d19fa30614 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -375,6 +375,8 @@ struct snd_sof_dev { /* current DSP power state */ struct sof_dsp_power_state dsp_power_state; + /* mutex to protect the dsp_power_state access */ + struct mutex power_state_access; /* Intended power target of system suspend */ enum sof_system_suspend_state system_suspend_target; -- cgit v1.2.3 From 9c6d7f9346b1526136dc142eb82085737112a3fe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2020 14:55:16 +0900 Subject: ASoC: soc-pcm: move dpcm_set_fe_update_state() This patch moves dpcm_set_fe_update_state() to top side. This is prepare for cleanup soc-pcm.c Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871rfw99jn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a253c9f918e1..1cc8d0b6ec3d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -203,6 +203,28 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) } #endif +/* Set FE's runtime_update state; the state is protected via PCM stream lock + * for avoiding the race with trigger callback. + * If the state is unset and a trigger is pending while the previous operation, + * process the pending trigger action here. + */ +static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); +static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, + int stream, enum snd_soc_dpcm_update state) +{ + struct snd_pcm_substream *substream = + snd_soc_dpcm_get_substream(fe, stream); + + snd_pcm_stream_lock_irq(substream); + if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { + dpcm_fe_dai_do_trigger(substream, + fe->dpcm[stream].trigger_pending - 1); + fe->dpcm[stream].trigger_pending = 0; + } + fe->dpcm[stream].runtime_update = state; + snd_pcm_stream_unlock_irq(substream); +} + /** * snd_soc_runtime_action() - Increment/Decrement active count for * PCM runtime components @@ -1710,29 +1732,6 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) &runtime->hw.rate_min, &runtime->hw.rate_max); } -static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); - -/* Set FE's runtime_update state; the state is protected via PCM stream lock - * for avoiding the race with trigger callback. - * If the state is unset and a trigger is pending while the previous operation, - * process the pending trigger action here. - */ -static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, - int stream, enum snd_soc_dpcm_update state) -{ - struct snd_pcm_substream *substream = - snd_soc_dpcm_get_substream(fe, stream); - - snd_pcm_stream_lock_irq(substream); - if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { - dpcm_fe_dai_do_trigger(substream, - fe->dpcm[stream].trigger_pending - 1); - fe->dpcm[stream].trigger_pending = 0; - } - fe->dpcm[stream].runtime_update = state; - snd_pcm_stream_unlock_irq(substream); -} - static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, int stream) { -- cgit v1.2.3 From a7e20444ef5e7ab74aec34f34eb0e53024c349e1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2020 14:55:22 +0900 Subject: ASoC: soc-pcm: add dpcm_set_be_update_state() soc-pcm has dpcm_set_fe_update_state() to update FE's runtime_update (except dpcm_fe_dai_do_trigger() which needs to update it without it). OTOH, it doesn't have BE's update function. O: dpcm_set_fe_update_state() X: dpcm_set_be_update_state() This patch add BE's dpcm_set_fe_update_state() Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zh2k7uz1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1cc8d0b6ec3d..54b460f08373 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -225,6 +225,12 @@ static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, snd_pcm_stream_unlock_irq(substream); } +static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be, + int stream, enum snd_soc_dpcm_update state) +{ + be->dpcm[stream].runtime_update = state; +} + /** * snd_soc_runtime_action() - Increment/Decrement active count for * PCM runtime components @@ -1357,7 +1363,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, stream ? "capture" : "playback", dpcm->be->dai_link->name, fe->dai_link->name); dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; - dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; + dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_BE); prune++; } @@ -1412,7 +1418,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, continue; /* new */ - be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; + dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE); new++; } @@ -1440,8 +1446,7 @@ void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) spin_lock_irqsave(&fe->card->dpcm_lock, flags); for_each_dpcm_be(fe, stream, dpcm) - dpcm->be->dpcm[stream].runtime_update = - SND_SOC_DPCM_UPDATE_NO; + dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_NO); spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); } -- cgit v1.2.3 From 2805b8bd3e0bdda15b3458ab9818d80f5d5b157f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2020 14:55:27 +0900 Subject: ASoC: soc-pcm: add soc_pcm_set_dai_params() Getting rate/channels/sample_bits from param needs fixed method. This patch adds new soc_pcm_set_dai_params() and replace existing code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y2i47uyw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 54b460f08373..6e9f14d482ab 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -329,6 +329,20 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, return 0; } +static void soc_pcm_set_dai_params(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params) +{ + if (params) { + dai->rate = params_rate(params); + dai->channels = params_channels(params); + dai->sample_bits = snd_pcm_format_physical_width(params_format(params)); + } else { + dai->rate = 0; + dai->channels = 0; + dai->sample_bits = 0; + } +} + static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_dai *soc_dai) { @@ -390,13 +404,12 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai d; struct snd_soc_dai *dai; struct snd_soc_dai *cpu_dai; - unsigned int rate, channels, sample_bits, symmetry, i; + unsigned int symmetry, i; - rate = params_rate(params); - channels = params_channels(params); - sample_bits = snd_pcm_format_physical_width(params_format(params)); + soc_pcm_set_dai_params(&d, params); /* reject unmatched parameters when applying symmetry */ symmetry = rtd->dai_link->symmetric_rates; @@ -406,9 +419,9 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (cpu_dai->rate && cpu_dai->rate != rate) { + if (cpu_dai->rate && cpu_dai->rate != d.rate) { dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", - cpu_dai->rate, rate); + cpu_dai->rate, d.rate); return -EINVAL; } } @@ -422,9 +435,9 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->channels && - cpu_dai->channels != channels) { + cpu_dai->channels != d.channels) { dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", - cpu_dai->channels, channels); + cpu_dai->channels, d.channels); return -EINVAL; } } @@ -438,9 +451,9 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->sample_bits && - cpu_dai->sample_bits != sample_bits) { + cpu_dai->sample_bits != d.sample_bits) { dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", - cpu_dai->sample_bits, sample_bits); + cpu_dai->sample_bits, d.sample_bits); return -EINVAL; } } @@ -898,11 +911,8 @@ static int soc_pcm_hw_clean(struct snd_pcm_substream *substream, int rollback) for_each_rtd_dais(rtd, i, dai) { int active = snd_soc_dai_stream_active(dai, substream->stream); - if (snd_soc_dai_active(dai) == 1) { - dai->rate = 0; - dai->channels = 0; - dai->sample_bits = 0; - } + if (snd_soc_dai_active(dai) == 1) + soc_pcm_set_dai_params(dai, NULL); if (active == 1) snd_soc_dai_digital_mute(dai, 1, substream->stream); @@ -999,11 +1009,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if(ret < 0) goto out; - codec_dai->rate = params_rate(&codec_params); - codec_dai->channels = params_channels(&codec_params); - codec_dai->sample_bits = snd_pcm_format_physical_width( - params_format(&codec_params)); - + soc_pcm_set_dai_params(codec_dai, &codec_params); snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); } @@ -1020,11 +1026,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, goto out; /* store the parameters for each DAI */ - cpu_dai->rate = params_rate(params); - cpu_dai->channels = params_channels(params); - cpu_dai->sample_bits = - snd_pcm_format_physical_width(params_format(params)); - + soc_pcm_set_dai_params(cpu_dai, params); snd_soc_dapm_update_dai(substream, params, cpu_dai); } -- cgit v1.2.3 From a39748d03cbc7c0a55d217731c7e16a22a2d2bed Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2020 14:55:33 +0900 Subject: ASoC: soc-pcm: cleanup soc_pcm_apply_symmetry() soc_pcm_apply_symmetry() want to call snd_pcm_hw_constraint_single() for rate/channel/sample_bits, but, it needs many condition check. These are very similar but different, thus, it needs to have very verbose code. This patch use macro for it and make code more simple. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wnxo7uyq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 67 ++++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6e9f14d482ab..f62136f16c2f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -349,53 +349,26 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; - if (soc_dai->rate && (soc_dai->driver->symmetric_rates || - rtd->dai_link->symmetric_rates)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", - soc_dai->rate); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - soc_dai->rate); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply rate constraint: %d\n", - ret); - return ret; - } - } - - if (soc_dai->channels && (soc_dai->driver->symmetric_channels || - rtd->dai_link->symmetric_channels)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", - soc_dai->channels); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, - soc_dai->channels); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply channel symmetry constraint: %d\n", - ret); - return ret; - } - } - - if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits || - rtd->dai_link->symmetric_samplebits)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", - soc_dai->sample_bits); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - soc_dai->sample_bits); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply sample bits symmetry constraint: %d\n", - ret); - return ret; - } - } +#define __soc_pcm_apply_symmetry(name, sname, NAME) \ + if (soc_dai->name && (soc_dai->driver->symmetric_##sname || \ + rtd->dai_link->symmetric_##sname)) { \ + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\ + #name, soc_dai->name); \ + \ + ret = snd_pcm_hw_constraint_single(substream->runtime, \ + SNDRV_PCM_HW_PARAM_##NAME,\ + soc_dai->name); \ + if (ret < 0) { \ + dev_err(soc_dai->dev, \ + "ASoC: Unable to apply %s constraint: %d\n",\ + #name, ret); \ + return ret; \ + } \ + } + + __soc_pcm_apply_symmetry(rate, rates, RATE); + __soc_pcm_apply_symmetry(channels, channels, CHANNELS); + __soc_pcm_apply_symmetry(sample_bits, samplebits, SAMPLE_BITS); return 0; } -- cgit v1.2.3 From 856fe64da84c95a1d415564b981ae3908eea2a76 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 11 Dec 2020 13:07:59 +0300 Subject: ASoC: cs42l56: fix up error handling in probe There are two issues with this code. The first error path forgot to set the error code and instead returns success. The second error path doesn't clean up. Fixes: 272b5edd3b8f ("ASoC: Add support for CS42L56 CODEC") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/X9NE/9nK9/TuxuL+@mwanda Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l56.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index bb9599cc832b..c44a5cdb796e 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1250,6 +1250,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L56 Device ID (%X). Expected %X\n", devid, CS42L56_DEVID); + ret = -EINVAL; goto err_enable; } alpha_rev = reg & CS42L56_AREV_MASK; @@ -1307,7 +1308,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, ret = devm_snd_soc_register_component(&i2c_client->dev, &soc_component_dev_cs42l56, &cs42l56_dai, 1); if (ret < 0) - return ret; + goto err_enable; return 0; -- cgit v1.2.3 From 6fd8d2d275f74baa7ac17b2656da1235f56dab99 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Fri, 11 Dec 2020 21:32:55 +0100 Subject: ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai At the moment it is necessary to set up the DAPM routes between front-end AIF<->DAI explicitly in the device tree, e.g. using audio-routing = "MM_DL1", "MultiMedia1 Playback", "MM_DL3", "MultiMedia3 Playback", "MM_DL4", "MultiMedia4 Playback", "MultiMedia2 Capture", "MM_UL2"; This is prone to mistakes and (sadly) there is no clear error if one of these routes is missing. :( Actually, this should not be necessary because the ASoC core normally automatically links AIF<->DAI within snd_soc_dapm_link_dai_widgets(). This is done using the "stname" parameter of SND_SOC_DAPM_AIF_IN/OUT. For SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0), it should create the route from above: MM_DL1 <-> MultiMedia1 Playback. This does not work at the moment because the AIF widget (MM_DL1) and the DAI widget (MultiMedia1 Playback) belong to different DAPM contexts (q6routing / q6asm-dai). Fix this by declaring the AIF widgets in the same driver as the DAIs (q6asm-dai). Now the routes above are created automatically and no longer need to be specified in the device tree. This is also more consistent with the back-end AIFs which are already declared in q6afe-dais instead of q6routing. q6routing should only link the components together using mixers. Cc: Srinivas Kandagatla Fixes: 2a9e92d371db ("ASoC: qdsp6: q6asm: Add q6asm dai driver") Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20201211203255.148246-1-stephan@gerhold.net Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6asm-dai.c | 21 +++++++++++++++++++++ sound/soc/qcom/qdsp6/q6routing.c | 18 ------------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index c9ac9c1d26c4..9766725c2916 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -1233,6 +1233,25 @@ static void q6asm_dai_pcm_free(struct snd_soc_component *component, } } +static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + static const struct snd_soc_component_driver q6asm_fe_dai_component = { .name = DRV_NAME, .open = q6asm_dai_open, @@ -1245,6 +1264,8 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .pcm_construct = q6asm_dai_pcm_new, .pcm_destruct = q6asm_dai_pcm_free, .compress_ops = &q6asm_dai_compress_ops, + .dapm_widgets = q6asm_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets), }; static struct snd_soc_dai_driver q6asm_fe_dais_template[] = { diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 53185e26fea1..0a6b9433f6ac 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -713,24 +713,6 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { Q6ROUTING_TX_MIXERS(MSM_FRONTEND_DAI_MULTIMEDIA8) }; static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { - /* Frontend AIF */ - SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0), - /* Mixer definitions */ SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, -- cgit v1.2.3 From 22eee4d3efe370fedf71ee6a9e4dead3f32ad461 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 6 Jan 2021 14:36:48 +0100 Subject: ASoC: atmel-pdc: Use managed DMA buffer allocation Instead of manually managing its DMA buffers using dma_{alloc,free}_coherent() lets the sound core take care of this using managed buffers. On one hand this reduces the amount of boiler plate code, but the main motivation for the change is to use the shared code where possible. This makes it easier to argue about correctness and that the code does not contain subtle bugs like data leakage or similar. Signed-off-by: Lars-Peter Clausen Reviewed-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210106133650.13509-1-lars@metafoo.de Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-pcm-pdc.c | 78 +++-------------------------------------- 1 file changed, 4 insertions(+), 74 deletions(-) diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index 704f700013d3..3e7ea2021b46 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c @@ -34,86 +34,21 @@ #include "atmel-pcm.h" -static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = ATMEL_SSC_DMABUF_SIZE; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n", - (void *)buf->area, (void *)(long)buf->addr, size); - - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} - -static int atmel_pcm_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return remap_pfn_range(vma, vma->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot); -} - static int atmel_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; int ret; ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret) return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n"); - ret = atmel_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, ATMEL_SSC_DMABUF_SIZE, + ATMEL_SSC_DMABUF_SIZE); - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n"); - ret = atmel_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - out: - return ret; -} - -static void atmel_pcm_free(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } + return 0; } /*--------------------------------------------------------------------------*\ @@ -210,9 +145,6 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component, /* this may get called several times by oss emulation * with different params */ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - prtd->params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); prtd->params->dma_intr_handler = atmel_pcm_dma_irq; @@ -384,9 +316,7 @@ static const struct snd_soc_component_driver atmel_soc_platform = { .prepare = atmel_pcm_prepare, .trigger = atmel_pcm_trigger, .pointer = atmel_pcm_pointer, - .mmap = atmel_pcm_mmap, .pcm_construct = atmel_pcm_new, - .pcm_destruct = atmel_pcm_free, }; int atmel_pcm_pdc_platform_register(struct device *dev) -- cgit v1.2.3 From 5ac813c83483e97a13b59aab34b89cebf9d5dcb8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 6 Jan 2021 14:36:49 +0100 Subject: ASoC: bcm: cygnus: Use managed DMA buffer allocation Instead of manually managing its DMA buffers using dma_{alloc,free}_coherent() lets the sound core take care of this using managed buffers. On one hand this reduces the amount of boiler plate code, but the main motivation for the change is to use the shared code where possible. This makes it easier to argue about correctness and that the code does not contain subtle bugs like data leakage or similar. Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20210106133650.13509-2-lars@metafoo.de Signed-off-by: Mark Brown --- sound/soc/bcm/cygnus-pcm.c | 107 ++------------------------------------------- 1 file changed, 3 insertions(+), 104 deletions(-) diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 7ad07239f99c..56b71b965624 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -636,36 +636,6 @@ static int cygnus_pcm_close(struct snd_soc_component *component, return 0; } -static int cygnus_pcm_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct cygnus_aio_port *aio; - - aio = cygnus_dai_get_dma_data(substream); - dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - return 0; -} - -static int cygnus_pcm_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct cygnus_aio_port *aio; - - aio = cygnus_dai_get_dma_data(substream); - dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); - - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - static int cygnus_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -730,87 +700,19 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component, return bytes_to_frames(substream->runtime, res); } -static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size; - - size = cygnus_pcm_hw.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - - dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: size 0x%zx @ %pK\n", - __func__, size, buf->area); - - if (!buf->area) { - dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: dma_alloc failed\n", __func__); - return -ENOMEM; - } - buf->bytes = size; - - return 0; -} - -static void cygnus_dma_free_dma_buffers(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - - substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - if (substream) { - buf = &substream->dma_buffer; - if (buf->area) { - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } - } - - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - if (substream) { - buf = &substream->dma_buffer; - if (buf->area) { - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } - } -} - static int cygnus_dma_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { + size_t size = cygnus_pcm_hw.buffer_bytes_max; struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; if (!card->dev->dma_mask) card->dev->dma_mask = &cygnus_dma_dmamask; if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = cygnus_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = cygnus_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) { - cygnus_dma_free_dma_buffers(component, pcm); - return ret; - } - } + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); return 0; } @@ -818,13 +720,10 @@ static int cygnus_dma_new(struct snd_soc_component *component, static struct snd_soc_component_driver cygnus_soc_platform = { .open = cygnus_pcm_open, .close = cygnus_pcm_close, - .hw_params = cygnus_pcm_hw_params, - .hw_free = cygnus_pcm_hw_free, .prepare = cygnus_pcm_prepare, .trigger = cygnus_pcm_trigger, .pointer = cygnus_pcm_pointer, .pcm_construct = cygnus_dma_new, - .pcm_destruct = cygnus_dma_free_dma_buffers, }; int cygnus_soc_platform_register(struct device *dev, -- cgit v1.2.3 From b3c0ae75f5d3efa40174230b8c9c01848e03d4d0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 6 Jan 2021 14:36:50 +0100 Subject: ASoC: kirkwood: Use managed DMA buffer allocation Instead of manually managing its DMA buffers using dma_{alloc,free}_coherent() lets the sound core take care of this using managed buffers. On one hand this reduces the amount of boiler plate code, but the main motivation for the change is to use the shared code where possible. This makes it easier to argue about correctness and that the code does not contain subtle bugs like data leakage or similar. Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20210106133650.13509-3-lars@metafoo.de Signed-off-by: Mark Brown --- sound/soc/kirkwood/kirkwood-dma.c | 79 ++------------------------------------- 1 file changed, 3 insertions(+), 76 deletions(-) diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index e037826b2451..c2a5933bfcfc 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -182,25 +182,6 @@ static int kirkwood_dma_close(struct snd_soc_component *component, return 0; } -static int kirkwood_dma_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - return 0; -} - -static int kirkwood_dma_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - static int kirkwood_dma_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -244,82 +225,28 @@ static snd_pcm_uframes_t kirkwood_dma_pointer( return count; } -static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = kirkwood_dma_snd_hw.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - buf->private_data = NULL; - - return 0; -} - static int kirkwood_dma_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { + size_t size = kirkwood_dma_snd_hw.buffer_bytes_max; struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; int ret; ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret) return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = kirkwood_dma_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = kirkwood_dma_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - return ret; - } + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); return 0; } -static void kirkwood_dma_free_dma_buffers(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - const struct snd_soc_component_driver kirkwood_soc_component = { .name = DRV_NAME, .open = kirkwood_dma_open, .close = kirkwood_dma_close, - .hw_params = kirkwood_dma_hw_params, - .hw_free = kirkwood_dma_hw_free, .prepare = kirkwood_dma_prepare, .pointer = kirkwood_dma_pointer, .pcm_construct = kirkwood_dma_new, - .pcm_destruct = kirkwood_dma_free_dma_buffers, }; -- cgit v1.2.3 From 7edb3051f11683640c38b93e183ef1676090a79b Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 13 Jan 2021 17:26:14 +0200 Subject: ASoC: SOF: add .shutdown() callback to snd_sof_dsp_ops Add .shutdown() callback to the struct snd_sof_dsp_ops, for doing platform specific actions at shutdown. Signed-off-by: Keyon Jie Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210113152617.4048541-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 8 ++++++++ sound/soc/sof/sof-priv.h | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 4c1f9daaa6e8..f0c9ca8820d2 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -37,6 +37,14 @@ static inline int snd_sof_remove(struct snd_sof_dev *sdev) return 0; } +static inline int snd_sof_shutdown(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev)->shutdown) + return sof_ops(sdev)->shutdown(sdev); + + return 0; +} + /* control */ /* diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 28d19fa30614..682c4b6d01ef 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -98,9 +98,10 @@ struct snd_sof_pdata; */ struct snd_sof_dsp_ops { - /* probe and remove */ + /* probe/remove/shutdown */ int (*probe)(struct snd_sof_dev *sof_dev); /* mandatory */ int (*remove)(struct snd_sof_dev *sof_dev); /* optional */ + int (*shutdown)(struct snd_sof_dev *sof_dev); /* optional */ /* DSP core boot / reset */ int (*run)(struct snd_sof_dev *sof_dev); /* mandatory */ @@ -462,6 +463,7 @@ struct snd_sof_dev { int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data); int snd_sof_device_remove(struct device *dev); +int snd_sof_device_shutdown(struct device *dev); int snd_sof_runtime_suspend(struct device *dev); int snd_sof_runtime_resume(struct device *dev); -- cgit v1.2.3 From daff7f1478e12cdee3e639c83c571cfd38bc5080 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 13 Jan 2021 17:26:15 +0200 Subject: ASoC: SOF: add snd_sof_device_shutdown() helper for shutdown Add helper snd_sof_device_shutdown() to wrap the platform specific .shutdown callbacks for SOF platforms. Signed-off-by: Keyon Jie Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210113152617.4048541-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 2b85ef5d6092..8d13eb13fe08 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -385,6 +385,14 @@ int snd_sof_device_remove(struct device *dev) } EXPORT_SYMBOL(snd_sof_device_remove); +int snd_sof_device_shutdown(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + return snd_sof_shutdown(sdev); +} +EXPORT_SYMBOL(snd_sof_device_shutdown); + MODULE_AUTHOR("Liam Girdwood"); MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core"); MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From 3475b44c7601d6f2b4d96e731047ef73fd2f1eb2 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 13 Jan 2021 17:26:16 +0200 Subject: ASoC: SOF: sof-pci-dev: add .shutdown() callback Add the .shutdown() callback to the sof-pci-dev driver, to help to handle shutting down specific tasks for SOF PCI platforms. Signed-off-by: Keyon Jie Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210113152617.4048541-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 63b989e3ec40..5f53c3e76e6f 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -450,6 +450,11 @@ static void sof_pci_remove(struct pci_dev *pci) pci_release_regions(pci); } +static void sof_pci_shutdown(struct pci_dev *pci) +{ + snd_sof_device_shutdown(&pci->dev); +} + /* PCI IDs */ static const struct pci_device_id sof_pci_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) @@ -523,6 +528,7 @@ static struct pci_driver snd_sof_pci_driver = { .id_table = sof_pci_ids, .probe = sof_pci_probe, .remove = sof_pci_remove, + .shutdown = sof_pci_shutdown, .driver = { .pm = &sof_pci_pm, }, -- cgit v1.2.3 From 44a4cfad8d78efcda9ec0dd97ceea38d8b602f24 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 13 Jan 2021 17:26:17 +0200 Subject: ASoC: SOF: Intel: tgl: do thorough remove at .shutdown() callback Invoke hda_dsp_remove() as the .shutdown() callback. This will help to perform shutdown of the DSP safely on TGL platforms before shutting down or rebooting the system. BugLink: https://github.com/thesofproject/linux/issues/2571 Signed-off-by: Keyon Jie Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210113152617.4048541-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/tgl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 2252ca38ff4b..419f05ba1920 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -22,9 +22,10 @@ static const struct snd_sof_debugfs_map tgl_dsp_debugfs[] = { /* Tigerlake ops */ const struct snd_sof_dsp_ops sof_tgl_ops = { - /* probe and remove */ + /* probe/remove/shutdown */ .probe = hda_dsp_probe, .remove = hda_dsp_remove, + .shutdown = hda_dsp_remove, /* Register IO */ .write = sof_io_write, -- cgit v1.2.3 From e8afdfdc8125801b1e28b5a54d2bd94cf2d59965 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jan 2021 10:57:58 +0100 Subject: ALSA: usb-audio: Convert remaining strlcpy() to strscpy() USB-audio driver still contains two calls of strlcpy() because the return size is evaluated. Basically it just checks whether the string is copied or not, but since strcpy() may return a negative error code, we should check the negative value and treat as filled. Link: https://lore.kernel.org/r/20210115095758.19707-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 85fed017710e..c7da38348035 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -115,11 +115,14 @@ find_map(const struct usbmix_name_map *p, int unitid, int control) static int check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen) { + int len; + if (!p || !p->name) return 0; buflen--; - return strlcpy(buf, p->name, buflen); + len = strscpy(buf, p->name, buflen); + return len < 0 ? buflen : len; } /* ignore the error value if ignore_ctl_error flag is set */ @@ -151,12 +154,15 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid, int index, char *buf, int buflen) { const struct usbmix_selector_map *p; + int len; if (!state->selector_map) return 0; for (p = state->selector_map; p->id; p++) { - if (p->id == unitid && index < p->count) - return strlcpy(buf, p->names[index], buflen); + if (p->id == unitid && index < p->count) { + len = strscpy(buf, p->names[index], buflen); + return len < 0 ? buflen : len; + } } return 0; } -- cgit v1.2.3 From 42ef170d57d8fc59b36619b00cadacac84ecfb90 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jan 2021 11:04:37 +0100 Subject: ALSA: usb-audio: Convert the last strlcpy() usage The last remaining usage of strlcpy() in USB-audio driver is the setup of the card longname string. Basically we need to know whether any non-empty string is set or not, and no real length is needed. Refactor the code and use strscpy() instead. After this change, strlcpy() is gone from all sound/* code. Link: https://lore.kernel.org/r/20210115100437.20906-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/card.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 85e79b9ecb08..45407cb81b66 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -514,18 +514,17 @@ static void usb_audio_make_longname(struct usb_device *dev, s = preset->vendor_name; else if (quirk && quirk->vendor_name) s = quirk->vendor_name; + *card->longname = 0; if (s && *s) { - len = strlcpy(card->longname, s, sizeof(card->longname)); + strscpy(card->longname, s, sizeof(card->longname)); } else { /* retrieve the vendor and device strings as longname */ if (dev->descriptor.iManufacturer) - len = usb_string(dev, dev->descriptor.iManufacturer, - card->longname, sizeof(card->longname)); - else - len = 0; + usb_string(dev, dev->descriptor.iManufacturer, + card->longname, sizeof(card->longname)); /* we don't really care if there isn't any vendor string */ } - if (len > 0) { + if (*card->longname) { strim(card->longname); if (*card->longname) strlcat(card->longname, " ", sizeof(card->longname)); -- cgit v1.2.3 From 9a08676fc5968be8575ee2fa8926e55d8aef166c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 15 Jan 2021 12:56:23 +0900 Subject: ALSA: dice: add support for Lexicon I-ONIX FW810s I-ONIX FW810s was shipped in Lexicon brand of HARMAN International industries, Inc 2009. The model uses TCD2220 ASIC as its communication engine. TCAT general protocol is supported, its extension isn't. This patch adds support for the model with hard-coded stream formats. $ python3 ~/git/linux-firewire-utils/src/crpp < /sys/bus/firewire/devices/fw1/config_rom ROM header and bus information block ----------------------------------------------------------------- 400 04042b91 bus_info_length 4, crc_length 4, crc 11153 404 31333934 bus_name "1394" 408 e0008102 irmc 1, cmc 1, isc 1, bmc 0, cyc_clk_acc 0, max_rec 8 (512) 40c 000fd720 company_id 000fd7 | 410 007d7ecf device_id 20007d7ecf | EUI-64 000fd720007d7ecf root directory ----------------------------------------------------------------- 414 00064c2d directory_length 6, crc 19501 418 03000fd7 vendor 41c 8100000a --> descriptor leaf at 444 420 17000001 model 424 8100000d --> descriptor leaf at 458 428 0c0087c0 node capabilities per IEEE 1394 42c d1000001 --> unit directory at 430 unit directory at 430 ----------------------------------------------------------------- 430 000438f2 directory_length 4, crc 14578 434 12000fd7 specifier id 438 13000001 version 43c 17000001 model 440 8100000d --> descriptor leaf at 474 descriptor leaf at 444 ----------------------------------------------------------------- 444 000489d5 leaf_length 4, crc 35285 448 00000000 textual descriptor 44c 00000000 minimal ASCII 450 4c657869 "Lexi" 454 636f6e00 "con" descriptor leaf at 458 ----------------------------------------------------------------- 458 0006594b leaf_length 6, crc 22859 45c 00000000 textual descriptor 460 00000000 minimal ASCII 464 492d4f4e "I-ON" 468 49585f46 "IX_F" 46c 57383130 "W810" 470 53000000 "S" descriptor leaf at 474 ----------------------------------------------------------------- 474 0006594b leaf_length 6, crc 22859 478 00000000 textual descriptor 47c 00000000 minimal ASCII 480 492d4f4e "I-ON" 484 49585f46 "IX_F" 488 57383130 "W810" 48c 53000000 "S" Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20210115035623.148580-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/dice/Makefile | 3 ++- sound/firewire/dice/dice-harman.c | 26 ++++++++++++++++++++++++++ sound/firewire/dice/dice.c | 12 ++++++++++++ sound/firewire/dice/dice.h | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 sound/firewire/dice/dice-harman.c diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile index 7a62dafd0f78..9bf7b960a720 100644 --- a/sound/firewire/dice/Makefile +++ b/sound/firewire/dice/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \ dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \ - dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o + dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o \ + dice-harman.o obj-$(CONFIG_SND_DICE) += snd-dice.o diff --git a/sound/firewire/dice/dice-harman.c b/sound/firewire/dice/dice-harman.c new file mode 100644 index 000000000000..a8ca00c397e8 --- /dev/null +++ b/sound/firewire/dice/dice-harman.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +// dice-harman.c - a part of driver for DICE based devices +// +// Copyright (c) 2021 Takashi Sakamoto +// +// Licensed under the terms of the GNU General Public License, version 2. + +#include "dice.h" + +int snd_dice_detect_harman_formats(struct snd_dice *dice) +{ + int i; + + // Lexicon I-ONYX FW810s supports sampling transfer frequency up to + // 96.0 kHz, 12 PCM channels and 1 MIDI channel in its first tx stream + // , 10 PCM channels and 1 MIDI channel in its first rx stream for all + // of the frequencies. + for (i = 0; i < 2; ++i) { + dice->tx_pcm_chs[0][i] = 12; + dice->tx_midi_ports[0] = 1; + dice->rx_pcm_chs[0][i] = 10; + dice->rx_midi_ports[0] = 1; + } + + return 0; +} diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 06c94f009dfb..107a81691f0e 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -20,10 +20,12 @@ MODULE_LICENSE("GPL v2"); #define OUI_MYTEK 0x001ee8 #define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE. #define OUI_PRESONUS 0x000a92 +#define OUI_HARMAN 0x000fd7 #define DICE_CATEGORY_ID 0x04 #define WEISS_CATEGORY_ID 0x00 #define LOUD_CATEGORY_ID 0x10 +#define HARMAN_CATEGORY_ID 0x20 #define MODEL_ALESIS_IO_BOTH 0x000001 @@ -56,6 +58,8 @@ static int check_dice_category(struct fw_unit *unit) category = WEISS_CATEGORY_ID; else if (vendor == OUI_LOUD) category = LOUD_CATEGORY_ID; + else if (vendor == OUI_HARMAN) + category = HARMAN_CATEGORY_ID; else category = DICE_CATEGORY_ID; if (device->config_rom[3] != ((vendor << 8) | category) || @@ -388,6 +392,14 @@ static const struct ieee1394_device_id dice_id_table[] = { .model_id = 0x000008, .driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats, }, + // Lexicon I-ONYX FW810S. + { + .match_flags = IEEE1394_MATCH_VENDOR_ID | + IEEE1394_MATCH_MODEL_ID, + .vendor_id = OUI_HARMAN, + .model_id = 0x000001, + .driver_data = (kernel_ulong_t)snd_dice_detect_harman_formats, + }, { .match_flags = IEEE1394_MATCH_VERSION, .version = DICE_INTERFACE, diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 7fbffcab94c2..adc6f7c84460 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -233,5 +233,6 @@ int snd_dice_detect_alesis_mastercontrol_formats(struct snd_dice *dice); int snd_dice_detect_extension_formats(struct snd_dice *dice); int snd_dice_detect_mytek_formats(struct snd_dice *dice); int snd_dice_detect_presonus_formats(struct snd_dice *dice); +int snd_dice_detect_harman_formats(struct snd_dice *dice); #endif -- cgit v1.2.3 From 669f65eaeb969ef60811939a5811479d3e8087af Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Jan 2021 13:54:11 +0100 Subject: ALSA: pci: Simplify with dma_set_mask_and_coherent() Many PCI drivers still have two explicit calls of dma_set_mask() and dma_set_coherent_mask(). Let's simplify with dma_set_mask_and_coherent(). Link: https://lore.kernel.org/r/20210114125412.993-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/ad1889.c | 3 +-- sound/pci/ali5451/ali5451.c | 3 +-- sound/pci/als300.c | 3 +-- sound/pci/als4000.c | 3 +-- sound/pci/au88x0/au88x0.c | 3 +-- sound/pci/aw2/aw2-alsa.c | 3 +-- sound/pci/azt3328.c | 3 +-- sound/pci/ca0106/ca0106_main.c | 3 +-- sound/pci/cs5535audio/cs5535audio.c | 3 +-- sound/pci/ctxfi/cthw20k1.c | 8 ++------ sound/pci/ctxfi/cthw20k2.c | 8 ++------ sound/pci/es1938.c | 3 +-- sound/pci/es1968.c | 3 +-- sound/pci/hda/hda_intel.c | 8 ++------ sound/pci/ice1712/ice1712.c | 3 +-- sound/pci/maestro3.c | 3 +-- sound/pci/sonicvibes.c | 3 +-- sound/pci/trident/trident_main.c | 3 +-- 18 files changed, 21 insertions(+), 48 deletions(-) diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 5d42c42491bf..5d835d2af054 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -857,8 +857,7 @@ snd_ad1889_create(struct snd_card *card, return err; /* check PCI availability (32bit DMA) */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { dev_err(card->dev, "error setting 32-bit DMA mask.\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 4462375d2d82..51f24796f03f 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2057,8 +2057,7 @@ static int snd_ali_create(struct snd_card *card, if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 31 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(31)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(31)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) { dev_err(card->dev, "architecture does not support 31bit PCI busmaster DMA\n"); pci_disable_device(pci); diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 8d2471ea090b..1dc8c4ed0592 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -625,8 +625,7 @@ static int snd_als300_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { dev_err(card->dev, "error setting 28bit DMA mask\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ba6390e9a694..2edc7455285a 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -837,8 +837,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci, return err; } /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index be276fb3f5af..5dd98e6ff34b 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -151,8 +151,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) // check PCI availability (DMA). if ((err = pci_enable_device(pci)) < 0) return err; - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { dev_err(card->dev, "error to set DMA mask\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index f1865afedc59..43396849a01c 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -236,8 +236,7 @@ static int snd_aw2_create(struct snd_card *card, pci_set_master(pci); /* check PCI availability (32bit DMA) */ - if ((dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) || - (dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0)) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { dev_err(card->dev, "Impossible to set 32bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 77c7030ebbfa..e3ea72a2116b 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2379,8 +2379,7 @@ snd_azf3328_create(struct snd_card *card, chip->irq = -1; /* check if we can restrict PCI DMA transfers to 24 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { dev_err(card->dev, "architecture does not support 24bit PCI busmaster DMA\n" ); diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index c189f70c82cb..ee20f9a1aae9 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1605,8 +1605,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card, err = pci_enable_device(pci); if (err < 0) return err; - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { dev_err(card->dev, "error to set 32bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 11ce3c4589fa..359bc6af8670 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -269,8 +269,7 @@ static int snd_cs5535audio_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { dev_warn(card->dev, "unable to get 32bit dma\n"); err = -ENXIO; goto pcifail; diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 108ab449c968..0cea4982ed7d 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1901,12 +1901,8 @@ static int hw_card_start(struct hw *hw) return err; /* Set DMA transfer mask */ - if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); - } else { - dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); - } + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits))) + dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)); if (!hw->io_base) { err = pci_request_regions(pci, "XFi"); diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index fc1bc18caee9..a855fb8c58bd 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -2026,12 +2026,8 @@ static int hw_card_start(struct hw *hw) return err; /* Set DMA transfer mask */ - if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); - } else { - dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); - } + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits))) + dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)); if (!hw->io_base) { err = pci_request_regions(pci, "XFi"); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 09704a78d799..3b5d68ce9dd5 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1560,8 +1560,7 @@ static int snd_es1938_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { dev_err(card->dev, "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index c6be14c4f311..747fa69bb1c9 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2668,8 +2668,7 @@ static int snd_es1968_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { dev_err(card->dev, "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 694d95e3a46e..292d3ff44709 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1967,12 +1967,8 @@ static int azx_first_init(struct azx *chip) /* allow 64bit DMA address if supported by H/W */ if (!(gcap & AZX_GCAP_64OK)) dma_bits = 32; - if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); - } else { - dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); - } + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits))) + dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)); /* read number of streams from GCAP register instead of using * hardcoded value diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 73e1e5400506..f814dbbec2a4 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2486,8 +2486,7 @@ static int snd_ice1712_create(struct snd_card *card, if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { dev_err(card->dev, "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index f622c2a6f746..d2c2cd6006f0 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2532,8 +2532,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, return -EIO; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { dev_err(card->dev, "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index bd805e416e12..26fd1d08c179 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1230,8 +1230,7 @@ static int snd_sonicvibes_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { dev_err(card->dev, "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 8d0d0d8335ec..20145143f6a6 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3497,8 +3497,7 @@ int snd_trident_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 30 bits */ - if (dma_set_mask(&pci->dev, DMA_BIT_MASK(30)) < 0 || - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(30)) < 0) { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) { dev_err(card->dev, "architecture does not support 30bit PCI busmaster DMA\n"); pci_disable_device(pci); -- cgit v1.2.3 From 915183b62276191ef767e00e683f4c085c4cc325 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Jan 2021 13:54:12 +0100 Subject: ALSA: x86: Simplify with dma_set_mask_and_coherent() LPE driver still has explicit calls of dma_set_mask() and dma_set_coherent_mask(). Let's simplify with dma_set_mask_and_coherent(). Link: https://lore.kernel.org/r/20210114125412.993-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/x86/intel_hdmi_audio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 5b351f4ca543..1d66c3a4fb10 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1770,8 +1770,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) card_ctx->irq = irq; /* only 32bit addressable */ - dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); init_channel_allocations(); -- cgit v1.2.3 From 16117beb16f01a470d40339960ffae1e287c03be Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 14 Jan 2021 19:43:24 -0800 Subject: ASoC: qcom: Remove useless debug print This looks like a left over debug print that tells us that HDMI is enabled. Let's remove it as that's definitely not an error to have HDMI enabled. Cc: V Sujith Kumar Reddy Cc: Srinivasa Rao Cc: Srinivas Kandagatla Cc: Cheng-Yi Chiang Fixes: 7cb37b7bd0d3 ("ASoC: qcom: Add support for lpass hdmi driver") Signed-off-by: Stephen Boyd Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210115034327.617223-2-swboyd@chromium.org Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index af684fd19ab9..8437ba31a306 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -742,7 +742,6 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev, } if (id == LPASS_DP_RX) { data->hdmi_port_enable = 1; - dev_err(dev, "HDMI Port is enabled: %d\n", id); } else { data->mi2s_playback_sd_mode[id] = of_lpass_cpu_parse_sd_lines(dev, node, -- cgit v1.2.3 From 03b49bf9a92b18bbfcc3b5eb206cca8447e9f2cb Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 14 Jan 2021 19:43:25 -0800 Subject: ASoC: qcom: Add some names to regmap configs This device can sometimes have multiple regmaps. Let's add a name so that we can differentiate in debugfs more easily. Cc: V Sujith Kumar Reddy Cc: Srinivasa Rao Cc: Srinivas Kandagatla Cc: Cheng-Yi Chiang Signed-off-by: Stephen Boyd Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210115034327.617223-3-swboyd@chromium.org Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 8437ba31a306..40126202a4a3 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -474,6 +474,7 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) } static struct regmap_config lpass_cpu_regmap_config = { + .name = "lpass_cpu", .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -674,6 +675,7 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg) } static struct regmap_config lpass_hdmi_regmap_config = { + .name = "lpass_hdmi", .reg_bits = 32, .reg_stride = 4, .val_bits = 32, -- cgit v1.2.3 From e697df66876c182927899950971c3b4888df3e6e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 14 Jan 2021 19:43:26 -0800 Subject: ASoC: qcom: Stop casting away __iomem for error pointers We don't need to cast away __iomem when testing with IS_ERR() or converting with PTR_ERR(). Modern sparse can handle this just fine. Drop it. Cc: V Sujith Kumar Reddy Cc: Srinivasa Rao Cc: Srinivas Kandagatla Cc: Cheng-Yi Chiang Signed-off-by: Stephen Boyd Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210115034327.617223-4-swboyd@chromium.org Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 40126202a4a3..b267fe8db3fc 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -788,10 +788,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); drvdata->lpaif = devm_ioremap_resource(dev, res); - if (IS_ERR((void const __force *)drvdata->lpaif)) { + if (IS_ERR(drvdata->lpaif)) { dev_err(dev, "error mapping reg resource: %ld\n", - PTR_ERR((void const __force *)drvdata->lpaif)); - return PTR_ERR((void const __force *)drvdata->lpaif); + PTR_ERR(drvdata->lpaif)); + return PTR_ERR(drvdata->lpaif); } lpass_cpu_regmap_config.max_register = LPAIF_WRDMAPER_REG(variant, @@ -810,10 +810,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-hdmiif"); drvdata->hdmiif = devm_ioremap_resource(dev, res); - if (IS_ERR((void const __force *)drvdata->hdmiif)) { + if (IS_ERR(drvdata->hdmiif)) { dev_err(dev, "error mapping reg resource: %ld\n", - PTR_ERR((void const __force *)drvdata->hdmiif)); - return PTR_ERR((void const __force *)drvdata->hdmiif); + PTR_ERR(drvdata->hdmiif)); + return PTR_ERR(drvdata->hdmiif); } lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant, -- cgit v1.2.3 From 4e15f5060d34dd28591cf3af43d3086a4b76c965 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 14 Jan 2021 19:43:27 -0800 Subject: ASoC: qcom: Remove duplicate error messages on ioremap We don't need to print an error message when these ioremap operations fail. The function that returns an error already prints an error message and properly attributes it to the device. Drop them to save some code. Cc: V Sujith Kumar Reddy Cc: Srinivasa Rao Cc: Srinivas Kandagatla Cc: Cheng-Yi Chiang Signed-off-by: Stephen Boyd Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210115034327.617223-5-swboyd@chromium.org Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index b267fe8db3fc..0ca957dcd3fe 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -788,11 +788,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); drvdata->lpaif = devm_ioremap_resource(dev, res); - if (IS_ERR(drvdata->lpaif)) { - dev_err(dev, "error mapping reg resource: %ld\n", - PTR_ERR(drvdata->lpaif)); + if (IS_ERR(drvdata->lpaif)) return PTR_ERR(drvdata->lpaif); - } lpass_cpu_regmap_config.max_register = LPAIF_WRDMAPER_REG(variant, variant->wrdma_channels + @@ -810,11 +807,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-hdmiif"); drvdata->hdmiif = devm_ioremap_resource(dev, res); - if (IS_ERR(drvdata->hdmiif)) { - dev_err(dev, "error mapping reg resource: %ld\n", - PTR_ERR(drvdata->hdmiif)); + if (IS_ERR(drvdata->hdmiif)) return PTR_ERR(drvdata->hdmiif); - } lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant, variant->hdmi_rdma_channels); -- cgit v1.2.3 From 7ef8c9edc86cff0881b2eb9a3274796258fbd872 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 15 Jan 2021 14:16:50 +0800 Subject: ASoC: codecs: soundwire: increase resume timeout The resume operation relies on multiple transactions to synchronize the regmap state, make sure the timeout is one order of magnitude larger than an individual transaction, so that timeouts of failed transactions are detected first. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Link: https://lore.kernel.org/r/20210115061651.9740-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 4 +++- sound/soc/codecs/rt1308-sdw.c | 2 +- sound/soc/codecs/rt5682.h | 2 +- sound/soc/codecs/rt700-sdw.c | 2 +- sound/soc/codecs/rt711-sdw.c | 2 +- sound/soc/codecs/rt715-sdw.c | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index b8d471d79e93..d8c47667a9ea 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -262,6 +262,8 @@ static __maybe_unused int max98373_suspend(struct device *dev) return 0; } +#define MAX98373_PROBE_TIMEOUT 5000 + static __maybe_unused int max98373_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -275,7 +277,7 @@ static __maybe_unused int max98373_resume(struct device *dev) goto regmap_sync; time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(2000)); + msecs_to_jiffies(MAX98373_PROBE_TIMEOUT)); if (!time) { dev_err(dev, "Initialization not complete, timed out\n"); return -ETIMEDOUT; diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index ec5564f780e8..afd2c3b687cc 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -701,7 +701,7 @@ static int __maybe_unused rt1308_dev_suspend(struct device *dev) return 0; } -#define RT1308_PROBE_TIMEOUT 2000 +#define RT1308_PROBE_TIMEOUT 5000 static int __maybe_unused rt1308_dev_resume(struct device *dev) { diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 99b85cfe6248..1f9c51a5b9bf 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1356,7 +1356,7 @@ #define RT5682_SAR_SOUR_TYPE (0x0) /* soundwire timeout */ -#define RT5682_PROBE_TIMEOUT 2000 +#define RT5682_PROBE_TIMEOUT 5000 #define RT5682_STEREO_RATES SNDRV_PCM_RATE_8000_192000 diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index fb77e77a4ebd..ce9255b881d4 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -490,7 +490,7 @@ static int __maybe_unused rt700_dev_suspend(struct device *dev) return 0; } -#define RT700_PROBE_TIMEOUT 2000 +#define RT700_PROBE_TIMEOUT 5000 static int __maybe_unused rt700_dev_resume(struct device *dev) { diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index fc7df79c3b91..756c0ada3b31 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -493,7 +493,7 @@ static int __maybe_unused rt711_dev_suspend(struct device *dev) return 0; } -#define RT711_PROBE_TIMEOUT 2000 +#define RT711_PROBE_TIMEOUT 5000 static int __maybe_unused rt711_dev_resume(struct device *dev) { diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 8f0aa1e8a273..71dd3b97a459 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -533,7 +533,7 @@ static int __maybe_unused rt715_dev_suspend(struct device *dev) return 0; } -#define RT715_PROBE_TIMEOUT 2000 +#define RT715_PROBE_TIMEOUT 5000 static int __maybe_unused rt715_dev_resume(struct device *dev) { -- cgit v1.2.3 From 160e8f96c626ae2bfeef18df467fd9f3814ec89a Mon Sep 17 00:00:00 2001 From: Michael Sit Wei Hong Date: Mon, 18 Jan 2021 18:27:06 +0800 Subject: ASoC: intel, keembay-i2s: Fix dt binding errors Fix devicetree binding errors caused by newly added parameters Signed-off-by: Michael Sit Wei Hong Link: https://lore.kernel.org/r/20210118102706.6125-1-michael.wei.hong.sit@intel.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index e0658f122cbb..dba25c33f0b0 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -47,13 +47,11 @@ properties: dmas: items: - - description: DMA controller phandle and DMA channel - for TX and RX + - description: DMA TX channel + - description: DMA RX channel dma-names: items: - - description: "tx" for the transmit channel - "rx" for the receive channel - const: tx - const: rx -- cgit v1.2.3 From 57c412d43d71b12df9aa414ec27cd793e9821274 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Mon, 18 Jan 2021 11:13:05 +0530 Subject: ASoC: audio-graph-card: Drop remote-endpoint as required property The remote-endpoint may not be available if it is part of some pluggable module. One such example would be an audio card, the Codec endpoint will not be available until it is plugged in. Hence drop 'remote-endpoint' as a required property. Cc: Rob Herring Cc: Kuninori Morimoto Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1610948585-16286-1-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/audio-graph-port.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml index 2005014161be..766e9109b2f7 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml @@ -71,9 +71,6 @@ properties: description: CPU to Codec rate channels. $ref: /schemas/types.yaml#/definitions/uint32 - required: - - remote-endpoint - ports: description: multi OF-Graph subnode type: object -- cgit v1.2.3 From 39860fe070c97e62ae9e80addce40ce0b3c2b082 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 14 Jan 2021 13:55:58 +0200 Subject: ASoC: SOF: Intel: initial support to AlderLake-P Add PCI id for the AlderLake-P. Signed-off-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210114115558.52699-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 5f53c3e76e6f..7757463bd81a 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -213,7 +213,7 @@ static const struct sof_dev_desc icl_desc = { }; #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) || IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) static const struct sof_dev_desc tgl_desc = { .machines = snd_soc_acpi_intel_tgl_machines, .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, @@ -230,7 +230,9 @@ static const struct sof_dev_desc tgl_desc = { .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", .ops = &sof_tgl_ops, }; +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) static const struct sof_dev_desc tglh_desc = { .machines = snd_soc_acpi_intel_tgl_machines, .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, @@ -517,6 +519,8 @@ static const struct pci_device_id sof_pci_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) { PCI_DEVICE(0x8086, 0x7ad0), .driver_data = (unsigned long)&adls_desc}, + { PCI_DEVICE(0x8086, 0x51c8), + .driver_data = (unsigned long)&tgl_desc}, #endif { 0, } }; -- cgit v1.2.3 From b952ac76a20bc0b23cd7e22de19fb407713238a3 Mon Sep 17 00:00:00 2001 From: Olivia Mackintosh Date: Mon, 18 Jan 2021 13:06:21 +0000 Subject: ALSA: usb-audio: Add support for Pioneer DJM-750 This adds the Pioneer DJ DJM-750 to the quirks table and ensures skip_pioneer_sync_ep() is (also) called: this device uses the vendor ID of 0x08e4 (I'm not sure why they use multiple vendor IDs but many just like to be awkward it seems). Playback on all 8 channels works. I'll likely keep this working in the future and submit futher patches and improvements as necessary. Signed-off-by: Olivia Mackintosh Link: https://lore.kernel.org/r/20210118130621.77miiie47wp7mump@base.nu Signed-off-by: Takashi Iwai --- sound/usb/implicit.c | 3 ++- sound/usb/quirks-table.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index 521cc846d9d9..e7216d0b860d 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -302,7 +302,8 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, /* Pioneer devices with vendor spec class */ if (attr == USB_ENDPOINT_SYNC_ASYNC && alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC && - USB_ID_VENDOR(chip->usb_id) == 0x2b73 /* Pioneer */) { + (USB_ID_VENDOR(chip->usb_id) == 0x2b73 || /* Pioneer */ + USB_ID_VENDOR(chip->usb_id) == 0x08e4 /* Pioneer */)) { if (skip_pioneer_sync_ep(chip, fmt, alts)) return 1; } diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index c8a4bdf18207..93d55cd1a5a4 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3757,6 +3757,66 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, +{ + /* + * Pioneer DJ DJM-750 + * 8 channels playback & 8 channels capture @ 44.1/48/96kHz S24LE + */ + USB_DEVICE_VENDOR_SPEC(0x08e4, 0x017f), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x05, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { 44100, 48000, 96000 } + } + }, + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x86, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_IMPLICIT_FB, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { 44100, 48000, 96000 } + } + }, + { + .ifnum = -1 + } + } + } +}, #undef USB_DEVICE_VENDOR_SPEC #undef USB_AUDIO_DEVICE -- cgit v1.2.3 From d3afb00220becf81bc2d9016f04e05949dfd5bb2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Jan 2021 14:33:35 +0100 Subject: ASoC: intel: skl: Simplify with dma_set_mask_and_coherent() ASoC Intel Skylake driver still has explicit calls of dma_set_mask() and dma_set_coherent_mask(). Let's simplify with dma_set_mask_and_coherent(). Cc: Cezary Rojewski Cc: Pierre-Louis Bossart Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20210114133337.1039-2-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 8b993722f74e..5b1a15e39912 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -950,12 +950,8 @@ static int skl_first_init(struct hdac_bus *bus) bus->num_streams = cp_streams + pb_streams; /* allow 64bit DMA address if supported by H/W */ - if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) { - dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64)); - } else { - dma_set_mask(bus->dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32)); - } + if (dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(64))) + dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(32)); /* initialize streams */ snd_hdac_ext_stream_init_all -- cgit v1.2.3 From ab152afa2427bb3e4eea7c9f21c4393287838774 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Jan 2021 14:33:36 +0100 Subject: ASoC: SOF: intel: Simplify with dma_set_mask_and_coherent() ASoC Intel SOF driver still has explicit calls of dma_set_mask() and dma_set_coherent_mask(). Let's simplify with dma_set_mask_and_coherent(). Cc: Pierre-Louis Bossart Cc: Ranjani Sridharan Cc: Kai Vehmanen Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20210114133337.1039-3-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 509a9b256423..7e703ce22fcd 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -809,13 +809,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) sdev->mailbox_bar = HDA_DSP_BAR; /* allow 64bit DMA address if supported by H/W */ - if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(64))) { - dev_dbg(sdev->dev, "DMA mask is 64 bit\n"); - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(64)); - } else { + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(64))) { dev_dbg(sdev->dev, "DMA mask is 32 bit\n"); - dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); - dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); + dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)); } /* init streams */ -- cgit v1.2.3 From 7cc206bff69b52be24fa13ee2c9afde3320c6cf6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Jan 2021 14:33:37 +0100 Subject: ASoC: tegra: Simplify with dma_set_mask_and_coherent() ASoC tegra PCM code still has explicit calls of dma_set_mask() and dma_set_coherent_mask(). Let's simplify with dma_set_mask_and_coherent(). Cc: Thierry Reding Cc: Jonathan Hunter Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20210114133337.1039-4-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_pcm.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index b3f36515cbc1..573374b89b10 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -255,11 +255,7 @@ static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd, struct snd_pcm *pcm = rtd->pcm; int ret; - ret = dma_set_mask(card->dev, DMA_BIT_MASK(32)); - if (ret < 0) - return ret; - - ret = dma_set_coherent_mask(card->dev, DMA_BIT_MASK(32)); + ret = dma_set_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret < 0) return ret; -- cgit v1.2.3 From 9e0f86fdcdab6a0e183ad4ec2410453985b4cf3c Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Tue, 19 Jan 2021 14:58:11 +0530 Subject: ASoC: dt-bindings: tegra: Add graph bindings Add device tree binding properties of generic graph to ASoC component devices. This allows to define audio ports out of these components or DAIs and audio graph based sound card can be realised with this. Signed-off-by: Sameer Pujar Reviewed-by: Jon Hunter Link: https://lore.kernel.org/r/1611048496-24650-2-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- .../bindings/sound/nvidia,tegra186-dspk.yaml | 18 +++++++++++++++++- .../bindings/sound/nvidia,tegra210-admaif.yaml | 13 ++++++++++++- .../bindings/sound/nvidia,tegra210-ahub.yaml | 13 +++++++++++-- .../bindings/sound/nvidia,tegra210-dmic.yaml | 18 +++++++++++++++++- .../devicetree/bindings/sound/nvidia,tegra210-i2s.yaml | 18 +++++++++++++++++- 5 files changed, 74 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml index ed2fb32fcdd4..b8645d9c38ac 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml @@ -17,6 +17,9 @@ maintainers: - Jon Hunter - Sameer Pujar +allOf: + - $ref: audio-graph-port.yaml# + properties: $nodename: pattern: "^dspk@[0-9a-f]*$" @@ -55,6 +58,19 @@ properties: The name can be "DSPK1" or "DSPKx", where x depends on the maximum available instances on a Tegra SoC. + ports: + type: object + properties: + port@0: + description: | + DSPK ACIF (Audio Client Interface) port connected to the + corresponding AHUB (Audio Hub) ACIF port. + + port@1: + description: | + DSPK DAP (Digital Audio Port) interface which can be connected + to external audio codec for playback. + required: - compatible - reg @@ -64,7 +80,7 @@ required: - assigned-clock-parents - sound-name-prefix -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml index c028b259e822..7cee7722df41 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml @@ -17,6 +17,9 @@ maintainers: - Jon Hunter - Sameer Pujar +allOf: + - $ref: audio-graph-port.yaml# + properties: $nodename: pattern: "^admaif@[0-9a-f]*$" @@ -37,6 +40,14 @@ properties: dma-names: true + ports: + description: | + Contains list of ACIF (Audio CIF) port nodes for ADMAIF channels. + The number of port nodes depends on the number of ADMAIF channels + that SoC may have. These are interfaced with respective ACIF ports + in AHUB (Audio Hub). Each port is capable of data transfers in + both directions. + if: properties: compatible: @@ -81,7 +92,7 @@ required: - dmas - dma-names -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml index d77219727768..31f3e51974bb 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml @@ -17,6 +17,9 @@ maintainers: - Jon Hunter - Sameer Pujar +allOf: + - $ref: audio-graph-port.yaml# + properties: $nodename: pattern: "^ahub@[0-9a-f]*$" @@ -56,6 +59,13 @@ properties: ranges: true + ports: + description: | + Contains list of ACIF (Audio CIF) port nodes for AHUB (Audio Hub). + These are connected to ACIF interfaces of AHUB clients. Thus the + number of port nodes depend on the number of clients that AHUB may + have depending on the SoC revision. + required: - compatible - reg @@ -67,8 +77,7 @@ required: - "#size-cells" - ranges -additionalProperties: - type: object +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml index 2a3207b550e7..89f4f471be24 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml @@ -16,6 +16,9 @@ maintainers: - Jon Hunter - Sameer Pujar +allOf: + - $ref: audio-graph-port.yaml# + properties: $nodename: pattern: "^dmic@[0-9a-f]*$" @@ -56,6 +59,19 @@ properties: The name can be "DMIC1" or "DMIC2" ... "DMICx", where x depends on the maximum available instances on a Tegra SoC. + ports: + type: object + properties: + port@0: + description: | + DMIC ACIF (Audio Client Interface) port connected to the + corresponding AHUB (Audio Hub) ACIF port. + + port@1: + description: | + DMIC DAP (Digital Audio Port) interface which can be connected + to external audio codec for capture. + required: - compatible - reg @@ -64,7 +80,7 @@ required: - assigned-clocks - assigned-clock-parents -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml index dfc1bf7b7722..556460332ffb 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml @@ -16,6 +16,9 @@ maintainers: - Jon Hunter - Sameer Pujar +allOf: + - $ref: audio-graph-port.yaml# + properties: $nodename: pattern: "^i2s@[0-9a-f]*$" @@ -74,6 +77,19 @@ properties: The name can be "I2S1" or "I2S2" ... "I2Sx", where x depends on the maximum available instances on a Tegra SoC. + ports: + type: object + properties: + port@0: + description: | + I2S ACIF (Audio Client Interface) port connected to the + corresponding AHUB (Audio Hub) ACIF port. + + port@1: + description: | + I2S DAP (Digital Audio Port) interface which can be connected + to external audio codec for playback or capture. + required: - compatible - reg @@ -82,7 +98,7 @@ required: - assigned-clocks - assigned-clock-parents -additionalProperties: false +unevaluatedProperties: false examples: - | -- cgit v1.2.3 From a9f22c03a8ac5d21ce7a9b9307d9654c963a1f9c Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Tue, 19 Jan 2021 14:58:12 +0530 Subject: ASoC: dt-bindings: tegra: Add json-schema for Tegra audio graph card Add YAML schema for Tegra audio graph sound card DT bindings. It uses the same DT bindings provided by generic audio graph driver. Along with this few standard clock DT bindings are added which are specifically required for Tegra audio. Signed-off-by: Sameer Pujar Reviewed-by: Jon Hunter Link: https://lore.kernel.org/r/1611048496-24650-3-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- .../sound/nvidia,tegra-audio-graph-card.yaml | 187 +++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml new file mode 100644 index 000000000000..fc271f644aaf --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml @@ -0,0 +1,187 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-graph-card.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Audio Graph based Tegra sound card driver + +description: | + This is based on generic audio graph card driver along with additional + customizations for Tegra platforms. It uses the same bindings with + additional standard clock DT bindings required for Tegra. + +maintainers: + - Jon Hunter + - Sameer Pujar + +allOf: + - $ref: audio-graph.yaml# + +properties: + compatible: + enum: + - nvidia,tegra210-audio-graph-card + - nvidia,tegra186-audio-graph-card + + clocks: + minItems: 2 + + clock-names: + minItems: 2 + items: + - const: pll_a + - const: plla_out0 + + assigned-clocks: + minItems: 1 + maxItems: 3 + + assigned-clock-parents: + minItems: 1 + maxItems: 3 + + assigned-clock-rates: + minItems: 1 + maxItems: 3 + +required: + - clocks + - clock-names + - assigned-clocks + - assigned-clock-parents + +unevaluatedProperties: false + +examples: + - | + #include + + tegra_sound { + compatible = "nvidia,tegra210-audio-graph-card"; + + clocks = <&tegra_car TEGRA210_CLK_PLL_A>, + <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + clock-names = "pll_a", "plla_out0"; + + assigned-clocks = <&tegra_car TEGRA210_CLK_PLL_A>, + <&tegra_car TEGRA210_CLK_PLL_A_OUT0>, + <&tegra_car TEGRA210_CLK_EXTERN1>; + assigned-clock-parents = <0>, <0>, <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <368640000>, <49152000>, <12288000>; + + dais = /* FE */ + <&admaif1_port>, + /* Router */ + <&xbar_i2s1_port>, + /* I/O DAP Ports */ + <&i2s1_port>; + + label = "jetson-tx1-ape"; + }; + + // The ports are defined for AHUB and its child devices. + ahub@702d0800 { + compatible = "nvidia,tegra210-ahub"; + reg = <0x702d0800 0x800>; + clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>; + clock-names = "ahub"; + assigned-clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x702d0000 0x702d0000 0x0000e400>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0x0>; + xbar_admaif1_ep: endpoint { + remote-endpoint = <&admaif1_ep>; + }; + }; + + // ... + + xbar_i2s1_port: port@a { + reg = <0xa>; + xbar_i2s1_ep: endpoint { + remote-endpoint = <&i2s1_cif_ep>; + }; + }; + }; + + admaif@702d0000 { + compatible = "nvidia,tegra210-admaif"; + reg = <0x702d0000 0x800>; + dmas = <&adma 1>, <&adma 1>, + <&adma 2>, <&adma 2>, + <&adma 3>, <&adma 3>, + <&adma 4>, <&adma 4>, + <&adma 5>, <&adma 5>, + <&adma 6>, <&adma 6>, + <&adma 7>, <&adma 7>, + <&adma 8>, <&adma 8>, + <&adma 9>, <&adma 9>, + <&adma 10>, <&adma 10>; + dma-names = "rx1", "tx1", + "rx2", "tx2", + "rx3", "tx3", + "rx4", "tx4", + "rx5", "tx5", + "rx6", "tx6", + "rx7", "tx7", + "rx8", "tx8", + "rx9", "tx9", + "rx10", "tx10"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + admaif1_port: port@0 { + reg = <0x0>; + admaif1_ep: endpoint { + remote-endpoint = <&xbar_admaif1_ep>; + }; + }; + + // More ADMAIF ports to follow + }; + }; + + i2s@702d1000 { + compatible = "nvidia,tegra210-i2s"; + clocks = <&tegra_car TEGRA210_CLK_I2S0>; + clock-names = "i2s"; + assigned-clocks = <&tegra_car TEGRA210_CLK_I2S0>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <1536000>; + reg = <0x702d1000 0x100>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0x0>; + + i2s1_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s1_ep>; + }; + }; + + i2s1_port: port@1 { + reg = <0x1>; + + i2s1_dap: endpoint { + dai-format = "i2s"; + }; + }; + }; + }; + }; + +... -- cgit v1.2.3 From 202e2f7745437aa5b694de92cbd30bb43b23fbed Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Tue, 19 Jan 2021 14:58:13 +0530 Subject: ASoC: tegra: Add audio graph based card driver Add Tegra audio machine driver which is based on generic audio graph card driver. It re-uses most of the common stuff from audio graph driver and uses the same DT binding. Required Tegra specific customizations are done in the driver and additional DT bindings are required for clock handling. Details on the customizations done: - Update PLL rates at runtime: Tegra HW supports multiple sample rates (multiples of 8x and 11.025x) and both of these groups require different PLL rates. Hence there is a requirement to update this at runtime. This is achieved by providing a custom 'snd_soc_ops' and in hw_param() callback PLL rate is updated as per the sample rate. - Internal structure 'tegra_audio_graph_data' is used to maintain clock handles of PLL. - The 'force_dpcm' flag is set to use DPCM for all DAI links. - The 'component_chaining' flag is set to use DPCM with component model. Signed-off-by: Sameer Pujar Reviewed-by: Jon Hunter Link: https://lore.kernel.org/r/1611048496-24650-4-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 9 ++ sound/soc/tegra/Makefile | 2 + sound/soc/tegra/tegra_audio_graph_card.c | 251 +++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 sound/soc/tegra/tegra_audio_graph_card.c diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index a62cc87551ac..6dc83ad8607a 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -117,6 +117,15 @@ config SND_SOC_TEGRA210_ADMAIF channel. Buffer size is configurable for each ADMAIIF channel. Say Y or M if you want to add support for Tegra210 ADMAIF module. +config SND_SOC_TEGRA_AUDIO_GRAPH_CARD + tristate "Audio Graph Card based Tegra driver" + depends on SND_AUDIO_GRAPH_CARD + help + Config to enable Tegra audio machine driver based on generic + audio graph driver. It is a thin driver written to customize + few things for Tegra audio. Most of the code is re-used from + audio graph driver and the same DT bindings are used. + config SND_SOC_TEGRA_RT5640 tristate "SoC Audio support for Tegra boards using an RT5640 codec" depends on SND_SOC_TEGRA && I2C && GPIOLIB diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 60040a06b814..b17dd6eef92a 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -38,6 +38,7 @@ snd-soc-tegra-trimslice-objs := trimslice.o snd-soc-tegra-alc5632-objs := tegra_alc5632.o snd-soc-tegra-max98090-objs := tegra_max98090.o snd-soc-tegra-sgtl5000-objs := tegra_sgtl5000.o +snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o @@ -48,3 +49,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o +obj-$(CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD) += snd-soc-tegra-audio-graph-card.o diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c new file mode 100644 index 000000000000..9e43f16f9336 --- /dev/null +++ b/sound/soc/tegra/tegra_audio_graph_card.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver +// +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include + +#define MAX_PLLA_OUT0_DIV 128 + +#define simple_to_tegra_priv(simple) \ + container_of(simple, struct tegra_audio_priv, simple) + +enum srate_type { + /* + * Sample rates multiple of 8000 Hz and below are supported: + * ( 8000, 16000, 32000, 48000, 96000, 192000 Hz ) + */ + x8_RATE, + + /* + * Sample rates multiple of 11025 Hz and below are supported: + * ( 11025, 22050, 44100, 88200, 176400 Hz ) + */ + x11_RATE, + + NUM_RATE_TYPE, +}; + +struct tegra_audio_priv { + struct asoc_simple_priv simple; + struct clk *clk_plla_out0; + struct clk *clk_plla; +}; + +/* Tegra audio chip data */ +struct tegra_audio_cdata { + unsigned int plla_rates[NUM_RATE_TYPE]; + unsigned int plla_out0_rates[NUM_RATE_TYPE]; +}; + +/* Setup PLL clock as per the given sample rate */ +static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(rtd->card); + struct tegra_audio_priv *priv = simple_to_tegra_priv(simple); + struct device *dev = rtd->card->dev; + const struct tegra_audio_cdata *data = of_device_get_match_data(dev); + unsigned int plla_rate, plla_out0_rate, bclk; + unsigned int srate = params_rate(params); + int err; + + switch (srate) { + case 11025: + case 22050: + case 44100: + case 88200: + case 176400: + plla_out0_rate = data->plla_out0_rates[x11_RATE]; + plla_rate = data->plla_rates[x11_RATE]; + break; + case 8000: + case 16000: + case 32000: + case 48000: + case 96000: + case 192000: + plla_out0_rate = data->plla_out0_rates[x8_RATE]; + plla_rate = data->plla_rates[x8_RATE]; + break; + default: + dev_err(rtd->card->dev, "Unsupported sample rate %u\n", + srate); + return -EINVAL; + } + + /* + * Below is the clock relation: + * + * PLLA + * | + * |--> PLLA_OUT0 + * | + * |---> I2S modules + * | + * |---> DMIC modules + * | + * |---> DSPK modules + * + * + * Default PLLA_OUT0 rate might be too high when I/O is running + * at minimum PCM configurations. This may result in incorrect + * clock rates and glitchy audio. The maximum divider is 128 + * and any thing higher than that won't work. Thus reduce PLLA_OUT0 + * to work for lower configurations. + * + * This problem is seen for I2S only, as DMIC and DSPK minimum + * clock requirements are under allowed divider limits. + */ + bclk = srate * params_channels(params) * params_width(params); + if (div_u64(plla_out0_rate, bclk) > MAX_PLLA_OUT0_DIV) + plla_out0_rate >>= 1; + + dev_dbg(rtd->card->dev, + "Update clock rates: PLLA(= %u Hz) and PLLA_OUT0(= %u Hz)\n", + plla_rate, plla_out0_rate); + + /* Set PLLA rate */ + err = clk_set_rate(priv->clk_plla, plla_rate); + if (err) { + dev_err(rtd->card->dev, + "Can't set plla rate for %u, err: %d\n", + plla_rate, err); + return err; + } + + /* Set PLLA_OUT0 rate */ + err = clk_set_rate(priv->clk_plla_out0, plla_out0_rate); + if (err) { + dev_err(rtd->card->dev, + "Can't set plla_out0 rate %u, err: %d\n", + plla_out0_rate, err); + return err; + } + + return err; +} + +static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + int err; + + /* + * This gets called for each DAI link (FE or BE) when DPCM is used. + * We may not want to update PLLA rate for each call. So PLLA update + * must be restricted to external I/O links (I2S, DMIC or DSPK) since + * they actually depend on it. I/O modules update their clocks in + * hw_param() of their respective component driver and PLLA rate + * update here helps them to derive appropriate rates. + * + * TODO: When more HW accelerators get added (like sample rate + * converter, volume gain controller etc., which don't really + * depend on PLLA) we need a better way to filter here. + */ + if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) { + err = tegra_audio_graph_update_pll(substream, params); + if (err) + return err; + } + + return asoc_simple_hw_params(substream, params); +} + +static const struct snd_soc_ops tegra_audio_graph_ops = { + .startup = asoc_simple_startup, + .shutdown = asoc_simple_shutdown, + .hw_params = tegra_audio_graph_hw_params, +}; + +static int tegra_audio_graph_card_probe(struct snd_soc_card *card) +{ + struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(card); + struct tegra_audio_priv *priv = simple_to_tegra_priv(simple); + + priv->clk_plla = devm_clk_get(card->dev, "pll_a"); + if (IS_ERR(priv->clk_plla)) { + dev_err(card->dev, "Can't retrieve clk pll_a\n"); + return PTR_ERR(priv->clk_plla); + } + + priv->clk_plla_out0 = devm_clk_get(card->dev, "plla_out0"); + if (IS_ERR(priv->clk_plla_out0)) { + dev_err(card->dev, "Can't retrieve clk plla_out0\n"); + return PTR_ERR(priv->clk_plla_out0); + } + + return graph_card_probe(card); +} + +static int tegra_audio_graph_probe(struct platform_device *pdev) +{ + struct tegra_audio_priv *priv; + struct device *dev = &pdev->dev; + struct snd_soc_card *card; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + card = simple_priv_to_card(&priv->simple); + + card->probe = tegra_audio_graph_card_probe; + + /* graph_parse_of() depends on below */ + card->component_chaining = 1; + priv->simple.ops = &tegra_audio_graph_ops; + priv->simple.force_dpcm = 1; + + return graph_parse_of(&priv->simple, dev); +} + +static const struct tegra_audio_cdata tegra210_data = { + /* PLLA */ + .plla_rates[x8_RATE] = 368640000, + .plla_rates[x11_RATE] = 338688000, + /* PLLA_OUT0 */ + .plla_out0_rates[x8_RATE] = 49152000, + .plla_out0_rates[x11_RATE] = 45158400, +}; + +static const struct tegra_audio_cdata tegra186_data = { + /* PLLA */ + .plla_rates[x8_RATE] = 245760000, + .plla_rates[x11_RATE] = 270950400, + /* PLLA_OUT0 */ + .plla_out0_rates[x8_RATE] = 49152000, + .plla_out0_rates[x11_RATE] = 45158400, +}; + +static const struct of_device_id graph_of_tegra_match[] = { + { .compatible = "nvidia,tegra210-audio-graph-card", + .data = &tegra210_data }, + { .compatible = "nvidia,tegra186-audio-graph-card", + .data = &tegra186_data }, + {}, +}; +MODULE_DEVICE_TABLE(of, graph_of_tegra_match); + +static struct platform_driver tegra_audio_graph_card = { + .driver = { + .name = "tegra-audio-graph-card", + .pm = &snd_soc_pm_ops, + .of_match_table = graph_of_tegra_match, + }, + .probe = tegra_audio_graph_probe, +}; +module_platform_driver(tegra_audio_graph_card); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("ASoC Tegra Audio Graph Sound Card"); +MODULE_AUTHOR("Sameer Pujar "); -- cgit v1.2.3 From f4d3bd8be4f2bc43e4b13490cbc9969d15c2f058 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Hsu Date: Fri, 15 Jan 2021 15:53:00 +0800 Subject: cros_ec_commands: Add EC_CODEC_I2S_RX_RESET Add the new command EC_CODEC_I2S_RX_RESET in ec_codec_i2s_rx_subcmd, which is used for resetting the EC codec. Signed-off-by: Yu-Hsuan Hsu Acked-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20210115075301.47995-1-yuhsuan@chromium.org Signed-off-by: Mark Brown --- include/linux/platform_data/cros_ec_commands.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 86376779ab31..95889ada83a3 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -4600,6 +4600,7 @@ enum ec_codec_i2s_rx_subcmd { EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH = 0x2, EC_CODEC_I2S_RX_SET_DAIFMT = 0x3, EC_CODEC_I2S_RX_SET_BCLK = 0x4, + EC_CODEC_I2S_RX_RESET = 0x5, EC_CODEC_I2S_RX_SUBCMD_COUNT, }; -- cgit v1.2.3 From 7f1f7ae102ea082745e320b3c8c003f43c063edf Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Hsu Date: Fri, 15 Jan 2021 15:53:01 +0800 Subject: ASoC: cros_ec_codec: Reset I2S RX when probing It is not guaranteed that I2S RX is disabled when the kernel booting. For example, if the kernel crashes while it is enabled, it will keep enabled until the next time EC reboots. Reset I2S RX when probing to fix this issue. Signed-off-by: Yu-Hsuan Hsu Reviewed-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20210115075301.47995-2-yuhsuan@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index f33a2a9654e7..c4772f82485a 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -1011,6 +1011,18 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev) } priv->ec_capabilities = r.capabilities; + /* Reset EC codec i2s rx. */ + p.cmd = EC_CODEC_I2S_RX_RESET; + ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX, + (uint8_t *)&p, sizeof(p), NULL, 0); + if (ret == -ENOPROTOOPT) { + dev_info(dev, + "Missing reset command. Please update EC firmware.\n"); + } else if (ret) { + dev_err(dev, "failed to EC_CODEC_I2S_RESET: %d\n", ret); + return ret; + } + platform_set_drvdata(pdev, priv); ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver, -- cgit v1.2.3 From 0dedbde5062dbc3cf71ab1ba40792c04a68008e9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 12 Jan 2021 18:47:04 +0100 Subject: ASoC: cpcap: Implement set_tdm_slot for voice call support ASoC: cpcap: Implement set_tdm_slot for voice call support For using cpcap for voice calls, we need to route audio directly from the modem to cpcap for TDM (Time Division Multiplexing). The voice call is direct data between the modem and cpcap with no CPU involvment. In this mode, the cpcap related audio mixer controls work for the speaker selection and volume though. To do this, we need to implement standard snd_soc_dai_set_tdm_slot() for cpcap. Then the modem codec driver can use snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt(), and snd_soc_dai_set_tdm_slot() to configure a voice call. Let's add cpcap_voice_set_tdm_slot() for this, and cpcap_voice_call() helper to configure the additional registers needed for voice call. Let's also clear CPCAP_REG_VAUDIOC on init in case we have the bit for CPCAP_BIT_VAUDIO_MODE0 set on init. Signed-off-by: Tony Lindgren Signed-off-by: Pavel Machek Link: https://lore.kernel.org/r/20210112174704.GA13496@duo.ucw.cz Signed-off-by: Mark Brown --- sound/soc/codecs/cpcap.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index f046987ee4cd..e266d993ab2a 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -16,6 +16,14 @@ #include #include +/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */ +#define CPCAP_BIT_AUDIO_LOW_PWR 6 +#define CPCAP_BIT_AUD_LOWPWR_SPEED 5 +#define CPCAP_BIT_VAUDIOPRISTBY 4 +#define CPCAP_BIT_VAUDIO_MODE1 2 +#define CPCAP_BIT_VAUDIO_MODE0 1 +#define CPCAP_BIT_V_AUDIO_EN 0 + /* Register 513 CPCAP_REG_CC --- CODEC */ #define CPCAP_BIT_CDC_CLK2 15 #define CPCAP_BIT_CDC_CLK1 14 @@ -221,6 +229,7 @@ struct cpcap_reg_info { }; static const struct cpcap_reg_info cpcap_default_regs[] = { + { CPCAP_REG_VAUDIOC, 0x003F, 0x0000 }, { CPCAP_REG_CC, 0xFFFF, 0x0000 }, { CPCAP_REG_CC, 0xFFFF, 0x0000 }, { CPCAP_REG_CDI, 0xBFFF, 0x0000 }, @@ -1371,8 +1380,121 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int cpcap_voice_set_mute(struct snd_soc_dai *dai, - int mute, int direction) + +/* + * Configure codec for voice call if requested. + * + * We can configure most with snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt() + * and snd_soc_dai_set_tdm_slot(). This function configures the rest of the + * cpcap related hardware as CPU is not involved in the voice call. + */ +static int cpcap_voice_call(struct cpcap_audio *cpcap, struct snd_soc_dai *dai, + bool voice_call) +{ + int mask, err; + + /* Modem to codec VAUDIO_MODE1 */ + mask = BIT(CPCAP_BIT_VAUDIO_MODE1); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_VAUDIOC, + mask, voice_call ? mask : 0); + if (err) + return err; + + /* Clear MIC1_MUX for call */ + mask = BIT(CPCAP_BIT_MIC1_MUX); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI, + mask, voice_call ? 0 : mask); + if (err) + return err; + + /* Set MIC2_MUX for call */ + mask = BIT(CPCAP_BIT_MB_ON1L) | BIT(CPCAP_BIT_MB_ON1R) | + BIT(CPCAP_BIT_MIC2_MUX) | BIT(CPCAP_BIT_MIC2_PGA_EN); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI, + mask, voice_call ? mask : 0); + if (err) + return err; + + /* Enable LDSP for call */ + mask = BIT(CPCAP_BIT_A2_LDSP_L_EN) | BIT(CPCAP_BIT_A2_LDSP_R_EN); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA, + mask, voice_call ? mask : 0); + if (err) + return err; + + /* Enable CPCAP_BIT_PGA_CDC_EN for call */ + mask = BIT(CPCAP_BIT_PGA_CDC_EN); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA, + mask, voice_call ? mask : 0); + if (err) + return err; + + /* Unmute voice for call */ + if (dai) { + err = snd_soc_dai_digital_mute(dai, !voice_call, + SNDRV_PCM_STREAM_PLAYBACK); + if (err) + return err; + } + + /* Set modem to codec mic CDC and HPF for call */ + mask = BIT(CPCAP_BIT_MIC2_CDC_EN) | BIT(CPCAP_BIT_CDC_EN_RX) | + BIT(CPCAP_BIT_AUDOHPF_1) | BIT(CPCAP_BIT_AUDOHPF_0) | + BIT(CPCAP_BIT_AUDIHPF_1) | BIT(CPCAP_BIT_AUDIHPF_0); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CC, + mask, voice_call ? mask : 0); + if (err) + return err; + + /* Enable modem to codec CDC for call*/ + mask = BIT(CPCAP_BIT_CDC_CLK_EN); + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI, + mask, voice_call ? mask : 0); + + return err; +} + +static int cpcap_voice_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); + int err, ts_mask, mask; + bool voice_call; + + /* + * Primitive test for voice call, probably needs more checks + * later on for 16-bit calls detected, Bluetooth headset etc. + */ + if (tx_mask == 0 && rx_mask == 1 && slot_width == 8) + voice_call = true; + else + voice_call = false; + + ts_mask = 0x7 << CPCAP_BIT_MIC2_TIMESLOT0; + ts_mask |= 0x7 << CPCAP_BIT_MIC1_RX_TIMESLOT0; + + mask = (tx_mask & 0x7) << CPCAP_BIT_MIC2_TIMESLOT0; + mask |= (rx_mask & 0x7) << CPCAP_BIT_MIC1_RX_TIMESLOT0; + + err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI, + ts_mask, mask); + if (err) + return err; + + err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, slot_width * 1000); + if (err) + return err; + + err = cpcap_voice_call(cpcap, dai, voice_call); + if (err) + return err; + + return 0; +} + +static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); @@ -1393,6 +1515,7 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = { .hw_params = cpcap_voice_hw_params, .set_sysclk = cpcap_voice_set_dai_sysclk, .set_fmt = cpcap_voice_set_dai_fmt, + .set_tdm_slot = cpcap_voice_set_tdm_slot, .mute_stream = cpcap_voice_set_mute, .no_capture_mute = 1, }; -- cgit v1.2.3 From 4e37528a97bfffb2cd4f645c945759e76d583848 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 20 Jan 2021 16:08:46 +0800 Subject: ASoC: mediatek: mt8192-mt6359: move headset_jack to card specific data Moves headset_jack to card specific data. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210120080850.699354-2-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index a988ce1e58de..72d337fc8534 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -31,7 +31,9 @@ #define RT5682_CODEC_DAI "rt5682-aif1" #define RT5682_DEV0_NAME "rt5682.1-001a" -static struct snd_soc_jack headset_jack; +struct mt8192_mt6359_priv { + struct snd_soc_jack headset_jack; +}; static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -305,7 +307,8 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *cmpnt_codec = asoc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_jack *jack = &headset_jack; + struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &priv->headset_jack; int ret; ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", @@ -1038,6 +1041,7 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) int ret, i; struct snd_soc_dai_link *dai_link; const struct of_device_id *match; + struct mt8192_mt6359_priv *priv; platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); @@ -1083,6 +1087,11 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) dai_link->platforms->of_node = platform_node; } + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + snd_soc_card_set_drvdata(card, priv); + ret = mt8192_afe_gpio_init(&pdev->dev); if (ret) { dev_err(&pdev->dev, "init gpio error %d\n", ret); -- cgit v1.2.3 From 12295ef97078db19683d8c0a23abc6f633ef0e23 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 20 Jan 2021 16:08:47 +0800 Subject: ASoC: mediatek: mt8192-mt6359: simplify mt8192_rt5682_init Returns snd_soc_component_set_jack() directly in mt8192_rt5682_init. No need to have another block to check the return value. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210120080850.699354-3-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 72d337fc8534..8ea24b32a535 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -326,13 +326,7 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd) snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL); - if (ret) { - dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret); - return ret; - } - - return 0; + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); }; static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, -- cgit v1.2.3 From df369921d726410a093de48d33e605fd4e0ee33c Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 20 Jan 2021 16:08:48 +0800 Subject: ASoC: mediatek: mt8192: change mclk_multiple of TDM from 128 to 512 mclk = rate * mclk_multiple bclk = rate * channel * sample_width If TDM outputs 8 channels and 32 bits, bclk will be greater than mclk. Changes the ratio from 128 to 512. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210120080850.699354-4-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-dai-tdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c index 8383536b7ae0..f5de1d769679 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c @@ -738,7 +738,7 @@ static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe) if (!tdm_priv) return NULL; - tdm_priv->mclk_multiple = 128; + tdm_priv->mclk_multiple = 512; tdm_priv->bck_id = MT8192_I2S4_BCK; tdm_priv->mclk_id = MT8192_I2S4_MCK; tdm_priv->id = MT8192_DAI_TDM; -- cgit v1.2.3 From 9bc20e8076c96a54c9fb20228d12ff35c88447d5 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 20 Jan 2021 16:08:49 +0800 Subject: ASoC: dt-bindings: mt8192-mt6359: add hdmi-codec property Adds optional property "hdmi-codec". If specified, the machine driver should: - Exposes a device that can write audio data to the DP bridge. - Detects jack plug events. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210120080850.699354-5-tzungbi@google.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml index bf8c8ba25009..a781e7aaaa38 100644 --- a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml +++ b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml @@ -23,6 +23,10 @@ properties: $ref: "/schemas/types.yaml#/definitions/phandle" description: The phandle of MT8192 ASoC platform. + mediatek,hdmi-codec: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: The phandle of HDMI codec. + additionalProperties: false required: @@ -35,6 +39,7 @@ examples: sound: mt8192-sound { compatible = "mediatek,mt8192_mt6359_rt1015_rt5682"; mediatek,platform = <&afe>; + mediatek,hdmi-codec = <&anx_bridge_dp>; pinctrl-names = "aud_clk_mosi_off", "aud_clk_mosi_on"; pinctrl-0 = <&aud_clk_mosi_off>; -- cgit v1.2.3 From 0d80c48c847842de488e76ae434ccb74397623c3 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 20 Jan 2021 16:08:50 +0800 Subject: ASoC: mediatek: mt8192-mt6359: support audio over DP If the DTS property is specified, the DP bridge should populate a "hdmi-codec" platform device (sound/soc/codecs/hdmi-codec.c). The "hdmi-codec" device is the communication relayer between the ASoC machine driver and the DP bridge. For example: - Notifies DP bridge when setting hw_param. - Notifies ASoC when jack detection events. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210120080850.699354-6-tzungbi@google.com Signed-off-by: Mark Brown --- .../mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 39 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 8ea24b32a535..cc0fc72305d2 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -33,6 +33,7 @@ struct mt8192_mt6359_priv { struct snd_soc_jack headset_jack; + struct snd_soc_jack hdmi_jack; }; static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, @@ -329,6 +330,23 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd) return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); }; +static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) { + dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); + return ret; + } + + return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); +} + static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -600,7 +618,7 @@ SND_SOC_DAILINK_DEFS(pcm2, SND_SOC_DAILINK_DEFS(tdm, DAILINK_COMP_ARRAY(COMP_CPU("TDM")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { @@ -936,8 +954,14 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { { .name = "TDM", .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM, .dpcm_playback = 1, .ignore_suspend = 1, + .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, + .ignore = 1, + .init = mt8192_mt6359_hdmi_init, SND_SOC_DAILINK_REG(tdm), }, }; @@ -948,6 +972,7 @@ mt8192_mt6359_rt1015_rt5682_widgets[] = { SND_SOC_DAPM_SPK("Right Spk", NULL), SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_OUTPUT("TDM Out"), }; static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = { @@ -958,6 +983,8 @@ static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = { { "Headphone Jack", NULL, "HPOL" }, { "Headphone Jack", NULL, "HPOR" }, { "IN1P", NULL, "Headset Mic" }, + /* TDM */ + { "TDM Out", NULL, "TDM" }, }; static const struct snd_kcontrol_new mt8192_mt6359_rt1015_rt5682_controls[] = { @@ -1031,7 +1058,7 @@ static struct snd_soc_card mt8192_mt6359_rt1015p_rt5682_card = { static int mt8192_mt6359_dev_probe(struct platform_device *pdev) { struct snd_soc_card *card; - struct device_node *platform_node; + struct device_node *platform_node, *hdmi_codec; int ret, i; struct snd_soc_dai_link *dai_link; const struct of_device_id *match; @@ -1051,6 +1078,9 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) card = (struct snd_soc_card *)match->data; card->dev = &pdev->dev; + hdmi_codec = of_parse_phandle(pdev->dev.of_node, + "mediatek,hdmi-codec", 0); + for_each_card_prelinks(card, i, dai_link) { if (strcmp(dai_link->name, "I2S3") == 0) { if (card == &mt8192_mt6359_rt1015_rt5682_card) { @@ -1077,6 +1107,11 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) } } + if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) { + dai_link->codecs->of_node = hdmi_codec; + dai_link->ignore = 0; + } + if (!dai_link->platforms->name) dai_link->platforms->of_node = platform_node; } -- cgit v1.2.3 From 9ce63203eb2071fe0117d2e2454c19d79af4a2f1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 Jan 2021 09:38:10 -0300 Subject: ASoC: fsl_ssi: Use of_device_get_match_data() The retrieval of driver data via of_device_get_match_data() can make the code simpler. Use of_device_get_match_data() to simplify the code. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210118123815.1630882-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 404be27c15fe..db4ba5f22b77 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1397,18 +1397,11 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi) { struct device *dev = ssi->dev; struct device_node *np = dev->of_node; - const struct of_device_id *of_id; const char *p, *sprop; const __be32 *iprop; u32 dmas[4]; int ret; - of_id = of_match_device(fsl_ssi_ids, dev); - if (!of_id || !of_id->data) - return -EINVAL; - - ssi->soc = of_id->data; - ret = of_property_match_string(np, "clock-names", "ipg"); /* Get error code if not found */ ssi->has_ipg_clk_name = ret >= 0; @@ -1492,6 +1485,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) return -ENOMEM; ssi->dev = dev; + ssi->soc = of_device_get_match_data(&pdev->dev); /* Probe from DT */ ret = fsl_ssi_probe_from_dt(ssi); -- cgit v1.2.3 From d7388718d491463ed0fb7383a4c678b94fdda785 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 Jan 2021 09:38:11 -0300 Subject: ASoC: fsl_micfil: Use of_device_get_match_data() The retrieval of driver data via of_device_get_match_data() can make the code simpler. Use of_device_get_match_data() to simplify the code. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210118123815.1630882-2-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index efc5daf53bba..8aedf6590b28 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -637,7 +637,6 @@ static irqreturn_t micfil_err_isr(int irq, void *devid) static int fsl_micfil_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_id; struct fsl_micfil *micfil; struct resource *res; void __iomem *regs; @@ -651,11 +650,7 @@ static int fsl_micfil_probe(struct platform_device *pdev) micfil->pdev = pdev; strncpy(micfil->name, np->name, sizeof(micfil->name) - 1); - of_id = of_match_device(fsl_micfil_dt_ids, &pdev->dev); - if (!of_id || !of_id->data) - return -EINVAL; - - micfil->soc = of_id->data; + micfil->soc = of_device_get_match_data(&pdev->dev); /* ipg_clk is used to control the registers * ipg_clk_app is used to operate the filter -- cgit v1.2.3 From 42450175a3d21d0818976114833d23ca5035e713 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 Jan 2021 09:38:12 -0300 Subject: ASoC: fsl_xcvr: Remove unused of_id variable The of_id variable is not used, so just remove it. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210118123815.1630882-3-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 3d58c88ea603..dd228b421e2c 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1130,16 +1130,11 @@ MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids); static int fsl_xcvr_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *of_id; struct fsl_xcvr *xcvr; struct resource *ram_res, *regs_res, *rx_res, *tx_res; void __iomem *regs; int ret, irq; - of_id = of_match_device(fsl_xcvr_dt_ids, dev); - if (!of_id) - return -EINVAL; - xcvr = devm_kzalloc(dev, sizeof(*xcvr), GFP_KERNEL); if (!xcvr) return -ENOMEM; -- cgit v1.2.3 From 214172a9ca26f77c3d6912f97246dc6ec9b16141 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 Jan 2021 09:38:13 -0300 Subject: ASoC: fsl_asrc: Remove of_device_get_match_data() error check The only way this driver can be probed is via devicetree, which always provides driver data. Remove the unneeded of_device_get_match_data() error check, as it can never fail. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210118123815.1630882-4-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 02c81d2e34ad..c325c984d165 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1083,11 +1083,6 @@ static int fsl_asrc_probe(struct platform_device *pdev) } asrc_priv->soc = of_device_get_match_data(&pdev->dev); - if (!asrc_priv->soc) { - dev_err(&pdev->dev, "failed to get soc data\n"); - return -ENODEV; - } - asrc->use_edma = asrc_priv->soc->use_edma; asrc->get_dma_channel = fsl_asrc_get_dma_channel; asrc->request_pair = fsl_asrc_request_pair; -- cgit v1.2.3 From 1ccf6e6ef9261c0c8c0be495070c45c030adcc40 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 Jan 2021 09:38:14 -0300 Subject: ASoC: fsl_esai: Remove of_device_get_match_data() error check The only way this driver can be probed is via devicetree, which always provides driver data. Remove the unneeded of_device_get_match_data() error check, as it can never fail. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210118123815.1630882-5-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 39637ca78cdb..614e22a95f53 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -967,10 +967,6 @@ static int fsl_esai_probe(struct platform_device *pdev) snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); esai_priv->soc = of_device_get_match_data(&pdev->dev); - if (!esai_priv->soc) { - dev_err(&pdev->dev, "failed to get soc data\n"); - return -ENODEV; - } /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3 From 4e63b56593e25937f22c01ae60574a3b0548553c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 18 Jan 2021 09:38:15 -0300 Subject: ASoC: fsl_spdif: Remove of_device_get_match_data() error check The only way this driver can be probed is via devicetree, which always provides driver data. Remove the unneeded of_device_get_match_data() error check, as it can never fail. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210118123815.1630882-6-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 5fa178f3f497..b4d3b04694bf 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1305,10 +1305,6 @@ static int fsl_spdif_probe(struct platform_device *pdev) spdif_priv->pdev = pdev; spdif_priv->soc = of_device_get_match_data(&pdev->dev); - if (!spdif_priv->soc) { - dev_err(&pdev->dev, "failed to get soc data\n"); - return -ENODEV; - } /* Initialize this copy of the CPU DAI driver structure */ memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); -- cgit v1.2.3 From 61fbeb5dcb3debb88d9f2eeed7e599b1ed7e3344 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jan 2021 17:25:52 +0100 Subject: ASoC: remove sirf prima/atlas drivers The CSR SiRF prima2/atlas platforms are getting removed, so this driver is no longer needed. Signed-off-by: Arnd Bergmann Acked-by: Barry Song Link: https://lore.kernel.org/r/20210120162553.21666-2-arnd@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/sirf-audio-codec.txt | 17 - .../devicetree/bindings/sound/sirf-usp.txt | 27 - sound/soc/Kconfig | 1 - sound/soc/Makefile | 1 - sound/soc/codecs/Makefile | 2 - sound/soc/codecs/sirf-audio-codec.c | 575 --------------------- sound/soc/sirf/Kconfig | 21 - sound/soc/sirf/Makefile | 8 - sound/soc/sirf/sirf-audio-port.c | 86 --- sound/soc/sirf/sirf-audio.c | 160 ------ sound/soc/sirf/sirf-usp.c | 435 ---------------- sound/soc/sirf/sirf-usp.h | 292 ----------- 12 files changed, 1625 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/sirf-audio-codec.txt delete mode 100644 Documentation/devicetree/bindings/sound/sirf-usp.txt delete mode 100644 sound/soc/codecs/sirf-audio-codec.c delete mode 100644 sound/soc/sirf/Kconfig delete mode 100644 sound/soc/sirf/Makefile delete mode 100644 sound/soc/sirf/sirf-audio-port.c delete mode 100644 sound/soc/sirf/sirf-audio.c delete mode 100644 sound/soc/sirf/sirf-usp.c delete mode 100644 sound/soc/sirf/sirf-usp.h diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt deleted file mode 100644 index 062f5ec36f9b..000000000000 --- a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt +++ /dev/null @@ -1,17 +0,0 @@ -SiRF internal audio CODEC - -Required properties: - - - compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec" - - - reg : the register address of the device. - - - clocks: the clock of SiRF internal audio codec - -Example: - -audiocodec: audiocodec@b0040000 { - compatible = "sirf,atlas6-audio-codec"; - reg = <0xb0040000 0x10000>; - clocks = <&clks 27>; -}; diff --git a/Documentation/devicetree/bindings/sound/sirf-usp.txt b/Documentation/devicetree/bindings/sound/sirf-usp.txt deleted file mode 100644 index 02f85b32d359..000000000000 --- a/Documentation/devicetree/bindings/sound/sirf-usp.txt +++ /dev/null @@ -1,27 +0,0 @@ -* SiRF SoC USP module - -Required properties: -- compatible: "sirf,prima2-usp-pcm" -- reg: Base address and size entries: -- dmas: List of DMA controller phandle and DMA request line ordered pairs. -- dma-names: Identifier string for each DMA request line in the dmas property. - These strings correspond 1:1 with the ordered pairs in dmas. - - One of the DMA channels will be responsible for transmission (should be - named "tx") and one for reception (should be named "rx"). - -- clocks: USP controller clock source -- pinctrl-names: Must contain a "default" entry. -- pinctrl-NNN: One property must exist for each entry in pinctrl-names. - -Example: -usp0: usp@b0080000 { - compatible = "sirf,prima2-usp-pcm"; - reg = <0xb0080000 0x10000>; - clocks = <&clks 28>; - dmas = <&dmac1 1>, <&dmac1 2>; - dma-names = "rx", "tx"; - pinctrl-names = "default"; - pinctrl-0 = <&usp0_only_utfs_pins_a>; -}; - diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 47da9ce17693..547b26ca714f 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -62,7 +62,6 @@ source "sound/soc/qcom/Kconfig" source "sound/soc/rockchip/Kconfig" source "sound/soc/samsung/Kconfig" source "sound/soc/sh/Kconfig" -source "sound/soc/sirf/Kconfig" source "sound/soc/sof/Kconfig" source "sound/soc/spear/Kconfig" source "sound/soc/sprd/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 508dbaa1814e..74508b0f9c47 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_SND_SOC) += qcom/ obj-$(CONFIG_SND_SOC) += rockchip/ obj-$(CONFIG_SND_SOC) += samsung/ obj-$(CONFIG_SND_SOC) += sh/ -obj-$(CONFIG_SND_SOC) += sirf/ obj-$(CONFIG_SND_SOC) += sof/ obj-$(CONFIG_SND_SOC) += spear/ obj-$(CONFIG_SND_SOC) += sprd/ diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d277f0366e09..c30762fc9b87 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -201,7 +201,6 @@ snd-soc-sigmadsp-objs := sigmadsp.o snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o snd-soc-si476x-objs := si476x.o -snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-rx-objs := spdif_receiver.o snd-soc-ssm2305-objs := ssm2305.o @@ -516,7 +515,6 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o -obj-$(CONFIG_SND_SOC_SIRF_AUDIO_CODEC) += sirf-audio-codec.o obj-$(CONFIG_SND_SOC_SSM2305) += snd-soc-ssm2305.o obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c deleted file mode 100644 index a061d78473ac..000000000000 --- a/sound/soc/codecs/sirf-audio-codec.c +++ /dev/null @@ -1,575 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * SiRF audio codec driver - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sirf-audio-codec.h" - -struct sirf_audio_codec { - struct clk *clk; - struct regmap *regmap; - u32 reg_ctrl0, reg_ctrl1; -}; - -static const char * const input_mode_mux[] = {"Single-ended", - "Differential"}; - -static const struct soc_enum input_mode_mux_enum = - SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux); - -static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control = - SOC_DAPM_ENUM("Route", input_mode_mux_enum); - -static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0); -static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0); -static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6, - 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0), - 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0), -); - -static struct snd_kcontrol_new volume_controls_atlas6[] = { - SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, - 0x7F, 0, playback_vol_tlv), - SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10, - 0x3F, 0, capture_vol_tlv_atlas6), -}; - -static struct snd_kcontrol_new volume_controls_prima2[] = { - SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, - 0x7F, 0, playback_vol_tlv), - SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10, - 0x1F, 0, capture_vol_tlv_prima2), -}; - -static struct snd_kcontrol_new left_input_path_controls[] = { - SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0), - SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0), -}; - -static struct snd_kcontrol_new right_input_path_controls[] = { - SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0), - SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0), -}; - -static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control = - SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0); - -static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control = - SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0); - -static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control = - SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0); - -static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control = - SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0); - -static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control = - SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0); - -static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control = - SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0); - -/* After enable adc, Delay 200ms to avoid pop noise */ -static int adc_enable_delay_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_POST_PMU: - msleep(200); - break; - default: - break; - } - - return 0; -} - -static void enable_and_reset_codec(struct regmap *regmap, - u32 codec_enable_bits, u32 codec_reset_bits) -{ - regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, - codec_enable_bits | codec_reset_bits, - codec_enable_bits); - msleep(20); - regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, - codec_reset_bits, codec_reset_bits); -} - -static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ -#define ATLAS6_CODEC_ENABLE_BITS (1 << 29) -#define ATLAS6_CODEC_RESET_BITS (1 << 28) - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component); - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - enable_and_reset_codec(sirf_audio_codec->regmap, - ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS); - break; - case SND_SOC_DAPM_POST_PMD: - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0); - break; - default: - break; - } - - return 0; -} - -static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ -#define PRIMA2_CODEC_ENABLE_BITS (1 << 27) -#define PRIMA2_CODEC_RESET_BITS (1 << 26) - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component); - switch (event) { - case SND_SOC_DAPM_POST_PMU: - enable_and_reset_codec(sirf_audio_codec->regmap, - PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS); - break; - case SND_SOC_DAPM_POST_PMD: - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0); - break; - default: - break; - } - - return 0; -} - -static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = { - SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, - 25, 0, NULL, 0), - SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, - 26, 0, NULL, 0), - SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, - 27, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = { - SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, - 23, 0, NULL, 0), - SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, - 24, 0, NULL, 0), - SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, - 25, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget = - SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, - atlas6_codec_enable_and_reset_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); - -static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget = - SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, - prima2_codec_enable_and_reset_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); - -static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0), - SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0), - SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0, - &left_dac_to_hp_left_amp_switch_control), - SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0, - &left_dac_to_hp_right_amp_switch_control), - SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0, - &right_dac_to_hp_left_amp_switch_control), - SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0, - &right_dac_to_hp_right_amp_switch_control), - SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0, - NULL, 0), - SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0, - NULL, 0), - - SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0, - &left_dac_to_speaker_lineout_switch_control), - SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0, - &right_dac_to_speaker_lineout_switch_control), - SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0, - NULL, 0), - - SND_SOC_DAPM_OUTPUT("HPOUTL"), - SND_SOC_DAPM_OUTPUT("HPOUTR"), - SND_SOC_DAPM_OUTPUT("SPKOUT"), - - SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0, - adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0, - adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0, - &left_input_path_controls[0], - ARRAY_SIZE(left_input_path_controls)), - SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0, - &right_input_path_controls[0], - ARRAY_SIZE(right_input_path_controls)), - - SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0, - &sirf_audio_codec_input_mode_control), - SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0), - SND_SOC_DAPM_INPUT("MICIN1"), - SND_SOC_DAPM_INPUT("MICIN2"), - SND_SOC_DAPM_INPUT("LINEIN1"), - SND_SOC_DAPM_INPUT("LINEIN2"), - - SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0, - 30, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { - {"SPKOUT", NULL, "Speaker Driver"}, - {"Speaker Driver", NULL, "Speaker amp driver"}, - {"Speaker amp driver", NULL, "Left dac to speaker lineout"}, - {"Speaker amp driver", NULL, "Right dac to speaker lineout"}, - {"Left dac to speaker lineout", "Switch", "DAC left"}, - {"Right dac to speaker lineout", "Switch", "DAC right"}, - {"HPOUTL", NULL, "HP Left Driver"}, - {"HPOUTR", NULL, "HP Right Driver"}, - {"HP Left Driver", NULL, "HP amp left driver"}, - {"HP Right Driver", NULL, "HP amp right driver"}, - {"HP amp left driver", NULL, "Right dac to hp left amp"}, - {"HP amp right driver", NULL , "Right dac to hp right amp"}, - {"HP amp left driver", NULL, "Left dac to hp left amp"}, - {"HP amp right driver", NULL , "Right dac to hp right amp"}, - {"Right dac to hp left amp", "Switch", "DAC left"}, - {"Right dac to hp right amp", "Switch", "DAC right"}, - {"Left dac to hp left amp", "Switch", "DAC left"}, - {"Left dac to hp right amp", "Switch", "DAC right"}, - {"DAC left", NULL, "codecclk"}, - {"DAC right", NULL, "codecclk"}, - {"DAC left", NULL, "Playback"}, - {"DAC right", NULL, "Playback"}, - {"DAC left", NULL, "HSL Phase Opposite"}, - {"DAC right", NULL, "HSL Phase Opposite"}, - - {"Capture", NULL, "ADC left"}, - {"Capture", NULL, "ADC right"}, - {"ADC left", NULL, "codecclk"}, - {"ADC right", NULL, "codecclk"}, - {"ADC left", NULL, "Left PGA mixer"}, - {"ADC right", NULL, "Right PGA mixer"}, - {"Left PGA mixer", "Line Left Switch", "LINEIN2"}, - {"Right PGA mixer", "Line Right Switch", "LINEIN1"}, - {"Left PGA mixer", "Mic Left Switch", "MICIN2"}, - {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"}, - {"Mic input mode mux", "Single-ended", "MICIN1"}, - {"Mic input mode mux", "Differential", "MICIN1"}, -}; - -static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec) -{ - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, - AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, - AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); - regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); - regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, - AUDIO_FIFO_START, AUDIO_FIFO_START); - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE); -} - -static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec) -{ - regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE); -} - -static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec, - int channels) -{ - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, - AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, - AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); - regmap_write(sirf_audio_codec->regmap, - AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); - regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, - AUDIO_FIFO_START, AUDIO_FIFO_START); - if (channels == 1) - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_PORT_IC_CODEC_RX_CTRL, - IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); - else - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_PORT_IC_CODEC_RX_CTRL, - IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); -} - -static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec) -{ - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_PORT_IC_CODEC_RX_CTRL, - IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); -} - -static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, - int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component); - int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - - /* - * This is a workaround, When stop playback, - * need disable HP amp, avoid the current noise. - */ - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (playback) { - snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0, - IC_HSLEN | IC_HSREN, 0); - sirf_audio_codec_tx_disable(sirf_audio_codec); - } else - sirf_audio_codec_rx_disable(sirf_audio_codec); - break; - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (playback) { - sirf_audio_codec_tx_enable(sirf_audio_codec); - snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0, - IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN); - } else - sirf_audio_codec_rx_enable(sirf_audio_codec, - substream->runtime->channels); - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { - .trigger = sirf_audio_codec_trigger, -}; - -static struct snd_soc_dai_driver sirf_audio_codec_dai = { - .name = "sirf-audio-codec", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &sirf_audio_codec_dai_ops, -}; - -static int sirf_audio_codec_probe(struct snd_soc_component *component) -{ - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - - pm_runtime_enable(component->dev); - - if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) { - snd_soc_dapm_new_controls(dapm, - prima2_output_driver_dapm_widgets, - ARRAY_SIZE(prima2_output_driver_dapm_widgets)); - snd_soc_dapm_new_controls(dapm, - &prima2_codec_clock_dapm_widget, 1); - return snd_soc_add_component_controls(component, - volume_controls_prima2, - ARRAY_SIZE(volume_controls_prima2)); - } - if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) { - snd_soc_dapm_new_controls(dapm, - atlas6_output_driver_dapm_widgets, - ARRAY_SIZE(atlas6_output_driver_dapm_widgets)); - snd_soc_dapm_new_controls(dapm, - &atlas6_codec_clock_dapm_widget, 1); - return snd_soc_add_component_controls(component, - volume_controls_atlas6, - ARRAY_SIZE(volume_controls_atlas6)); - } - - return -EINVAL; -} - -static void sirf_audio_codec_remove(struct snd_soc_component *component) -{ - pm_runtime_disable(component->dev); -} - -static const struct snd_soc_component_driver soc_codec_device_sirf_audio_codec = { - .probe = sirf_audio_codec_probe, - .remove = sirf_audio_codec_remove, - .dapm_widgets = sirf_audio_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets), - .dapm_routes = sirf_audio_codec_map, - .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map), - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - -static const struct of_device_id sirf_audio_codec_of_match[] = { - { .compatible = "sirf,prima2-audio-codec" }, - { .compatible = "sirf,atlas6-audio-codec" }, - {} -}; -MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match); - -static const struct regmap_config sirf_audio_codec_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, - .cache_type = REGCACHE_NONE, -}; - -static int sirf_audio_codec_driver_probe(struct platform_device *pdev) -{ - int ret; - struct sirf_audio_codec *sirf_audio_codec; - void __iomem *base; - - sirf_audio_codec = devm_kzalloc(&pdev->dev, - sizeof(struct sirf_audio_codec), GFP_KERNEL); - if (!sirf_audio_codec) - return -ENOMEM; - - platform_set_drvdata(pdev, sirf_audio_codec); - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - - sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &sirf_audio_codec_regmap_config); - if (IS_ERR(sirf_audio_codec->regmap)) - return PTR_ERR(sirf_audio_codec->regmap); - - sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(sirf_audio_codec->clk)) { - dev_err(&pdev->dev, "Get clock failed.\n"); - return PTR_ERR(sirf_audio_codec->clk); - } - - ret = clk_prepare_enable(sirf_audio_codec->clk); - if (ret) { - dev_err(&pdev->dev, "Enable clock failed.\n"); - return ret; - } - - ret = devm_snd_soc_register_component(&(pdev->dev), - &soc_codec_device_sirf_audio_codec, - &sirf_audio_codec_dai, 1); - if (ret) { - dev_err(&pdev->dev, "Register Audio Codec dai failed.\n"); - goto err_clk_put; - } - - /* - * Always open charge pump, if not, when the charge pump closed the - * adc will not stable - */ - regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, - IC_CPFREQ, IC_CPFREQ); - - if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec")) - regmap_update_bits(sirf_audio_codec->regmap, - AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN); - return 0; - -err_clk_put: - clk_disable_unprepare(sirf_audio_codec->clk); - return ret; -} - -static int sirf_audio_codec_driver_remove(struct platform_device *pdev) -{ - struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev); - - clk_disable_unprepare(sirf_audio_codec->clk); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int sirf_audio_codec_suspend(struct device *dev) -{ - struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); - - regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, - &sirf_audio_codec->reg_ctrl0); - regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, - &sirf_audio_codec->reg_ctrl1); - clk_disable_unprepare(sirf_audio_codec->clk); - - return 0; -} - -static int sirf_audio_codec_resume(struct device *dev) -{ - struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); - int ret; - - ret = clk_prepare_enable(sirf_audio_codec->clk); - if (ret) - return ret; - - regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, - sirf_audio_codec->reg_ctrl0); - regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, - sirf_audio_codec->reg_ctrl1); - - return 0; -} -#endif - -static const struct dev_pm_ops sirf_audio_codec_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume) -}; - -static struct platform_driver sirf_audio_codec_driver = { - .driver = { - .name = "sirf-audio-codec", - .of_match_table = sirf_audio_codec_of_match, - .pm = &sirf_audio_codec_pm_ops, - }, - .probe = sirf_audio_codec_driver_probe, - .remove = sirf_audio_codec_driver_remove, -}; - -module_platform_driver(sirf_audio_codec_driver); - -MODULE_DESCRIPTION("SiRF audio codec driver"); -MODULE_AUTHOR("RongJun Ying "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig deleted file mode 100644 index 094a1c89c59d..000000000000 --- a/sound/soc/sirf/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config SND_SOC_SIRF - tristate "SoC Audio for the SiRF SoC chips" - depends on ARCH_SIRF || COMPILE_TEST - select SND_SOC_GENERIC_DMAENGINE_PCM - -config SND_SOC_SIRF_AUDIO - tristate "SoC Audio support for SiRF internal audio codec" - depends on SND_SOC_SIRF - select SND_SOC_SIRF_AUDIO_CODEC - select SND_SOC_SIRF_AUDIO_PORT - -config SND_SOC_SIRF_AUDIO_PORT - select REGMAP_MMIO - tristate - -config SND_SOC_SIRF_USP - tristate "SoC Audio (I2S protocol) for SiRF SoC USP interface" - depends on SND_SOC_SIRF - select REGMAP_MMIO - tristate diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile deleted file mode 100644 index 16ed11965ff9..000000000000 --- a/sound/soc/sirf/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -snd-soc-sirf-audio-objs := sirf-audio.o -snd-soc-sirf-audio-port-objs := sirf-audio-port.o -snd-soc-sirf-usp-objs := sirf-usp.o - -obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o -obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o -obj-$(CONFIG_SND_SOC_SIRF_USP) += snd-soc-sirf-usp.o diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c deleted file mode 100644 index 8be2f0bc477b..000000000000 --- a/sound/soc/sirf/sirf-audio-port.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * SiRF Audio port driver - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - */ -#include -#include -#include - -struct sirf_audio_port { - struct regmap *regmap; - struct snd_dmaengine_dai_dma_data playback_dma_data; - struct snd_dmaengine_dai_dma_data capture_dma_data; -}; - - -static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) -{ - struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, - &port->capture_dma_data); - return 0; -} - -static struct snd_soc_dai_driver sirf_audio_port_dai = { - .probe = sirf_audio_port_dai_probe, - .name = "sirf-audio-port", - .id = 0, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; - -static const struct snd_soc_component_driver sirf_audio_port_component = { - .name = "sirf-audio-port", -}; - -static int sirf_audio_port_probe(struct platform_device *pdev) -{ - int ret; - struct sirf_audio_port *port; - - port = devm_kzalloc(&pdev->dev, - sizeof(struct sirf_audio_port), GFP_KERNEL); - if (!port) - return -ENOMEM; - - ret = devm_snd_soc_register_component(&pdev->dev, - &sirf_audio_port_component, &sirf_audio_port_dai, 1); - if (ret) - return ret; - - platform_set_drvdata(pdev, port); - return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); -} - -static const struct of_device_id sirf_audio_port_of_match[] = { - { .compatible = "sirf,audio-port", }, - {} -}; -MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match); - -static struct platform_driver sirf_audio_port_driver = { - .driver = { - .name = "sirf-audio-port", - .of_match_table = sirf_audio_port_of_match, - }, - .probe = sirf_audio_port_probe, -}; - -module_platform_driver(sirf_audio_port_driver); - -MODULE_DESCRIPTION("SiRF Audio Port driver"); -MODULE_AUTHOR("RongJun Ying "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c deleted file mode 100644 index c923b6772b22..000000000000 --- a/sound/soc/sirf/sirf-audio.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * SiRF audio card driver - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct sirf_audio_card { - unsigned int gpio_hp_pa; - unsigned int gpio_spk_pa; -}; - -static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *ctrl, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); - int on = !SND_SOC_DAPM_EVENT_OFF(event); - - if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) - gpio_set_value(sirf_audio_card->gpio_hp_pa, on); - return 0; -} - -static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *ctrl, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); - int on = !SND_SOC_DAPM_EVENT_OFF(event); - - if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) - gpio_set_value(sirf_audio_card->gpio_spk_pa, on); - - return 0; -} -static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = { - SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event), - SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event), - SND_SOC_DAPM_MIC("Ext Mic", NULL), -}; - -static const struct snd_soc_dapm_route intercon[] = { - {"Hp", NULL, "HPOUTL"}, - {"Hp", NULL, "HPOUTR"}, - {"Ext Spk", NULL, "SPKOUT"}, - {"MICIN1", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Ext Mic"}, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -SND_SOC_DAILINK_DEFS(sirf, - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sirf-audio-codec")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -static struct snd_soc_dai_link sirf_audio_dai_link[] = { - { - .name = "SiRF audio card", - .stream_name = "SiRF audio HiFi", - SND_SOC_DAILINK_REG(sirf), - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_sirf_audio_card = { - .name = "SiRF audio card", - .owner = THIS_MODULE, - .dai_link = sirf_audio_dai_link, - .num_links = ARRAY_SIZE(sirf_audio_dai_link), - .dapm_widgets = sirf_audio_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), -}; - -static int sirf_audio_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_sirf_audio_card; - struct sirf_audio_card *sirf_audio_card; - int ret; - - sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card), - GFP_KERNEL); - if (sirf_audio_card == NULL) - return -ENOMEM; - - sirf_audio_dai_link[0].cpus->of_node = - of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); - sirf_audio_dai_link[0].platforms->of_node = - of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); - sirf_audio_dai_link[0].codecs->of_node = - of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); - sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, - "spk-pa-gpios", 0); - sirf_audio_card->gpio_hp_pa = of_get_named_gpio(pdev->dev.of_node, - "hp-pa-gpios", 0); - if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) { - ret = devm_gpio_request_one(&pdev->dev, - sirf_audio_card->gpio_spk_pa, - GPIOF_OUT_INIT_LOW, "SPA_PA_SD"); - if (ret) { - dev_err(&pdev->dev, - "Failed to request GPIO_%d for reset: %d\n", - sirf_audio_card->gpio_spk_pa, ret); - return ret; - } - } - if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) { - ret = devm_gpio_request_one(&pdev->dev, - sirf_audio_card->gpio_hp_pa, - GPIOF_OUT_INIT_LOW, "HP_PA_SD"); - if (ret) { - dev_err(&pdev->dev, - "Failed to request GPIO_%d for reset: %d\n", - sirf_audio_card->gpio_hp_pa, ret); - return ret; - } - } - - card->dev = &pdev->dev; - snd_soc_card_set_drvdata(card, sirf_audio_card); - - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); - - return ret; -} - -static const struct of_device_id sirf_audio_of_match[] = { - {.compatible = "sirf,sirf-audio-card", }, - { }, -}; -MODULE_DEVICE_TABLE(of, sirf_audio_of_match); - -static struct platform_driver sirf_audio_driver = { - .driver = { - .name = "sirf-audio-card", - .pm = &snd_soc_pm_ops, - .of_match_table = sirf_audio_of_match, - }, - .probe = sirf_audio_probe, -}; -module_platform_driver(sirf_audio_driver); - -MODULE_AUTHOR("RongJun Ying "); -MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c deleted file mode 100644 index 2af0c6f14ee6..000000000000 --- a/sound/soc/sirf/sirf-usp.c +++ /dev/null @@ -1,435 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * SiRF USP in I2S/DSP mode - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sirf-usp.h" - -struct sirf_usp { - struct regmap *regmap; - struct clk *clk; - u32 mode1_reg; - u32 mode2_reg; - int daifmt_format; - struct snd_dmaengine_dai_dma_data playback_dma_data; - struct snd_dmaengine_dai_dma_data capture_dma_data; -}; - -static void sirf_usp_tx_enable(struct sirf_usp *usp) -{ - regmap_update_bits(usp->regmap, USP_TX_FIFO_OP, - USP_TX_FIFO_RESET, USP_TX_FIFO_RESET); - regmap_write(usp->regmap, USP_TX_FIFO_OP, 0); - - regmap_update_bits(usp->regmap, USP_TX_FIFO_OP, - USP_TX_FIFO_START, USP_TX_FIFO_START); - - regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, - USP_TX_ENA, USP_TX_ENA); -} - -static void sirf_usp_tx_disable(struct sirf_usp *usp) -{ - regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, - USP_TX_ENA, ~USP_TX_ENA); - /* FIFO stop */ - regmap_write(usp->regmap, USP_TX_FIFO_OP, 0); -} - -static void sirf_usp_rx_enable(struct sirf_usp *usp) -{ - regmap_update_bits(usp->regmap, USP_RX_FIFO_OP, - USP_RX_FIFO_RESET, USP_RX_FIFO_RESET); - regmap_write(usp->regmap, USP_RX_FIFO_OP, 0); - - regmap_update_bits(usp->regmap, USP_RX_FIFO_OP, - USP_RX_FIFO_START, USP_RX_FIFO_START); - - regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, - USP_RX_ENA, USP_RX_ENA); -} - -static void sirf_usp_rx_disable(struct sirf_usp *usp) -{ - regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE, - USP_RX_ENA, ~USP_RX_ENA); - /* FIFO stop */ - regmap_write(usp->regmap, USP_RX_FIFO_OP, 0); -} - -static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai) -{ - struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data, - &usp->capture_dma_data); - return 0; -} - -static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) -{ - struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - dev_err(dai->dev, "Only CBM and CFM supported\n"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_DSP_A: - usp->daifmt_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK); - break; - default: - dev_err(dai->dev, "Only I2S and DSP_A format supported\n"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - usp->daifmt_format |= (fmt & SND_SOC_DAIFMT_INV_MASK); - break; - default: - return -EINVAL; - } - - return 0; -} - -static void sirf_usp_i2s_init(struct sirf_usp *usp) -{ - /* Configure RISC mode */ - regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE, - USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL); - - /* - * Configure DMA IO Length register - * Set no limit, USP can receive data continuously until it is diabled - */ - regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0); - regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0); - - /* Configure Mode2 register */ - regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) | - (0 << USP_TXD_DELAY_LEN_OFFSET) | - USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE); - - /* Configure Mode1 register */ - regmap_write(usp->regmap, USP_MODE1, - USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING | - USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 | - USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE); - - /* Configure RX DMA IO Control register */ - regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0); - - /* Congiure RX FIFO Control register */ - regmap_write(usp->regmap, USP_RX_FIFO_CTRL, - (USP_RX_FIFO_THRESHOLD << USP_RX_FIFO_THD_OFFSET) | - (USP_TX_RX_FIFO_WIDTH_DWORD << USP_RX_FIFO_WIDTH_OFFSET)); - - /* Congiure RX FIFO Level Check register */ - regmap_write(usp->regmap, USP_RX_FIFO_LEVEL_CHK, - RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B)); - - /* Configure TX DMA IO Control register*/ - regmap_write(usp->regmap, USP_TX_DMA_IO_CTRL, 0); - - /* Configure TX FIFO Control register */ - regmap_write(usp->regmap, USP_TX_FIFO_CTRL, - (USP_TX_FIFO_THRESHOLD << USP_TX_FIFO_THD_OFFSET) | - (USP_TX_RX_FIFO_WIDTH_DWORD << USP_TX_FIFO_WIDTH_OFFSET)); - /* Congiure TX FIFO Level Check register */ - regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK, - TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04)); -} - -static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); - u32 data_len, frame_len, shifter_len; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - data_len = 16; - frame_len = 16; - break; - case SNDRV_PCM_FORMAT_S24_LE: - data_len = 24; - frame_len = 32; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - data_len = 24; - frame_len = 24; - break; - default: - dev_err(dai->dev, "Format unsupported\n"); - return -EINVAL; - } - - shifter_len = data_len; - - switch (usp->daifmt_format & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, - USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG); - break; - case SND_SOC_DAIFMT_DSP_A: - regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, - USP_I2S_SYNC_CHG, 0); - frame_len = data_len * params_channels(params); - data_len = frame_len; - break; - default: - dev_err(dai->dev, "Only support I2S and DSP_A mode\n"); - return -EINVAL; - } - - switch (usp->daifmt_format & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - regmap_update_bits(usp->regmap, USP_MODE1, - USP_RXD_ACT_EDGE_FALLING | USP_TXD_ACT_EDGE_FALLING, - USP_RXD_ACT_EDGE_FALLING); - break; - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, - USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK - | USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE, - ((data_len - 1) << USP_TXC_DATA_LEN_OFFSET) - | ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET) - | ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET) - | USP_TXC_SLAVE_CLK_SAMPLE); - else - regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, - USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK - | USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE, - ((data_len - 1) << USP_RXC_DATA_LEN_OFFSET) - | ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET) - | ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET) - | USP_SINGLE_SYNC_MODE); - - return 0; -} - -static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sirf_usp_tx_enable(usp); - else - sirf_usp_rx_enable(usp); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sirf_usp_tx_disable(usp); - else - sirf_usp_rx_disable(usp); - break; - } - - return 0; -} - -static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = { - .trigger = sirf_usp_pcm_trigger, - .set_fmt = sirf_usp_pcm_set_dai_fmt, - .hw_params = sirf_usp_pcm_hw_params, -}; - -static struct snd_soc_dai_driver sirf_usp_pcm_dai = { - .probe = sirf_usp_pcm_dai_probe, - .name = "sirf-usp-pcm", - .id = 0, - .playback = { - .stream_name = "SiRF USP PCM Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE, - }, - .capture = { - .stream_name = "SiRF USP PCM Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE, - }, - .ops = &sirf_usp_pcm_dai_ops, -}; - -static int sirf_usp_pcm_runtime_suspend(struct device *dev) -{ - struct sirf_usp *usp = dev_get_drvdata(dev); - - clk_disable_unprepare(usp->clk); - return 0; -} - -static int sirf_usp_pcm_runtime_resume(struct device *dev) -{ - struct sirf_usp *usp = dev_get_drvdata(dev); - int ret; - - ret = clk_prepare_enable(usp->clk); - if (ret) { - dev_err(dev, "clk_enable failed: %d\n", ret); - return ret; - } - sirf_usp_i2s_init(usp); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int sirf_usp_pcm_suspend(struct device *dev) -{ - struct sirf_usp *usp = dev_get_drvdata(dev); - - if (!pm_runtime_status_suspended(dev)) { - regmap_read(usp->regmap, USP_MODE1, &usp->mode1_reg); - regmap_read(usp->regmap, USP_MODE2, &usp->mode2_reg); - sirf_usp_pcm_runtime_suspend(dev); - } - return 0; -} - -static int sirf_usp_pcm_resume(struct device *dev) -{ - struct sirf_usp *usp = dev_get_drvdata(dev); - int ret; - - if (!pm_runtime_status_suspended(dev)) { - ret = sirf_usp_pcm_runtime_resume(dev); - if (ret) - return ret; - regmap_write(usp->regmap, USP_MODE1, usp->mode1_reg); - regmap_write(usp->regmap, USP_MODE2, usp->mode2_reg); - } - return 0; -} -#endif - -static const struct snd_soc_component_driver sirf_usp_component = { - .name = "sirf-usp", -}; - -static const struct regmap_config sirf_usp_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = USP_RX_FIFO_DATA, - .cache_type = REGCACHE_NONE, -}; - -static int sirf_usp_pcm_probe(struct platform_device *pdev) -{ - int ret; - struct sirf_usp *usp; - void __iomem *base; - - usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp), - GFP_KERNEL); - if (!usp) - return -ENOMEM; - - platform_set_drvdata(pdev, usp); - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &sirf_usp_regmap_config); - if (IS_ERR(usp->regmap)) - return PTR_ERR(usp->regmap); - - usp->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(usp->clk)) { - dev_err(&pdev->dev, "Get clock failed.\n"); - return PTR_ERR(usp->clk); - } - - pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = sirf_usp_pcm_runtime_resume(&pdev->dev); - if (ret) - return ret; - } - - ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component, - &sirf_usp_pcm_dai, 1); - if (ret) { - dev_err(&pdev->dev, "Register Audio SoC dai failed.\n"); - return ret; - } - return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); -} - -static int sirf_usp_pcm_remove(struct platform_device *pdev) -{ - if (!pm_runtime_enabled(&pdev->dev)) - sirf_usp_pcm_runtime_suspend(&pdev->dev); - else - pm_runtime_disable(&pdev->dev); - return 0; -} - -static const struct of_device_id sirf_usp_pcm_of_match[] = { - { .compatible = "sirf,prima2-usp-pcm", }, - {} -}; -MODULE_DEVICE_TABLE(of, sirf_usp_pcm_of_match); - -static const struct dev_pm_ops sirf_usp_pcm_pm_ops = { - SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend, - sirf_usp_pcm_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend, sirf_usp_pcm_resume) -}; - -static struct platform_driver sirf_usp_pcm_driver = { - .driver = { - .name = "sirf-usp-pcm", - .of_match_table = sirf_usp_pcm_of_match, - .pm = &sirf_usp_pcm_pm_ops, - }, - .probe = sirf_usp_pcm_probe, - .remove = sirf_usp_pcm_remove, -}; - -module_platform_driver(sirf_usp_pcm_driver); - -MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver"); -MODULE_AUTHOR("RongJun Ying "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-usp.h b/sound/soc/sirf/sirf-usp.h deleted file mode 100644 index 08993b5992c4..000000000000 --- a/sound/soc/sirf/sirf-usp.h +++ /dev/null @@ -1,292 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * arch/arm/mach-prima2/include/mach/sirfsoc_usp.h - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - */ - -#ifndef _SIRF_USP_H -#define _SIRF_USP_H - -/* USP Registers */ -#define USP_MODE1 0x00 -#define USP_MODE2 0x04 -#define USP_TX_FRAME_CTRL 0x08 -#define USP_RX_FRAME_CTRL 0x0C -#define USP_TX_RX_ENABLE 0x10 -#define USP_INT_ENABLE 0x14 -#define USP_INT_STATUS 0x18 -#define USP_PIN_IO_DATA 0x1C -#define USP_RISC_DSP_MODE 0x20 -#define USP_AYSNC_PARAM_REG 0x24 -#define USP_IRDA_X_MODE_DIV 0x28 -#define USP_SM_CFG 0x2C -#define USP_TX_DMA_IO_CTRL 0x100 -#define USP_TX_DMA_IO_LEN 0x104 -#define USP_TX_FIFO_CTRL 0x108 -#define USP_TX_FIFO_LEVEL_CHK 0x10C -#define USP_TX_FIFO_OP 0x110 -#define USP_TX_FIFO_STATUS 0x114 -#define USP_TX_FIFO_DATA 0x118 -#define USP_RX_DMA_IO_CTRL 0x120 -#define USP_RX_DMA_IO_LEN 0x124 -#define USP_RX_FIFO_CTRL 0x128 -#define USP_RX_FIFO_LEVEL_CHK 0x12C -#define USP_RX_FIFO_OP 0x130 -#define USP_RX_FIFO_STATUS 0x134 -#define USP_RX_FIFO_DATA 0x138 - -/* USP MODE register-1 */ -#define USP_SYNC_MODE 0x00000001 -#define USP_CLOCK_MODE_SLAVE 0x00000002 -#define USP_LOOP_BACK_EN 0x00000004 -#define USP_HPSIR_EN 0x00000008 -#define USP_ENDIAN_CTRL_LSBF 0x00000010 -#define USP_EN 0x00000020 -#define USP_RXD_ACT_EDGE_FALLING 0x00000040 -#define USP_TXD_ACT_EDGE_FALLING 0x00000080 -#define USP_RFS_ACT_LEVEL_LOGIC1 0x00000100 -#define USP_TFS_ACT_LEVEL_LOGIC1 0x00000200 -#define USP_SCLK_IDLE_MODE_TOGGLE 0x00000400 -#define USP_SCLK_IDLE_LEVEL_LOGIC1 0x00000800 -#define USP_SCLK_PIN_MODE_IO 0x00001000 -#define USP_RFS_PIN_MODE_IO 0x00002000 -#define USP_TFS_PIN_MODE_IO 0x00004000 -#define USP_RXD_PIN_MODE_IO 0x00008000 -#define USP_TXD_PIN_MODE_IO 0x00010000 -#define USP_SCLK_IO_MODE_INPUT 0x00020000 -#define USP_RFS_IO_MODE_INPUT 0x00040000 -#define USP_TFS_IO_MODE_INPUT 0x00080000 -#define USP_RXD_IO_MODE_INPUT 0x00100000 -#define USP_TXD_IO_MODE_INPUT 0x00200000 -#define USP_IRDA_WIDTH_DIV_MASK 0x3FC00000 -#define USP_IRDA_WIDTH_DIV_OFFSET 0 -#define USP_IRDA_IDLE_LEVEL_HIGH 0x40000000 -#define USP_TX_UFLOW_REPEAT_ZERO 0x80000000 -#define USP_TX_ENDIAN_MODE 0x00000020 -#define USP_RX_ENDIAN_MODE 0x00000020 - -/* USP Mode Register-2 */ -#define USP_RXD_DELAY_LEN_MASK 0x000000FF -#define USP_RXD_DELAY_LEN_OFFSET 0 - -#define USP_TXD_DELAY_LEN_MASK 0x0000FF00 -#define USP_TXD_DELAY_LEN_OFFSET 8 - -#define USP_ENA_CTRL_MODE 0x00010000 -#define USP_FRAME_CTRL_MODE 0x00020000 -#define USP_TFS_SOURCE_MODE 0x00040000 -#define USP_TFS_MS_MODE 0x00080000 -#define USP_CLK_DIVISOR_MASK 0x7FE00000 -#define USP_CLK_DIVISOR_OFFSET 21 - -#define USP_TFS_CLK_SLAVE_MODE (1<<20) -#define USP_RFS_CLK_SLAVE_MODE (1<<19) - -#define USP_IRDA_DATA_WIDTH 0x80000000 - -/* USP Transmit Frame Control Register */ - -#define USP_TXC_DATA_LEN_MASK 0x000000FF -#define USP_TXC_DATA_LEN_OFFSET 0 - -#define USP_TXC_SYNC_LEN_MASK 0x0000FF00 -#define USP_TXC_SYNC_LEN_OFFSET 8 - -#define USP_TXC_FRAME_LEN_MASK 0x00FF0000 -#define USP_TXC_FRAME_LEN_OFFSET 16 - -#define USP_TXC_SHIFTER_LEN_MASK 0x1F000000 -#define USP_TXC_SHIFTER_LEN_OFFSET 24 - -#define USP_TXC_SLAVE_CLK_SAMPLE 0x20000000 - -#define USP_TXC_CLK_DIVISOR_MASK 0xC0000000 -#define USP_TXC_CLK_DIVISOR_OFFSET 30 - -/* USP Receive Frame Control Register */ - -#define USP_RXC_DATA_LEN_MASK 0x000000FF -#define USP_RXC_DATA_LEN_OFFSET 0 - -#define USP_RXC_FRAME_LEN_MASK 0x0000FF00 -#define USP_RXC_FRAME_LEN_OFFSET 8 - -#define USP_RXC_SHIFTER_LEN_MASK 0x001F0000 -#define USP_RXC_SHIFTER_LEN_OFFSET 16 - -#define USP_START_EDGE_MODE 0x00800000 -#define USP_I2S_SYNC_CHG 0x00200000 - -#define USP_RXC_CLK_DIVISOR_MASK 0x0F000000 -#define USP_RXC_CLK_DIVISOR_OFFSET 24 -#define USP_SINGLE_SYNC_MODE 0x00400000 - -/* Tx - RX Enable Register */ - -#define USP_RX_ENA 0x00000001 -#define USP_TX_ENA 0x00000002 - -/* USP Interrupt Enable and status Register */ -#define USP_RX_DONE_INT 0x00000001 -#define USP_TX_DONE_INT 0x00000002 -#define USP_RX_OFLOW_INT 0x00000004 -#define USP_TX_UFLOW_INT 0x00000008 -#define USP_RX_IO_DMA_INT 0x00000010 -#define USP_TX_IO_DMA_INT 0x00000020 -#define USP_RXFIFO_FULL_INT 0x00000040 -#define USP_TXFIFO_EMPTY_INT 0x00000080 -#define USP_RXFIFO_THD_INT 0x00000100 -#define USP_TXFIFO_THD_INT 0x00000200 -#define USP_UART_FRM_ERR_INT 0x00000400 -#define USP_RX_TIMEOUT_INT 0x00000800 -#define USP_TX_ALLOUT_INT 0x00001000 -#define USP_RXD_BREAK_INT 0x00008000 - -/* All possible TX interruots */ -#define USP_TX_INTERRUPT (USP_TX_DONE_INT|USP_TX_UFLOW_INT|\ - USP_TX_IO_DMA_INT|\ - USP_TXFIFO_EMPTY_INT|\ - USP_TXFIFO_THD_INT) -/* All possible RX interruots */ -#define USP_RX_INTERRUPT (USP_RX_DONE_INT|USP_RX_OFLOW_INT|\ - USP_RX_IO_DMA_INT|\ - USP_RXFIFO_FULL_INT|\ - USP_RXFIFO_THD_INT|\ - USP_RX_TIMEOUT_INT) - -#define USP_INT_ALL 0x1FFF - -/* USP Pin I/O Data Register */ - -#define USP_RFS_PIN_VALUE_MASK 0x00000001 -#define USP_TFS_PIN_VALUE_MASK 0x00000002 -#define USP_RXD_PIN_VALUE_MASK 0x00000004 -#define USP_TXD_PIN_VALUE_MASK 0x00000008 -#define USP_SCLK_PIN_VALUE_MASK 0x00000010 - -/* USP RISC/DSP Mode Register */ -#define USP_RISC_DSP_SEL 0x00000001 - -/* USP ASYNC PARAMETER Register*/ - -#define USP_ASYNC_TIMEOUT_MASK 0x0000FFFF -#define USP_ASYNC_TIMEOUT_OFFSET 0 -#define USP_ASYNC_TIMEOUT(x) (((x)&USP_ASYNC_TIMEOUT_MASK) \ - < Cc: Shawn Guo Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210120162553.21666-3-arnd@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/zte,tdm.txt | 30 -- .../devicetree/bindings/sound/zte,zx-aud96p22.txt | 24 -- .../devicetree/bindings/sound/zte,zx-i2s.txt | 45 -- .../devicetree/bindings/sound/zte,zx-spdif.txt | 27 -- sound/soc/Kconfig | 1 - sound/soc/Makefile | 1 - sound/soc/codecs/Makefile | 2 - sound/soc/codecs/zx_aud96p22.c | 401 ------------------ sound/soc/zte/Kconfig | 26 -- sound/soc/zte/Makefile | 4 - sound/soc/zte/zx-i2s.c | 452 -------------------- sound/soc/zte/zx-spdif.c | 363 ---------------- sound/soc/zte/zx-tdm.c | 458 --------------------- 13 files changed, 1834 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/zte,tdm.txt delete mode 100644 Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt delete mode 100644 Documentation/devicetree/bindings/sound/zte,zx-i2s.txt delete mode 100644 Documentation/devicetree/bindings/sound/zte,zx-spdif.txt delete mode 100644 sound/soc/codecs/zx_aud96p22.c delete mode 100644 sound/soc/zte/Kconfig delete mode 100644 sound/soc/zte/Makefile delete mode 100644 sound/soc/zte/zx-i2s.c delete mode 100644 sound/soc/zte/zx-spdif.c delete mode 100644 sound/soc/zte/zx-tdm.c diff --git a/Documentation/devicetree/bindings/sound/zte,tdm.txt b/Documentation/devicetree/bindings/sound/zte,tdm.txt deleted file mode 100644 index 2a07ca655264..000000000000 --- a/Documentation/devicetree/bindings/sound/zte,tdm.txt +++ /dev/null @@ -1,30 +0,0 @@ -ZTE TDM DAI driver - -Required properties: - -- compatible : should be one of the following. - * zte,zx296718-tdm -- reg : physical base address of the controller and length of memory mapped - region. -- clocks : Pairs of phandle and specifier referencing the controller's clocks. -- clock-names: "wclk" for the wclk. - "pclk" for the pclk. --#clock-cells: should be 1. -- zte,tdm-dma-sysctrl : Reference to the sysctrl controller controlling - the dma. includes: - phandle of sysctrl. - register offset in sysctrl for control dma. - mask of the register that be written to sysctrl. - -Example: - - tdm: tdm@1487000 { - compatible = "zte,zx296718-tdm"; - reg = <0x01487000 0x1000>; - clocks = <&audiocrm AUDIO_TDM_WCLK>, <&audiocrm AUDIO_TDM_PCLK>; - clock-names = "wclk", "pclk"; - #clock-cells = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&tdm_global_pin>; - zte,tdm-dma-sysctrl = <&sysctrl 0x10c 4>; - }; diff --git a/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt b/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt deleted file mode 100644 index 41bb1040eb71..000000000000 --- a/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt +++ /dev/null @@ -1,24 +0,0 @@ -ZTE ZX AUD96P22 Audio Codec - -Required properties: - - compatible: Must be "zte,zx-aud96p22" - - #sound-dai-cells: Should be 0 - - reg: I2C bus slave address of AUD96P22 - -Example: - - i2c0: i2c@1486000 { - compatible = "zte,zx296718-i2c"; - reg = <0x01486000 0x1000>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&audiocrm AUDIO_I2C0_WCLK>; - clock-frequency = <1600000>; - - aud96p22: codec@22 { - compatible = "zte,zx-aud96p22"; - #sound-dai-cells = <0>; - reg = <0x22>; - }; - }; diff --git a/Documentation/devicetree/bindings/sound/zte,zx-i2s.txt b/Documentation/devicetree/bindings/sound/zte,zx-i2s.txt deleted file mode 100644 index 3927251464f0..000000000000 --- a/Documentation/devicetree/bindings/sound/zte,zx-i2s.txt +++ /dev/null @@ -1,45 +0,0 @@ -ZTE ZX296702 I2S controller - -Required properties: - - compatible : Must be one of: - "zte,zx296718-i2s", "zte,zx296702-i2s" - "zte,zx296702-i2s" - - reg : Must contain I2S core's registers location and length - - clocks : Pairs of phandle and specifier referencing the controller's clocks. - - clock-names: "wclk" for the wclk, "pclk" for the pclk to the I2S interface. - - dmas: Pairs of phandle and specifier for the DMA channel that is used by - the core. The core expects two dma channels for transmit. - - dma-names : Must be "tx" and "rx" - -For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties -please check: - * resource-names.txt - * clock/clock-bindings.txt - * dma/dma.txt - -Example: - i2s0: i2s@b005000 { - #sound-dai-cells = <0>; - compatible = "zte,zx296718-i2s", "zte,zx296702-i2s"; - reg = <0x0b005000 0x1000>; - clocks = <&audiocrm AUDIO_I2S0_WCLK>, <&audiocrm AUDIO_I2S0_PCLK>; - clock-names = "wclk", "pclk"; - interrupts = ; - dmas = <&dma 5>, <&dma 6>; - dma-names = "tx", "rx"; - }; - - sound { - compatible = "simple-audio-card"; - simple-audio-card,name = "zx296702_snd"; - simple-audio-card,format = "left_j"; - simple-audio-card,bitclock-master = <&sndcodec>; - simple-audio-card,frame-master = <&sndcodec>; - sndcpu: simple-audio-card,cpu { - sound-dai = <&i2s0>; - }; - - sndcodec: simple-audio-card,codec { - sound-dai = <&acodec>; - }; - }; diff --git a/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt b/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt deleted file mode 100644 index 09231d7586b2..000000000000 --- a/Documentation/devicetree/bindings/sound/zte,zx-spdif.txt +++ /dev/null @@ -1,27 +0,0 @@ -ZTE ZX296702 SPDIF controller - -Required properties: - - compatible : Must be "zte,zx296702-spdif" - - reg : Must contain SPDIF core's registers location and length - - clocks : Pairs of phandle and specifier referencing the controller's clocks. - - clock-names: "tx" for the clock to the SPDIF interface. - - dmas: Pairs of phandle and specifier for the DMA channel that is used by - the core. The core expects one dma channel for transmit. - - dma-names : Must be "tx" - -For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties -please check: - * resource-names.txt - * clock/clock-bindings.txt - * dma/dma.txt - -Example: - spdif0: spdif0@b004000 { - compatible = "zte,zx296702-spdif"; - reg = <0x0b004000 0x1000>; - clocks = <&lsp0clk ZX296702_SPDIF0_DIV>; - clock-names = "tx"; - interrupts = ; - dmas = <&dma 4>; - dma-names = "tx"; - }; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 547b26ca714f..ba79d5f4e299 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -74,7 +74,6 @@ source "sound/soc/uniphier/Kconfig" source "sound/soc/ux500/Kconfig" source "sound/soc/xilinx/Kconfig" source "sound/soc/xtensa/Kconfig" -source "sound/soc/zte/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 74508b0f9c47..eee370492eee 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -57,4 +57,3 @@ obj-$(CONFIG_SND_SOC) += uniphier/ obj-$(CONFIG_SND_SOC) += ux500/ obj-$(CONFIG_SND_SOC) += xilinx/ obj-$(CONFIG_SND_SOC) += xtensa/ -obj-$(CONFIG_SND_SOC) += zte/ diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index c30762fc9b87..628b0c9b3e2a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -301,7 +301,6 @@ snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o snd-soc-wsa881x-objs := wsa881x.o snd-soc-zl38060-objs := zl38060.o -snd-soc-zx-aud96p22-objs := zx_aud96p22.o # Amp snd-soc-max9877-objs := max9877.o snd-soc-max98504-objs := max98504.o @@ -616,7 +615,6 @@ obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o -obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o # Amp obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c deleted file mode 100644 index 16d44efb132d..000000000000 --- a/sound/soc/codecs/zx_aud96p22.c +++ /dev/null @@ -1,401 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2017 Sanechips Technology Co., Ltd. - * Copyright 2017 Linaro Ltd. - * - * Author: Baoyou Xie - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AUD96P22_RESET 0x00 -#define RST_DAC_DPZ BIT(0) -#define RST_ADC_DPZ BIT(1) -#define AUD96P22_I2S1_CONFIG_0 0x03 -#define I2S1_MS_MODE BIT(3) -#define I2S1_MODE_MASK 0x7 -#define I2S1_MODE_RIGHT_J 0x0 -#define I2S1_MODE_I2S 0x1 -#define I2S1_MODE_LEFT_J 0x2 -#define AUD96P22_PD_0 0x15 -#define AUD96P22_PD_1 0x16 -#define AUD96P22_PD_3 0x18 -#define AUD96P22_PD_4 0x19 -#define AUD96P22_MUTE_0 0x1d -#define AUD96P22_MUTE_2 0x1f -#define AUD96P22_MUTE_4 0x21 -#define AUD96P22_RECVOL_0 0x24 -#define AUD96P22_RECVOL_1 0x25 -#define AUD96P22_PGA1VOL_0 0x26 -#define AUD96P22_PGA1VOL_1 0x27 -#define AUD96P22_LMVOL_0 0x34 -#define AUD96P22_LMVOL_1 0x35 -#define AUD96P22_HS1VOL_0 0x38 -#define AUD96P22_HS1VOL_1 0x39 -#define AUD96P22_PGA1SEL_0 0x47 -#define AUD96P22_PGA1SEL_1 0x48 -#define AUD96P22_LDR1SEL_0 0x59 -#define AUD96P22_LDR1SEL_1 0x60 -#define AUD96P22_LDR2SEL_0 0x5d -#define AUD96P22_REG_MAX 0xfb - -struct aud96p22_priv { - struct regmap *regmap; -}; - -static int aud96p22_adc_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct aud96p22_priv *priv = snd_soc_component_get_drvdata(component); - struct regmap *regmap = priv->regmap; - - if (event != SND_SOC_DAPM_POST_PMU) - return -EINVAL; - - /* Assert/de-assert the bit to reset ADC data path */ - regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, 0); - regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, RST_ADC_DPZ); - - return 0; -} - -static int aud96p22_dac_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct aud96p22_priv *priv = snd_soc_component_get_drvdata(component); - struct regmap *regmap = priv->regmap; - - if (event != SND_SOC_DAPM_POST_PMU) - return -EINVAL; - - /* Assert/de-assert the bit to reset DAC data path */ - regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, 0); - regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, RST_DAC_DPZ); - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(lm_tlv, -11550, 50, 0); -static const DECLARE_TLV_DB_SCALE(hs_tlv, -3900, 300, 0); -static const DECLARE_TLV_DB_SCALE(rec_tlv, -9550, 50, 0); -static const DECLARE_TLV_DB_SCALE(pga_tlv, -1800, 100, 0); - -static const struct snd_kcontrol_new aud96p22_snd_controls[] = { - /* Volume control */ - SOC_DOUBLE_R_TLV("Master Playback Volume", AUD96P22_LMVOL_0, - AUD96P22_LMVOL_1, 0, 0xff, 0, lm_tlv), - SOC_DOUBLE_R_TLV("Headphone Volume", AUD96P22_HS1VOL_0, - AUD96P22_HS1VOL_1, 0, 0xf, 0, hs_tlv), - SOC_DOUBLE_R_TLV("Master Capture Volume", AUD96P22_RECVOL_0, - AUD96P22_RECVOL_1, 0, 0xff, 0, rec_tlv), - SOC_DOUBLE_R_TLV("Analogue Capture Volume", AUD96P22_PGA1VOL_0, - AUD96P22_PGA1VOL_1, 0, 0x37, 0, pga_tlv), - - /* Mute control */ - SOC_DOUBLE("Master Playback Switch", AUD96P22_MUTE_2, 0, 1, 1, 1), - SOC_DOUBLE("Headphone Switch", AUD96P22_MUTE_2, 4, 5, 1, 1), - SOC_DOUBLE("Line Out Switch", AUD96P22_MUTE_4, 0, 1, 1, 1), - SOC_DOUBLE("Speaker Switch", AUD96P22_MUTE_4, 2, 3, 1, 1), - SOC_DOUBLE("Master Capture Switch", AUD96P22_MUTE_0, 0, 1, 1, 1), - SOC_DOUBLE("Analogue Capture Switch", AUD96P22_MUTE_0, 2, 3, 1, 1), -}; - -/* Input mux kcontrols */ -static const unsigned int ain_mux_values[] = { - 0, 1, 3, 4, 5, -}; - -static const char * const ainl_mux_texts[] = { - "AINL1 differential", - "AINL1 single-ended", - "AINL3 single-ended", - "AINL2 differential", - "AINL2 single-ended", -}; - -static const char * const ainr_mux_texts[] = { - "AINR1 differential", - "AINR1 single-ended", - "AINR3 single-ended", - "AINR2 differential", - "AINR2 single-ended", -}; - -static SOC_VALUE_ENUM_SINGLE_DECL(ainl_mux_enum, AUD96P22_PGA1SEL_0, - 0, 0x7, ainl_mux_texts, ain_mux_values); -static SOC_VALUE_ENUM_SINGLE_DECL(ainr_mux_enum, AUD96P22_PGA1SEL_1, - 0, 0x7, ainr_mux_texts, ain_mux_values); - -static const struct snd_kcontrol_new ainl_mux_kcontrol = - SOC_DAPM_ENUM("AINL Mux", ainl_mux_enum); -static const struct snd_kcontrol_new ainr_mux_kcontrol = - SOC_DAPM_ENUM("AINR Mux", ainr_mux_enum); - -/* Output mixer kcontrols */ -static const struct snd_kcontrol_new ld1_left_kcontrols[] = { - SOC_DAPM_SINGLE("DACL LD1L Switch", AUD96P22_LDR1SEL_0, 0, 1, 0), - SOC_DAPM_SINGLE("AINL LD1L Switch", AUD96P22_LDR1SEL_0, 1, 1, 0), - SOC_DAPM_SINGLE("AINR LD1L Switch", AUD96P22_LDR1SEL_0, 2, 1, 0), -}; - -static const struct snd_kcontrol_new ld1_right_kcontrols[] = { - SOC_DAPM_SINGLE("DACR LD1R Switch", AUD96P22_LDR1SEL_1, 8, 1, 0), - SOC_DAPM_SINGLE("AINR LD1R Switch", AUD96P22_LDR1SEL_1, 9, 1, 0), - SOC_DAPM_SINGLE("AINL LD1R Switch", AUD96P22_LDR1SEL_1, 10, 1, 0), -}; - -static const struct snd_kcontrol_new ld2_kcontrols[] = { - SOC_DAPM_SINGLE("DACL LD2 Switch", AUD96P22_LDR2SEL_0, 0, 1, 0), - SOC_DAPM_SINGLE("AINL LD2 Switch", AUD96P22_LDR2SEL_0, 1, 1, 0), - SOC_DAPM_SINGLE("DACR LD2 Switch", AUD96P22_LDR2SEL_0, 2, 1, 0), -}; - -static const struct snd_soc_dapm_widget aud96p22_dapm_widgets[] = { - /* Overall power bit */ - SND_SOC_DAPM_SUPPLY("POWER", AUD96P22_PD_0, 0, 0, NULL, 0), - - /* Input pins */ - SND_SOC_DAPM_INPUT("AINL1P"), - SND_SOC_DAPM_INPUT("AINL2P"), - SND_SOC_DAPM_INPUT("AINL3"), - SND_SOC_DAPM_INPUT("AINL1N"), - SND_SOC_DAPM_INPUT("AINL2N"), - SND_SOC_DAPM_INPUT("AINR2N"), - SND_SOC_DAPM_INPUT("AINR1N"), - SND_SOC_DAPM_INPUT("AINR3"), - SND_SOC_DAPM_INPUT("AINR2P"), - SND_SOC_DAPM_INPUT("AINR1P"), - - /* Input muxes */ - SND_SOC_DAPM_MUX("AINLMUX", AUD96P22_PD_1, 2, 0, &ainl_mux_kcontrol), - SND_SOC_DAPM_MUX("AINRMUX", AUD96P22_PD_1, 3, 0, &ainr_mux_kcontrol), - - /* ADCs */ - SND_SOC_DAPM_ADC_E("ADCL", "Capture Left", AUD96P22_PD_1, 0, 0, - aud96p22_adc_event, SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_ADC_E("ADCR", "Capture Right", AUD96P22_PD_1, 1, 0, - aud96p22_adc_event, SND_SOC_DAPM_POST_PMU), - - /* DACs */ - SND_SOC_DAPM_DAC_E("DACL", "Playback Left", AUD96P22_PD_3, 0, 0, - aud96p22_dac_event, SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_DAC_E("DACR", "Playback Right", AUD96P22_PD_3, 1, 0, - aud96p22_dac_event, SND_SOC_DAPM_POST_PMU), - - /* Output mixers */ - SND_SOC_DAPM_MIXER("LD1L", AUD96P22_PD_3, 6, 0, ld1_left_kcontrols, - ARRAY_SIZE(ld1_left_kcontrols)), - SND_SOC_DAPM_MIXER("LD1R", AUD96P22_PD_3, 7, 0, ld1_right_kcontrols, - ARRAY_SIZE(ld1_right_kcontrols)), - SND_SOC_DAPM_MIXER("LD2", AUD96P22_PD_4, 2, 0, ld2_kcontrols, - ARRAY_SIZE(ld2_kcontrols)), - - /* Headset power switch */ - SND_SOC_DAPM_SUPPLY("HS1L", AUD96P22_PD_3, 4, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("HS1R", AUD96P22_PD_3, 5, 0, NULL, 0), - - /* Output pins */ - SND_SOC_DAPM_OUTPUT("HSOUTL"), - SND_SOC_DAPM_OUTPUT("LINEOUTL"), - SND_SOC_DAPM_OUTPUT("LINEOUTMP"), - SND_SOC_DAPM_OUTPUT("LINEOUTMN"), - SND_SOC_DAPM_OUTPUT("LINEOUTR"), - SND_SOC_DAPM_OUTPUT("HSOUTR"), -}; - -static const struct snd_soc_dapm_route aud96p22_dapm_routes[] = { - { "AINLMUX", "AINL1 differential", "AINL1N" }, - { "AINLMUX", "AINL1 single-ended", "AINL1P" }, - { "AINLMUX", "AINL3 single-ended", "AINL3" }, - { "AINLMUX", "AINL2 differential", "AINL2N" }, - { "AINLMUX", "AINL2 single-ended", "AINL2P" }, - - { "AINRMUX", "AINR1 differential", "AINR1N" }, - { "AINRMUX", "AINR1 single-ended", "AINR1P" }, - { "AINRMUX", "AINR3 single-ended", "AINR3" }, - { "AINRMUX", "AINR2 differential", "AINR2N" }, - { "AINRMUX", "AINR2 single-ended", "AINR2P" }, - - { "ADCL", NULL, "AINLMUX" }, - { "ADCR", NULL, "AINRMUX" }, - - { "ADCL", NULL, "POWER" }, - { "ADCR", NULL, "POWER" }, - { "DACL", NULL, "POWER" }, - { "DACR", NULL, "POWER" }, - - { "LD1L", "DACL LD1L Switch", "DACL" }, - { "LD1L", "AINL LD1L Switch", "AINLMUX" }, - { "LD1L", "AINR LD1L Switch", "AINRMUX" }, - - { "LD1R", "DACR LD1R Switch", "DACR" }, - { "LD1R", "AINR LD1R Switch", "AINRMUX" }, - { "LD1R", "AINL LD1R Switch", "AINLMUX" }, - - { "LD2", "DACL LD2 Switch", "DACL" }, - { "LD2", "AINL LD2 Switch", "AINLMUX" }, - { "LD2", "DACR LD2 Switch", "DACR" }, - - { "HSOUTL", NULL, "LD1L" }, - { "HSOUTR", NULL, "LD1R" }, - { "HSOUTL", NULL, "HS1L" }, - { "HSOUTR", NULL, "HS1R" }, - - { "LINEOUTL", NULL, "LD1L" }, - { "LINEOUTR", NULL, "LD1R" }, - - { "LINEOUTMP", NULL, "LD2" }, - { "LINEOUTMN", NULL, "LD2" }, -}; - -static const struct snd_soc_component_driver aud96p22_driver = { - .controls = aud96p22_snd_controls, - .num_controls = ARRAY_SIZE(aud96p22_snd_controls), - .dapm_widgets = aud96p22_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aud96p22_dapm_widgets), - .dapm_routes = aud96p22_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(aud96p22_dapm_routes), - .idle_bias_on = 1, - .use_pmdown_time = 1, - .endianness = 1, - .non_legacy_dai_naming = 1, -}; - -static int aud96p22_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct aud96p22_priv *priv = snd_soc_component_get_drvdata(dai->component); - struct regmap *regmap = priv->regmap; - unsigned int val; - - /* Master/slave mode */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - val = 0; - break; - case SND_SOC_DAIFMT_CBM_CFM: - val = I2S1_MS_MODE; - break; - default: - return -EINVAL; - } - - regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MS_MODE, val); - - /* Audio format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - val = I2S1_MODE_RIGHT_J; - break; - case SND_SOC_DAIFMT_I2S: - val = I2S1_MODE_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - val = I2S1_MODE_LEFT_J; - break; - default: - return -EINVAL; - } - - regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MODE_MASK, val); - - return 0; -} - -static const struct snd_soc_dai_ops aud96p22_dai_ops = { - .set_fmt = aud96p22_set_fmt, -}; - -#define AUD96P22_RATES SNDRV_PCM_RATE_8000_192000 -#define AUD96P22_FORMATS (\ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_driver aud96p22_dai = { - .name = "aud96p22-dai", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = AUD96P22_RATES, - .formats = AUD96P22_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = AUD96P22_RATES, - .formats = AUD96P22_FORMATS, - }, - .ops = &aud96p22_dai_ops, -}; - -static const struct regmap_config aud96p22_regmap = { - .reg_bits = 8, - .val_bits = 8, - .max_register = AUD96P22_REG_MAX, - .cache_type = REGCACHE_RBTREE, -}; - -static int aud96p22_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct device *dev = &i2c->dev; - struct aud96p22_priv *priv; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - priv->regmap = devm_regmap_init_i2c(i2c, &aud96p22_regmap); - if (IS_ERR(priv->regmap)) { - ret = PTR_ERR(priv->regmap); - dev_err(dev, "failed to init i2c regmap: %d\n", ret); - return ret; - } - - i2c_set_clientdata(i2c, priv); - - ret = devm_snd_soc_register_component(dev, &aud96p22_driver, &aud96p22_dai, 1); - if (ret) { - dev_err(dev, "failed to register component: %d\n", ret); - return ret; - } - - return 0; -} - -static int aud96p22_i2c_remove(struct i2c_client *i2c) -{ - return 0; -} - -static const struct of_device_id aud96p22_dt_ids[] = { - { .compatible = "zte,zx-aud96p22", }, - { } -}; -MODULE_DEVICE_TABLE(of, aud96p22_dt_ids); - -static struct i2c_driver aud96p22_i2c_driver = { - .driver = { - .name = "zx_aud96p22", - .of_match_table = aud96p22_dt_ids, - }, - .probe = aud96p22_i2c_probe, - .remove = aud96p22_i2c_remove, -}; -module_i2c_driver(aud96p22_i2c_driver); - -MODULE_DESCRIPTION("ZTE ASoC AUD96P22 CODEC driver"); -MODULE_AUTHOR("Baoyou Xie "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/zte/Kconfig b/sound/soc/zte/Kconfig deleted file mode 100644 index a23d4f13ca19..000000000000 --- a/sound/soc/zte/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config ZX_SPDIF - tristate "ZTE ZX SPDIF Driver Support" - depends on ARCH_ZX || COMPILE_TEST - depends on COMMON_CLK - select SND_SOC_GENERIC_DMAENGINE_PCM - help - Say Y or M if you want to add support for codecs attached to the - ZTE ZX SPDIF interface - -config ZX_I2S - tristate "ZTE ZX I2S Driver Support" - depends on ARCH_ZX || COMPILE_TEST - depends on COMMON_CLK - select SND_SOC_GENERIC_DMAENGINE_PCM - help - Say Y or M if you want to add support for codecs attached to the - ZTE ZX I2S interface - -config ZX_TDM - tristate "ZTE ZX TDM Driver Support" - depends on COMMON_CLK - select SND_SOC_GENERIC_DMAENGINE_PCM - help - Say Y or M if you want to add support for codecs attached to the - ZTE ZX TDM interface diff --git a/sound/soc/zte/Makefile b/sound/soc/zte/Makefile deleted file mode 100644 index 2f7cdefa42df..000000000000 --- a/sound/soc/zte/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_ZX_SPDIF) += zx-spdif.o -obj-$(CONFIG_ZX_I2S) += zx-i2s.o -obj-$(CONFIG_ZX_TDM) += zx-tdm.o diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c deleted file mode 100644 index 1c1a44e08a67..000000000000 --- a/sound/soc/zte/zx-i2s.c +++ /dev/null @@ -1,452 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2015 Linaro - * - * Author: Jun Nie - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define ZX_I2S_PROCESS_CTRL 0x04 -#define ZX_I2S_TIMING_CTRL 0x08 -#define ZX_I2S_FIFO_CTRL 0x0C -#define ZX_I2S_FIFO_STATUS 0x10 -#define ZX_I2S_INT_EN 0x14 -#define ZX_I2S_INT_STATUS 0x18 -#define ZX_I2S_DATA 0x1C -#define ZX_I2S_FRAME_CNTR 0x20 - -#define I2S_DEAGULT_FIFO_THRES (0x10) -#define I2S_MAX_FIFO_THRES (0x20) - -#define ZX_I2S_PROCESS_TX_EN (1 << 0) -#define ZX_I2S_PROCESS_TX_DIS (0 << 0) -#define ZX_I2S_PROCESS_RX_EN (1 << 1) -#define ZX_I2S_PROCESS_RX_DIS (0 << 1) -#define ZX_I2S_PROCESS_I2S_EN (1 << 2) -#define ZX_I2S_PROCESS_I2S_DIS (0 << 2) - -#define ZX_I2S_TIMING_MAST (1 << 0) -#define ZX_I2S_TIMING_SLAVE (0 << 0) -#define ZX_I2S_TIMING_MS_MASK (1 << 0) -#define ZX_I2S_TIMING_LOOP (1 << 1) -#define ZX_I2S_TIMING_NOR (0 << 1) -#define ZX_I2S_TIMING_LOOP_MASK (1 << 1) -#define ZX_I2S_TIMING_PTNR (1 << 2) -#define ZX_I2S_TIMING_NTPR (0 << 2) -#define ZX_I2S_TIMING_PHASE_MASK (1 << 2) -#define ZX_I2S_TIMING_TDM (1 << 3) -#define ZX_I2S_TIMING_I2S (0 << 3) -#define ZX_I2S_TIMING_TIMING_MASK (1 << 3) -#define ZX_I2S_TIMING_LONG_SYNC (1 << 4) -#define ZX_I2S_TIMING_SHORT_SYNC (0 << 4) -#define ZX_I2S_TIMING_SYNC_MASK (1 << 4) -#define ZX_I2S_TIMING_TEAK_EN (1 << 5) -#define ZX_I2S_TIMING_TEAK_DIS (0 << 5) -#define ZX_I2S_TIMING_TEAK_MASK (1 << 5) -#define ZX_I2S_TIMING_STD_I2S (0 << 6) -#define ZX_I2S_TIMING_MSB_JUSTIF (1 << 6) -#define ZX_I2S_TIMING_LSB_JUSTIF (2 << 6) -#define ZX_I2S_TIMING_ALIGN_MASK (3 << 6) -#define ZX_I2S_TIMING_CHN_MASK (7 << 8) -#define ZX_I2S_TIMING_CHN(x) ((x - 1) << 8) -#define ZX_I2S_TIMING_LANE_MASK (3 << 11) -#define ZX_I2S_TIMING_LANE(x) ((x - 1) << 11) -#define ZX_I2S_TIMING_TSCFG_MASK (7 << 13) -#define ZX_I2S_TIMING_TSCFG(x) (x << 13) -#define ZX_I2S_TIMING_TS_WIDTH_MASK (0x1f << 16) -#define ZX_I2S_TIMING_TS_WIDTH(x) ((x - 1) << 16) -#define ZX_I2S_TIMING_DATA_SIZE_MASK (0x1f << 21) -#define ZX_I2S_TIMING_DATA_SIZE(x) ((x - 1) << 21) -#define ZX_I2S_TIMING_CFG_ERR_MASK (1 << 31) - -#define ZX_I2S_FIFO_CTRL_TX_RST (1 << 0) -#define ZX_I2S_FIFO_CTRL_TX_RST_MASK (1 << 0) -#define ZX_I2S_FIFO_CTRL_RX_RST (1 << 1) -#define ZX_I2S_FIFO_CTRL_RX_RST_MASK (1 << 1) -#define ZX_I2S_FIFO_CTRL_TX_DMA_EN (1 << 4) -#define ZX_I2S_FIFO_CTRL_TX_DMA_DIS (0 << 4) -#define ZX_I2S_FIFO_CTRL_TX_DMA_MASK (1 << 4) -#define ZX_I2S_FIFO_CTRL_RX_DMA_EN (1 << 5) -#define ZX_I2S_FIFO_CTRL_RX_DMA_DIS (0 << 5) -#define ZX_I2S_FIFO_CTRL_RX_DMA_MASK (1 << 5) -#define ZX_I2S_FIFO_CTRL_TX_THRES_MASK (0x1F << 8) -#define ZX_I2S_FIFO_CTRL_RX_THRES_MASK (0x1F << 16) - -#define CLK_RAT (32 * 4) - -struct zx_i2s_info { - struct snd_dmaengine_dai_dma_data dma_playback; - struct snd_dmaengine_dai_dma_data dma_capture; - struct clk *dai_wclk; - struct clk *dai_pclk; - void __iomem *reg_base; - int master; - resource_size_t mapbase; -}; - -static void zx_i2s_tx_en(void __iomem *base, bool on) -{ - unsigned long val; - - val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL); - if (on) - val |= ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN; - else - val &= ~(ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN); - writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL); -} - -static void zx_i2s_rx_en(void __iomem *base, bool on) -{ - unsigned long val; - - val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL); - if (on) - val |= ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN; - else - val &= ~(ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN); - writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL); -} - -static void zx_i2s_tx_dma_en(void __iomem *base, bool on) -{ - unsigned long val; - - val = readl_relaxed(base + ZX_I2S_FIFO_CTRL); - val |= ZX_I2S_FIFO_CTRL_TX_RST | (I2S_DEAGULT_FIFO_THRES << 8); - if (on) - val |= ZX_I2S_FIFO_CTRL_TX_DMA_EN; - else - val &= ~ZX_I2S_FIFO_CTRL_TX_DMA_EN; - writel_relaxed(val, base + ZX_I2S_FIFO_CTRL); -} - -static void zx_i2s_rx_dma_en(void __iomem *base, bool on) -{ - unsigned long val; - - val = readl_relaxed(base + ZX_I2S_FIFO_CTRL); - val |= ZX_I2S_FIFO_CTRL_RX_RST | (I2S_DEAGULT_FIFO_THRES << 16); - if (on) - val |= ZX_I2S_FIFO_CTRL_RX_DMA_EN; - else - val &= ~ZX_I2S_FIFO_CTRL_RX_DMA_EN; - writel_relaxed(val, base + ZX_I2S_FIFO_CTRL); -} - -#define ZX_I2S_RATES \ - (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000| \ - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) - -#define ZX_I2S_FMTBIT \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) - -static int zx_i2s_dai_probe(struct snd_soc_dai *dai) -{ - struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); - - snd_soc_dai_set_drvdata(dai, zx_i2s); - zx_i2s->dma_playback.addr = zx_i2s->mapbase + ZX_I2S_DATA; - zx_i2s->dma_playback.maxburst = 16; - zx_i2s->dma_capture.addr = zx_i2s->mapbase + ZX_I2S_DATA; - zx_i2s->dma_capture.maxburst = 16; - snd_soc_dai_init_dma_data(dai, &zx_i2s->dma_playback, - &zx_i2s->dma_capture); - return 0; -} - -static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) -{ - struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long val; - - val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); - val &= ~(ZX_I2S_TIMING_TIMING_MASK | ZX_I2S_TIMING_ALIGN_MASK | - ZX_I2S_TIMING_TEAK_MASK | ZX_I2S_TIMING_SYNC_MASK | - ZX_I2S_TIMING_MS_MASK); - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_STD_I2S); - break; - case SND_SOC_DAIFMT_LEFT_J: - val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_MSB_JUSTIF); - break; - case SND_SOC_DAIFMT_RIGHT_J: - val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_LSB_JUSTIF); - break; - default: - dev_err(cpu_dai->dev, "Unknown i2s timing\n"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - /* Codec is master, and I2S is slave. */ - i2s->master = 0; - val |= ZX_I2S_TIMING_SLAVE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - /* Codec is slave, and I2S is master. */ - i2s->master = 1; - val |= ZX_I2S_TIMING_MAST; - break; - default: - dev_err(cpu_dai->dev, "Unknown master/slave format\n"); - return -EINVAL; - } - - writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL); - return 0; -} - -static int zx_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *socdai) -{ - struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); - struct snd_dmaengine_dai_dma_data *dma_data; - unsigned int lane, ch_num, len, ret = 0; - unsigned int ts_width = 32; - unsigned long val; - unsigned long chn_cfg; - - dma_data = snd_soc_dai_get_dma_data(socdai, substream); - dma_data->addr_width = ts_width >> 3; - - val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); - val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK | - ZX_I2S_TIMING_LANE_MASK | ZX_I2S_TIMING_CHN_MASK | - ZX_I2S_TIMING_TSCFG_MASK); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - len = 16; - break; - case SNDRV_PCM_FORMAT_S24_LE: - len = 24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - len = 32; - break; - default: - dev_err(socdai->dev, "Unknown data format\n"); - return -EINVAL; - } - val |= ZX_I2S_TIMING_TS_WIDTH(ts_width) | ZX_I2S_TIMING_DATA_SIZE(len); - - ch_num = params_channels(params); - switch (ch_num) { - case 1: - lane = 1; - chn_cfg = 2; - break; - case 2: - case 4: - case 6: - case 8: - lane = ch_num / 2; - chn_cfg = 3; - break; - default: - dev_err(socdai->dev, "Not support channel num %d\n", ch_num); - return -EINVAL; - } - val |= ZX_I2S_TIMING_LANE(lane); - val |= ZX_I2S_TIMING_TSCFG(chn_cfg); - val |= ZX_I2S_TIMING_CHN(ch_num); - writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL); - - if (i2s->master) - ret = clk_set_rate(i2s->dai_wclk, - params_rate(params) * ch_num * CLK_RAT); - - return ret; -} - -static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); - int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (capture) - zx_i2s_rx_dma_en(zx_i2s->reg_base, true); - else - zx_i2s_tx_dma_en(zx_i2s->reg_base, true); - fallthrough; - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (capture) - zx_i2s_rx_en(zx_i2s->reg_base, true); - else - zx_i2s_tx_en(zx_i2s->reg_base, true); - break; - - case SNDRV_PCM_TRIGGER_STOP: - if (capture) - zx_i2s_rx_dma_en(zx_i2s->reg_base, false); - else - zx_i2s_tx_dma_en(zx_i2s->reg_base, false); - fallthrough; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (capture) - zx_i2s_rx_en(zx_i2s->reg_base, false); - else - zx_i2s_tx_en(zx_i2s->reg_base, false); - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int zx_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); - int ret; - - ret = clk_prepare_enable(zx_i2s->dai_wclk); - if (ret) - return ret; - - ret = clk_prepare_enable(zx_i2s->dai_pclk); - if (ret) { - clk_disable_unprepare(zx_i2s->dai_wclk); - return ret; - } - - return ret; -} - -static void zx_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev); - - clk_disable_unprepare(zx_i2s->dai_wclk); - clk_disable_unprepare(zx_i2s->dai_pclk); -} - -static const struct snd_soc_dai_ops zx_i2s_dai_ops = { - .trigger = zx_i2s_trigger, - .hw_params = zx_i2s_hw_params, - .set_fmt = zx_i2s_set_fmt, - .startup = zx_i2s_startup, - .shutdown = zx_i2s_shutdown, -}; - -static const struct snd_soc_component_driver zx_i2s_component = { - .name = "zx-i2s", -}; - -static struct snd_soc_dai_driver zx_i2s_dai = { - .name = "zx-i2s-dai", - .id = 0, - .probe = zx_i2s_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 8, - .rates = ZX_I2S_RATES, - .formats = ZX_I2S_FMTBIT, - }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = ZX_I2S_RATES, - .formats = ZX_I2S_FMTBIT, - }, - .ops = &zx_i2s_dai_ops, -}; - -static int zx_i2s_probe(struct platform_device *pdev) -{ - struct resource *res; - struct zx_i2s_info *zx_i2s; - int ret; - - zx_i2s = devm_kzalloc(&pdev->dev, sizeof(*zx_i2s), GFP_KERNEL); - if (!zx_i2s) - return -ENOMEM; - - zx_i2s->dai_wclk = devm_clk_get(&pdev->dev, "wclk"); - if (IS_ERR(zx_i2s->dai_wclk)) { - dev_err(&pdev->dev, "Fail to get wclk\n"); - return PTR_ERR(zx_i2s->dai_wclk); - } - - zx_i2s->dai_pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(zx_i2s->dai_pclk)) { - dev_err(&pdev->dev, "Fail to get pclk\n"); - return PTR_ERR(zx_i2s->dai_pclk); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - zx_i2s->mapbase = res->start; - zx_i2s->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(zx_i2s->reg_base)) { - dev_err(&pdev->dev, "ioremap failed!\n"); - return PTR_ERR(zx_i2s->reg_base); - } - - writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL); - platform_set_drvdata(pdev, zx_i2s); - - ret = devm_snd_soc_register_component(&pdev->dev, &zx_i2s_component, - &zx_i2s_dai, 1); - if (ret) { - dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); - return ret; - } - - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); - if (ret) - dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); - - return ret; -} - -static const struct of_device_id zx_i2s_dt_ids[] = { - { .compatible = "zte,zx296702-i2s", }, - {} -}; -MODULE_DEVICE_TABLE(of, zx_i2s_dt_ids); - -static struct platform_driver i2s_driver = { - .probe = zx_i2s_probe, - .driver = { - .name = "zx-i2s", - .of_match_table = zx_i2s_dt_ids, - }, -}; - -module_platform_driver(i2s_driver); - -MODULE_AUTHOR("Jun Nie "); -MODULE_DESCRIPTION("ZTE I2S SoC DAI"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/zte/zx-spdif.c b/sound/soc/zte/zx-spdif.c deleted file mode 100644 index b4168bd532b7..000000000000 --- a/sound/soc/zte/zx-spdif.c +++ /dev/null @@ -1,363 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2015 Linaro - * - * Author: Jun Nie - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ZX_CTRL 0x04 -#define ZX_FIFOCTRL 0x08 -#define ZX_INT_STATUS 0x10 -#define ZX_INT_MASK 0x14 -#define ZX_DATA 0x18 -#define ZX_VALID_BIT 0x1c -#define ZX_CH_STA_1 0x20 -#define ZX_CH_STA_2 0x24 -#define ZX_CH_STA_3 0x28 -#define ZX_CH_STA_4 0x2c -#define ZX_CH_STA_5 0x30 -#define ZX_CH_STA_6 0x34 - -#define ZX_CTRL_MODA_16 (0 << 6) -#define ZX_CTRL_MODA_18 BIT(6) -#define ZX_CTRL_MODA_20 (2 << 6) -#define ZX_CTRL_MODA_24 (3 << 6) -#define ZX_CTRL_MODA_MASK (3 << 6) - -#define ZX_CTRL_ENB BIT(4) -#define ZX_CTRL_DNB (0 << 4) -#define ZX_CTRL_ENB_MASK BIT(4) - -#define ZX_CTRL_TX_OPEN BIT(0) -#define ZX_CTRL_TX_CLOSE (0 << 0) -#define ZX_CTRL_TX_MASK BIT(0) - -#define ZX_CTRL_OPEN (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB) -#define ZX_CTRL_CLOSE (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB) - -#define ZX_CTRL_DOUBLE_TRACK (0 << 8) -#define ZX_CTRL_LEFT_TRACK BIT(8) -#define ZX_CTRL_RIGHT_TRACK (2 << 8) -#define ZX_CTRL_TRACK_MASK (3 << 8) - -#define ZX_FIFOCTRL_TXTH_MASK (0x1f << 8) -#define ZX_FIFOCTRL_TXTH(x) (x << 8) -#define ZX_FIFOCTRL_TX_DMA_EN BIT(2) -#define ZX_FIFOCTRL_TX_DMA_DIS (0 << 2) -#define ZX_FIFOCTRL_TX_DMA_EN_MASK BIT(2) -#define ZX_FIFOCTRL_TX_FIFO_RST BIT(0) -#define ZX_FIFOCTRL_TX_FIFO_RST_MASK BIT(0) - -#define ZX_VALID_DOUBLE_TRACK (0 << 0) -#define ZX_VALID_LEFT_TRACK BIT(1) -#define ZX_VALID_RIGHT_TRACK (2 << 0) -#define ZX_VALID_TRACK_MASK (3 << 0) - -#define ZX_SPDIF_CLK_RAT (2 * 32) - -struct zx_spdif_info { - struct snd_dmaengine_dai_dma_data dma_data; - struct clk *dai_clk; - void __iomem *reg_base; - resource_size_t mapbase; -}; - -static int zx_spdif_dai_probe(struct snd_soc_dai *dai) -{ - struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); - - snd_soc_dai_set_drvdata(dai, zx_spdif); - zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA; - zx_spdif->dma_data.maxburst = 8; - snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL); - return 0; -} - -static int zx_spdif_chanstats(void __iomem *base, unsigned int rate) -{ - u32 cstas1; - - switch (rate) { - case 22050: - cstas1 = IEC958_AES3_CON_FS_22050; - break; - case 24000: - cstas1 = IEC958_AES3_CON_FS_24000; - break; - case 32000: - cstas1 = IEC958_AES3_CON_FS_32000; - break; - case 44100: - cstas1 = IEC958_AES3_CON_FS_44100; - break; - case 48000: - cstas1 = IEC958_AES3_CON_FS_48000; - break; - case 88200: - cstas1 = IEC958_AES3_CON_FS_88200; - break; - case 96000: - cstas1 = IEC958_AES3_CON_FS_96000; - break; - case 176400: - cstas1 = IEC958_AES3_CON_FS_176400; - break; - case 192000: - cstas1 = IEC958_AES3_CON_FS_192000; - break; - default: - return -EINVAL; - } - cstas1 = cstas1 << 24; - cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT; - - writel_relaxed(cstas1, base + ZX_CH_STA_1); - return 0; -} - -static int zx_spdif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *socdai) -{ - struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev); - struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai); - struct snd_dmaengine_dai_dma_data *dma_data = - snd_soc_dai_get_dma_data(socdai, substream); - u32 val, ch_num, rate; - int ret; - - dma_data->addr_width = params_width(params) >> 3; - - val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL); - val &= ~ZX_CTRL_MODA_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - val |= ZX_CTRL_MODA_16; - break; - - case SNDRV_PCM_FORMAT_S18_3LE: - val |= ZX_CTRL_MODA_18; - break; - - case SNDRV_PCM_FORMAT_S20_3LE: - val |= ZX_CTRL_MODA_20; - break; - - case SNDRV_PCM_FORMAT_S24_LE: - val |= ZX_CTRL_MODA_24; - break; - default: - dev_err(socdai->dev, "Format not support!\n"); - return -EINVAL; - } - - ch_num = params_channels(params); - if (ch_num == 2) - val |= ZX_CTRL_DOUBLE_TRACK; - else - val |= ZX_CTRL_LEFT_TRACK; - writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL); - - val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT); - val &= ~ZX_VALID_TRACK_MASK; - if (ch_num == 2) - val |= ZX_VALID_DOUBLE_TRACK; - else - val |= ZX_VALID_RIGHT_TRACK; - writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT); - - rate = params_rate(params); - ret = zx_spdif_chanstats(zx_spdif->reg_base, rate); - if (ret) - return ret; - return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT); -} - -static void zx_spdif_cfg_tx(void __iomem *base, int on) -{ - u32 val; - - val = readl_relaxed(base + ZX_CTRL); - val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK); - val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE; - writel_relaxed(val, base + ZX_CTRL); - - val = readl_relaxed(base + ZX_FIFOCTRL); - val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK; - if (on) - val |= ZX_FIFOCTRL_TX_DMA_EN; - writel_relaxed(val, base + ZX_FIFOCTRL); -} - -static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - u32 val; - struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL); - val |= ZX_FIFOCTRL_TX_FIFO_RST; - writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL); - fallthrough; - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - zx_spdif_cfg_tx(zx_spdif->reg_base, true); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - zx_spdif_cfg_tx(zx_spdif->reg_base, false); - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int zx_spdif_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); - - return clk_prepare_enable(zx_spdif->dai_clk); -} - -static void zx_spdif_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); - - clk_disable_unprepare(zx_spdif->dai_clk); -} - -#define ZX_RATES \ - (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) - -#define ZX_FORMAT \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \ - | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops zx_spdif_dai_ops = { - .trigger = zx_spdif_trigger, - .startup = zx_spdif_startup, - .shutdown = zx_spdif_shutdown, - .hw_params = zx_spdif_hw_params, -}; - -static struct snd_soc_dai_driver zx_spdif_dai = { - .name = "spdif", - .id = 0, - .probe = zx_spdif_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = ZX_RATES, - .formats = ZX_FORMAT, - }, - .ops = &zx_spdif_dai_ops, -}; - -static const struct snd_soc_component_driver zx_spdif_component = { - .name = "spdif", -}; - -static void zx_spdif_dev_init(void __iomem *base) -{ - u32 val; - - writel_relaxed(0, base + ZX_CTRL); - writel_relaxed(0, base + ZX_INT_MASK); - writel_relaxed(0xf, base + ZX_INT_STATUS); - writel_relaxed(0x1, base + ZX_FIFOCTRL); - - val = readl_relaxed(base + ZX_FIFOCTRL); - val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK); - val |= ZX_FIFOCTRL_TXTH(8); - writel_relaxed(val, base + ZX_FIFOCTRL); -} - -static int zx_spdif_probe(struct platform_device *pdev) -{ - struct resource *res; - struct zx_spdif_info *zx_spdif; - int ret; - - zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL); - if (!zx_spdif) - return -ENOMEM; - - zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx"); - if (IS_ERR(zx_spdif->dai_clk)) { - dev_err(&pdev->dev, "Fail to get clk\n"); - return PTR_ERR(zx_spdif->dai_clk); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - zx_spdif->mapbase = res->start; - zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(zx_spdif->reg_base)) { - return PTR_ERR(zx_spdif->reg_base); - } - - zx_spdif_dev_init(zx_spdif->reg_base); - platform_set_drvdata(pdev, zx_spdif); - - ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component, - &zx_spdif_dai, 1); - if (ret) { - dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); - return ret; - } - - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); - if (ret) - dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); - - return ret; -} - -static const struct of_device_id zx_spdif_dt_ids[] = { - { .compatible = "zte,zx296702-spdif", }, - {} -}; -MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids); - -static struct platform_driver spdif_driver = { - .probe = zx_spdif_probe, - .driver = { - .name = "zx-spdif", - .of_match_table = zx_spdif_dt_ids, - }, -}; - -module_platform_driver(spdif_driver); - -MODULE_AUTHOR("Jun Nie "); -MODULE_DESCRIPTION("ZTE SPDIF SoC DAI"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c deleted file mode 100644 index 4f787185d630..000000000000 --- a/sound/soc/zte/zx-tdm.c +++ /dev/null @@ -1,458 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * ZTE's TDM driver - * - * Copyright (C) 2017 ZTE Ltd - * - * Author: Baoyou Xie - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define REG_TIMING_CTRL 0x04 -#define REG_TX_FIFO_CTRL 0x0C -#define REG_RX_FIFO_CTRL 0x10 -#define REG_INT_EN 0x1C -#define REG_INT_STATUS 0x20 -#define REG_DATABUF 0x24 -#define REG_TS_MASK0 0x44 -#define REG_PROCESS_CTRL 0x54 - -#define FIFO_CTRL_TX_RST BIT(0) -#define FIFO_CTRL_RX_RST BIT(0) -#define DEAGULT_FIFO_THRES GENMASK(4, 2) - -#define FIFO_CTRL_TX_DMA_EN BIT(1) -#define FIFO_CTRL_RX_DMA_EN BIT(1) - -#define TX_FIFO_RST_MASK BIT(0) -#define RX_FIFO_RST_MASK BIT(0) - -#define FIFOCTRL_TX_FIFO_RST BIT(0) -#define FIFOCTRL_RX_FIFO_RST BIT(0) - -#define TXTH_MASK GENMASK(5, 2) -#define RXTH_MASK GENMASK(5, 2) - -#define FIFOCTRL_THRESHOLD(x) ((x) << 2) - -#define TIMING_MS_MASK BIT(1) -/* - * 00: 8 clk cycles every timeslot - * 01: 16 clk cycles every timeslot - * 10: 32 clk cycles every timeslot - */ -#define TIMING_SYNC_WIDTH_MASK GENMASK(6, 5) -#define TIMING_WIDTH_SHIFT 5 -#define TIMING_DEFAULT_WIDTH 0 -#define TIMING_TS_WIDTH(x) ((x) << TIMING_WIDTH_SHIFT) -#define TIMING_WIDTH_FACTOR 8 - -#define TIMING_MASTER_MODE BIT(21) -#define TIMING_LSB_FIRST BIT(20) -#define TIMING_TS_NUM(x) (((x) - 1) << 7) -#define TIMING_CLK_SEL_MASK GENMASK(2, 0) -#define TIMING_CLK_SEL_DEF BIT(2) - -#define PROCESS_TX_EN BIT(0) -#define PROCESS_RX_EN BIT(1) -#define PROCESS_TDM_EN BIT(2) -#define PROCESS_DISABLE_ALL 0 - -#define INT_DISABLE_ALL 0 -#define INT_STATUS_MASK GENMASK(6, 0) - -struct zx_tdm_info { - struct snd_dmaengine_dai_dma_data dma_playback; - struct snd_dmaengine_dai_dma_data dma_capture; - resource_size_t phy_addr; - void __iomem *regbase; - struct clk *dai_wclk; - struct clk *dai_pclk; - int master; - struct device *dev; -}; - -static inline u32 zx_tdm_readl(struct zx_tdm_info *tdm, u16 reg) -{ - return readl_relaxed(tdm->regbase + reg); -} - -static inline void zx_tdm_writel(struct zx_tdm_info *tdm, u16 reg, u32 val) -{ - writel_relaxed(val, tdm->regbase + reg); -} - -static void zx_tdm_tx_en(struct zx_tdm_info *tdm, bool on) -{ - unsigned long val; - - val = zx_tdm_readl(tdm, REG_PROCESS_CTRL); - if (on) - val |= PROCESS_TX_EN | PROCESS_TDM_EN; - else - val &= ~(PROCESS_TX_EN | PROCESS_TDM_EN); - zx_tdm_writel(tdm, REG_PROCESS_CTRL, val); -} - -static void zx_tdm_rx_en(struct zx_tdm_info *tdm, bool on) -{ - unsigned long val; - - val = zx_tdm_readl(tdm, REG_PROCESS_CTRL); - if (on) - val |= PROCESS_RX_EN | PROCESS_TDM_EN; - else - val &= ~(PROCESS_RX_EN | PROCESS_TDM_EN); - zx_tdm_writel(tdm, REG_PROCESS_CTRL, val); -} - -static void zx_tdm_tx_dma_en(struct zx_tdm_info *tdm, bool on) -{ - unsigned long val; - - val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL); - val |= FIFO_CTRL_TX_RST | DEAGULT_FIFO_THRES; - if (on) - val |= FIFO_CTRL_TX_DMA_EN; - else - val &= ~FIFO_CTRL_TX_DMA_EN; - zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val); -} - -static void zx_tdm_rx_dma_en(struct zx_tdm_info *tdm, bool on) -{ - unsigned long val; - - val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL); - val |= FIFO_CTRL_RX_RST | DEAGULT_FIFO_THRES; - if (on) - val |= FIFO_CTRL_RX_DMA_EN; - else - val &= ~FIFO_CTRL_RX_DMA_EN; - zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val); -} - -#define ZX_TDM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000) - -#define ZX_TDM_FMTBIT \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \ - SNDRV_PCM_FMTBIT_A_LAW) - -static int zx_tdm_dai_probe(struct snd_soc_dai *dai) -{ - struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev); - - snd_soc_dai_set_drvdata(dai, zx_tdm); - zx_tdm->dma_playback.addr = zx_tdm->phy_addr + REG_DATABUF; - zx_tdm->dma_playback.maxburst = 16; - zx_tdm->dma_capture.addr = zx_tdm->phy_addr + REG_DATABUF; - zx_tdm->dma_capture.maxburst = 16; - snd_soc_dai_init_dma_data(dai, &zx_tdm->dma_playback, - &zx_tdm->dma_capture); - return 0; -} - -static int zx_tdm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) -{ - struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long val; - - val = zx_tdm_readl(tdm, REG_TIMING_CTRL); - val &= ~(TIMING_SYNC_WIDTH_MASK | TIMING_MS_MASK); - val |= TIMING_DEFAULT_WIDTH << TIMING_WIDTH_SHIFT; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - tdm->master = 1; - val |= TIMING_MASTER_MODE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - tdm->master = 0; - val &= ~TIMING_MASTER_MODE; - break; - default: - dev_err(cpu_dai->dev, "Unknown master/slave format\n"); - return -EINVAL; - } - - - zx_tdm_writel(tdm, REG_TIMING_CTRL, val); - - return 0; -} - -static int zx_tdm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *socdai) -{ - struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(socdai); - struct snd_dmaengine_dai_dma_data *dma_data; - unsigned int ts_width = TIMING_DEFAULT_WIDTH; - unsigned int ch_num = 32; - unsigned int mask = 0; - unsigned int ret = 0; - unsigned long val; - - dma_data = snd_soc_dai_get_dma_data(socdai, substream); - dma_data->addr_width = ch_num >> 3; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_MU_LAW: - case SNDRV_PCM_FORMAT_A_LAW: - case SNDRV_PCM_FORMAT_S16_LE: - ts_width = 1; - break; - default: - dev_err(socdai->dev, "Unknown data format\n"); - return -EINVAL; - } - - val = zx_tdm_readl(tdm, REG_TIMING_CTRL); - val |= TIMING_TS_WIDTH(ts_width) | TIMING_TS_NUM(1); - zx_tdm_writel(tdm, REG_TIMING_CTRL, val); - zx_tdm_writel(tdm, REG_TS_MASK0, mask); - - if (tdm->master) - ret = clk_set_rate(tdm->dai_wclk, - params_rate(params) * TIMING_WIDTH_FACTOR * ch_num); - - return ret; -} - -static int zx_tdm_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev); - unsigned int val; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (capture) { - val = zx_tdm_readl(zx_tdm, REG_RX_FIFO_CTRL); - val |= FIFOCTRL_RX_FIFO_RST; - zx_tdm_writel(zx_tdm, REG_RX_FIFO_CTRL, val); - - zx_tdm_rx_dma_en(zx_tdm, true); - } else { - val = zx_tdm_readl(zx_tdm, REG_TX_FIFO_CTRL); - val |= FIFOCTRL_TX_FIFO_RST; - zx_tdm_writel(zx_tdm, REG_TX_FIFO_CTRL, val); - - zx_tdm_tx_dma_en(zx_tdm, true); - } - break; - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (capture) - zx_tdm_rx_en(zx_tdm, true); - else - zx_tdm_tx_en(zx_tdm, true); - break; - case SNDRV_PCM_TRIGGER_STOP: - if (capture) - zx_tdm_rx_dma_en(zx_tdm, false); - else - zx_tdm_tx_dma_en(zx_tdm, false); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (capture) - zx_tdm_rx_en(zx_tdm, false); - else - zx_tdm_tx_en(zx_tdm, false); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int zx_tdm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev); - int ret; - - ret = clk_prepare_enable(zx_tdm->dai_wclk); - if (ret) - return ret; - - ret = clk_prepare_enable(zx_tdm->dai_pclk); - if (ret) { - clk_disable_unprepare(zx_tdm->dai_wclk); - return ret; - } - - return 0; -} - -static void zx_tdm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev); - - clk_disable_unprepare(zx_tdm->dai_pclk); - clk_disable_unprepare(zx_tdm->dai_wclk); -} - -static const struct snd_soc_dai_ops zx_tdm_dai_ops = { - .trigger = zx_tdm_trigger, - .hw_params = zx_tdm_hw_params, - .set_fmt = zx_tdm_set_fmt, - .startup = zx_tdm_startup, - .shutdown = zx_tdm_shutdown, -}; - -static const struct snd_soc_component_driver zx_tdm_component = { - .name = "zx-tdm", -}; - -static void zx_tdm_init_state(struct zx_tdm_info *tdm) -{ - unsigned int val; - - zx_tdm_writel(tdm, REG_PROCESS_CTRL, PROCESS_DISABLE_ALL); - - val = zx_tdm_readl(tdm, REG_TIMING_CTRL); - val |= TIMING_LSB_FIRST; - val &= ~TIMING_CLK_SEL_MASK; - val |= TIMING_CLK_SEL_DEF; - zx_tdm_writel(tdm, REG_TIMING_CTRL, val); - - zx_tdm_writel(tdm, REG_INT_EN, INT_DISABLE_ALL); - /* - * write INT_STATUS register to clear it. - */ - zx_tdm_writel(tdm, REG_INT_STATUS, INT_STATUS_MASK); - zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, FIFOCTRL_RX_FIFO_RST); - zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, FIFOCTRL_TX_FIFO_RST); - - val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL); - val &= ~(RXTH_MASK | RX_FIFO_RST_MASK); - val |= FIFOCTRL_THRESHOLD(8); - zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val); - - val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL); - val &= ~(TXTH_MASK | TX_FIFO_RST_MASK); - val |= FIFOCTRL_THRESHOLD(8); - zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val); -} - -static struct snd_soc_dai_driver zx_tdm_dai = { - .name = "zx-tdm-dai", - .id = 0, - .probe = zx_tdm_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 4, - .rates = ZX_TDM_RATES, - .formats = ZX_TDM_FMTBIT, - }, - .capture = { - .channels_min = 1, - .channels_max = 4, - .rates = ZX_TDM_RATES, - .formats = ZX_TDM_FMTBIT, - }, - .ops = &zx_tdm_dai_ops, -}; - -static int zx_tdm_probe(struct platform_device *pdev) -{ - struct of_phandle_args out_args; - unsigned int dma_reg_offset; - struct zx_tdm_info *zx_tdm; - unsigned int dma_mask; - struct resource *res; - struct regmap *regmap_sysctrl; - int ret; - - zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL); - if (!zx_tdm) - return -ENOMEM; - - zx_tdm->dev = &pdev->dev; - - zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk"); - if (IS_ERR(zx_tdm->dai_wclk)) { - dev_err(&pdev->dev, "Fail to get wclk\n"); - return PTR_ERR(zx_tdm->dai_wclk); - } - - zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(zx_tdm->dai_pclk)) { - dev_err(&pdev->dev, "Fail to get pclk\n"); - return PTR_ERR(zx_tdm->dai_pclk); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - zx_tdm->phy_addr = res->start; - zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(zx_tdm->regbase)) - return PTR_ERR(zx_tdm->regbase); - - ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, - "zte,tdm-dma-sysctrl", 2, 0, &out_args); - if (ret) { - dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n"); - return ret; - } - - dma_reg_offset = out_args.args[0]; - dma_mask = out_args.args[1]; - regmap_sysctrl = syscon_node_to_regmap(out_args.np); - if (IS_ERR(regmap_sysctrl)) { - of_node_put(out_args.np); - return PTR_ERR(regmap_sysctrl); - } - - regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask); - of_node_put(out_args.np); - - zx_tdm_init_state(zx_tdm); - platform_set_drvdata(pdev, zx_tdm); - - ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component, - &zx_tdm_dai, 1); - if (ret) { - dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); - return ret; - } - - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); - if (ret) - dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); - - return ret; -} - -static const struct of_device_id zx_tdm_dt_ids[] = { - { .compatible = "zte,zx296718-tdm", }, - {} -}; -MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids); - -static struct platform_driver tdm_driver = { - .probe = zx_tdm_probe, - .driver = { - .name = "zx-tdm", - .of_match_table = zx_tdm_dt_ids, - }, -}; -module_platform_driver(tdm_driver); - -MODULE_AUTHOR("Baoyou Xie "); -MODULE_DESCRIPTION("ZTE TDM DAI driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 086b957cc17f53f03bae9d2baf930ac51cf68b99 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jan 2021 22:39:31 +0100 Subject: ALSA: usb-audio: Skip the clock selector inquiry for single connections The current USB-audio driver gets an error at probing NUX MG-300 about parsing the clocks. This is because the firmware doesn't return the proper connection of the clock selector that is connected to a single clock; it's likely that the firmware was lazy^w optimized and the inquiry wasn't handled. Actually it makes little sense to inquire and set up the single connection explicitly. This patch fixes the issue by simply skipping the clock selector inquiry if it's a single connection. Reported-by: Mike Oliphant Link: https://lore.kernel.org/r/20210120213932.1971-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/clock.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index dc68ed65e478..8243652d5604 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -298,6 +298,11 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, if (selector) { int ret, i, cur; + if (selector->bNrInPins == 1) { + ret = 1; + goto find_source; + } + /* the entity ID we are looking for is a selector. * find out what it currently selects */ ret = uac_clock_selector_get_val(chip, selector->bClockID); @@ -314,6 +319,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, return -EINVAL; } + find_source: cur = ret; ret = __uac_clock_find_source(chip, fmt, selector->baCSourceID[ret - 1], -- cgit v1.2.3 From 85db1cfb13e37d24be225739dc0e2da478dd2c1c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jan 2021 22:39:32 +0100 Subject: ALSA: usb-audio: Fix "RANGE setting not yet supported" errors At probing a UAC2/UAC3 device like NUX MG-300 USB interface, we get error messages "RANGE setting not yet supported". It comes the place where the driver tries to determine the resolution of mixer volumes via SET_CUR_RES and GET_CUR_RES verbs. Those verbs aren't supported on UAC2 and UAC3, hence the driver warns like the above. Although the driver handles this error and works as expected, it's still ugly to show such errors unnecessarily. This patch papers over the errors by applying the resolution detection only for UAC1 and skipping it for UAC2/UAC3. Reported-by: Mike Oliphant Link: https://lore.kernel.org/r/20210120213932.1971-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c7da38348035..b1c78db0d470 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1238,7 +1238,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, (cval->control << 8) | minchn, &cval->res) < 0) { cval->res = 1; - } else { + } else if (cval->head.mixer->protocol == UAC_VERSION_1) { int last_valid_res = cval->res; while (cval->res > 1) { -- cgit v1.2.3 From d52bbf747cfa8a2988289009241214a84982cc7d Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 20 Jan 2021 16:28:44 +0100 Subject: ASoC: topology: KUnit: Add KUnit tests passing various arguments to snd_soc_tplg_component_load In order to ensure correct behaviour of topology API, add unit tests exercising topology functionality. Start with adding cases for passing various arguments to snd_soc_tplg_component_load as it is part of exposed topology API. First test case adds test passing NULL component as argument. Following one adds test case for passing NULL ops as argument. Finally add test case passing NULL fw as argument. Signed-off-by: Amadeusz Sławiński Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210120152846.1703655-4-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/Kconfig | 17 +++ sound/soc/Makefile | 5 + sound/soc/soc-topology-test.c | 303 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 sound/soc/soc-topology-test.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index ba79d5f4e299..640494f76cbd 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -37,6 +37,23 @@ config SND_SOC_COMPRESS config SND_SOC_TOPOLOGY bool +config SND_SOC_TOPOLOGY_KUNIT_TESTS + tristate "KUnit tests for SoC topology" + depends on KUNIT + depends on SND_SOC_TOPOLOGY + default KUNIT_ALL_TESTS + help + If you want to perform tests on ALSA SoC topology support say Y here. + + This builds a module which can be later manually loaded to run KUNIT + test cases against soc-topology.c API. This should be primarily used + by developers to test their changes to ASoC. + + Do note that it creates fake playback devices which do not interact + well with userspace. When running tests one may want to disable + userspace applications such as pulseaudio, to prevent unnecessary + problems. + config SND_SOC_ACPI tristate diff --git a/sound/soc/Makefile b/sound/soc/Makefile index eee370492eee..f56ad996eae8 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -7,6 +7,11 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) snd-soc-core-objs += soc-topology.o endif +ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS),) +# snd-soc-test-objs := soc-topology-test.o +obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS) := soc-topology-test.o +endif + ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) snd-soc-core-objs += soc-generic-dmaengine-pcm.o endif diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c new file mode 100644 index 000000000000..7276ed95d83d --- /dev/null +++ b/sound/soc/soc-topology-test.c @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * soc-topology-test.c -- ALSA SoC Topology Kernel Unit Tests + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +/* ===== HELPER FUNCTIONS =================================================== */ + +/* + * snd_soc_component needs device to operate on (primarily for prints), create + * fake one, as we don't register with PCI or anything else + * device_driver name is used in some of the prints (fmt_single_name) so + * we also mock up minimal one + */ +static struct device *test_dev; + +static struct device_driver test_drv = { + .name = "sound-soc-topology-test-driver", +}; + +static int snd_soc_tplg_test_init(struct kunit *test) +{ + test_dev = root_device_register("sound-soc-topology-test"); + test_dev = get_device(test_dev); + if (!test_dev) + return -ENODEV; + + test_dev->driver = &test_drv; + + return 0; +} + +static void snd_soc_tplg_test_exit(struct kunit *test) +{ + put_device(test_dev); + root_device_unregister(test_dev); +} + +/* + * helper struct we use when registering component, as we load topology during + * component probe, we need to pass struct kunit somehow to probe function, so + * we can report test result + */ +struct kunit_soc_component { + struct kunit *kunit; + int expect; /* what result we expect when loading topology */ + struct snd_soc_component comp; + struct snd_soc_card card; + struct firmware fw; +}; + +static int d_probe(struct snd_soc_component *component) +{ + struct kunit_soc_component *kunit_comp = + container_of(component, struct kunit_soc_component, comp); + int ret; + + ret = snd_soc_tplg_component_load(component, NULL, &kunit_comp->fw); + KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret, + "Failed topology load"); + + return 0; +} + +static void d_remove(struct snd_soc_component *component) +{ + struct kunit_soc_component *kunit_comp = + container_of(component, struct kunit_soc_component, comp); + int ret; + + ret = snd_soc_tplg_component_remove(component); + KUNIT_EXPECT_EQ(kunit_comp->kunit, 0, ret); +} + +/* + * ASoC minimal boiler plate + */ +SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test"))); + +static struct snd_soc_dai_link kunit_dai_links[] = { + { + .name = "KUNIT Audio Port", + .id = 0, + .stream_name = "Audio Playback/Capture", + .nonatomic = 1, + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(dummy, dummy, platform), + }, +}; + +static const struct snd_soc_component_driver test_component = { + .name = "sound-soc-topology-test", + .probe = d_probe, + .remove = d_remove, + .non_legacy_dai_naming = 1, +}; + +/* ===== TEST CASES ========================================================= */ + +// TEST CASE +// Test passing NULL component as parameter to snd_soc_tplg_component_load + +/* + * need to override generic probe function with one using NULL when calling + * topology load during component initialization, we don't need .remove + * handler as load should fail + */ +static int d_probe_null_comp(struct snd_soc_component *component) +{ + struct kunit_soc_component *kunit_comp = + container_of(component, struct kunit_soc_component, comp); + int ret; + + /* instead of passing component pointer as first argument, pass NULL here */ + ret = snd_soc_tplg_component_load(NULL, NULL, &kunit_comp->fw); + KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret, + "Failed topology load"); + + return 0; +} + +static const struct snd_soc_component_driver test_component_null_comp = { + .name = "sound-soc-topology-test", + .probe = d_probe_null_comp, + .non_legacy_dai_naming = 1, +}; + +static void snd_soc_tplg_test_load_with_null_comp(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = -EINVAL; /* expect failure */ + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_comp, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +// TEST CASE +// Test passing NULL ops as parameter to snd_soc_tplg_component_load + +/* + * NULL ops is default case, we pass empty topology (fw), so we don't have + * anything to parse and just do nothing, which results in return 0; from + * calling soc_tplg_dapm_complete in soc_tplg_process_headers + */ +static void snd_soc_tplg_test_load_with_null_ops(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = 0; /* expect success */ + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +// TEST CASE +// Test passing NULL fw as parameter to snd_soc_tplg_component_load + +/* + * need to override generic probe function with one using NULL pointer to fw + * when calling topology load during component initialization, we don't need + * .remove handler as load should fail + */ +static int d_probe_null_fw(struct snd_soc_component *component) +{ + struct kunit_soc_component *kunit_comp = + container_of(component, struct kunit_soc_component, comp); + int ret; + + /* instead of passing fw pointer as third argument, pass NULL here */ + ret = snd_soc_tplg_component_load(component, NULL, NULL); + KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret, + "Failed topology load"); + + return 0; +} + +static const struct snd_soc_component_driver test_component_null_fw = { + .name = "sound-soc-topology-test", + .probe = d_probe_null_fw, + .non_legacy_dai_naming = 1, +}; + +static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = -EINVAL; /* expect failure */ + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_fw, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +/* ===== KUNIT MODULE DEFINITIONS =========================================== */ + +static struct kunit_case snd_soc_tplg_test_cases[] = { + KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp), + KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops), + KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw), + {} +}; + +static struct kunit_suite snd_soc_tplg_test_suite = { + .name = "snd_soc_tplg_test", + .init = snd_soc_tplg_test_init, + .exit = snd_soc_tplg_test_exit, + .test_cases = snd_soc_tplg_test_cases, +}; + +kunit_test_suites(&snd_soc_tplg_test_suite); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From cec9128dfcf9101f903470e43d46278e5b07ef24 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 20 Jan 2021 16:28:45 +0100 Subject: ASoC: topology: KUnit: Add KUnit tests passing empty topology with variants to snd_soc_tplg_component_load In order to ensure correct behaviour of topology API, add unit tests exercising topology functionality. Add "empty" topology template and tests for parsing it. Also adds few variants with bad magic numbers. Signed-off-by: Amadeusz Sławiński Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210120152846.1703655-5-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology-test.c | 311 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 310 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c index 7276ed95d83d..bae40c111f9b 100644 --- a/sound/soc/soc-topology-test.c +++ b/sound/soc/soc-topology-test.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -108,6 +107,37 @@ static const struct snd_soc_component_driver test_component = { .non_legacy_dai_naming = 1, }; +/* ===== TOPOLOGY TEMPLATES ================================================= */ + +// Structural representation of topology which can be generated with: +// $ touch empty +// $ alsatplg -c empty -o empty.tplg +// $ xxd -i empty.tplg + +struct tplg_tmpl_001 { + struct snd_soc_tplg_hdr header; + struct snd_soc_tplg_manifest manifest; +} __packed; + +static struct tplg_tmpl_001 tplg_tmpl_empty = { + .header = { + .magic = SND_SOC_TPLG_MAGIC, + .abi = 5, + .version = 0, + .type = SND_SOC_TPLG_TYPE_MANIFEST, + .size = sizeof(struct snd_soc_tplg_hdr), + .vendor_type = 0, + .payload_size = sizeof(struct snd_soc_tplg_manifest), + .index = 0, + .count = 1, + }, + + .manifest = { + .size = sizeof(struct snd_soc_tplg_manifest), + /* rest of fields is 0 */ + }, +}; + /* ===== TEST CASES ========================================================= */ // TEST CASE @@ -282,12 +312,291 @@ static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test) snd_soc_unregister_component(test_dev); } +// TEST CASE +// Test passing "empty" topology file +static void snd_soc_tplg_test_load_empty_tplg(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + struct tplg_tmpl_001 *data; + int size; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = 0; /* expect success */ + + size = sizeof(tplg_tmpl_empty); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); + + kunit_comp->fw.data = (u8 *)data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +// TEST CASE +// Test "empty" topology file, but with bad "magic" +// In theory we could loop through all possible bad values, but it takes too +// long, so just use SND_SOC_TPLG_MAGIC + 1 +static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + struct tplg_tmpl_001 *data; + int size; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = -EINVAL; /* expect failure */ + + size = sizeof(tplg_tmpl_empty); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); + /* + * override abi + * any value != magic number is wrong + */ + data->header.magic = SND_SOC_TPLG_MAGIC + 1; + + kunit_comp->fw.data = (u8 *)data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +// TEST CASE +// Test "empty" topology file, but with bad "abi" +// In theory we could loop through all possible bad values, but it takes too +// long, so just use SND_SOC_TPLG_ABI_VERSION + 1 +static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + struct tplg_tmpl_001 *data; + int size; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = -EINVAL; /* expect failure */ + + size = sizeof(tplg_tmpl_empty); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); + /* + * override abi + * any value != accepted range is wrong + */ + data->header.abi = SND_SOC_TPLG_ABI_VERSION + 1; + + kunit_comp->fw.data = (u8 *)data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +// TEST CASE +// Test "empty" topology file, but with bad "size" +// In theory we could loop through all possible bad values, but it takes too +// long, so just use sizeof(struct snd_soc_tplg_hdr) + 1 +static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + struct tplg_tmpl_001 *data; + int size; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = -EINVAL; /* expect failure */ + + size = sizeof(tplg_tmpl_empty); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); + /* + * override size + * any value != struct size is wrong + */ + data->header.size = sizeof(struct snd_soc_tplg_hdr) + 1; + + kunit_comp->fw.data = (u8 *)data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); +} + +// TEST CASE +// Test "empty" topology file, but with bad "payload_size" +// In theory we could loop through all possible bad values, but it takes too +// long, so just use the known wrong one +static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + struct tplg_tmpl_001 *data; + int size; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = -EINVAL; /* expect failure */ + + size = sizeof(tplg_tmpl_empty); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); + /* + * override payload size + * there is only explicit check for 0, so check with it, other values + * are handled by just not reading behind EOF + */ + data->header.payload_size = 0; + + kunit_comp->fw.data = (u8 *)data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + /* cleanup */ + snd_soc_unregister_component(test_dev); + + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); +} + /* ===== KUNIT MODULE DEFINITIONS =========================================== */ static struct kunit_case snd_soc_tplg_test_cases[] = { KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp), KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops), KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw), + KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg), + KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_magic), + KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi), + KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size), + KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size), {} }; -- cgit v1.2.3 From 3ad8c8e9efc53d14d928b84aabe1a27dd5d3171b Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 20 Jan 2021 16:28:46 +0100 Subject: ASoC: topology: KUnit: Add KUnit tests passing topology with PCM to snd_soc_tplg_component_load In order to ensure correct behaviour of topology API, add unit tests exercising topology functionality. Add topology containing PCM template and tests for parsing it. Also adds test cases simulating modules reloads in case of separate drivers for card and component. Signed-off-by: Amadeusz Sławiński Tested-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210120152846.1703655-6-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology-test.c | 231 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c index bae40c111f9b..36e2a3486dbf 100644 --- a/sound/soc/soc-topology-test.c +++ b/sound/soc/soc-topology-test.c @@ -138,6 +138,79 @@ static struct tplg_tmpl_001 tplg_tmpl_empty = { }, }; +// Structural representation of topology containing SectionPCM + +struct tplg_tmpl_002 { + struct snd_soc_tplg_hdr header; + struct snd_soc_tplg_manifest manifest; + struct snd_soc_tplg_hdr pcm_header; + struct snd_soc_tplg_pcm pcm; +} __packed; + +static struct tplg_tmpl_002 tplg_tmpl_with_pcm = { + .header = { + .magic = SND_SOC_TPLG_MAGIC, + .abi = 5, + .version = 0, + .type = SND_SOC_TPLG_TYPE_MANIFEST, + .size = sizeof(struct snd_soc_tplg_hdr), + .vendor_type = 0, + .payload_size = sizeof(struct snd_soc_tplg_manifest), + .index = 0, + .count = 1, + }, + .manifest = { + .size = sizeof(struct snd_soc_tplg_manifest), + .pcm_elems = 1, + /* rest of fields is 0 */ + }, + .pcm_header = { + .magic = SND_SOC_TPLG_MAGIC, + .abi = 5, + .version = 0, + .type = SND_SOC_TPLG_TYPE_PCM, + .size = sizeof(struct snd_soc_tplg_hdr), + .vendor_type = 0, + .payload_size = sizeof(struct snd_soc_tplg_pcm), + .index = 0, + .count = 1, + }, + .pcm = { + .size = sizeof(struct snd_soc_tplg_pcm), + .pcm_name = "KUNIT Audio", + .dai_name = "kunit-audio-dai", + .pcm_id = 0, + .dai_id = 0, + .playback = 1, + .capture = 1, + .compress = 0, + .stream = { + [0] = { + .channels = 2, + }, + [1] = { + .channels = 2, + }, + }, + .num_streams = 0, + .caps = { + [0] = { + .name = "kunit-audio-playback", + .channels_min = 2, + .channels_max = 2, + }, + [1] = { + .name = "kunit-audio-capture", + .channels_min = 2, + .channels_max = 2, + }, + }, + .flag_mask = 0, + .flags = 0, + .priv = { 0 }, + }, +}; + /* ===== TEST CASES ========================================================= */ // TEST CASE @@ -586,6 +659,161 @@ static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *tes KUNIT_EXPECT_EQ(test, 0, ret); } +// TEST CASE +// Test passing topology file with PCM definition +static void snd_soc_tplg_test_load_pcm_tplg(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + u8 *data; + int size; + int ret; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = 0; /* expect success */ + + size = sizeof(tplg_tmpl_with_pcm); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm)); + + kunit_comp->fw.data = data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); +} + +// TEST CASE +// Test passing topology file with PCM definition +// with component reload +static void snd_soc_tplg_test_load_pcm_tplg_reload_comp(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + u8 *data; + int size; + int ret; + int i; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = 0; /* expect success */ + + size = sizeof(tplg_tmpl_with_pcm); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm)); + + kunit_comp->fw.data = data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + for (i = 0; i < 100; i++) { + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + snd_soc_unregister_component(test_dev); + } + + /* cleanup */ + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); +} + +// TEST CASE +// Test passing topology file with PCM definition +// with card reload +static void snd_soc_tplg_test_load_pcm_tplg_reload_card(struct kunit *test) +{ + struct kunit_soc_component *kunit_comp; + u8 *data; + int size; + int ret; + int i; + + /* prepare */ + kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); + kunit_comp->kunit = test; + kunit_comp->expect = 0; /* expect success */ + + size = sizeof(tplg_tmpl_with_pcm); + data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); + + memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm)); + + kunit_comp->fw.data = data; + kunit_comp->fw.size = size; + + kunit_comp->card.dev = test_dev, + kunit_comp->card.name = "kunit-card", + kunit_comp->card.owner = THIS_MODULE, + kunit_comp->card.dai_link = kunit_dai_links, + kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links), + kunit_comp->card.fully_routed = true, + + /* run test */ + ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); + KUNIT_EXPECT_EQ(test, 0, ret); + + ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); + KUNIT_EXPECT_EQ(test, 0, ret); + + for (i = 0; i < 100; i++) { + ret = snd_soc_register_card(&kunit_comp->card); + if (ret != 0 && ret != -EPROBE_DEFER) + KUNIT_FAIL(test, "Failed to register card"); + + ret = snd_soc_unregister_card(&kunit_comp->card); + KUNIT_EXPECT_EQ(test, 0, ret); + } + + /* cleanup */ + snd_soc_unregister_component(test_dev); +} + /* ===== KUNIT MODULE DEFINITIONS =========================================== */ static struct kunit_case snd_soc_tplg_test_cases[] = { @@ -597,6 +825,9 @@ static struct kunit_case snd_soc_tplg_test_cases[] = { KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi), KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size), KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size), + KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg), + KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_comp), + KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_card), {} }; -- cgit v1.2.3 From d40ab86f7db3612074d08a317bdb1eb8ba06a37e Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Thu, 14 Jan 2021 11:36:01 -0500 Subject: ASoC: topology: Ensure that needed parameters are set As snd_soc_tplg_component_load is exported function, which means it is part of API, there should be checks if it is called with proper parameters. Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20210114163602.911205-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 950c45008e24..0d182a190c98 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2659,8 +2659,14 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp, struct soc_tplg tplg; int ret; - /* component needs to exist to keep and reference data while parsing */ - if (!comp) + /* + * check if we have sane parameters: + * comp - needs to exist to keep and reference data while parsing + * comp->dev - used for resource management and prints + * comp->card - used for setting card related parameters + * fw - we need it, as it is the very thing we parse + */ + if (!comp || !comp->dev || !comp->card || !fw) return -EINVAL; /* setup parsing context */ -- cgit v1.2.3 From 9c88a9838352c43550ab18080c924824bc660546 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Thu, 14 Jan 2021 11:36:02 -0500 Subject: ASoC: topology: Check if ops is set before dereference Topology can be created without ops overrides, in that case trying to assign any value would lead to dereferencing NULL pointer. Other places in code have either checks for tplg->ops or loop using *_count variables, hence they can't dereference NULL pointer and there is no need to add more checks. Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20210114163602.911205-3-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 0d182a190c98..5476854c12b0 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2674,11 +2674,13 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp, tplg.fw = fw; tplg.dev = comp->dev; tplg.comp = comp; - tplg.ops = ops; - tplg.io_ops = ops->io_ops; - tplg.io_ops_count = ops->io_ops_count; - tplg.bytes_ext_ops = ops->bytes_ext_ops; - tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; + if (ops) { + tplg.ops = ops; + tplg.io_ops = ops->io_ops; + tplg.io_ops_count = ops->io_ops_count; + tplg.bytes_ext_ops = ops->bytes_ext_ops; + tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; + } ret = soc_tplg_load(&tplg); /* free the created components if fail to load topology */ -- cgit v1.2.3 From 80f454e283708c28f5220eda68511fc495e5ffaf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:52:38 +0900 Subject: ASoC: soc-pcm: revert soc_pcm_apply_symmetry() commit a39748d03cbc ("ASoC: soc-pcm: cleanup soc_pcm_apply_symmetry()") was applied by miscommunication. To more cleanup code, and to be easy review, this patch reverts it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y2guoljm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 67 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index f62136f16c2f..6e9f14d482ab 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -349,26 +349,53 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; -#define __soc_pcm_apply_symmetry(name, sname, NAME) \ - if (soc_dai->name && (soc_dai->driver->symmetric_##sname || \ - rtd->dai_link->symmetric_##sname)) { \ - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\ - #name, soc_dai->name); \ - \ - ret = snd_pcm_hw_constraint_single(substream->runtime, \ - SNDRV_PCM_HW_PARAM_##NAME,\ - soc_dai->name); \ - if (ret < 0) { \ - dev_err(soc_dai->dev, \ - "ASoC: Unable to apply %s constraint: %d\n",\ - #name, ret); \ - return ret; \ - } \ - } - - __soc_pcm_apply_symmetry(rate, rates, RATE); - __soc_pcm_apply_symmetry(channels, channels, CHANNELS); - __soc_pcm_apply_symmetry(sample_bits, samplebits, SAMPLE_BITS); + if (soc_dai->rate && (soc_dai->driver->symmetric_rates || + rtd->dai_link->symmetric_rates)) { + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", + soc_dai->rate); + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + soc_dai->rate); + if (ret < 0) { + dev_err(soc_dai->dev, + "ASoC: Unable to apply rate constraint: %d\n", + ret); + return ret; + } + } + + if (soc_dai->channels && (soc_dai->driver->symmetric_channels || + rtd->dai_link->symmetric_channels)) { + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", + soc_dai->channels); + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, + soc_dai->channels); + if (ret < 0) { + dev_err(soc_dai->dev, + "ASoC: Unable to apply channel symmetry constraint: %d\n", + ret); + return ret; + } + } + + if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits || + rtd->dai_link->symmetric_samplebits)) { + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", + soc_dai->sample_bits); + + ret = snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + soc_dai->sample_bits); + if (ret < 0) { + dev_err(soc_dai->dev, + "ASoC: Unable to apply sample bits symmetry constraint: %d\n", + ret); + return ret; + } + } return 0; } -- cgit v1.2.3 From f14654ddf2e982537ab476d392a87fcbf90374c3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:52:54 +0900 Subject: ASoC: sync parameter naming : rate / sample_bits snd_pcm_runtime / snd_soc_dai / snd_soc_dai_driver / snd_soc_dai_link have related parameter which is similar but not same naming. struct snd_pcm_runtime { ... (A) unsigned int rate; ... (B) unsigned int sample_bits; ... }; struct snd_soc_dai { ... (A) unsigned int rate; (B) unsigned int sample_bits; ... }; struct snd_soc_dai_driver { ... (A) unsigned int symmetric_rates:1; (B) unsigned int symmetric_samplebits:1; ... }; struct snd_soc_dai_link { ... (A) unsigned int symmetric_rates:1; (B) unsigned int symmetric_samplebits:1; ... }; Because it is similar but not same naming rule, code can be verbose / can't share macro. This patch sync naming rule for framework. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; old name will be removed if all drivers were switched to new naming rule. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wnweolj6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 6 ++++-- include/sound/soc.h | 4 ++-- sound/soc/rockchip/rockchip_i2s.c | 2 +- sound/soc/soc-core.c | 9 +++++++++ sound/soc/soc-pcm.c | 24 ++++++++++++------------ sound/soc/soc-topology.c | 8 ++++---- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 34d0dbf73ca9..ee3c6deb5719 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -353,9 +353,11 @@ struct snd_soc_dai_driver { /* DAI capabilities */ struct snd_soc_pcm_stream capture; struct snd_soc_pcm_stream playback; - unsigned int symmetric_rates:1; + unsigned int symmetric_rates:1; /* will be removed */ + unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; - unsigned int symmetric_samplebits:1; + unsigned int symmetric_samplebits:1; /* will be removed */ + unsigned int symmetric_sample_bits:1; /* probe ordering - for components with runtime dependencies */ int probe_order; diff --git a/include/sound/soc.h b/include/sound/soc.h index 3fa6c40a63b7..bd38015d6c6d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -685,9 +685,9 @@ struct snd_soc_dai_link { unsigned int ignore_suspend:1; /* Symmetry requirements */ - unsigned int symmetric_rates:1; + unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; - unsigned int symmetric_samplebits:1; + unsigned int symmetric_sample_bits:1; /* Do not create a PCM for this DAI link (Backend link) */ unsigned int no_pcm:1; diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index eae287d905eb..662de86eca11 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -373,7 +373,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, I2S_DMACR_RDL(16)); val = I2S_CKR_TRCM_TXRX; - if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates) + if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate) val = I2S_CKR_TRCM_TXONLY; regmap_update_bits(i2s->regmap, I2S_CKR, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f6d4e99b590c..bb8323cad51a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2509,6 +2509,15 @@ int snd_soc_register_component(struct device *dev, { struct snd_soc_component *component; int ret; + int i; + + /* Remove ME */ + for (i = 0; i < num_dai; i++) { + if (dai_drv[i].symmetric_rates) + dai_drv[i].symmetric_rate = dai_drv[i].symmetric_rates; + if (dai_drv[i].symmetric_samplebits) + dai_drv[i].symmetric_sample_bits = dai_drv[i].symmetric_samplebits; + } component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); if (!component) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6e9f14d482ab..1a5d0cb3dc69 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -349,8 +349,8 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; - if (soc_dai->rate && (soc_dai->driver->symmetric_rates || - rtd->dai_link->symmetric_rates)) { + if (soc_dai->rate && (soc_dai->driver->symmetric_rate || + rtd->dai_link->symmetric_rate)) { dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate); @@ -381,8 +381,8 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, } } - if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits || - rtd->dai_link->symmetric_samplebits)) { + if (soc_dai->sample_bits && (soc_dai->driver->symmetric_sample_bits || + rtd->dai_link->symmetric_sample_bits)) { dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", soc_dai->sample_bits); @@ -412,10 +412,10 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, soc_pcm_set_dai_params(&d, params); /* reject unmatched parameters when applying symmetry */ - symmetry = rtd->dai_link->symmetric_rates; + symmetry = rtd->dai_link->symmetric_rate; for_each_rtd_cpu_dais(rtd, i, dai) - symmetry |= dai->driver->symmetric_rates; + symmetry |= dai->driver->symmetric_rate; if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { @@ -443,10 +443,10 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, } } - symmetry = rtd->dai_link->symmetric_samplebits; + symmetry = rtd->dai_link->symmetric_sample_bits; for_each_rtd_dais(rtd, i, dai) - symmetry |= dai->driver->symmetric_samplebits; + symmetry |= dai->driver->symmetric_sample_bits; if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { @@ -469,15 +469,15 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) struct snd_soc_dai *dai; unsigned int symmetry, i; - symmetry = link->symmetric_rates || + symmetry = link->symmetric_rate || link->symmetric_channels || - link->symmetric_samplebits; + link->symmetric_sample_bits; for_each_rtd_dais(rtd, i, dai) symmetry = symmetry || - dai->driver->symmetric_rates || + dai->driver->symmetric_rate || dai->driver->symmetric_channels || - dai->driver->symmetric_samplebits; + dai->driver->symmetric_sample_bits; return symmetry; } diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 950c45008e24..27f7dd8fb7f6 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1672,7 +1672,7 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv, unsigned int flag_mask, unsigned int flags) { if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES) - dai_drv->symmetric_rates = + dai_drv->symmetric_rate = flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0; if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS) @@ -1681,7 +1681,7 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv, 1 : 0; if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS) - dai_drv->symmetric_samplebits = + dai_drv->symmetric_sample_bits = flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ? 1 : 0; } @@ -1763,7 +1763,7 @@ static void set_link_flags(struct snd_soc_dai_link *link, unsigned int flag_mask, unsigned int flags) { if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES) - link->symmetric_rates = + link->symmetric_rate = flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES ? 1 : 0; if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS) @@ -1772,7 +1772,7 @@ static void set_link_flags(struct snd_soc_dai_link *link, 1 : 0; if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS) - link->symmetric_samplebits = + link->symmetric_sample_bits = flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS ? 1 : 0; -- cgit v1.2.3 From 55d0056ba6a1bc8be2ae804cadf106ff2ae712ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:00 +0900 Subject: ASoC: adi: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v9byolj1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/adi/axi-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c index 8c4dc82be0df..aa082131fb90 100644 --- a/sound/soc/adi/axi-i2s.c +++ b/sound/soc/adi/axi-i2s.c @@ -156,7 +156,7 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = { static struct snd_soc_dai_driver axi_i2s_dai = { .probe = axi_i2s_dai_probe, .ops = &axi_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver axi_i2s_component = { -- cgit v1.2.3 From ba471f8d1655753bd1fad226a1c47ffc4568c02e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:13 +0900 Subject: ASoC: atmel: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87turiolio.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-i2s.c | 2 +- sound/soc/atmel/mchp-i2s-mcc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index 232300dda548..7c6187e41f2b 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -541,7 +541,7 @@ static struct snd_soc_dai_driver atmel_i2s_dai = { .formats = ATMEL_I2S_FORMATS, }, .ops = &atmel_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver atmel_i2s_component = { diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 04acc18f2d72..6d5ae18f8b38 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -859,8 +859,8 @@ static struct snd_soc_dai_driver mchp_i2s_mcc_dai = { .formats = MCHP_I2SMCC_FORMATS, }, .ops = &mchp_i2s_mcc_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, .symmetric_channels = 1, }; -- cgit v1.2.3 From 3470c2398ce9f6e80a5434c1c8649b036544a1d4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:18 +0900 Subject: ASoC: au1x: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sg72olij.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/au1x/i2sc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index 7fd08fafa490..65bd39f5032d 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -210,7 +210,7 @@ static const struct snd_soc_dai_ops au1xi2s_dai_ops = { }; static struct snd_soc_dai_driver au1xi2s_dai_driver = { - .symmetric_rates = 1, + .symmetric_rate = 1, .playback = { .rates = AU1XI2SC_RATES, .formats = AU1XI2SC_FMTS, -- cgit v1.2.3 From a8e940222bdf60b9957515e80064b1230a3fc774 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:23 +0900 Subject: ASoC: bcm: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r1mmolie.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 4 ++-- sound/soc/bcm/bcm63xx-i2s-whistler.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index c2f7631e8705..3d668f449bc1 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -783,8 +783,8 @@ static struct snd_soc_dai_driver bcm2835_i2s_dai = { | SNDRV_PCM_FMTBIT_S32_LE }, .ops = &bcm2835_i2s_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }; static bool bcm2835_i2s_volatile_reg(struct device *dev, unsigned int reg) diff --git a/sound/soc/bcm/bcm63xx-i2s-whistler.c b/sound/soc/bcm/bcm63xx-i2s-whistler.c index 246a57ac6679..527caf430715 100644 --- a/sound/soc/bcm/bcm63xx-i2s-whistler.c +++ b/sound/soc/bcm/bcm63xx-i2s-whistler.c @@ -212,7 +212,7 @@ static struct snd_soc_dai_driver bcm63xx_i2s_dai = { .formats = SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &bcm63xx_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, }; -- cgit v1.2.3 From f1e6b04baba690e3bd08669c73e8d78032c2b905 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:29 +0900 Subject: ASoC: cirrus: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pn26oli8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 371708b17c09..0d26550d0df8 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -404,7 +404,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) static struct snd_soc_dai_driver ep93xx_i2s_dai = { - .symmetric_rates= 1, + .symmetric_rate = 1, .probe = ep93xx_i2s_dai_probe, .playback = { .channels_min = 2, -- cgit v1.2.3 From c6d152a8de560f50a37e9580b7550dc2001eaccf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:33 +0900 Subject: ASoC: tegra: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o8hqoli4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra186_dspk.c | 2 +- sound/soc/tegra/tegra20_i2s.c | 2 +- sound/soc/tegra/tegra210_dmic.c | 2 +- sound/soc/tegra/tegra210_i2s.c | 2 +- sound/soc/tegra/tegra30_i2s.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index 7d9948fb2ca7..8ee9a77bd83d 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -217,7 +217,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = { SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra186_dspk_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 005fc4e645aa..d7a3d046c8f8 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -260,7 +260,7 @@ static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .ops = &tegra20_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver tegra20_i2s_component = { diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c index ead2c99bf72e..b096478cd2ef 100644 --- a/sound/soc/tegra/tegra210_dmic.c +++ b/sound/soc/tegra/tegra210_dmic.c @@ -228,7 +228,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = { SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_dmic_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index ca31ec92e508..45f31ccb49d8 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -577,7 +577,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = { SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &tegra210_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index db5a8587bfa4..6740df541508 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -316,7 +316,7 @@ static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .ops = &tegra30_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver tegra30_i2s_component = { -- cgit v1.2.3 From fadaed3023138197000d37c2fafe15b2208ec9bc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:38 +0900 Subject: ASoC: rockchip: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mtxaolhz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 2 +- sound/soc/rockchip/rockchip_pdm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 662de86eca11..0740764e7f71 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -471,7 +471,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = { SNDRV_PCM_FMTBIT_S32_LE), }, .ops = &rockchip_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver rockchip_i2s_component = { diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index e5f732747f71..9295d648624e 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -338,7 +338,7 @@ static struct snd_soc_dai_driver rockchip_pdm_dai = { .formats = ROCKCHIP_PDM_FORMATS, }, .ops = &rockchip_pdm_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver rockchip_pdm_component = { -- cgit v1.2.3 From d11ff0bf6ac1a85fcf51f4ca52934b0fb6ac47a6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:43 +0900 Subject: ASoC: samsung: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfcuolhu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 2 +- sound/soc/samsung/pcm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 4bdc268fd981..b043183174b2 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1175,7 +1175,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, dai_drv->probe = samsung_i2s_dai_probe; dai_drv->remove = samsung_i2s_dai_remove; - dai_drv->symmetric_rates = 1; + dai_drv->symmetric_rate = 1; dai_drv->ops = &samsung_i2s_dai_ops; dai_drv->playback.channels_min = 1; diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 6f50c7b47326..bfd76e9cc0ca 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -452,7 +452,7 @@ static int s3c_pcm_dai_probe(struct snd_soc_dai *dai) #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 #define S3C_PCM_DAI_DECLARE \ - .symmetric_rates = 1, \ + .symmetric_rate = 1, \ .probe = s3c_pcm_dai_probe, \ .ops = &s3c_pcm_dai_ops, \ .playback = { \ -- cgit v1.2.3 From f1cd5f3bbcef13980734ea18797f192c344d850e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:49 +0900 Subject: ASoC: sh: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0seolho.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 6e670b3e92a0..c405bf3b4c99 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1320,8 +1320,8 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, if (rsnd_ssi_is_pin_sharing(io_capture) || rsnd_ssi_is_pin_sharing(io_playback)) { - /* should have symmetric_rates if pin sharing */ - drv->symmetric_rates = 1; + /* should have symmetric_rate if pin sharing */ + drv->symmetric_rate = 1; } dev_dbg(dev, "%s (%s/%s)\n", rdai->name, -- cgit v1.2.3 From c756316f0027a8659562d7df76fb24a9ff7c2068 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:53 +0900 Subject: ASoC: ti: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87im7yolhk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-mcasp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 6247ec3d3a09..b94220306d1a 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1641,7 +1641,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }, .ops = &davinci_mcasp_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "davinci-mcasp.1", -- cgit v1.2.3 From c658b2185818ac39ca5b71001f30ab14a517219a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:53:58 +0900 Subject: ASoC: pxa: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7niolhf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 5301859a8453..bcde4a96c168 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -353,7 +353,7 @@ static struct snd_soc_dai_driver pxa_i2s_dai = { .rates = PXA2XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .ops = &pxa_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver pxa_i2s_component = { -- cgit v1.2.3 From 4b7ead032ecd1b1af5ce0dfbc2479cfdee7063b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:03 +0900 Subject: ASoC: mediatek: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ft32olha.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 10 +++++----- sound/soc/mediatek/mt6797/mt6797-dai-pcm.c | 8 ++++---- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 2 +- sound/soc/mediatek/mt8183/mt8183-dai-pcm.c | 8 ++++---- sound/soc/mediatek/mt8192/mt8192-dai-pcm.c | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index df29641c74aa..d5cffe7a7e15 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -655,7 +655,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { }, .ops = &mt2701_afe_i2s_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "I2S1", @@ -679,7 +679,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { | SNDRV_PCM_FMTBIT_S32_LE) }, .ops = &mt2701_afe_i2s_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "I2S2", @@ -703,7 +703,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { | SNDRV_PCM_FMTBIT_S32_LE) }, .ops = &mt2701_afe_i2s_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "I2S3", @@ -727,7 +727,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { | SNDRV_PCM_FMTBIT_S32_LE) }, .ops = &mt2701_afe_i2s_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "MRG BT", @@ -749,7 +749,7 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .ops = &mt2701_btmrg_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; diff --git a/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c b/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c index 3136f0bc7827..51f736f319e4 100644 --- a/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-dai-pcm.c @@ -270,8 +270,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { .formats = MTK_PCM_FORMATS, }, .ops = &mtk_dai_pcm_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "PCM 2", @@ -291,8 +291,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { .formats = MTK_PCM_FORMATS, }, .ops = &mtk_dai_pcm_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, }; diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 7e7bda70d12e..685f4074b4e0 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -571,7 +571,7 @@ static struct snd_soc_dai_driver mt8173_afe_pcm_dais[] = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .ops = &mt8173_afe_i2s_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c b/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c index bc3ba3228f08..38ce0e36cdb4 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c @@ -270,8 +270,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { .formats = MTK_PCM_FORMATS, }, .ops = &mtk_dai_pcm_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "PCM 2", @@ -291,8 +291,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { .formats = MTK_PCM_FORMATS, }, .ops = &mtk_dai_pcm_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, }; diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c b/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c index 6e94cfdf06fc..239e3f5b53d3 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-pcm.c @@ -360,8 +360,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { .formats = MTK_PCM_FORMATS, }, .ops = &mtk_dai_pcm_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "PCM 2", @@ -381,8 +381,8 @@ static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { .formats = MTK_PCM_FORMATS, }, .ops = &mtk_dai_pcm_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, }; -- cgit v1.2.3 From cb2f6927faf44d0cd3e55d3f9a9211f2aad26850 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:08 +0900 Subject: ASoC: fsl: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eeimolh5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 4 ++-- sound/soc/fsl/fsl_sai.c | 8 ++++---- sound/soc/fsl/fsl_ssi.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 614e22a95f53..bac9f059c9fc 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -1038,9 +1038,9 @@ static int fsl_esai_probe(struct platform_device *pdev) /* Implement full symmetry for synchronous mode */ if (esai_priv->synchronous) { - fsl_esai_dai.symmetric_rates = 1; + fsl_esai_dai.symmetric_rate = 1; fsl_esai_dai.symmetric_channels = 1; - fsl_esai_dai.symmetric_samplebits = 1; + fsl_esai_dai.symmetric_sample_bits = 1; } dev_set_drvdata(&pdev->dev, esai_priv); diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index f3d3d20d35d7..5e65b456d3e2 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1079,9 +1079,9 @@ static int fsl_sai_probe(struct platform_device *pdev) /* Sync Tx with Rx as default by following old DT binding */ sai->synchronous[RX] = true; sai->synchronous[TX] = false; - sai->cpu_dai_drv.symmetric_rates = 1; + sai->cpu_dai_drv.symmetric_rate = 1; sai->cpu_dai_drv.symmetric_channels = 1; - sai->cpu_dai_drv.symmetric_samplebits = 1; + sai->cpu_dai_drv.symmetric_sample_bits = 1; if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) && of_find_property(np, "fsl,sai-asynchronous", NULL)) { @@ -1098,9 +1098,9 @@ static int fsl_sai_probe(struct platform_device *pdev) /* Discard all settings for asynchronous mode */ sai->synchronous[RX] = false; sai->synchronous[TX] = false; - sai->cpu_dai_drv.symmetric_rates = 0; + sai->cpu_dai_drv.symmetric_rate = 0; sai->cpu_dai_drv.symmetric_channels = 0; - sai->cpu_dai_drv.symmetric_samplebits = 0; + sai->cpu_dai_drv.symmetric_sample_bits = 0; } if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index db4ba5f22b77..57811743c294 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1531,9 +1531,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) /* Set software limitations for synchronous mode except AC97 */ if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) { - ssi->cpu_dai_drv.symmetric_rates = 1; + ssi->cpu_dai_drv.symmetric_rate = 1; ssi->cpu_dai_drv.symmetric_channels = 1; - ssi->cpu_dai_drv.symmetric_samplebits = 1; + ssi->cpu_dai_drv.symmetric_sample_bits = 1; } /* -- cgit v1.2.3 From 0769575294e4c965cc2a4f4817fa696e20c2c05f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:13 +0900 Subject: ASoC: wm*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87czy6olh0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 12 ++++++------ sound/soc/codecs/wm5110.c | 12 ++++++------ sound/soc/codecs/wm8510.c | 2 +- sound/soc/codecs/wm8731.c | 2 +- sound/soc/codecs/wm8770.c | 2 +- sound/soc/codecs/wm8804.c | 2 +- sound/soc/codecs/wm8903.c | 2 +- sound/soc/codecs/wm8904.c | 2 +- sound/soc/codecs/wm8940.c | 2 +- sound/soc/codecs/wm8960.c | 2 +- sound/soc/codecs/wm8962.c | 2 +- sound/soc/codecs/wm8974.c | 2 +- sound/soc/codecs/wm8978.c | 2 +- sound/soc/codecs/wm8983.c | 2 +- sound/soc/codecs/wm8985.c | 2 +- sound/soc/codecs/wm8988.c | 2 +- sound/soc/codecs/wm8993.c | 2 +- sound/soc/codecs/wm8994.c | 4 ++-- sound/soc/codecs/wm8997.c | 8 ++++---- sound/soc/codecs/wm8998.c | 12 ++++++------ sound/soc/codecs/wm9713.c | 2 +- 21 files changed, 40 insertions(+), 40 deletions(-) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 70d353b63fe0..fe33f2d88f55 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1780,8 +1780,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .formats = WM5102_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5102-aif2", @@ -1802,8 +1802,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .formats = WM5102_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5102-aif3", @@ -1824,8 +1824,8 @@ static struct snd_soc_dai_driver wm5102_dai[] = { .formats = WM5102_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5102-slim1", diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 4238929b2375..52c0a575cc4f 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2089,8 +2089,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = { .formats = WM5110_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5110-aif2", @@ -2111,8 +2111,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = { .formats = WM5110_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5110-aif3", @@ -2133,8 +2133,8 @@ static struct snd_soc_dai_driver wm5110_dai[] = { .formats = WM5110_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm5110-slim1", diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 73c4a8b9f59e..a18e2290b8c8 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -569,7 +569,7 @@ static struct snd_soc_dai_driver wm8510_dai = { .rates = WM8510_RATES, .formats = WM8510_FORMATS,}, .ops = &wm8510_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8510_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 304bf725a613..dcee7b2bd3d7 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -567,7 +567,7 @@ static struct snd_soc_dai_driver wm8731_dai = { .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, .ops = &wm8731_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8731_request_supplies(struct device *dev, diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 1176a6ad269d..5f394065030d 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -562,7 +562,7 @@ static struct snd_soc_dai_driver wm8770_dai = { .formats = WM8770_FORMATS }, .ops = &wm8770_dai_ops, - .symmetric_rates = 1 + .symmetric_rate = 1 }; static int wm8770_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 4ddb5e32df5d..21bf0cfa1e7e 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -536,7 +536,7 @@ static struct snd_soc_dai_driver wm8804_dai = { .formats = WM8804_FORMATS, }, .ops = &wm8804_dai_ops, - .symmetric_rates = 1 + .symmetric_rate = 1 }; static const struct snd_soc_component_driver soc_component_dev_wm8804 = { diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 09f4980630c7..026603ae44ce 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1760,7 +1760,7 @@ static struct snd_soc_dai_driver wm8903_dai = { .formats = WM8903_FORMATS, }, .ops = &wm8903_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8903_resume(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 1c360bae5652..a02a77fef360 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1983,7 +1983,7 @@ static struct snd_soc_dai_driver wm8904_dai = { .formats = WM8904_FORMATS, }, .ops = &wm8904_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static void wm8904_handle_retune_mobile_pdata(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 016cd8aeef37..440d048ef0c0 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -688,7 +688,7 @@ static struct snd_soc_dai_driver wm8940_dai = { .formats = WM8940_FORMATS, }, .ops = &wm8940_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8940_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 660ec46eecf2..df351519a3a6 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1338,7 +1338,7 @@ static struct snd_soc_dai_driver wm8960_dai = { .rates = WM8960_RATES, .formats = WM8960_FORMATS,}, .ops = &wm8960_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8960_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 3af456010b9c..ce4666a74793 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2973,7 +2973,7 @@ static struct snd_soc_dai_driver wm8962_dai = { .formats = WM8962_FORMATS, }, .ops = &wm8962_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static void wm8962_mic_work(struct work_struct *work) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index c86231dfcf4f..fdc68ab49742 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -643,7 +643,7 @@ static struct snd_soc_dai_driver wm8974_dai = { .rates = WM8974_RATES, .formats = WM8974_FORMATS,}, .ops = &wm8974_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct regmap_config wm8974_regmap = { diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a7acb8981715..4b5ecd142249 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -918,7 +918,7 @@ static struct snd_soc_dai_driver wm8978_dai = { .formats = WM8978_FORMATS, }, .ops = &wm8978_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8978_suspend(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index d1d2d408ad95..d8ed22a9caac 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -971,7 +971,7 @@ static struct snd_soc_dai_driver wm8983_dai = { .formats = WM8983_FORMATS, }, .ops = &wm8983_dai_ops, - .symmetric_rates = 1 + .symmetric_rate = 1 }; static const struct snd_soc_component_driver soc_component_dev_wm8983 = { diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 3f27482349b2..a7e01106fbc0 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -1100,7 +1100,7 @@ static struct snd_soc_dai_driver wm8985_dai = { .formats = WM8985_FORMATS, }, .ops = &wm8985_dai_ops, - .symmetric_rates = 1 + .symmetric_rate = 1 }; static const struct snd_soc_component_driver soc_component_dev_wm8985 = { diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index d2c2d0d943f0..1d2f881bbcae 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -787,7 +787,7 @@ static struct snd_soc_dai_driver wm8988_dai = { .formats = WM8988_FORMATS, }, .ops = &wm8988_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8988_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9f310082e3c1..c4f41692b806 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1476,7 +1476,7 @@ static struct snd_soc_dai_driver wm8993_dai = { .sig_bits = 24, }, .ops = &wm8993_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int wm8993_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index f57884113406..f117ec0c489f 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4351,7 +4351,7 @@ static int wm8994_component_probe(struct snd_soc_component *component) } if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { wm8994->lrclk_shared[0] = 1; - wm8994_dai[0].symmetric_rates = 1; + wm8994_dai[0].symmetric_rate = 1; } else { wm8994->lrclk_shared[0] = 0; } @@ -4363,7 +4363,7 @@ static int wm8994_component_probe(struct snd_soc_component *component) } if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { wm8994->lrclk_shared[1] = 1; - wm8994_dai[1].symmetric_rates = 1; + wm8994_dai[1].symmetric_rate = 1; } else { wm8994->lrclk_shared[1] = 0; } diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 229f2986cd96..99c3ebae6ba6 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -969,8 +969,8 @@ static struct snd_soc_dai_driver wm8997_dai[] = { .formats = WM8997_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm8997-aif2", @@ -991,8 +991,8 @@ static struct snd_soc_dai_driver wm8997_dai[] = { .formats = WM8997_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm8997-slim1", diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 5413254295b7..b6f717aa5478 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1161,8 +1161,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = { .formats = WM8998_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm8998-aif2", @@ -1183,8 +1183,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = { .formats = WM8998_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm8998-aif3", @@ -1205,8 +1205,8 @@ static struct snd_soc_dai_driver wm8998_dai[] = { .formats = WM8998_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "wm8998-slim1", diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f333e2ff4a16..e0ce32dd4a81 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1134,7 +1134,7 @@ static struct snd_soc_dai_driver wm9713_dai[] = { .rates = WM9713_PCM_RATES, .formats = WM9713_PCM_FORMATS,}, .ops = &wm9713_dai_ops_voice, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; -- cgit v1.2.3 From a9aef184f7b47c355e4d78aa08792ff74fd5c4f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:17 +0900 Subject: ASoC: tlv*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bldqolgw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 2 +- sound/soc/codecs/tlv320aic31xx.c | 4 ++-- sound/soc/codecs/tlv320aic32x4.c | 2 +- sound/soc/codecs/tlv320aic3x.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 3f027c8234a6..32b120d624b2 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -1069,7 +1069,7 @@ static struct snd_soc_dai_driver adcx140_dai_driver[] = { .formats = ADCX140_FORMATS, }, .ops = &adcx140_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 5ac7ce264431..51870d50f419 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1395,7 +1395,7 @@ static struct snd_soc_dai_driver dac31xx_dai_driver[] = { .formats = AIC31XX_FORMATS, }, .ops = &aic31xx_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; @@ -1417,7 +1417,7 @@ static struct snd_soc_dai_driver aic31xx_dai_driver[] = { .formats = AIC31XX_FORMATS, }, .ops = &aic31xx_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 9e3de9ded0ef..f04f88c8d425 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -916,7 +916,7 @@ static struct snd_soc_dai_driver aic32x4_dai = { .rates = AIC32X4_RATES, .formats = AIC32X4_FORMATS,}, .ops = &aic32x4_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static void aic32x4_setup_gpios(struct snd_soc_component *component) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 6d066bc58ac8..db1444127444 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1503,7 +1503,7 @@ static struct snd_soc_dai_driver aic3x_dai = { .rates = AIC3X_RATES, .formats = AIC3X_FORMATS,}, .ops = &aic3x_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static void aic3x_mono_init(struct snd_soc_component *component) -- cgit v1.2.3 From bc03b3910ef6e228ef8b192e08030a1e177ad273 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:21 +0900 Subject: ASoC: rt*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6taolgs.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt274.c | 2 +- sound/soc/codecs/rt286.c | 4 ++-- sound/soc/codecs/rt298.c | 4 ++-- sound/soc/codecs/rt5670.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index 70cf17c0aa99..0d3773c576f8 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -1056,7 +1056,7 @@ static struct snd_soc_dai_driver rt274_dai[] = { .formats = RT274_FORMATS, }, .ops = &rt274_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 5fb9653d9131..8abe232ca4a4 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1017,7 +1017,7 @@ static struct snd_soc_dai_driver rt286_dai[] = { .formats = RT286_FORMATS, }, .ops = &rt286_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "rt286-aif2", @@ -1037,7 +1037,7 @@ static struct snd_soc_dai_driver rt286_dai[] = { .formats = RT286_FORMATS, }, .ops = &rt286_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index dc0273a5a11f..32cc9b6287d2 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1084,7 +1084,7 @@ static struct snd_soc_dai_driver rt298_dai[] = { .formats = RT298_FORMATS, }, .ops = &rt298_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "rt298-aif2", @@ -1104,7 +1104,7 @@ static struct snd_soc_dai_driver rt298_dai[] = { .formats = RT298_FORMATS, }, .ops = &rt298_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index a0c8f58d729b..c29317ea5df2 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2741,7 +2741,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = { .formats = RT5670_FORMATS, }, .ops = &rt5670_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "rt5670-aif2", @@ -2761,7 +2761,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = { .formats = RT5670_FORMATS, }, .ops = &rt5670_aif_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; -- cgit v1.2.3 From 42c9b5bec1c5218b33eda3b519381b38b89d5ccd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:25 +0900 Subject: ASoC: nau*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878s8uolgo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8810.c | 2 +- sound/soc/codecs/nau8822.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index 33ebc6398426..13676b544f58 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -837,7 +837,7 @@ static struct snd_soc_dai_driver nau8810_dai = { .formats = NAU8810_FORMATS, }, .ops = &nau8810_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct regmap_config nau8810_regmap_config = { diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 609aeeb27818..58123390c7a3 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -991,7 +991,7 @@ static struct snd_soc_dai_driver nau8822_dai = { .formats = NAU8822_FORMATS, }, .ops = &nau8822_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int nau8822_suspend(struct snd_soc_component *component) -- cgit v1.2.3 From fa056c07367e443271837c8500de8c7e6d9b2722 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:29 +0900 Subject: ASoC: tas*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877doeolgk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 2 +- sound/soc/codecs/tas2770.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 14a193e48dc7..8ff4d9e8d568 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -490,7 +490,7 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = { .formats = TAS2764_FORMATS, }, .ops = &tas2764_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index a91a0a31e74d..15fca5109e14 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -499,7 +499,7 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = { .formats = TAS2770_FORMATS, }, .ops = &tas2770_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; -- cgit v1.2.3 From 1c6d1c4f6874345a31d12a9f3843876c49d637fa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:33 +0900 Subject: ASoC: da*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875z3yolgf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7210.c | 2 +- sound/soc/codecs/da7213.c | 2 +- sound/soc/codecs/da7218.c | 4 ++-- sound/soc/codecs/da7219.c | 4 ++-- sound/soc/codecs/da9055.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3d05c37f676e..8af344b2fdbf 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1059,7 +1059,7 @@ static struct snd_soc_dai_driver da7210_dai = { .formats = DA7210_FORMATS, }, .ops = &da7210_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int da7210_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 72402467adcc..3ab89387b4e6 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1551,7 +1551,7 @@ static struct snd_soc_dai_driver da7213_dai = { .formats = DA7213_FORMATS, }, .ops = &da7213_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 2bfafbe9e3dc..0e5b91eb420b 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -2194,9 +2194,9 @@ static struct snd_soc_dai_driver da7218_dai = { .formats = DA7218_FORMATS, }, .ops = &da7218_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }; diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index e9b45daec0ca..13009d08b09a 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1692,9 +1692,9 @@ static struct snd_soc_dai_driver da7219_dai = { .formats = DA7219_FORMATS, }, .ops = &da7219_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index aed92f615b02..a9676b261129 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1347,7 +1347,7 @@ static struct snd_soc_dai_driver da9055_dai = { .formats = DA9055_FORMATS, }, .ops = &da9055_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int da9055_set_bias_level(struct snd_soc_component *component, -- cgit v1.2.3 From 4060064e8baf047a64b6286f5fd87cb0a34d8b89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:39 +0900 Subject: ASoC: es*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/874kjiolga.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 2 +- sound/soc/codecs/es8328.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 1ce84f12a4cf..d632055370e0 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -543,7 +543,7 @@ static struct snd_soc_dai_driver es8316_dai = { .formats = ES8316_FORMATS, }, .ops = &es8316_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static void es8316_enable_micbias_for_mic_gnd_short_detect( diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index b537300d0ce8..9632afc2d4d6 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -715,7 +715,7 @@ static struct snd_soc_dai_driver es8328_dai = { .formats = ES8328_FORMATS, }, .ops = &es8328_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int es8328_suspend(struct snd_soc_component *component) -- cgit v1.2.3 From cb40d1b4581c0f6e2a828ebfcb7cc9a04dca1e11 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:44 +0900 Subject: ASoC: max*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8735z2olg5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/max9860.c | 2 +- sound/soc/codecs/max9867.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index d5925c42b4b5..dd29b183ecd6 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -489,7 +489,7 @@ static struct snd_soc_dai_driver max9860_dai = { SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &max9860_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int max9860_set_bias_level(struct snd_soc_component *component, diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 512e6f2513d3..09b2d730e9fd 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -520,7 +520,7 @@ static struct snd_soc_dai_driver max9867_dai[] = { .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .ops = &max9867_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; -- cgit v1.2.3 From 260b668cf356dbab5f73e651cfc96a90ed220b98 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:48 +0900 Subject: ASoC: cs*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871remolg1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l32.c | 2 +- sound/soc/codecs/cs35l33.c | 2 +- sound/soc/codecs/cs35l34.c | 2 +- sound/soc/codecs/cs35l35.c | 2 +- sound/soc/codecs/cs35l36.c | 2 +- sound/soc/codecs/cs4234.c | 2 +- sound/soc/codecs/cs4271.c | 2 +- sound/soc/codecs/cs42l73.c | 6 +++--- sound/soc/codecs/cs43130.c | 6 +++--- sound/soc/codecs/cs4341.c | 2 +- sound/soc/codecs/cs4349.c | 2 +- sound/soc/codecs/cs47l15.c | 12 ++++++------ sound/soc/codecs/cs47l24.c | 12 ++++++------ sound/soc/codecs/cs47l35.c | 12 ++++++------ sound/soc/codecs/cs47l85.c | 16 ++++++++-------- sound/soc/codecs/cs47l90.c | 16 ++++++++-------- sound/soc/codecs/cs47l92.c | 12 ++++++------ sound/soc/codecs/cs53l30.c | 2 +- 18 files changed, 56 insertions(+), 56 deletions(-) diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 3a644a35c464..f4067230ac42 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -194,7 +194,7 @@ static struct snd_soc_dai_driver cs35l32_dai[] = { .formats = CS35L32_FORMATS, }, .ops = &cs35l32_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 6042194d95d3..7ad7b733af9b 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -691,7 +691,7 @@ static struct snd_soc_dai_driver cs35l33_dai = { .formats = CS35L33_FORMATS, }, .ops = &cs35l33_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int cs35l33_set_hg_data(struct snd_soc_component *component, diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index b792c006e530..110ee2d06358 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -666,7 +666,7 @@ static struct snd_soc_dai_driver cs35l34_dai = { .formats = CS35L34_FORMATS, }, .ops = &cs35l34_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int cs35l34_boost_inductor(struct cs35l34_private *cs35l34, diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index e330427a4314..55d529aa0011 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -692,7 +692,7 @@ static struct snd_soc_dai_driver cs35l35_dai[] = { .formats = CS35L35_FORMATS, }, .ops = &cs35l35_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "cs35l35-pdm", diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index e9b5f76f27a8..4451ca9f4916 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -995,7 +995,7 @@ static struct snd_soc_dai_driver cs35l36_dai[] = { .formats = CS35L36_TX_FORMATS, }, .ops = &cs35l36_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c index 2ea83233c3f1..20126cc675b1 100644 --- a/sound/soc/codecs/cs4234.c +++ b/sound/soc/codecs/cs4234.c @@ -585,7 +585,7 @@ static struct snd_soc_dai_driver cs4234_dai[] = { .formats = CS4234_FORMATS, }, .ops = &cs4234_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index d43762ae8f3d..7663f89ac6a2 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -481,7 +481,7 @@ static struct snd_soc_dai_driver cs4271_dai = { .formats = CS4271_PCM_FORMATS, }, .ops = &cs4271_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int cs4271_reset(struct snd_soc_component *component) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 988ca7e19821..c3f974ec78e5 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1181,7 +1181,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "cs42l73-asp", @@ -1201,7 +1201,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "cs42l73-vsp", @@ -1221,7 +1221,7 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index 7fb34422a2a4..80bc7c10ed75 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -1581,7 +1581,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = { .formats = CS43130_PCM_FORMATS, }, .ops = &cs43130_pcm_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "cs43130-asp-dop", @@ -1594,7 +1594,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = { .formats = CS43130_DOP_FORMATS, }, .ops = &cs43130_dop_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "cs43130-xsp-dop", @@ -1607,7 +1607,7 @@ static struct snd_soc_dai_driver cs43130_dai[] = { .formats = CS43130_DOP_FORMATS, }, .ops = &cs43130_dop_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "cs43130-xsp-dsd", diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c index f566604de78c..7d3e54d8eef3 100644 --- a/sound/soc/codecs/cs4341.c +++ b/sound/soc/codecs/cs4341.c @@ -189,7 +189,7 @@ static struct snd_soc_dai_driver cs4341_dai = { SNDRV_PCM_FMTBIT_S24_LE, }, .ops = &cs4341_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver soc_component_cs4341 = { diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index fd5526319779..786c69a8ec4a 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -250,7 +250,7 @@ static struct snd_soc_dai_driver cs4349_dai = { .formats = CS4349_PCM_FORMATS, }, .ops = &cs4349_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver soc_component_dev_cs4349 = { diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 254f9d96e766..1ee83160b83f 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -1160,8 +1160,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l15-aif2", @@ -1182,8 +1182,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l15-aif3", @@ -1204,8 +1204,8 @@ static struct snd_soc_dai_driver cs47l15_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l15-cpu-trace", diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index f6d173d0120e..eaabbb56a173 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -977,8 +977,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = { .formats = CS47L24_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l24-aif2", @@ -999,8 +999,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = { .formats = CS47L24_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l24-aif3", @@ -1021,8 +1021,8 @@ static struct snd_soc_dai_driver cs47l24_dai[] = { .formats = CS47L24_FORMATS, }, .ops = &arizona_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l24-cpu-voicectrl", diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index e967609da8a3..3f04a2a74521 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -1368,8 +1368,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l35-aif2", @@ -1390,8 +1390,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l35-aif3", @@ -1412,8 +1412,8 @@ static struct snd_soc_dai_driver cs47l35_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l35-slim1", diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 47b16466b6c1..748a180870bc 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -2269,8 +2269,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l85-aif2", @@ -2291,8 +2291,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l85-aif3", @@ -2313,8 +2313,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l85-aif4", @@ -2335,8 +2335,8 @@ static struct snd_soc_dai_driver cs47l85_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l85-slim1", diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 8838dd557321..d2911c014b86 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -2188,8 +2188,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l90-aif2", @@ -2210,8 +2210,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l90-aif3", @@ -2232,8 +2232,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l90-aif4", @@ -2254,8 +2254,8 @@ static struct snd_soc_dai_driver cs47l90_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l90-slim1", diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index 52dc29942ec2..1a0280416d92 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -1704,8 +1704,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l92-aif2", @@ -1726,8 +1726,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l92-aif3", @@ -1748,8 +1748,8 @@ static struct snd_soc_dai_driver cs47l92_dai[] = { .formats = MADERA_FORMATS, }, .ops = &madera_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }, { .name = "cs47l92-slim1", diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index ed22361b35c1..3d67cbf9eaaa 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -869,7 +869,7 @@ static struct snd_soc_dai_driver cs53l30_dai = { .formats = CS53L30_FORMATS, }, .ops = &cs53l30_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int cs53l30_component_probe(struct snd_soc_component *component) -- cgit v1.2.3 From 9b4488efdeccbe1d4dceb13aee9e58371f6ba926 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:52 +0900 Subject: ASoC: tscs*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zh1an6vh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/tscs42xx.c | 4 ++-- sound/soc/codecs/tscs454.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 6200fab7896f..fb861baf50e8 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -1397,9 +1397,9 @@ static struct snd_soc_dai_driver tscs42xx_dai = { .rates = TSCS42XX_RATES, .formats = TSCS42XX_FORMATS,}, .ops = &tscs42xx_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }; static const struct reg_sequence tscs42xx_patch[] = { diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index cd1f1a592386..1bafc9d1101c 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -3346,9 +3346,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = { .rates = TSCS454_RATES, .formats = TSCS454_FORMATS,}, .ops = &tscs454_dai1_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }, { .name = "tscs454-dai2", @@ -3366,9 +3366,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = { .rates = TSCS454_RATES, .formats = TSCS454_FORMATS,}, .ops = &tscs454_dai23_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }, { .name = "tscs454-dai3", @@ -3386,9 +3386,9 @@ static struct snd_soc_dai_driver tscs454_dais[] = { .rates = TSCS454_RATES, .formats = TSCS454_FORMATS,}, .ops = &tscs454_dai23_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, }, }; -- cgit v1.2.3 From 870b76ea7d0c0e5d6e5f305d8eca9ba45b89241a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:54:56 +0900 Subject: ASoC: ak*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y2gun6vc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak4554.c | 2 +- sound/soc/codecs/ak4613.c | 2 +- sound/soc/codecs/ak4641.c | 4 ++-- sound/soc/codecs/ak4642.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c index 2fa83a1a84cf..8e60e2b56ad6 100644 --- a/sound/soc/codecs/ak4554.c +++ b/sound/soc/codecs/ak4554.c @@ -56,7 +56,7 @@ static struct snd_soc_dai_driver ak4554_dai = { .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver soc_component_dev_ak4554 = { diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 8d663e8d64c4..fe208cfdd3ba 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -575,7 +575,7 @@ static struct snd_soc_dai_driver ak4613_dai = { .formats = AK4613_PCM_FMTBIT, }, .ops = &ak4613_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int ak4613_suspend(struct snd_soc_component *component) diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 77004cd7caa3..04aef0e72aa5 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -499,7 +499,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = { .formats = AK4641_FORMATS, }, .ops = &ak4641_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "ak4641-voice", @@ -519,7 +519,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = { .formats = AK4641_FORMATS, }, .ops = &ak4641_pcm_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 353237025514..c49c58eeb476 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -516,7 +516,7 @@ static struct snd_soc_dai_driver ak4642_dai = { .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE }, .ops = &ak4642_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int ak4642_suspend(struct snd_soc_component *component) -- cgit v1.2.3 From f88f45861bbd5da303a997f92800fa0d7958c929 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:01 +0900 Subject: ASoC: adau*: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wnwen6v8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/adau1372.c | 2 +- sound/soc/codecs/adau1373.c | 6 +++--- sound/soc/codecs/adau1701.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c index 5ccbf1b6bcf5..6811a8b3866d 100644 --- a/sound/soc/codecs/adau1372.c +++ b/sound/soc/codecs/adau1372.c @@ -890,7 +890,7 @@ static struct snd_soc_dai_driver adau1372_dai_driver = { .sig_bits = 24, }, .ops = &adau1372_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int adau1372_setup_pll(struct adau1372 *adau1372, unsigned int rate) diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index e71fde001b46..9887aa6f0be5 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1205,7 +1205,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = { .formats = ADAU1373_FORMATS, }, .ops = &adau1373_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .id = 1, @@ -1225,7 +1225,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = { .formats = ADAU1373_FORMATS, }, .ops = &adau1373_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .id = 2, @@ -1245,7 +1245,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = { .formats = ADAU1373_FORMATS, }, .ops = &adau1373_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 68130eaa64a4..5ce74697564a 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -653,7 +653,7 @@ static struct snd_soc_dai_driver adau1701_dai = { .formats = ADAU1701_FORMATS, }, .ops = &adau1701_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; #ifdef CONFIG_OF -- cgit v1.2.3 From 0547dece8dcbb80983b3c37ad20ceca76a1f06a5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:20 +0900 Subject: ASoC: jz4740: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v9byn6uo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4740.c | 2 +- sound/soc/jz4740/jz4740-i2s.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 5e58bfee2b49..081485f784e9 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -214,7 +214,7 @@ static struct snd_soc_dai_driver jz4740_codec_dai = { .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, }, .ops = &jz4740_codec_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static void jz4740_codec_wakeup(struct regmap *regmap) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 0a68f4c3d15a..52ba0e3a9e95 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -455,7 +455,7 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = { .rates = SNDRV_PCM_RATE_8000_48000, .formats = JZ4740_I2S_FMTS, }, - .symmetric_rates = 1, + .symmetric_rate = 1, .ops = &jz4740_i2s_dai_ops, }; -- cgit v1.2.3 From 813857086191aace3a39c056c8acb6946ff75f03 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:25 +0900 Subject: ASoC: sunxi: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87turin6uk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 2 +- sound/soc/sunxi/sun8i-codec.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 4b8ca5be0a29..78506c3811dc 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1105,7 +1105,7 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { .formats = SUN4I_FORMATS, }, .ops = &sun4i_i2s_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static const struct snd_soc_component_driver sun4i_i2s_component = { diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 180442c62be1..460924fc173f 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -640,9 +640,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { .rates = SUN8I_CODEC_PCM_RATES, .formats = SUN8I_CODEC_PCM_FORMATS, }, - .symmetric_rates = true, + .symmetric_rate = true, .symmetric_channels = true, - .symmetric_samplebits = true, + .symmetric_sample_bits = true, }, { .name = "sun8i-codec-aif2", @@ -665,9 +665,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { .rates = SUN8I_CODEC_PCM_RATES, .formats = SUN8I_CODEC_PCM_FORMATS, }, - .symmetric_rates = true, + .symmetric_rate = true, .symmetric_channels = true, - .symmetric_samplebits = true, + .symmetric_sample_bits = true, }, { .name = "sun8i-codec-aif3", @@ -690,9 +690,9 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { .rates = SUN8I_CODEC_PCM_RATES, .formats = SUN8I_CODEC_PCM_FORMATS, }, - .symmetric_rates = true, + .symmetric_rate = true, .symmetric_channels = true, - .symmetric_samplebits = true, + .symmetric_sample_bits = true, }, }; -- cgit v1.2.3 From b33c088a9b0b15df987dae05177ef9b0816dc4cf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:29 +0900 Subject: ASoC: zl38060: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sg72n6ug.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/zl38060.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/zl38060.c b/sound/soc/codecs/zl38060.c index 42726dc0ba39..d21a72314d37 100644 --- a/sound/soc/codecs/zl38060.c +++ b/sound/soc/codecs/zl38060.c @@ -360,8 +360,8 @@ static struct snd_soc_dai_driver zl38_dai = { .formats = ZL38_FORMATS, }, .ops = &zl38_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, .symmetric_channels = 1, }; -- cgit v1.2.3 From 4735c8cadd54ef74726718ad93a27d16b23089b0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:34 +0900 Subject: ASoC: ssm2602: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r1mmn6ub.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2602.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 905160246614..7964e922b07f 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -526,8 +526,8 @@ static struct snd_soc_dai_driver ssm2602_dai = { .rates = SSM2602_RATES, .formats = SSM2602_FORMATS,}, .ops = &ssm2602_dai_ops, - .symmetric_rates = 1, - .symmetric_samplebits = 1, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, }; static int ssm2602_resume(struct snd_soc_component *component) -- cgit v1.2.3 From bea17630c4ad398b6cd9b454c1649a962a7e0258 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:40 +0900 Subject: ASoC: sgtl5000: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pn26n6u4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 4d6ff8114622..73551e36695e 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1187,7 +1187,7 @@ static struct snd_soc_dai_driver sgtl5000_dai = { .formats = SGTL5000_FORMATS, }, .ops = &sgtl5000_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static bool sgtl5000_volatile(struct device *dev, unsigned int reg) -- cgit v1.2.3 From 23df7f69ff134d108ddffcde622b7ffc904ac789 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:47 +0900 Subject: ASoC: mc13783: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o8hqn6ty.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 9e6a0cda43d0..a21072503cb9 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -712,7 +712,7 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = { .formats = MC13783_FORMATS, }, .ops = &mc13783_ops_sync, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; -- cgit v1.2.3 From 852d4daa9689188f25cd1aa92d4daf3a88d73101 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:51 +0900 Subject: ASoC: mt6660: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mtxan6tt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6660.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index d1797003c83d..358c500377df 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -404,9 +404,9 @@ static struct snd_soc_dai_driver mt6660_codec_dai = { .formats = STUB_FORMATS, }, /* dai properties */ - .symmetric_rates = 1, + .symmetric_rate = 1, .symmetric_channels = 1, - .symmetric_samplebits = 1, + .symmetric_sample_bits = 1, /* dai operations */ .ops = &mt6660_component_aif_ops, }; -- cgit v1.2.3 From 65ba325625e74f44fe7c0052a85bcdfac2b012ec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:55:56 +0900 Subject: ASoC: lochnagar-sc: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfcun6tp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/lochnagar-sc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/lochnagar-sc.c b/sound/soc/codecs/lochnagar-sc.c index 3209b39e46af..54426a90bc0b 100644 --- a/sound/soc/codecs/lochnagar-sc.c +++ b/sound/soc/codecs/lochnagar-sc.c @@ -166,8 +166,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = { .formats = SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &lochnagar_sc_line_ops, - .symmetric_rates = true, - .symmetric_samplebits = true, + .symmetric_rate = true, + .symmetric_sample_bits = true, }, { .name = "lochnagar-usb1", @@ -186,8 +186,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = { .formats = SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &lochnagar_sc_usb_ops, - .symmetric_rates = true, - .symmetric_samplebits = true, + .symmetric_rate = true, + .symmetric_sample_bits = true, }, { .name = "lochnagar-usb2", @@ -206,8 +206,8 @@ static struct snd_soc_dai_driver lochnagar_sc_dai[] = { .formats = SNDRV_PCM_FMTBIT_S32_LE, }, .ops = &lochnagar_sc_usb_ops, - .symmetric_rates = true, - .symmetric_samplebits = true, + .symmetric_rate = true, + .symmetric_sample_bits = true, }, }; -- cgit v1.2.3 From 6058bcb4974418bdec55738383755b83e57e555e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:00 +0900 Subject: ASoC: ab8500: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0sen6tl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 31a8c4162d20..c95f007cede1 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2384,7 +2384,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = { .formats = AB8500_SUPPORTED_FMT, }, .ops = &ab8500_codec_ops, - .symmetric_rates = 1 + .symmetric_rate = 1 }, { .name = "ab8500-codec-dai.1", @@ -2397,7 +2397,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = { .formats = AB8500_SUPPORTED_FMT, }, .ops = &ab8500_codec_ops, - .symmetric_rates = 1 + .symmetric_rate = 1 } }; -- cgit v1.2.3 From 278eacf3dc717f27463d56d605c2ea919e308e49 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:04 +0900 Subject: ASoC: alc5632: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87im7yn6th.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/alc5632.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index bde5ded67754..79813882a955 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -1032,7 +1032,7 @@ static struct snd_soc_dai_driver alc5632_dai = { .formats = ALC5632_FORMATS,}, .ops = &alc5632_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; #ifdef CONFIG_PM -- cgit v1.2.3 From 15d27c2b129fc8234ed709bdcbd17fa3fff0808e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:09 +0900 Subject: ASoC: cx2072x: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7nin6tc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index 2f10991a8bdb..8ab22815c2c9 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1572,7 +1572,7 @@ static struct snd_soc_dai_driver soc_codec_cx2072x_dai[] = { .formats = CX2072X_FORMATS, }, .ops = &cx2072x_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { /* plabayck only, return echo reference to Conexant DSP chip */ .name = "cx2072x-dsp", -- cgit v1.2.3 From d5d396c8b01e1fea696c68d255c2d7206de6499f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:12 +0900 Subject: ASoC: inno_rk3036: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ft32n6t8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/inno_rk3036.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 4dbce24c5f76..e05c4f27486e 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -325,7 +325,7 @@ static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = { .formats = RK3036_CODEC_FMTS, }, .ops = &rk3036_codec_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, }; -- cgit v1.2.3 From 3b940ecd2ebfdd9a2b4a7a97aef1f25d1844d3ba Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:16 +0900 Subject: ASoC: lm49453: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eeimn6t4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 06ab61f6f719..eb3dd0bd80d9 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1343,7 +1343,7 @@ static struct snd_soc_dai_driver lm49453_dai[] = { .formats = LM49453_FORMATS, }, .ops = &lm49453_headset_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }, { .name = "LM49453 Speaker", -- cgit v1.2.3 From 6944db0ab8c4b7c19b7ff9fbbe98322efcd9595a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:21 +0900 Subject: ASoC: ml26124: sync parameter naming (rate/sample_bits) This patch syncs naming rule. - xxx_rates; + xxx_rate; - xxx_samplebits; + xxx_sample_bits; Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87czy6n6t0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/ml26124.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 70c17be455ca..4d7c0be2a4aa 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -513,7 +513,7 @@ static struct snd_soc_dai_driver ml26124_dai = { .rates = ML26124_RATES, .formats = ML26124_FORMATS,}, .ops = &ml26124_dai_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, }; static int ml26124_probe(struct snd_soc_component *component) -- cgit v1.2.3 From fa31a2c787aeaf61d02b2a57bd9765ca5e67d949 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:30 +0900 Subject: ASoC: soc-dai.h: remove symmetric_rates/samplebits All drivers are using new name. Let's remove old one. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bldqn6sr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 -- sound/soc/soc-core.c | 9 --------- 2 files changed, 11 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index ee3c6deb5719..1358a0ceb4d0 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -353,10 +353,8 @@ struct snd_soc_dai_driver { /* DAI capabilities */ struct snd_soc_pcm_stream capture; struct snd_soc_pcm_stream playback; - unsigned int symmetric_rates:1; /* will be removed */ unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; - unsigned int symmetric_samplebits:1; /* will be removed */ unsigned int symmetric_sample_bits:1; /* probe ordering - for components with runtime dependencies */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index bb8323cad51a..f6d4e99b590c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2509,15 +2509,6 @@ int snd_soc_register_component(struct device *dev, { struct snd_soc_component *component; int ret; - int i; - - /* Remove ME */ - for (i = 0; i < num_dai; i++) { - if (dai_drv[i].symmetric_rates) - dai_drv[i].symmetric_rate = dai_drv[i].symmetric_rates; - if (dai_drv[i].symmetric_samplebits) - dai_drv[i].symmetric_sample_bits = dai_drv[i].symmetric_samplebits; - } component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); if (!component) -- cgit v1.2.3 From fac110cbcddec115c7d4b79d7491aebebbe44469 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:35 +0900 Subject: ASoC: soc-pcm: cleanup soc_pcm_apply_symmetry() soc_pcm_apply_symmetry() want to call snd_pcm_hw_constraint_single() for rate/channel/sample_bits, but, it needs many condition checks. These are very similar but different, thus, it needs to have very verbose code. This patch use macro for it and make code more simple. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6tan6sm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 67 ++++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1a5d0cb3dc69..57341a0fd67c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -349,53 +349,26 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; - if (soc_dai->rate && (soc_dai->driver->symmetric_rate || - rtd->dai_link->symmetric_rate)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", - soc_dai->rate); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - soc_dai->rate); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply rate constraint: %d\n", - ret); - return ret; - } - } - - if (soc_dai->channels && (soc_dai->driver->symmetric_channels || - rtd->dai_link->symmetric_channels)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", - soc_dai->channels); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, - soc_dai->channels); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply channel symmetry constraint: %d\n", - ret); - return ret; - } - } - - if (soc_dai->sample_bits && (soc_dai->driver->symmetric_sample_bits || - rtd->dai_link->symmetric_sample_bits)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", - soc_dai->sample_bits); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - soc_dai->sample_bits); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply sample bits symmetry constraint: %d\n", - ret); - return ret; - } - } +#define __soc_pcm_apply_symmetry(name, NAME) \ + if (soc_dai->name && (soc_dai->driver->symmetric_##name || \ + rtd->dai_link->symmetric_##name)) { \ + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\ + #name, soc_dai->name); \ + \ + ret = snd_pcm_hw_constraint_single(substream->runtime, \ + SNDRV_PCM_HW_PARAM_##NAME,\ + soc_dai->name); \ + if (ret < 0) { \ + dev_err(soc_dai->dev, \ + "ASoC: Unable to apply %s constraint: %d\n",\ + #name, ret); \ + return ret; \ + } \ + } + + __soc_pcm_apply_symmetry(rate, RATE); + __soc_pcm_apply_symmetry(channels, CHANNELS); + __soc_pcm_apply_symmetry(sample_bits, SAMPLE_BITS); return 0; } -- cgit v1.2.3 From 3a906721112263f1698d7752f6f0133c78fc12c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 15 Jan 2021 13:56:39 +0900 Subject: ASoC: soc-pcm: cleanup soc_pcm_params_symmetry() soc_pcm_params_symmetry() checks rate/channel/sample_bits state. These are very similar but different, thus, it needs to have very verbose code. This patch use macro for it and make code more simple. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878s8un6si.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 60 ++++++++++++++--------------------------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 57341a0fd67c..7079a301ec31 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -384,53 +384,23 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, soc_pcm_set_dai_params(&d, params); - /* reject unmatched parameters when applying symmetry */ - symmetry = rtd->dai_link->symmetric_rate; - - for_each_rtd_cpu_dais(rtd, i, dai) - symmetry |= dai->driver->symmetric_rate; - - if (symmetry) { - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (cpu_dai->rate && cpu_dai->rate != d.rate) { - dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", - cpu_dai->rate, d.rate); - return -EINVAL; - } - } - } - - symmetry = rtd->dai_link->symmetric_channels; - - for_each_rtd_dais(rtd, i, dai) - symmetry |= dai->driver->symmetric_channels; - - if (symmetry) { - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (cpu_dai->channels && - cpu_dai->channels != d.channels) { - dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", - cpu_dai->channels, d.channels); - return -EINVAL; +#define __soc_pcm_params_symmetry(name) \ + symmetry = rtd->dai_link->symmetric_##name; \ + for_each_rtd_dais(rtd, i, dai) \ + symmetry |= dai->driver->symmetric_##name; \ + \ + if (symmetry) \ + for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ + if (cpu_dai->name && cpu_dai->name != d.name) { \ + dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %d - %d\n", \ + #name, cpu_dai->name, d.name); \ + return -EINVAL; \ } - } - } - symmetry = rtd->dai_link->symmetric_sample_bits; - - for_each_rtd_dais(rtd, i, dai) - symmetry |= dai->driver->symmetric_sample_bits; - - if (symmetry) { - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (cpu_dai->sample_bits && - cpu_dai->sample_bits != d.sample_bits) { - dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", - cpu_dai->sample_bits, d.sample_bits); - return -EINVAL; - } - } - } + /* reject unmatched parameters when applying symmetry */ + __soc_pcm_params_symmetry(rate); + __soc_pcm_params_symmetry(channels); + __soc_pcm_params_symmetry(sample_bits); return 0; } -- cgit v1.2.3 From 06c8456753f6fc89ff5894cc8cca24b1ac92a5d6 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Thu, 21 Jan 2021 18:03:53 +0800 Subject: ASoC: rt5682: remove connection with LDO2 in DAPM graph The application circuit shall provide MICVDD power. In default, the codec driver doesn't need to enable LDO2. In case, a board wants to use VBAT for micbias, it should add a DAPM route which IN1P connects with LDO2 in the machine driver. e.g. { "IN1P", NULL, "LDO2" }, Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210121100353.6402-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 42ad5bea86b5..185906d6d4e0 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1854,8 +1854,6 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { {"CLKDET SYS", NULL, "CLKDET"}, - {"IN1P", NULL, "LDO2"}, - {"BST1 CBJ", NULL, "IN1P"}, {"RECMIX1L", "CBJ Switch", "BST1 CBJ"}, -- cgit v1.2.3 From d15f73315deb45fccbf44c6a4024d430bbb26b0c Mon Sep 17 00:00:00 2001 From: Jiapeng Zhong Date: Mon, 18 Jan 2021 16:27:49 +0800 Subject: ALSA: hda: boolean values to a bool variable Fix the following coccicheck warnings: ./sound/pci/hda/patch_conexant.c:570:2-20: WARNING: Assignment of 0/1 to bool variable. Reported-by: Abaci Robot Signed-off-by: Jiapeng Zhong Link: https://lore.kernel.org/r/1610958469-65856-1-git-send-email-abaci-bugfix@linux.alibaba.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d49cc4409d59..f2aa226d1373 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -567,7 +567,7 @@ static void cxt_fixup_mute_led_eapd(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->mute_led_eapd = 0x1b; - spec->dynamic_eapd = 1; + spec->dynamic_eapd = true; snd_hda_gen_add_mute_led_cdev(codec, cx_auto_vmaster_mute_led); } } -- cgit v1.2.3 From 62c2b4be0d858bb4d381868459fb8f82c3b58a21 Mon Sep 17 00:00:00 2001 From: Jiapeng Zhong Date: Mon, 25 Jan 2021 15:17:27 +0800 Subject: ALSA: hda: Assign boolean values to a bool variable Fix the following coccicheck warnings: ./sound/pci/hda/hda_intel.c:2309:3-23: WARNING: Assignment of 0/1 to bool variable. Reported-by: Abaci Robot Signed-off-by: Jiapeng Zhong Link: https://lore.kernel.org/r/1611559047-106928-1-git-send-email-abaci-bugfix@linux.alibaba.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7f0000e2c953..6c439f377a7e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2300,7 +2300,7 @@ static int azx_probe_continue(struct azx *chip) /* HSW/BDW controllers need this power */ if (CONTROLLER_IN_GPU(pci)) - hda->need_i915_power = 1; + hda->need_i915_power = true; } /* Request display power well for the HDA controller or codec. For -- cgit v1.2.3 From 00f3a4113c73823e22bb30129d3ec0523706a158 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 25 Jan 2021 14:12:54 +0300 Subject: ALSA: oxfw: remove an unnecessary condition in hwdep_read() Smatch complains that "count" isn't clamped properly and "oxfw->dev_lock_changed" is false then it leads to an information leak. But it turns out that "oxfw->dev_lock_changed" is always set and the condition can be removed. Signed-off-by: Dan Carpenter Acked-by: Takashi Sakamoto Link: https://lore.kernel.org/r/YA6ntkBxT/4DJ4YK@mwanda Signed-off-by: Takashi Iwai --- sound/firewire/oxfw/oxfw-hwdep.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/firewire/oxfw/oxfw-hwdep.c b/sound/firewire/oxfw/oxfw-hwdep.c index 9e1b3e151bad..a0fe99618554 100644 --- a/sound/firewire/oxfw/oxfw-hwdep.c +++ b/sound/firewire/oxfw/oxfw-hwdep.c @@ -35,13 +35,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, } memset(&event, 0, sizeof(event)); - if (oxfw->dev_lock_changed) { - event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; - event.lock_status.status = (oxfw->dev_lock_count > 0); - oxfw->dev_lock_changed = false; + event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; + event.lock_status.status = (oxfw->dev_lock_count > 0); + oxfw->dev_lock_changed = false; - count = min_t(long, count, sizeof(event.lock_status)); - } + count = min_t(long, count, sizeof(event.lock_status)); spin_unlock_irq(&oxfw->lock); -- cgit v1.2.3 From f4514249d6483effbc08984ed908fc741de798f0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 25 Jan 2021 14:13:44 +0300 Subject: ALSA: fireface: remove unnecessary condition in hwdep_read() Smatch complains that "count" is not clamped when "ff->dev_lock_changed" and it leads to an information leak. Fortunately, that's not actually possible and the condition can be deleted. Signed-off-by: Dan Carpenter Acked-by: Takashi Sakamoto Link: https://lore.kernel.org/r/YA6n6I8EcNAO5ZFs@mwanda Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-hwdep.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/firewire/fireface/ff-hwdep.c b/sound/firewire/fireface/ff-hwdep.c index 4b2e0dff5ddb..ea64a2a41eea 100644 --- a/sound/firewire/fireface/ff-hwdep.c +++ b/sound/firewire/fireface/ff-hwdep.c @@ -35,13 +35,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, } memset(&event, 0, sizeof(event)); - if (ff->dev_lock_changed) { - event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; - event.lock_status.status = (ff->dev_lock_count > 0); - ff->dev_lock_changed = false; + event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; + event.lock_status.status = (ff->dev_lock_count > 0); + ff->dev_lock_changed = false; - count = min_t(long, count, sizeof(event.lock_status)); - } + count = min_t(long, count, sizeof(event.lock_status)); spin_unlock_irq(&ff->lock); -- cgit v1.2.3 From 24a41a38dd2df065ee942221c2fae5e314770865 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 03:31:52 +0300 Subject: ASoC: tegra: ahub: Add missing resets AHUB driver misses D_AUDIO and APBIF resets. CPU hangs on trying to access hardware if resets aren't de-asserted. This problem is currently masked by the tegra-clk driver which implicitly de-asserts the resets when the corresponding clocks are enabled. Soon the implicit de-assertion will be gone from the tegra-clk driver, thus we need to fix the AHUB driver. Add the missing resets to the driver. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Tested-by: Dmitry Osipenko # Nexus7 T30 audio works Tested-by: Nicolas Chauvet # TK1 boot-tested Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-5-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 156e3b9d613c..8c32333cc08c 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -337,6 +337,8 @@ static const struct { const char *rst_name; u32 mod_list_mask; } configlink_mods[] = { + { "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER }, + { "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER }, { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER }, { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER }, { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER }, -- cgit v1.2.3 From 6d8ac9b1dd2f138f4aa39008994600f561eeede8 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 03:31:53 +0300 Subject: ASoC: tegra: ahub: Use clk_bulk helpers Use clk_bulk helpers to make code cleaner. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Tested-by: Dmitry Osipenko # Nexus7 T30 audio works Tested-by: Nicolas Chauvet # TK1 boot-tested Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-6-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 30 +++++++----------------------- sound/soc/tegra/tegra30_ahub.h | 4 ++-- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 8c32333cc08c..12ca8e3ca4f6 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -45,8 +45,7 @@ static int tegra30_ahub_runtime_suspend(struct device *dev) regcache_cache_only(ahub->regmap_apbif, true); regcache_cache_only(ahub->regmap_ahub, true); - clk_disable_unprepare(ahub->clk_apbif); - clk_disable_unprepare(ahub->clk_d_audio); + clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks); return 0; } @@ -66,17 +65,9 @@ static int tegra30_ahub_runtime_resume(struct device *dev) { int ret; - ret = clk_prepare_enable(ahub->clk_d_audio); - if (ret) { - dev_err(dev, "clk_enable d_audio failed: %d\n", ret); + ret = clk_bulk_prepare_enable(ahub->nclocks, ahub->clocks); + if (ret) return ret; - } - ret = clk_prepare_enable(ahub->clk_apbif); - if (ret) { - dev_err(dev, "clk_enable apbif failed: %d\n", ret); - clk_disable(ahub->clk_d_audio); - return ret; - } regcache_cache_only(ahub->regmap_apbif, false); regcache_cache_only(ahub->regmap_ahub, false); @@ -559,19 +550,12 @@ static int tegra30_ahub_probe(struct platform_device *pdev) ahub->soc_data = soc_data; ahub->dev = &pdev->dev; - ahub->clk_d_audio = devm_clk_get(&pdev->dev, "d_audio"); - if (IS_ERR(ahub->clk_d_audio)) { - dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n"); - ret = PTR_ERR(ahub->clk_d_audio); - return ret; - } + ahub->clocks[ahub->nclocks++].id = "apbif"; + ahub->clocks[ahub->nclocks++].id = "d_audio"; - ahub->clk_apbif = devm_clk_get(&pdev->dev, "apbif"); - if (IS_ERR(ahub->clk_apbif)) { - dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n"); - ret = PTR_ERR(ahub->clk_apbif); + ret = devm_clk_bulk_get(&pdev->dev, ahub->nclocks, ahub->clocks); + if (ret) return ret; - } res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs_apbif = devm_ioremap_resource(&pdev->dev, res0); diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h index 6889c5f23d02..01480d7dc940 100644 --- a/sound/soc/tegra/tegra30_ahub.h +++ b/sound/soc/tegra/tegra30_ahub.h @@ -511,8 +511,8 @@ struct tegra30_ahub_soc_data { struct tegra30_ahub { const struct tegra30_ahub_soc_data *soc_data; struct device *dev; - struct clk *clk_d_audio; - struct clk *clk_apbif; + struct clk_bulk_data clocks[2]; + unsigned int nclocks; resource_size_t apbif_addr; struct regmap *regmap_apbif; struct regmap *regmap_ahub; -- cgit v1.2.3 From ed9ce1ed2239909c23d48c723c6549417c476246 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 03:31:54 +0300 Subject: ASoC: tegra: ahub: Reset hardware properly Assert hardware resets before clocks are enabled and then de-assert them after clocks are enabled. This brings hardware into a predictable state. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Tested-by: Dmitry Osipenko # Nexus7 T30 audio works Tested-by: Nicolas Chauvet # TK1 boot-tested Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-7-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 36 ++++++++++++++++++++++++++++++++---- sound/soc/tegra/tegra30_ahub.h | 1 + 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 12ca8e3ca4f6..9ef05ca4f6c4 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -65,14 +65,39 @@ static int tegra30_ahub_runtime_resume(struct device *dev) { int ret; + ret = reset_control_assert(ahub->reset); + if (ret) + return ret; + ret = clk_bulk_prepare_enable(ahub->nclocks, ahub->clocks); if (ret) return ret; + usleep_range(10, 100); + + ret = reset_control_deassert(ahub->reset); + if (ret) + goto disable_clocks; + regcache_cache_only(ahub->regmap_apbif, false); regcache_cache_only(ahub->regmap_ahub, false); + regcache_mark_dirty(ahub->regmap_apbif); + regcache_mark_dirty(ahub->regmap_ahub); + + ret = regcache_sync(ahub->regmap_apbif); + if (ret) + goto disable_clocks; + + ret = regcache_sync(ahub->regmap_ahub); + if (ret) + goto disable_clocks; return 0; + +disable_clocks: + clk_bulk_disable_unprepare(ahub->nclocks, ahub->clocks); + + return ret; } int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, @@ -519,7 +544,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev) /* * The AHUB hosts a register bus: the "configlink". For this to * operate correctly, all devices on this bus must be out of reset. - * Ensure that here. */ for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) { if (!(configlink_mods[i].mod_list_mask & @@ -535,10 +559,8 @@ static int tegra30_ahub_probe(struct platform_device *pdev) return ret; } - ret = reset_control_deassert(rst); + /* just check presence of the reset control in DT */ reset_control_put(rst); - if (ret) - return ret; } ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), @@ -557,6 +579,12 @@ static int tegra30_ahub_probe(struct platform_device *pdev) if (ret) return ret; + ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev); + if (IS_ERR(ahub->reset)) { + dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset); + return PTR_ERR(ahub->reset); + } + res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs_apbif = devm_ioremap_resource(&pdev->dev, res0); if (IS_ERR(regs_apbif)) diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h index 01480d7dc940..3b85244f87f1 100644 --- a/sound/soc/tegra/tegra30_ahub.h +++ b/sound/soc/tegra/tegra30_ahub.h @@ -511,6 +511,7 @@ struct tegra30_ahub_soc_data { struct tegra30_ahub { const struct tegra30_ahub_soc_data *soc_data; struct device *dev; + struct reset_control *reset; struct clk_bulk_data clocks[2]; unsigned int nclocks; resource_size_t apbif_addr; -- cgit v1.2.3 From e32da5eb627c9dd60fd245cb5beb3079e96890d1 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 25 Jan 2021 23:02:08 +0900 Subject: ALSA: bebob: remove an unnecessary condition in hwdep_read() Drivers in ALSA firewire stack supports eventing to userspace applications via ALSA hwdep interface. All of the drivers supports stream lock events. Some of them supports their unique events according to specification of target device. ALSA bebob driver supports the stream lock event only. In the case, it's enough to check condition only in loop with process blocking. However, current implementation check it again after breaking the loop. This commit removes the redundant check. Reported-by: Dan Carpenter Reported-by: Christophe JAILLET Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20210125140208.26318-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_hwdep.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/firewire/bebob/bebob_hwdep.c b/sound/firewire/bebob/bebob_hwdep.c index 8677e3ec8d14..6f9331655d43 100644 --- a/sound/firewire/bebob/bebob_hwdep.c +++ b/sound/firewire/bebob/bebob_hwdep.c @@ -37,11 +37,9 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, memset(&event, 0, sizeof(event)); count = min_t(long, count, sizeof(event.lock_status)); - if (bebob->dev_lock_changed) { - event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; - event.lock_status.status = (bebob->dev_lock_count > 0); - bebob->dev_lock_changed = false; - } + event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; + event.lock_status.status = (bebob->dev_lock_count > 0); + bebob->dev_lock_changed = false; spin_unlock_irq(&bebob->lock); -- cgit v1.2.3 From 3a465f027a33cbd2af74f882ad41729583195e8f Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 03:31:49 +0300 Subject: ALSA: hda/tegra: Use clk_bulk helpers Use clk_bulk helpers to make code cleaner. Note that this patch changed the order in which clocks are enabled to make code look nicer, but this doesn't matter in terms of hardware. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Tested-by: Nicolas Chauvet # TK1 boot-tested Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-2-digetx@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_tegra.c | 68 +++++++---------------------------------------- 1 file changed, 9 insertions(+), 59 deletions(-) diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 361cf2041911..a25bf7083c28 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -70,9 +70,8 @@ struct hda_tegra { struct azx chip; struct device *dev; - struct clk *hda_clk; - struct clk *hda2codec_2x_clk; - struct clk *hda2hdmi_clk; + struct clk_bulk_data clocks[3]; + unsigned int nclocks; void __iomem *regs; struct work_struct probe_work; }; @@ -113,36 +112,6 @@ static void hda_tegra_init(struct hda_tegra *hda) writel(v, hda->regs + HDA_IPFS_INTR_MASK); } -static int hda_tegra_enable_clocks(struct hda_tegra *data) -{ - int rc; - - rc = clk_prepare_enable(data->hda_clk); - if (rc) - return rc; - rc = clk_prepare_enable(data->hda2codec_2x_clk); - if (rc) - goto disable_hda; - rc = clk_prepare_enable(data->hda2hdmi_clk); - if (rc) - goto disable_codec_2x; - - return 0; - -disable_codec_2x: - clk_disable_unprepare(data->hda2codec_2x_clk); -disable_hda: - clk_disable_unprepare(data->hda_clk); - return rc; -} - -static void hda_tegra_disable_clocks(struct hda_tegra *data) -{ - clk_disable_unprepare(data->hda2hdmi_clk); - clk_disable_unprepare(data->hda2codec_2x_clk); - clk_disable_unprepare(data->hda_clk); -} - /* * power management */ @@ -186,7 +155,7 @@ static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev) azx_stop_chip(chip); azx_enter_link_reset(chip); } - hda_tegra_disable_clocks(hda); + clk_bulk_disable_unprepare(hda->nclocks, hda->clocks); return 0; } @@ -198,7 +167,7 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev) struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); int rc; - rc = hda_tegra_enable_clocks(hda); + rc = clk_bulk_prepare_enable(hda->nclocks, hda->clocks); if (rc != 0) return rc; if (chip && chip->running) { @@ -268,29 +237,6 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) return 0; } -static int hda_tegra_init_clk(struct hda_tegra *hda) -{ - struct device *dev = hda->dev; - - hda->hda_clk = devm_clk_get(dev, "hda"); - if (IS_ERR(hda->hda_clk)) { - dev_err(dev, "failed to get hda clock\n"); - return PTR_ERR(hda->hda_clk); - } - hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x"); - if (IS_ERR(hda->hda2codec_2x_clk)) { - dev_err(dev, "failed to get hda2codec_2x clock\n"); - return PTR_ERR(hda->hda2codec_2x_clk); - } - hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi"); - if (IS_ERR(hda->hda2hdmi_clk)) { - dev_err(dev, "failed to get hda2hdmi clock\n"); - return PTR_ERR(hda->hda2hdmi_clk); - } - - return 0; -} - static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) { struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); @@ -495,7 +441,11 @@ static int hda_tegra_probe(struct platform_device *pdev) return err; } - err = hda_tegra_init_clk(hda); + hda->clocks[hda->nclocks++].id = "hda"; + hda->clocks[hda->nclocks++].id = "hda2hdmi"; + hda->clocks[hda->nclocks++].id = "hda2codec_2x"; + + err = devm_clk_bulk_get(&pdev->dev, hda->nclocks, hda->clocks); if (err < 0) goto out_free; -- cgit v1.2.3 From 87f0e46e7559beb6f1d1ff99f8f48b1b9d86db52 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 03:31:50 +0300 Subject: ALSA: hda/tegra: Reset hardware Reset hardware on RPM-resume in order to bring it into a predictable state. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Tested-by: Nicolas Chauvet # TK1 boot-tested Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-3-digetx@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_tegra.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index a25bf7083c28..04dcd4cdfd9e 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,7 @@ struct hda_tegra { struct azx chip; struct device *dev; + struct reset_control *reset; struct clk_bulk_data clocks[3]; unsigned int nclocks; void __iomem *regs; @@ -167,6 +169,12 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev) struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); int rc; + if (!chip->running) { + rc = reset_control_assert(hda->reset); + if (rc) + return rc; + } + rc = clk_bulk_prepare_enable(hda->nclocks, hda->clocks); if (rc != 0) return rc; @@ -176,6 +184,12 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev) /* disable controller wake up event*/ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & ~STATESTS_INT_MASK); + } else { + usleep_range(10, 100); + + rc = reset_control_deassert(hda->reset); + if (rc) + return rc; } return 0; @@ -441,6 +455,12 @@ static int hda_tegra_probe(struct platform_device *pdev) return err; } + hda->reset = devm_reset_control_array_get_exclusive(&pdev->dev); + if (IS_ERR(hda->reset)) { + err = PTR_ERR(hda->reset); + goto out_free; + } + hda->clocks[hda->nclocks++].id = "hda"; hda->clocks[hda->nclocks++].id = "hda2hdmi"; hda->clocks[hda->nclocks++].id = "hda2codec_2x"; -- cgit v1.2.3 From 6755568ad111394da224c823e8baf31a05a1469c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 20 Jan 2021 03:31:51 +0300 Subject: ALSA: hda/tegra: Remove unnecessary null-check from hda_tegra_runtime_resume() The "chip" can't be NULL in hda_tegra_runtime_resume() because code would crash otherwise. Let's remove the unnecessary check in order to clean up code a tad. Tested-by: Peter Geis # Ouya T30 audio works Tested-by: Matt Merhar # Ouya T30 boot-tested Suggested-by: Thierry Reding Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210120003154.26749-4-digetx@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 04dcd4cdfd9e..6f2b743b9d75 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -178,7 +178,7 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev) rc = clk_bulk_prepare_enable(hda->nclocks, hda->clocks); if (rc != 0) return rc; - if (chip && chip->running) { + if (chip->running) { hda_tegra_init(hda); azx_init_chip(chip, 1); /* disable controller wake up event*/ -- cgit v1.2.3 From d2006bb79411c56b7bb6173f753a0ba6172d1fe6 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 22 Jan 2021 10:24:47 +0100 Subject: watchdog: pcwd: drop always-false if from remove callback If pcwd_isa_probe() succeeded pcwd_private.io_addr cannot be NULL. (And if pcwd_isa_probe() failed, pcwd_isa_remove() isn't called.) Acked-by: Guenter Roeck Acked-by: William Breathitt Gray Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20210122092449.426097-2-uwe@kleine-koenig.org Signed-off-by: Takashi Iwai --- drivers/watchdog/pcwd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index e86fa7f8351d..b95cd38f3ceb 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c @@ -956,9 +956,6 @@ static int pcwd_isa_remove(struct device *dev, unsigned int id) if (debug >= DEBUG) pr_debug("pcwd_isa_remove id=%d\n", id); - if (!pcwd_private.io_addr) - return 1; - /* Disable the board */ if (!nowayout) pcwd_stop(); -- cgit v1.2.3 From 7797b4e00faf3229ef67ac37015dd2ee8e4c7901 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 22 Jan 2021 10:24:48 +0100 Subject: media/radio: Make radio_isa_common_remove() return void Instead of an unconditional return 0, return no value. One of the two callers ignored the return value already before. This simplifies the next patch. Signed-off-by: Uwe Kleine-König Reviewed-by: Hans Verkuil Link: https://lore.kernel.org/r/20210122092449.426097-3-uwe@kleine-koenig.org Signed-off-by: Takashi Iwai --- drivers/media/radio/radio-isa.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c index ad2ac16ff12d..527f4c3b0ca4 100644 --- a/drivers/media/radio/radio-isa.c +++ b/drivers/media/radio/radio-isa.c @@ -273,8 +273,8 @@ err_dev_reg: return res; } -static int radio_isa_common_remove(struct radio_isa_card *isa, - unsigned region_size) +static void radio_isa_common_remove(struct radio_isa_card *isa, + unsigned region_size) { const struct radio_isa_ops *ops = isa->drv->ops; @@ -285,7 +285,6 @@ static int radio_isa_common_remove(struct radio_isa_card *isa, release_region(isa->io, region_size); v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); kfree(isa); - return 0; } int radio_isa_probe(struct device *pdev, unsigned int dev) @@ -342,7 +341,9 @@ int radio_isa_remove(struct device *pdev, unsigned int dev) { struct radio_isa_card *isa = dev_get_drvdata(pdev); - return radio_isa_common_remove(isa, isa->drv->region_size); + radio_isa_common_remove(isa, isa->drv->region_size); + + return 0; } EXPORT_SYMBOL_GPL(radio_isa_remove); -- cgit v1.2.3 From 30e88d017fcbeb50c4b07577fe059558361067e7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 22 Jan 2021 10:24:49 +0100 Subject: isa: Make the remove callback for isa drivers return void The driver core ignores the return value of the remove callback, so don't give isa drivers the chance to provide a value. Adapt all isa_drivers with a remove callbacks accordingly; they all return 0 unconditionally anyhow. Acked-by: Marc Kleine-Budde # for drivers/net/can/sja1000/tscan1.c Acked-by: William Breathitt Gray Acked-by: Wolfram Sang # for drivers/i2c/ Reviewed-by: Takashi Iway # for sound/ Reviewed-by: Hans Verkuil # for drivers/media/ Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20210122092449.426097-4-uwe@kleine-koenig.org Signed-off-by: Takashi Iwai --- drivers/base/isa.c | 2 +- drivers/i2c/busses/i2c-elektor.c | 4 +--- drivers/i2c/busses/i2c-pca-isa.c | 4 +--- drivers/input/touchscreen/htcpen.c | 4 +--- drivers/media/radio/radio-isa.c | 4 +--- drivers/media/radio/radio-isa.h | 2 +- drivers/media/radio/radio-sf16fmr2.c | 4 +--- drivers/net/can/sja1000/tscan1.c | 4 +--- drivers/net/ethernet/3com/3c509.c | 3 +-- drivers/scsi/advansys.c | 3 +-- drivers/scsi/aha1542.c | 3 +-- drivers/scsi/fdomain_isa.c | 3 +-- drivers/scsi/g_NCR5380.c | 5 ++--- drivers/watchdog/pcwd.c | 4 +--- include/linux/isa.h | 2 +- sound/isa/ad1848/ad1848.c | 3 +-- sound/isa/adlib.c | 3 +-- sound/isa/cmi8328.c | 3 +-- sound/isa/cmi8330.c | 3 +-- sound/isa/cs423x/cs4231.c | 3 +-- sound/isa/cs423x/cs4236.c | 3 +-- sound/isa/es1688/es1688.c | 3 +-- sound/isa/es18xx.c | 5 ++--- sound/isa/galaxy/galaxy.c | 3 +-- sound/isa/gus/gusclassic.c | 3 +-- sound/isa/gus/gusextreme.c | 3 +-- sound/isa/gus/gusmax.c | 3 +-- sound/isa/gus/interwave.c | 3 +-- sound/isa/msnd/msnd_pinnacle.c | 3 +-- sound/isa/opl3sa2.c | 3 +-- sound/isa/opti9xx/miro.c | 3 +-- sound/isa/opti9xx/opti92x-ad1848.c | 5 ++--- sound/isa/sb/jazz16.c | 3 +-- sound/isa/sb/sb16.c | 3 +-- sound/isa/sb/sb8.c | 3 +-- sound/isa/sc6000.c | 3 +-- sound/isa/sscape.c | 3 +-- sound/isa/wavefront/wavefront.c | 3 +-- 38 files changed, 41 insertions(+), 83 deletions(-) diff --git a/drivers/base/isa.c b/drivers/base/isa.c index 2772f5d1948a..aa4737667026 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -51,7 +51,7 @@ static int isa_bus_remove(struct device *dev) struct isa_driver *isa_driver = dev->platform_data; if (isa_driver && isa_driver->remove) - return isa_driver->remove(dev, to_isa_dev(dev)->id); + isa_driver->remove(dev, to_isa_dev(dev)->id); return 0; } diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 140426db28df..b72a3c3ef2ab 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -282,7 +282,7 @@ static int elektor_probe(struct device *dev, unsigned int id) return -ENODEV; } -static int elektor_remove(struct device *dev, unsigned int id) +static void elektor_remove(struct device *dev, unsigned int id) { i2c_del_adapter(&pcf_isa_ops); @@ -298,8 +298,6 @@ static int elektor_remove(struct device *dev, unsigned int id) iounmap(base_iomem); release_mem_region(base, 2); } - - return 0; } static struct isa_driver i2c_elektor_driver = { diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index f27bc1e55385..85e8cf58e8bf 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -161,7 +161,7 @@ static int pca_isa_probe(struct device *dev, unsigned int id) return -ENODEV; } -static int pca_isa_remove(struct device *dev, unsigned int id) +static void pca_isa_remove(struct device *dev, unsigned int id) { i2c_del_adapter(&pca_isa_ops); @@ -170,8 +170,6 @@ static int pca_isa_remove(struct device *dev, unsigned int id) free_irq(irq, &pca_isa_ops); } release_region(base, IO_SIZE); - - return 0; } static struct isa_driver pca_isa_driver = { diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index 2f261a34f9c2..056ba76087e8 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c @@ -171,7 +171,7 @@ static int htcpen_isa_probe(struct device *dev, unsigned int id) return err; } -static int htcpen_isa_remove(struct device *dev, unsigned int id) +static void htcpen_isa_remove(struct device *dev, unsigned int id) { struct input_dev *htcpen_dev = dev_get_drvdata(dev); @@ -182,8 +182,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id) release_region(HTCPEN_PORT_INDEX, 2); release_region(HTCPEN_PORT_INIT, 1); release_region(HTCPEN_PORT_IRQ_CLEAR, 1); - - return 0; } #ifdef CONFIG_PM diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c index 527f4c3b0ca4..c591c0851fa2 100644 --- a/drivers/media/radio/radio-isa.c +++ b/drivers/media/radio/radio-isa.c @@ -337,13 +337,11 @@ int radio_isa_probe(struct device *pdev, unsigned int dev) } EXPORT_SYMBOL_GPL(radio_isa_probe); -int radio_isa_remove(struct device *pdev, unsigned int dev) +void radio_isa_remove(struct device *pdev, unsigned int dev) { struct radio_isa_card *isa = dev_get_drvdata(pdev); radio_isa_common_remove(isa, isa->drv->region_size); - - return 0; } EXPORT_SYMBOL_GPL(radio_isa_remove); diff --git a/drivers/media/radio/radio-isa.h b/drivers/media/radio/radio-isa.h index 2f0736edfda8..c9159958203e 100644 --- a/drivers/media/radio/radio-isa.h +++ b/drivers/media/radio/radio-isa.h @@ -91,7 +91,7 @@ struct radio_isa_driver { int radio_isa_match(struct device *pdev, unsigned int dev); int radio_isa_probe(struct device *pdev, unsigned int dev); -int radio_isa_remove(struct device *pdev, unsigned int dev); +void radio_isa_remove(struct device *pdev, unsigned int dev); #ifdef CONFIG_PNP int radio_isa_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 0388894cfe41..d0dde55b7930 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -293,11 +293,9 @@ static void fmr2_remove(struct fmr2 *fmr2) kfree(fmr2); } -static int fmr2_isa_remove(struct device *pdev, unsigned int ndev) +static void fmr2_isa_remove(struct device *pdev, unsigned int ndev) { fmr2_remove(dev_get_drvdata(pdev)); - - return 0; } static void fmr2_pnp_remove(struct pnp_dev *pdev) diff --git a/drivers/net/can/sja1000/tscan1.c b/drivers/net/can/sja1000/tscan1.c index 6ea802c66124..3dbba8d61afb 100644 --- a/drivers/net/can/sja1000/tscan1.c +++ b/drivers/net/can/sja1000/tscan1.c @@ -159,7 +159,7 @@ static int tscan1_probe(struct device *dev, unsigned id) return -ENXIO; } -static int tscan1_remove(struct device *dev, unsigned id /*unused*/) +static void tscan1_remove(struct device *dev, unsigned id /*unused*/) { struct net_device *netdev; struct sja1000_priv *priv; @@ -179,8 +179,6 @@ static int tscan1_remove(struct device *dev, unsigned id /*unused*/) release_region(pld_base, TSCAN1_PLD_SIZE); free_sja1000dev(netdev); - - return 0; } static struct isa_driver tscan1_isa_driver = { diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 667f38c9e4c6..53e1f7e07959 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -335,12 +335,11 @@ static int el3_isa_match(struct device *pdev, unsigned int ndev) return 1; } -static int el3_isa_remove(struct device *pdev, +static void el3_isa_remove(struct device *pdev, unsigned int ndev) { el3_device_remove(pdev); dev_set_drvdata(pdev, NULL); - return 0; } #ifdef CONFIG_PM diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 79830e77afa9..b1e97f75b0ba 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -11459,12 +11459,11 @@ static int advansys_isa_probe(struct device *dev, unsigned int id) return err; } -static int advansys_isa_remove(struct device *dev, unsigned int id) +static void advansys_isa_remove(struct device *dev, unsigned int id) { int ioport = _asc_def_iop_base[id]; advansys_release(dev_get_drvdata(dev)); release_region(ioport, ASC_IOADR_GAP); - return 0; } static struct isa_driver advansys_isa_driver = { diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index dc5667afeb27..e0d8cca1c70b 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -1025,12 +1025,11 @@ static int aha1542_isa_match(struct device *pdev, unsigned int ndev) return 1; } -static int aha1542_isa_remove(struct device *pdev, +static void aha1542_isa_remove(struct device *pdev, unsigned int ndev) { aha1542_release(dev_get_drvdata(pdev)); dev_set_drvdata(pdev, NULL); - return 0; } static struct isa_driver aha1542_isa_driver = { diff --git a/drivers/scsi/fdomain_isa.c b/drivers/scsi/fdomain_isa.c index e0cdcd2003d0..2b4280a43a53 100644 --- a/drivers/scsi/fdomain_isa.c +++ b/drivers/scsi/fdomain_isa.c @@ -175,7 +175,7 @@ static int fdomain_isa_param_match(struct device *dev, unsigned int ndev) return 1; } -static int fdomain_isa_remove(struct device *dev, unsigned int ndev) +static void fdomain_isa_remove(struct device *dev, unsigned int ndev) { struct Scsi_Host *sh = dev_get_drvdata(dev); int base = sh->io_port; @@ -183,7 +183,6 @@ static int fdomain_isa_remove(struct device *dev, unsigned int ndev) fdomain_destroy(sh); release_region(base, FDOMAIN_REGION_SIZE); dev_set_drvdata(dev, NULL); - return 0; } static struct isa_driver fdomain_isa_driver = { diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 2df2f38a9b12..7ba3c9312731 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -720,12 +720,11 @@ static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev) return 1; } -static int generic_NCR5380_isa_remove(struct device *pdev, - unsigned int ndev) +static void generic_NCR5380_isa_remove(struct device *pdev, + unsigned int ndev) { generic_NCR5380_release_resources(dev_get_drvdata(pdev)); dev_set_drvdata(pdev, NULL); - return 0; } static struct isa_driver generic_NCR5380_isa_driver = { diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index b95cd38f3ceb..a793b03a785d 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c @@ -951,7 +951,7 @@ error_request_region: return ret; } -static int pcwd_isa_remove(struct device *dev, unsigned int id) +static void pcwd_isa_remove(struct device *dev, unsigned int id) { if (debug >= DEBUG) pr_debug("pcwd_isa_remove id=%d\n", id); @@ -968,8 +968,6 @@ static int pcwd_isa_remove(struct device *dev, unsigned int id) (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); pcwd_private.io_addr = 0x0000; cards_found--; - - return 0; } static void pcwd_isa_shutdown(struct device *dev, unsigned int id) diff --git a/include/linux/isa.h b/include/linux/isa.h index 41336da0f4e7..e30963190968 100644 --- a/include/linux/isa.h +++ b/include/linux/isa.h @@ -13,7 +13,7 @@ struct isa_driver { int (*match)(struct device *, unsigned int); int (*probe)(struct device *, unsigned int); - int (*remove)(struct device *, unsigned int); + void (*remove)(struct device *, unsigned int); void (*shutdown)(struct device *, unsigned int); int (*suspend)(struct device *, unsigned int, pm_message_t); int (*resume)(struct device *, unsigned int); diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 593c6e959afe..48f7cc57c3da 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -118,10 +118,9 @@ out: snd_card_free(card); return error; } -static int snd_ad1848_remove(struct device *dev, unsigned int n) +static void snd_ad1848_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index 5105524b6f38..e6cd7c4da38e 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c @@ -97,10 +97,9 @@ out: snd_card_free(card); return error; } -static int snd_adlib_remove(struct device *dev, unsigned int n) +static void snd_adlib_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } static struct isa_driver snd_adlib_driver = { diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index faca5dd95bfe..3b9fbb02864b 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c @@ -403,7 +403,7 @@ error: return err; } -static int snd_cmi8328_remove(struct device *pdev, unsigned int dev) +static void snd_cmi8328_remove(struct device *pdev, unsigned int dev) { struct snd_card *card = dev_get_drvdata(pdev); struct snd_cmi8328 *cmi = card->private_data; @@ -420,7 +420,6 @@ static int snd_cmi8328_remove(struct device *pdev, unsigned int dev) snd_cmi8328_cfg_write(cmi->port, CFG2, 0); snd_cmi8328_cfg_write(cmi->port, CFG3, 0); snd_card_free(card); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 4669eb0cc8ce..19e258527d69 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -631,11 +631,10 @@ static int snd_cmi8330_isa_probe(struct device *pdev, return 0; } -static int snd_cmi8330_isa_remove(struct device *devptr, +static void snd_cmi8330_isa_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index 2135963eba78..383ee621cea1 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -135,10 +135,9 @@ out: snd_card_free(card); return error; } -static int snd_cs4231_remove(struct device *dev, unsigned int n) +static void snd_cs4231_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index fa3c39cff5f8..24688271e73f 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -487,11 +487,10 @@ static int snd_cs423x_isa_probe(struct device *pdev, return 0; } -static int snd_cs423x_isa_remove(struct device *pdev, +static void snd_cs423x_isa_remove(struct device *pdev, unsigned int dev) { snd_card_free(dev_get_drvdata(pdev)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 64610571a5e1..d99bb3f8f0c1 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -192,10 +192,9 @@ out: return error; } -static int snd_es1688_isa_remove(struct device *dev, unsigned int n) +static void snd_es1688_isa_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } static struct isa_driver snd_es1688_driver = { diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 5f8d7e8a5477..9beef8079177 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2210,11 +2210,10 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev) } } -static int snd_es18xx_isa_remove(struct device *devptr, - unsigned int dev) +static void snd_es18xx_isa_remove(struct device *devptr, + unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index 65f9f46c9f58..d33d69f29924 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c @@ -608,10 +608,9 @@ error: return err; } -static int snd_galaxy_remove(struct device *dev, unsigned int n) +static void snd_galaxy_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } static struct isa_driver snd_galaxy_driver = { diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 7419b1939754..015f88a11352 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -195,10 +195,9 @@ out: snd_card_free(card); return error; } -static int snd_gusclassic_remove(struct device *dev, unsigned int n) +static void snd_gusclassic_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } static struct isa_driver snd_gusclassic_driver = { diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index ed2f9d64efae..c9f31b4fb887 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -324,10 +324,9 @@ out: snd_card_free(card); return error; } -static int snd_gusextreme_remove(struct device *dev, unsigned int n) +static void snd_gusextreme_remove(struct device *dev, unsigned int n) { snd_card_free(dev_get_drvdata(dev)); - return 0; } static struct isa_driver snd_gusextreme_driver = { diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 05cd9be4dd8a..dc09fbd6f88d 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -338,10 +338,9 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) return err; } -static int snd_gusmax_remove(struct device *devptr, unsigned int dev) +static void snd_gusmax_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #define DEV_NAME "gusmax" diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 3e9ad930deae..e4d412e72b75 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -825,10 +825,9 @@ static int snd_interwave_isa_probe(struct device *pdev, } } -static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev) +static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } static struct isa_driver snd_interwave_driver = { diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 24b34ecf5e5b..69647b41300d 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -1049,10 +1049,9 @@ cfg_error: #endif } -static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev) +static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev) { snd_msnd_unload(dev_get_drvdata(pdev)); - return 0; } static struct isa_driver snd_msnd_driver = { diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 85a181acd388..7649a8a4128d 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -878,11 +878,10 @@ static int snd_opl3sa2_isa_probe(struct device *pdev, return 0; } -static int snd_opl3sa2_isa_remove(struct device *devptr, +static void snd_opl3sa2_isa_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 44ed1b65f6ce..20933342f5eb 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1480,11 +1480,10 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) return 0; } -static int snd_miro_isa_remove(struct device *devptr, +static void snd_miro_isa_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #define DEV_NAME "miro" diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 881d3b5711d2..758f5b579138 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -1024,11 +1024,10 @@ static int snd_opti9xx_isa_probe(struct device *devptr, return 0; } -static int snd_opti9xx_isa_remove(struct device *devptr, - unsigned int dev) +static void snd_opti9xx_isa_remove(struct device *devptr, + unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index ee379bbf70a4..0e2e0ab3b9e4 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c @@ -339,12 +339,11 @@ err_free: return err; } -static int snd_jazz16_remove(struct device *devptr, unsigned int dev) +static void snd_jazz16_remove(struct device *devptr, unsigned int dev) { struct snd_card *card = dev_get_drvdata(devptr); snd_card_free(card); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 479197c13803..db284b7b88a7 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -547,10 +547,9 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev) } } -static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev) +static void snd_sb16_isa_remove(struct device *pdev, unsigned int dev) { snd_card_free(dev_get_drvdata(pdev)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 438109f167d6..8e3e67b9a341 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -192,10 +192,9 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) return err; } -static int snd_sb8_remove(struct device *pdev, unsigned int dev) +static void snd_sb8_remove(struct device *pdev, unsigned int dev) { snd_card_free(dev_get_drvdata(pdev)); - return 0; } #ifdef CONFIG_PM diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 3d0bea44f454..def137579717 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -672,7 +672,7 @@ err_exit: return err; } -static int snd_sc6000_remove(struct device *devptr, unsigned int dev) +static void snd_sc6000_remove(struct device *devptr, unsigned int dev) { struct snd_card *card = dev_get_drvdata(devptr); char __iomem **vport = card->private_data; @@ -684,7 +684,6 @@ static int snd_sc6000_remove(struct device *devptr, unsigned int dev) release_region(mss_port[dev], 4); snd_card_free(card); - return 0; } static struct isa_driver snd_sc6000_driver = { diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 2e5a5c5279e8..e70ef9aee545 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -1183,10 +1183,9 @@ _release_card: return ret; } -static int snd_sscape_remove(struct device *devptr, unsigned int dev) +static void snd_sscape_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #define DEV_NAME "sscape" diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 9e0f6b226775..b750a4fd40de 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -565,11 +565,10 @@ static int snd_wavefront_isa_probe(struct device *pdev, return 0; } -static int snd_wavefront_isa_remove(struct device *devptr, +static void snd_wavefront_isa_remove(struct device *devptr, unsigned int dev) { snd_card_free(dev_get_drvdata(devptr)); - return 0; } #define DEV_NAME "wavefront" -- cgit v1.2.3 From ae07f5c7c5e9ebca5b9d6471bb4b99a9da5c6d88 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Jan 2021 16:47:02 +0100 Subject: ASoC: siu: Fix build error by a wrong const prefix A const prefix was put wrongly in the middle at the code refactoring commit 932eaf7c7904 ("ASoC: sh: siu_pcm: remove snd_pcm_ops"), which leads to a build error as: sound/soc/sh/siu_pcm.c:546:8: error: expected '{' before 'const' Also, another inconsistency is that the declaration of siu_component misses the const prefix. This patch corrects both failures. Fixes: 932eaf7c7904 ("ASoC: sh: siu_pcm: remove snd_pcm_ops") Cc: Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20210126154702.3974-1-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sh/siu.h | 2 +- sound/soc/sh/siu_pcm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h index 6201840f1bc0..a675c36fc9d9 100644 --- a/sound/soc/sh/siu.h +++ b/sound/soc/sh/siu.h @@ -169,7 +169,7 @@ static inline u32 siu_read32(u32 __iomem *addr) #define SIU_BRGBSEL (0x108 / sizeof(u32)) #define SIU_BRRB (0x10c / sizeof(u32)) -extern struct snd_soc_component_driver siu_component; +extern const struct snd_soc_component_driver siu_component; extern struct siu_info *siu_i2s_data; int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card); diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 45c4320976ab..4785886df4f0 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -543,7 +543,7 @@ static void siu_pcm_free(struct snd_soc_component *component, dev_dbg(pcm->card->dev, "%s\n", __func__); } -struct const snd_soc_component_driver siu_component = { +const struct snd_soc_component_driver siu_component = { .name = DRV_NAME, .open = siu_pcm_open, .close = siu_pcm_close, -- cgit v1.2.3 From 7da99ef9757a3dd6e66a9b4854c5e58cd65a0b9a Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 25 Jan 2021 09:04:58 +0200 Subject: ASoC: SOF: allow soundwire use desc->default_fw_filename The old code always uses sof_fw_filename in struct snd_soc_acpi_mach as the firmware name. However, firmware name should depend on the platform instead of the machine. For example, different machines may use the same soundwire link topology, but they are using the different firmware. In this case, it's hard to determine in struct snd_soc_acpi_mach which firmware it should use. Signed-off-by: Libin Yang Reviewed-by: Bard Liao Reviewed-by: Guennadi Liakhovetski Signed-off-by: Kai Vehmanen Tested-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20210125070500.807474-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 509a9b256423..b625d852b999 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1173,7 +1173,10 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; mach->mach_params.platform = dev_name(sdev->dev); - pdata->fw_filename = mach->sof_fw_filename; + if (mach->sof_fw_filename) + pdata->fw_filename = mach->sof_fw_filename; + else + pdata->fw_filename = pdata->desc->default_fw_filename; pdata->tplg_filename = mach->sof_tplg_filename; } else { dev_info(sdev->dev, -- cgit v1.2.3 From 3d14932527ff09517f052e54e7c25d676120b33a Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 25 Jan 2021 09:04:59 +0200 Subject: ASoC: Intel: tgl: remove sof_fw_filename set for tgl_3_in_1_default tgl_3_in_1_default link topology may be used by both TGL-LP and TGL-H. Let's remove the sof_fw_filename setting in struct snd_soc_acpi_mach and use the default_fw_filename setting in struct sof_dev_desc. Signed-off-by: Libin Yang Reviewed-by: Bard Liao Reviewed-by: Guennadi Liakhovetski Signed-off-by: Kai Vehmanen Tested-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20210125070500.807474-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 98196e9fad62..711aed06c6dd 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -358,14 +358,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .link_mask = 0x7, .links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg", }, { .link_mask = 0xF, /* 4 active links required */ .links = tgl_3_in_1_default, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg", }, { @@ -377,35 +375,30 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .link_mask = 0xF, .links = tgl_3_in_1_mono_amp, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg", }, { .link_mask = 0xF, /* 4 active links required */ .links = tgl_3_in_1_sdca, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg", }, { .link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */ .links = tgl_rvp, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg", }, { .link_mask = 0x3, /* rt5682 on link0 & 2xmax98373 on link 1 */ .links = tgl_chromebook_base, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg", }, { .link_mask = 0x1, /* this will only enable rt5682 for now */ .links = tgl_chromebook_base, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-tgl.ri", .sof_tplg_filename = "sof-tgl-rt5682.tplg", }, {}, -- cgit v1.2.3 From 89e641ae647a4ebc1d608fd56f331a4f4886da5f Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 27 Jan 2021 14:23:58 +0200 Subject: ASoC: SOF: add a pointer to download repo in case FW request fails The SOF firmware and topology files are not distributed via linux-firmware. To help debugging cases where correct firmware is not installed, print a pointer to the official upstream repository for Sound Open Firmware releases. BugLink: https://github.com/thesofproject/sof/issues/3665 Reported-by: Bruce Perens Signed-off-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Reviewed-by: Marc Herbert Reviewed-by: Liam Girdwood Link: https://lore.kernel.org/r/20210127122358.1014458-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 2 ++ sound/soc/sof/topology.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 08a17abb63ff..eabeaf7b260e 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -731,6 +731,8 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", fw_filename, ret); + dev_err(sdev->dev, + "you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n"); goto err; } else { dev_dbg(sdev->dev, "request_firmware %s successful\n", diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b6b32a7a91f8..59f89f3d61a2 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3740,6 +3740,8 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) if (ret < 0) { dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n", file, ret); + dev_err(scomp->dev, + "you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n"); return ret; } -- cgit v1.2.3 From 89a400bdeb129dbc7e1c8ad2151cc8141a619709 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 26 Jan 2021 18:07:36 -0800 Subject: ASoC: SOF: Intel: hda: enable DMI L1 for D0i3-compatible streams DMI L1 entry is currently disabled whenever any capture stream is opened to prevent xruns during pause/release. But, in order to maximise power savings for the wake-on-voice usecase, DMI L1 entry should be enabled for D0i3-compatible capture streams. Introduce a new field, flags in struct sof_intel_hda_stream that stores whether a stream is dmi_l1_compatible. All playback streams, and D0i3-compatible capture streams are DMI L1 compatible. Reviewed-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210127020737.1088960-2-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-compress.c | 2 +- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/intel/hda-pcm.c | 16 +++++++++++++++- sound/soc/sof/intel/hda-stream.c | 38 ++++++++++++++++++++++---------------- sound/soc/sof/intel/hda-trace.c | 3 +-- sound/soc/sof/intel/hda.h | 6 +++++- 6 files changed, 45 insertions(+), 22 deletions(-) diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c index 53c08034fa22..c6cf7b313934 100644 --- a/sound/soc/sof/intel/hda-compress.c +++ b/sound/soc/sof/intel/hda-compress.c @@ -25,7 +25,7 @@ int hda_probe_compr_assign(struct snd_sof_dev *sdev, { struct hdac_ext_stream *stream; - stream = hda_dsp_stream_get(sdev, cstream->direction); + stream = hda_dsp_stream_get(sdev, cstream->direction, 0); if (!stream) return -EBUSY; diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index ed773696b495..365a79fc7081 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -35,7 +35,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig struct pci_dev *pci = to_pci_dev(sdev->dev); int ret; - dsp_stream = hda_dsp_stream_get(sdev, direction); + dsp_stream = hda_dsp_stream_get(sdev, direction, 0); if (!dsp_stream) { dev_err(sdev->dev, "error: no stream available\n"); diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 5d35bb18660a..689934131a68 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -215,11 +215,25 @@ found: int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *scomp = sdev->component; struct hdac_ext_stream *dsp_stream; + struct snd_sof_pcm *spcm; int direction = substream->stream; + u32 flags = 0; + + spcm = snd_sof_find_spcm_dai(scomp, rtd); + if (!spcm) { + dev_err(sdev->dev, "error: can't find PCM with DAI ID %d\n", rtd->dai_link->id); + return -EINVAL; + } - dsp_stream = hda_dsp_stream_get(sdev, direction); + /* All playback and D0i3 compatible streams are DMI L1 capable */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK || + spcm->stream[substream->stream].d0i3_compatible) + flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE; + dsp_stream = hda_dsp_stream_get(sdev, direction, flags); if (!dsp_stream) { dev_err(sdev->dev, "error: no stream available\n"); return -ENODEV; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 0e09ede922c7..40a3993ae2cb 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -155,7 +155,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, /* get next unused stream */ struct hdac_ext_stream * -hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) +hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) { struct hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *hda_stream; @@ -183,18 +183,22 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) spin_unlock_irq(&bus->reg_lock); /* stream found ? */ - if (!stream) + if (!stream) { dev_err(sdev->dev, "error: no free %s streams\n", direction == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); + return stream; + } + + hda_stream->flags = flags; /* - * Disable DMI Link L1 entry when capture stream is opened. + * Prevent DMI Link L1 entry for streams that don't support it. * Workaround to address a known issue with host DMA that results * in xruns during pause/release in capture scenarios. */ if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) - if (stream && direction == SNDRV_PCM_STREAM_CAPTURE) + if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, 0); @@ -206,37 +210,39 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) { struct hdac_bus *bus = sof_to_bus(sdev); + struct sof_intel_hda_stream *hda_stream; + struct hdac_ext_stream *stream; struct hdac_stream *s; - bool active_capture_stream = false; + bool dmi_l1_enable = true; bool found = false; spin_lock_irq(&bus->reg_lock); /* - * close stream matching the stream tag - * and check if there are any open capture streams. + * close stream matching the stream tag and check if there are any open streams + * that are DMI L1 incompatible. */ list_for_each_entry(s, &bus->stream_list, list) { + stream = stream_to_hdac_ext_stream(s); + hda_stream = container_of(stream, struct sof_intel_hda_stream, hda_stream); + if (!s->opened) continue; if (s->direction == direction && s->stream_tag == stream_tag) { s->opened = false; found = true; - } else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) { - active_capture_stream = true; + } else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { + dmi_l1_enable = false; } } spin_unlock_irq(&bus->reg_lock); - /* Enable DMI L1 entry if there are no capture streams open */ - if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) - if (!active_capture_stream) - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, - HDA_VS_INTEL_EM2_L1SEN); + /* Enable DMI L1 if permitted */ + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); if (!found) { dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag); diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index 1eb746d5adeb..ca869038e909 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -42,8 +42,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; int ret; - hda->dtrace_stream = hda_dsp_stream_get(sdev, - SNDRV_PCM_STREAM_CAPTURE); + hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE, 0); if (!hda->dtrace_stream) { dev_err(sdev->dev, diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 9ec8ae0fd649..8e9b94bf0333 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -402,6 +402,9 @@ struct sof_intel_dsp_bdl { #define SOF_HDA_PLAYBACK 0 #define SOF_HDA_CAPTURE 1 +/* stream flags */ +#define SOF_HDA_STREAM_DMI_L1_COMPATIBLE 1 + /* * Time in ms for opportunistic D0I3 entry delay. * This has been deliberately chosen to be long to avoid race conditions. @@ -471,6 +474,7 @@ struct sof_intel_hda_stream { struct hdac_ext_stream hda_stream; struct sof_intel_stream stream; int host_reserved; /* reserve host DMA channel */ + u32 flags; }; #define hstream_to_sof_hda_stream(hstream) \ @@ -562,7 +566,7 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev); bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev); struct hdac_ext_stream * - hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction); + hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags); int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag); int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream, -- cgit v1.2.3 From 6e0210763024ac43c5716dc873065ce5069edbf0 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 26 Jan 2021 18:07:37 -0800 Subject: ASoC: SOF: Intel: hda: Enable DMI L1 for trace Enabling DMI L1 for capture streams could result in xruns during pause/release. As pause/release is not a valid scenario for trace, we can safely enable DMI L1 for it. Reviewed-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210127020737.1088960-3-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index ca869038e909..81d76d3debc6 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -42,7 +42,8 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; int ret; - hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE, 0); + hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE, + SOF_HDA_STREAM_DMI_L1_COMPATIBLE); if (!hda->dtrace_stream) { dev_err(sdev->dev, -- cgit v1.2.3 From 1da0b9899abdbc7103d3ec6b1a888efda41dbb59 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 26 Jan 2021 17:17:48 +0000 Subject: ASoC: soc-component: add snd_soc_component_read/write_field() It's often the case that we would write or read a particular field in register. With the current soc_component apis, reading a particular field in register would involve first read the register and then perform shift operations. Ex: to read from a field mask of 0xf0 val = snd_soc_component_read(component, reg); field = ((val & 0xf0) >> 0x4); This is sometimes prone to errors and code become less readable! With this new api we could just do field = snd_soc_component_read_field(component, reg, 0xf0); this makes it bit simple, easy to write and less error prone! This also applies to writing! There are various places in kernel which provides such field interfaces however soc_component seems to be missing this. This patch is inspired by FIELD_GET/FIELD_PREP macros in include/linux/bitfield.h Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210126171749.1863-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- include/sound/soc-component.h | 6 +++++ sound/soc/soc-component.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 0bce41fefd30..5b47768222b7 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -353,6 +353,12 @@ int snd_soc_component_test_bits(struct snd_soc_component *component, unsigned int reg, unsigned int mask, unsigned int value); +unsigned int snd_soc_component_read_field(struct snd_soc_component *component, + unsigned int reg, unsigned int mask); +int snd_soc_component_write_field(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, + unsigned int val); + /* component wide operations */ int snd_soc_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 760523382f3c..361a79d655e3 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -34,6 +34,18 @@ static inline int _soc_component_ret(struct snd_soc_component *component, return ret; } +static inline int soc_component_field_shift(struct snd_soc_component *component, + unsigned int mask) +{ + if (!mask) { + dev_err(component->dev, "ASoC: error field mask is zero for %s\n", + component->name); + return 0; + } + + return (__builtin_ffs(mask) - 1); +} + /* * We might want to check substream by using list. * In such case, we can update these macros. @@ -839,6 +851,47 @@ int snd_soc_component_update_bits_async(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); +/** + * snd_soc_component_read_field() - Read register field value + * @component: Component to read from + * @reg: Register to read + * @mask: mask of the register field + * + * Return: read value of register field. + */ +unsigned int snd_soc_component_read_field(struct snd_soc_component *component, + unsigned int reg, unsigned int mask) +{ + unsigned int val; + + val = snd_soc_component_read(component, reg); + + val = (val & mask) >> soc_component_field_shift(component, mask); + + return val; +} +EXPORT_SYMBOL_GPL(snd_soc_component_read_field); + +/** + * snd_soc_component_write_field() - write to register field + * @component: Component to write to + * @reg: Register to write + * @mask: mask of the register field to update + * @val: value of the field to write + * + * Return: 1 for change, otherwise 0. + */ +int snd_soc_component_write_field(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, + unsigned int val) +{ + + val = (val << soc_component_field_shift(component, mask)) & mask; + + return snd_soc_component_update_bits(component, reg, mask, val); +} +EXPORT_SYMBOL_GPL(snd_soc_component_write_field); + /** * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed * @component: Component for which to wait -- cgit v1.2.3 From 7db4c4cd767e5c2418e7892c6b2f06982d34369a Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 26 Jan 2021 17:17:49 +0000 Subject: ASoC: codecs: lpass-wsa-macro: make use of snd_soc_component_read_field() Make use of snd_soc_component_read_field() to make the code more readable! Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210126171749.1863-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 43 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 25f1df214ca5..5ebcd935ba89 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -40,9 +40,11 @@ #define CDC_WSA_TOP_I2S_CLK (0x00A4) #define CDC_WSA_TOP_I2S_RESET (0x00A8) #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (0x0100) -#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3) -#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0) +#define CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(2, 0) +#define CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(5, 3) #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (0x0104) +#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0) +#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3) #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (0x0108) #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (0x010C) #define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (0x0110) @@ -229,8 +231,6 @@ #define NUM_INTERPOLATORS 2 #define WSA_NUM_CLKS_MAX 5 #define WSA_MACRO_MCLK_FREQ 19200000 -#define WSA_MACRO_MUX_INP_SHFT 0x3 -#define WSA_MACRO_MUX_INP_MASK1 0x07 #define WSA_MACRO_MUX_INP_MASK2 0x38 #define WSA_MACRO_MUX_CFG_OFFSET 0x8 #define WSA_MACRO_MUX_CFG1_OFFSET 0x4 @@ -843,7 +843,6 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, u32 j, port; u16 int_mux_cfg0, int_mux_cfg1; u16 int_fs_reg; - u8 int_mux_cfg0_val, int_mux_cfg1_val; u8 inp0_sel, inp1_sel, inp2_sel; struct snd_soc_component *component = dai->component; struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); @@ -865,15 +864,13 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, */ for (j = 0; j < NUM_INTERPOLATORS; j++) { int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET; - int_mux_cfg0_val = snd_soc_component_read(component, - int_mux_cfg0); - int_mux_cfg1_val = snd_soc_component_read(component, - int_mux_cfg1); - inp0_sel = int_mux_cfg0_val & WSA_MACRO_MUX_INP_MASK1; - inp1_sel = (int_mux_cfg0_val >> WSA_MACRO_MUX_INP_SHFT) & - WSA_MACRO_MUX_INP_MASK1; - inp2_sel = (int_mux_cfg1_val >> WSA_MACRO_MUX_INP_SHFT) & - WSA_MACRO_MUX_INP_MASK1; + inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK); + inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK); + inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1, + CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK); + if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) { @@ -912,9 +909,9 @@ static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai, int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1; for (j = 0; j < NUM_INTERPOLATORS; j++) { - int_mux_cfg1_val = snd_soc_component_read(component, - int_mux_cfg1) & - WSA_MACRO_MUX_INP_MASK1; + int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1, + CDC_WSA_RX_INTX_2_SEL_MASK); + if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) { int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL + WSA_MACRO_RX_PATH_OFFSET * j; @@ -1410,25 +1407,25 @@ static bool wsa_macro_adie_lb(struct snd_soc_component *component, int interp_idx) { u16 int_mux_cfg0, int_mux_cfg1; - u8 int_mux_cfg0_val, int_mux_cfg1_val; u8 int_n_inp0, int_n_inp1, int_n_inp2; int_mux_cfg0 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8; int_mux_cfg1 = int_mux_cfg0 + 4; - int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0); - int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1); - int_n_inp0 = int_mux_cfg0_val & 0x0F; + int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK); if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || int_n_inp0 == INTn_1_INP_SEL_DEC1) return true; - int_n_inp1 = int_mux_cfg0_val >> 4; + int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK); if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || int_n_inp1 == INTn_1_INP_SEL_DEC1) return true; - int_n_inp2 = int_mux_cfg1_val >> 4; + int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1, + CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK); if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || int_n_inp2 == INTn_1_INP_SEL_DEC1) return true; -- cgit v1.2.3 From 9fd5599a9b2618b315983d8a097e6dead640f55c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 26 Jan 2021 15:20:23 -0600 Subject: ASoC: q6asm: fix 'physical' typos Fix misspellings of "physical". Signed-off-by: Bjorn Helgaas Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210126212023.2921168-1-helgaas@kernel.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6asm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index a6618efe22f2..36bf8bd4edd7 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -491,7 +491,7 @@ static int __q6asm_memory_map_regions(struct audio_client *ac, int dir, * * @dir: direction of audio stream * @ac: audio client instanace - * @phys: physcial address that needs mapping. + * @phys: physical address that needs mapping. * @period_sz: audio period size * @periods: number of periods * -- cgit v1.2.3 From ded055eea679139f11bd808795d9697b430d1c7d Mon Sep 17 00:00:00 2001 From: Judy Hsiao Date: Wed, 27 Jan 2021 21:56:20 +0800 Subject: ASoC: max98373: Fixes a typo in max98373_feedback_get The snd_soc_put_volsw in max98373_feedback_get is a typo, change it to snd_soc_get_volsw. Fixes: 349dd23931d1 ("ASoC: max98373: don't access volatile registers in bias level off") Signed-off-by: Judy Hsiao Link: https://lore.kernel.org/r/20210127135620.1143942-1-judyhsiao@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/max98373.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 31d571d4fac1..746c829312b8 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -190,7 +190,7 @@ static int max98373_feedback_get(struct snd_kcontrol *kcontrol, } } - return snd_soc_put_volsw(kcontrol, ucontrol); + return snd_soc_get_volsw(kcontrol, ucontrol); } static const struct snd_kcontrol_new max98373_snd_controls[] = { -- cgit v1.2.3 From e32df142359fb6f4d27977b7652549f0844aa62f Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 25 Jan 2021 09:05:00 +0200 Subject: ASoC: Intel: adl: remove sof_fw_filename setting in ADL snd_soc_acpi_mach ADL will use sof-adl-s.ri if it is ADL-S platform. So let's use the default_fw_filename in pdata->desc for the ADL FW filename. Signed-off-by: Libin Yang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210125070500.807474-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 06b233d63b73..0aca340ebc25 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -44,7 +44,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { .link_mask = 0x1, /* link0 required */ .links = adl_rvp, .drv_name = "sof_sdw", - .sof_fw_filename = "sof-adl.ri", .sof_tplg_filename = "sof-adl-rt711.tplg", }, {}, -- cgit v1.2.3 From 6c28377b7114d04cf82eedffe9dcc8fa66ecec48 Mon Sep 17 00:00:00 2001 From: Srinivasa Rao Mandadapu Date: Wed, 27 Jan 2021 20:48:24 +0530 Subject: ASoC: qcom: lpass-cpu: Remove bit clock state check No need of BCLK state maintenance from driver side as clock_enable and clk_disable API's maintaing state counter. One of the major issue was spotted when Headset jack inserted while playback continues, due to same PCM device node opens twice for playaback/capture and closes once for capture and playback continues. It can resolve the errors in such scenarios. Fixes: b1824968221c ("ASoC: qcom: Fix enabling BCLK and LRCLK in LPAIF invalid state") Signed-off-by: Srinivasa Rao Mandadapu Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210127151824.8929-1-srivasam@codeaurora.org Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 22 ++++++++-------------- sound/soc/qcom/lpass-lpaif-reg.h | 3 --- sound/soc/qcom/lpass.h | 1 - 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 66b834312f33..73ca24c0a08b 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -286,16 +286,12 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); - if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_DISABLE) { - ret = clk_enable(drvdata->mi2s_bit_clk[id]); - if (ret) { - dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); - clk_disable(drvdata->mi2s_osr_clk[id]); - return ret; - } - drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_ENABLE; + ret = clk_enable(drvdata->mi2s_bit_clk[id]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + clk_disable(drvdata->mi2s_osr_clk[id]); + return ret; } - break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -310,10 +306,9 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, if (ret) dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); - if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_ENABLE) { - clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]); - drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_DISABLE; - } + + clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]); + break; } @@ -866,7 +861,6 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); } - drvdata->bit_clk_state[dai_id] = LPAIF_BIT_CLK_DISABLE; } /* Allocation for i2sctl regmap fields */ diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index baf72f124ea9..2eb03ad9b7c7 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -60,9 +60,6 @@ #define LPAIF_I2SCTL_BITWIDTH_24 1 #define LPAIF_I2SCTL_BITWIDTH_32 2 -#define LPAIF_BIT_CLK_DISABLE 0 -#define LPAIF_BIT_CLK_ENABLE 1 - #define LPAIF_I2SCTL_RESET_STATE 0x003C0004 #define LPAIF_DMACTL_RESET_STATE 0x00200000 diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 2d68af0da34d..83b2e08ade06 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -68,7 +68,6 @@ struct lpass_data { unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS]; unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS]; int hdmi_port_enable; - int bit_clk_state[LPASS_MAX_MI2S_PORTS]; /* low-power audio interface (LPAIF) registers */ void __iomem *lpaif; -- cgit v1.2.3 From 0084364d9678e9d722ee620ed916f2f9954abdbf Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 28 Jan 2021 11:23:45 +0200 Subject: ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend Cancel the D0i3 work during runtime suspend as no streams are active at this point anyway. Fixes: 63e51fd33fef ("ASoC: SOF: Intel: cnl: Implement feature to support DSP D0i3 in S0") Signed-off-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210128092345.1033085-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 1c5e05b88a90..1799fc56a3e4 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -802,11 +802,15 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_dsp_power_state target_state = { .state = SOF_DSP_PM_D3, }; int ret; + /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + /* stop hda controller and power dsp off */ ret = hda_suspend(sdev, true); if (ret < 0) -- cgit v1.2.3 From f6c246eacb62977dea5c9c65ac6fb4921cad5bcd Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 28 Jan 2021 11:38:46 +0200 Subject: ASoC: SOF: Intel: hda: use snd_sof_dsp_core_power_up/down API To implement common logic in SOF core, core power up/down flows should use common SOF API and not directly use low-level platform specific helper functions. Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210128093850.1041387-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 2 +- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/intel/hda.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 2b001151fe37..4fe4175179d4 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -624,7 +624,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) #endif /* power down DSP */ - ret = hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask); + ret = snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask); if (ret < 0) { dev_err(sdev->dev, "error: failed to power down core during suspend\n"); diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 365a79fc7081..4b2ab351e2cc 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -183,7 +183,7 @@ err: flags |= SOF_DBG_DUMP_FORCE_ERR_LEVEL; hda_dsp_dump(sdev, flags); - hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask); + snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask); return ret; } diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7e703ce22fcd..d57d484a42d1 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -928,7 +928,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) /* disable cores */ if (chip) - hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask); + snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask); /* disable DSP */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, -- cgit v1.2.3 From cedd502d18b5b7a913fa13fa18a037cc51b1798d Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 28 Jan 2021 11:38:47 +0200 Subject: ASoC: SOF: Intel: hda-loader: keep init cores alive init_core_mask should be the available cores mask after fw boot. So we should keep not core 0 but init cores alive. Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210128093850.1041387-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 4b2ab351e2cc..07b73fe3c5e5 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -147,8 +147,9 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) chip->ipc_ack_mask, chip->ipc_ack_mask); - /* step 5: power down corex */ - ret = hda_dsp_core_power_down(sdev, chip->host_managed_cores_mask & ~(BIT(0))); + /* step 5: power down cores that are no longer needed */ + ret = hda_dsp_core_power_down(sdev, chip->host_managed_cores_mask & + ~(chip->init_core_mask)); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, -- cgit v1.2.3 From 42077f08b3f1ba891dca1f8f479810f16b7d6cbd Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 28 Jan 2021 11:38:48 +0200 Subject: ASoC: SOF: update dsp core power status in common APIs Only manage enabled_cores_mask in common snd_sof_dsp_core_power_up/down APIs to ensure it stays in sync with actual DSP core state. Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210128093850.1041387-4-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/loader.c | 6 ------ sound/soc/sof/ops.h | 22 ++++++++++++++++------ sound/soc/sof/pm.c | 1 - sound/soc/sof/topology.c | 8 -------- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 08a17abb63ff..4ade55bf6d75 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -811,7 +811,6 @@ EXPORT_SYMBOL(snd_sof_load_firmware); int snd_sof_run_firmware(struct snd_sof_dev *sdev) { int ret; - int init_core_mask; init_waitqueue_head(&sdev->boot_wait); @@ -843,8 +842,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) return ret; } - init_core_mask = ret; - /* * now wait for the DSP to boot. There are 3 possible outcomes: * 1. Boot wait times out indicating FW boot failure. @@ -874,9 +871,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) return ret; } - /* fw boot is complete. Update the active cores mask */ - sdev->enabled_cores_mask = init_core_mask; - return 0; } EXPORT_SYMBOL(snd_sof_run_firmware); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index f0c9ca8820d2..2e9a8da53d57 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -76,19 +76,29 @@ static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev) static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) { - if (sof_ops(sdev)->core_power_up) - return sof_ops(sdev)->core_power_up(sdev, core_mask); + int ret = 0; - return 0; + if (sof_ops(sdev)->core_power_up) { + ret = sof_ops(sdev)->core_power_up(sdev, core_mask); + if (!ret) + sdev->enabled_cores_mask |= core_mask; + } + + return ret; } static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask) { - if (sof_ops(sdev)->core_power_down) - return sof_ops(sdev)->core_power_down(sdev, core_mask); + int ret = 0; - return 0; + if (sof_ops(sdev)->core_power_down) { + ret = sof_ops(sdev)->core_power_down(sdev, core_mask); + if (!ret) + sdev->enabled_cores_mask &= ~core_mask; + } + + return ret; } /* pre/post fw load */ diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index c83fb6255961..fd265803f7bc 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -256,7 +256,6 @@ suspend: /* reset FW state */ sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; - sdev->enabled_cores_mask = 0; return ret; } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index b6b32a7a91f8..b69f493b5faa 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1352,10 +1352,6 @@ static int sof_core_enable(struct snd_sof_dev *sdev, int core) core, ret); goto err; } - - /* update enabled cores mask */ - sdev->enabled_cores_mask |= BIT(core); - return ret; err: /* power down core if it is host managed and return the original error if this fails too */ @@ -2603,10 +2599,6 @@ static int sof_widget_unload(struct snd_soc_component *scomp, if (ret < 0) dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n", pipeline->core); - - /* update enabled cores mask */ - sdev->enabled_cores_mask &= ~(1 << pipeline->core); - break; default: break; -- cgit v1.2.3 From 30876e2a06f35b525dc71f94dfc3c6f329e55a28 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 28 Jan 2021 11:38:49 +0200 Subject: ASoC: SOF: Filter out unneeded core power up/downs Exclude cores that are already powered on/off correctly. This allows to simplify dsp_power_up/down() implementations and avoid unexpected error. Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210128093850.1041387-5-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 2e9a8da53d57..5099ad03df72 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -78,7 +78,8 @@ static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev, { int ret = 0; - if (sof_ops(sdev)->core_power_up) { + core_mask &= ~sdev->enabled_cores_mask; + if (sof_ops(sdev)->core_power_up && core_mask) { ret = sof_ops(sdev)->core_power_up(sdev, core_mask); if (!ret) sdev->enabled_cores_mask |= core_mask; @@ -92,7 +93,8 @@ static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev, { int ret = 0; - if (sof_ops(sdev)->core_power_down) { + core_mask &= sdev->enabled_cores_mask; + if (sof_ops(sdev)->core_power_down && core_mask) { ret = sof_ops(sdev)->core_power_down(sdev, core_mask); if (!ret) sdev->enabled_cores_mask &= ~core_mask; -- cgit v1.2.3 From 92c6ec606cd12c16091b70442da536bdeddb1f7f Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 28 Jan 2021 11:38:50 +0200 Subject: ASoC: SOF: intel: hda-loader: use snd_sof_dsp_core_power_down/up APIs To manage enabled_cores_mask flag, we should always use snd_sof_dsp_ core_power_down/up APIs to power up/down dsp cores. The APIs do a little bit more than the original functions, but it is harmless. Suggested-by: Ranjani Sridharan Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210128093850.1041387-6-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 07b73fe3c5e5..d744952f6954 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -93,7 +93,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) int i; /* step 1: power up corex */ - ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask); + ret = snd_sof_dsp_core_power_up(sdev, chip->host_managed_cores_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); @@ -148,8 +148,8 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) chip->ipc_ack_mask); /* step 5: power down cores that are no longer needed */ - ret = hda_dsp_core_power_down(sdev, chip->host_managed_cores_mask & - ~(chip->init_core_mask)); + ret = snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask & + ~(chip->init_core_mask)); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, -- cgit v1.2.3 From 1fc96dc29c3ba342915c3a935c9d177f8f420d03 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 28 Jan 2021 12:57:51 +0200 Subject: ASoC: Intel: remove duplicate MODULE_LICENSE/DESCRIPTION tags The snd-soc-acpi-intel-match has duplicate module tags for all platforms separately. Remove all but one and save some storage space and cleanup modinfo output. Signed-off-by: Kai Vehmanen Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210128105751.1049837-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-bxt-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-byt-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-cfl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-cht-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-ehl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-glk-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-icl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-jsl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-kbl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-skl-match.c | 3 --- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 3 --- 14 files changed, 42 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index 32f77e29c2ff..398cc771c835 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -85,6 +85,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index c348607b49a5..31e60df131c3 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -233,6 +233,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_baytrail_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c index 27b4b73d94d4..1733dfb23e79 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cfl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cfl-match.c @@ -18,6 +18,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[] = { {} }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cfl_sdw_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c index 2752dc955733..227424236fd5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c @@ -196,6 +196,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cherrytrail_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index adddc91918df..2161b3b85b4a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -309,6 +309,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[] = { {} }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_sdw_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index b80f032a8b76..ec77a57a07ba 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -63,6 +63,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = { {} }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index 5c7a1214403d..6222708a98e7 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -20,6 +20,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ehl_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 26cb3b16cdd3..6ceaab19ccb6 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c @@ -43,6 +43,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c index 35958553652e..fe343a95b5ff 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c @@ -53,6 +53,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_broadwell_machines[] = { {} }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_broadwell_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 9a529a785288..d38ff7d187c4 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -185,6 +185,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_icl_sdw_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 34f5fcad5701..52238db0bcb5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -63,6 +63,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index a4fbe6707ca7..47dadc9d5d2a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c @@ -128,6 +128,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c index 26f9ce146523..961df8d6b5e4 100644 --- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c @@ -42,6 +42,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_skl_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 4933184df5f5..ee25451dfdd0 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -411,6 +411,3 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Common ACPI Match module"); -- cgit v1.2.3 From 8ac9e476b86851c94e0f33bea758e0a00e3f875e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 29 Jan 2021 10:05:39 +0000 Subject: ASoC: soc-component: fix undefined reference to __ffssi2 microblaze-linux-gcc (GCC) 9.3.0 complains about missing __ffssi2 symbol while using __builtin_ffs at runtime. This is because arch/h8300 is compiled with -fno-builtin option. so fallback and use kernel ffs() instead to all the arch builds happy! Fixes: 1da0b9899abd ("ASoC: soc-component: add snd_soc_component_read/write_field()") Reported-by: kernel test robot Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210129100539.23459-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/soc-component.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 361a79d655e3..159bf88b9f8c 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -11,6 +11,7 @@ #include #include #include +#include #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) static inline int _soc_component_ret(struct snd_soc_component *component, @@ -43,7 +44,7 @@ static inline int soc_component_field_shift(struct snd_soc_component *component, return 0; } - return (__builtin_ffs(mask) - 1); + return (ffs(mask) - 1); } /* -- cgit v1.2.3 From fa2e5a647ed2ed299974ea5916c1e7648f81030b Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sun, 31 Jan 2021 01:12:40 +0100 Subject: ALSA: ac97: Constify static struct attribute_group The only usage of ac97_adapter_attr_group is to put its address in an array of pointers to const attribute_group structs. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Link: https://lore.kernel.org/r/20210131001241.2278-2-rikard.falkeborn@gmail.com Signed-off-by: Takashi Iwai --- sound/ac97/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 7985dd8198b6..d9077e91382b 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -273,7 +273,7 @@ static struct attribute *ac97_controller_device_attrs[] = { NULL }; -static struct attribute_group ac97_adapter_attr_group = { +static const struct attribute_group ac97_adapter_attr_group = { .name = "ac97_operations", .attrs = ac97_controller_device_attrs, }; -- cgit v1.2.3 From 0417fadab493b55093ba2590f4e66c828f7084fe Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sun, 31 Jan 2021 01:12:41 +0100 Subject: ALSA: hda: Constify static attribute_group The only usage of hdac_dev_attr_group is to put its address in an array of pointers to const attribute_group structs. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Link: https://lore.kernel.org/r/20210131001241.2278-3-rikard.falkeborn@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/hdac_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c index e56e83325903..0d7771fca9f0 100644 --- a/sound/hda/hdac_sysfs.c +++ b/sound/hda/hdac_sysfs.c @@ -66,7 +66,7 @@ static struct attribute *hdac_dev_attrs[] = { NULL }; -static struct attribute_group hdac_dev_attr_group = { +static const struct attribute_group hdac_dev_attr_group = { .attrs = hdac_dev_attrs, }; -- cgit v1.2.3 From 0074946932cbd42647da947408a9d620746a4e0e Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Sun, 31 Jan 2021 18:09:14 +0800 Subject: ALSA: intel8x0: Fix missing check in snd_intel8x0m_create When device_type == DEVICE_ALI, we should also check the return value of pci_iomap() to avoid potential null pointer dereference. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20210131100916.7915-1-dinghao.liu@zju.edu.cn Signed-off-by: Takashi Iwai --- sound/pci/intel8x0m.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 1b7df0c4e57c..19872cecc9d2 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -1129,13 +1129,14 @@ static int snd_intel8x0m_create(struct snd_card *card, chip->bmaddr = pci_iomap(pci, 3, 0); else chip->bmaddr = pci_iomap(pci, 1, 0); + +port_inited: if (!chip->bmaddr) { dev_err(card->dev, "Controller space ioremap problem\n"); snd_intel8x0m_free(chip); return -EIO; } - port_inited: /* initialize offsets */ chip->bdbars_count = 2; tbl = intel_regs; -- cgit v1.2.3 From 941d3f0d7e9ffcbee1efeb6f07fa5fc5ef8347ff Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 1 Feb 2021 11:31:28 +0200 Subject: ASoC: SOF: topology: Prevent NULL pointer dereference with no TLV When there is no TLV data in topology, extracting the TLV data could result in a NULL pointer exception. Prevent this by making sure that the TLV data exists before extracting it. Signed-off-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Reviewed-by: Paul Olaru Reviewed-by: Bard Liao Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210201093128.1226603-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 59f89f3d61a2..480cf75a7575 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1073,7 +1073,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, scontrol->cmd = SOF_CTRL_CMD_VOLUME; /* extract tlv data */ - if (get_tlv_data(kc->tlv.p, tlv) < 0) { + if (!kc->tlv.p || get_tlv_data(kc->tlv.p, tlv) < 0) { dev_err(scomp->dev, "error: invalid TLV data\n"); ret = -EINVAL; goto out_free; -- cgit v1.2.3 From 6bbb859012e905736c852b518be16c653e451967 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 29 Jan 2021 23:57:38 +0530 Subject: ASoC: dt-bindings: rt5659: Update binding doc Update following in rt5659.txt binding doc - Add JD source for Intel HDA header: Commit 041e74b71491 ("ASoC: rt5659: Add the support of Intel HDA Header") added driver support. Add missing info here. - sound-name-prefix: Used to prefix component widgets/kcontrols with given prefix. - ports: Helps to use the Codec with audio graph card Signed-off-by: Sameer Pujar Reported-by: Jon Hunter Cc: Oder Chiou Cc: Bard Liao Link: https://lore.kernel.org/r/1611944866-29373-2-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt5659.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rt5659.txt b/Documentation/devicetree/bindings/sound/rt5659.txt index 56788f50b6cf..c473df5c878c 100644 --- a/Documentation/devicetree/bindings/sound/rt5659.txt +++ b/Documentation/devicetree/bindings/sound/rt5659.txt @@ -37,10 +37,21 @@ Optional properties: - realtek,jd-src 0: No JD is used 1: using JD3 as JD source + 2: JD source for Intel HDA header - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. - realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin. +- sound-name-prefix: Please refer to name-prefix.txt + +- ports: A Codec may have a single or multiple I2S interfaces. These + interfaces on Codec side can be described under 'ports' or 'port'. + When the SoC or host device is connected to multiple interfaces of + the Codec, the connectivity can be described using 'ports' property. + If a single interface is used, then 'port' can be used. The usage + depends on the platform or board design. + Please refer to Documentation/devicetree/bindings/graph.txt + Pins on the device (for linking into audio routes) for RT5659/RT5658: * DMIC L1 -- cgit v1.2.3 From 70f0bc65f6cf757fa4cca2d6fcb84f613bc0d8cc Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 29 Jan 2021 23:57:39 +0530 Subject: ASoC: dt-bindings: tegra: Add iommus property to Tegra graph card Document 'iommus' property for APE (Audio Processing Engine) sound card. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1611944866-29373-3-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml index fc271f644aaf..249970952202 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-graph-card.yaml @@ -45,6 +45,9 @@ properties: minItems: 1 maxItems: 3 + iommus: + maxItems: 1 + required: - clocks - clock-names -- cgit v1.2.3 From 531e5b7abbde3c190aeff5b13c17f7ef3e0f3543 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 29 Jan 2021 23:57:40 +0530 Subject: ASoC: audio-graph-card: Add clocks property to endpoint node Add optional 'clocks' property to audio port 'endpoint' node. One such example is where SoC supplies a clock to external audio codec component. Signed-off-by: Sameer Pujar Cc: Kuninori Morimoto Reviewed-by: Jon Hunter Link: https://lore.kernel.org/r/1611944866-29373-4-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/audio-graph-port.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml index 766e9109b2f7..08ed8f52c962 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml @@ -33,6 +33,9 @@ properties: properties: remote-endpoint: maxItems: 1 + clocks: + maxItems: 1 + description: Describes the clock used by audio component. mclk-fs: description: | Multiplication factor between stream rate and codec mclk. -- cgit v1.2.3 From 563c2681d4313f55b9b1d9a8f635946cd4972170 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 29 Jan 2021 23:57:41 +0530 Subject: ASoC: rt5659: Add Kconfig prompt Add tristate prompt to allow codec selection. Cc: Oder Chiou Cc: Bard Liao Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1611944866-29373-5-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9bf6bfdaf11e..df34b3b3bb14 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1162,7 +1162,7 @@ config SND_SOC_RT5651 depends on I2C config SND_SOC_RT5659 - tristate + tristate "Realtek RT5658/RT5659 Codec" depends on I2C config SND_SOC_RT5660 -- cgit v1.2.3 From e86caa011c80507783e5975bca1458f28c1d2b8c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 29 Jan 2021 13:59:15 +0100 Subject: ASoC: tegra: SND_SOC_TEGRA_AUDIO_GRAPH_CARD should depend on SND_SOC_TEGRA Audio Graph Card based Tegra driver is only useful on NVIDIA Tegra SoCs. Hence add a dependency on SND_SOC_TEGRA, to prevent asking the user about this driver when configuring a kernel without Tegra sound support. Wrap all Tegra sound config options inside a big if/endif block, instead of just adding the dependency to the single config option that does not have it yet, to preventing similar future mistakes. Fixes: 202e2f7745437aa5 ("ASoC: tegra: Add audio graph based card driver") Signed-off-by: Geert Uytterhoeven Acked-by: Sameer Pujar Link: https://lore.kernel.org/r/20210129125915.2652952-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 6dc83ad8607a..a4e6760944d0 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -9,9 +9,10 @@ config SND_SOC_TEGRA help Say Y or M here if you want support for SoC audio on Tegra. +if SND_SOC_TEGRA + config SND_SOC_TEGRA20_AC97 tristate "Tegra20 AC97 interface" - depends on SND_SOC_TEGRA select SND_SOC_AC97_BUS select SND_SOC_TEGRA20_DAS help @@ -21,7 +22,6 @@ config SND_SOC_TEGRA20_AC97 config SND_SOC_TEGRA20_DAS tristate "Tegra20 DAS module" - depends on SND_SOC_TEGRA help Say Y or M if you want to add support for the Tegra20 DAS module. You will also need to select the individual machine drivers to @@ -29,7 +29,6 @@ config SND_SOC_TEGRA20_DAS config SND_SOC_TEGRA20_I2S tristate "Tegra20 I2S interface" - depends on SND_SOC_TEGRA select SND_SOC_TEGRA20_DAS help Say Y or M if you want to add support for codecs attached to the @@ -38,7 +37,6 @@ config SND_SOC_TEGRA20_I2S config SND_SOC_TEGRA20_SPDIF tristate "Tegra20 SPDIF interface" - depends on SND_SOC_TEGRA help Say Y or M if you want to add support for the Tegra20 SPDIF interface. You will also need to select the individual machine drivers to support @@ -46,7 +44,6 @@ config SND_SOC_TEGRA20_SPDIF config SND_SOC_TEGRA30_AHUB tristate "Tegra30 AHUB module" - depends on SND_SOC_TEGRA help Say Y or M if you want to add support for the Tegra30 AHUB module. You will also need to select the individual machine drivers to @@ -54,7 +51,6 @@ config SND_SOC_TEGRA30_AHUB config SND_SOC_TEGRA30_I2S tristate "Tegra30 I2S interface" - depends on SND_SOC_TEGRA select SND_SOC_TEGRA30_AHUB help Say Y or M if you want to add support for codecs attached to the @@ -63,7 +59,6 @@ config SND_SOC_TEGRA30_I2S config SND_SOC_TEGRA210_AHUB tristate "Tegra210 AHUB module" - depends on SND_SOC_TEGRA help Config to enable Audio Hub (AHUB) module, which comprises of a switch called Audio Crossbar (AXBAR) used to configure or modify @@ -73,7 +68,6 @@ config SND_SOC_TEGRA210_AHUB config SND_SOC_TEGRA210_DMIC tristate "Tegra210 DMIC module" - depends on SND_SOC_TEGRA help Config to enable the Digital MIC (DMIC) controller which is used to interface with Pulse Density Modulation (PDM) input devices. @@ -84,7 +78,6 @@ config SND_SOC_TEGRA210_DMIC config SND_SOC_TEGRA210_I2S tristate "Tegra210 I2S module" - depends on SND_SOC_TEGRA help Config to enable the Inter-IC Sound (I2S) Controller which implements full-duplex and bidirectional and single direction @@ -94,7 +87,6 @@ config SND_SOC_TEGRA210_I2S config SND_SOC_TEGRA186_DSPK tristate "Tegra186 DSPK module" - depends on SND_SOC_TEGRA help Config to enable the Digital Speaker Controller (DSPK) which converts the multi-bit Pulse Code Modulation (PCM) audio input to @@ -107,7 +99,6 @@ config SND_SOC_TEGRA186_DSPK config SND_SOC_TEGRA210_ADMAIF tristate "Tegra210 ADMAIF module" - depends on SND_SOC_TEGRA help Config to enable ADMAIF which is the interface between ADMA and Audio Hub (AHUB). Each ADMA channel that sends/receives data to/ @@ -128,7 +119,7 @@ config SND_SOC_TEGRA_AUDIO_GRAPH_CARD config SND_SOC_TEGRA_RT5640 tristate "SoC Audio support for Tegra boards using an RT5640 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_RT5640 help Say Y or M here if you want to add support for SoC audio on Tegra @@ -136,7 +127,7 @@ config SND_SOC_TEGRA_RT5640 config SND_SOC_TEGRA_WM8753 tristate "SoC Audio support for Tegra boards using a WM8753 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_WM8753 help Say Y or M here if you want to add support for SoC audio on Tegra @@ -144,7 +135,7 @@ config SND_SOC_TEGRA_WM8753 config SND_SOC_TEGRA_WM8903 tristate "SoC Audio support for Tegra boards using a WM8903 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_WM8903 help Say Y or M here if you want to add support for SoC audio on Tegra @@ -153,7 +144,7 @@ config SND_SOC_TEGRA_WM8903 config SND_SOC_TEGRA_WM9712 tristate "SoC Audio support for Tegra boards using a WM9712 codec" - depends on SND_SOC_TEGRA && GPIOLIB + depends on GPIOLIB select SND_SOC_TEGRA20_AC97 select SND_SOC_WM9712 help @@ -162,7 +153,7 @@ config SND_SOC_TEGRA_WM9712 config SND_SOC_TEGRA_TRIMSLICE tristate "SoC Audio support for TrimSlice board" - depends on SND_SOC_TEGRA && I2C + depends on I2C select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for SoC audio on the @@ -170,7 +161,7 @@ config SND_SOC_TEGRA_TRIMSLICE config SND_SOC_TEGRA_ALC5632 tristate "SoC Audio support for Tegra boards using an ALC5632 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_ALC5632 help Say Y or M here if you want to add support for SoC audio on the @@ -178,7 +169,7 @@ config SND_SOC_TEGRA_ALC5632 config SND_SOC_TEGRA_MAX98090 tristate "SoC Audio support for Tegra boards using a MAX98090 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_MAX98090 help Say Y or M here if you want to add support for SoC audio on Tegra @@ -186,7 +177,7 @@ config SND_SOC_TEGRA_MAX98090 config SND_SOC_TEGRA_RT5677 tristate "SoC Audio support for Tegra boards using a RT5677 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_RT5677 help Say Y or M here if you want to add support for SoC audio on Tegra @@ -194,9 +185,11 @@ config SND_SOC_TEGRA_RT5677 config SND_SOC_TEGRA_SGTL5000 tristate "SoC Audio support for Tegra boards using a SGTL5000 codec" - depends on SND_SOC_TEGRA && I2C && GPIOLIB + depends on I2C && GPIOLIB select SND_SOC_SGTL5000 help Say Y or M here if you want to add support for SoC audio on Tegra boards using the SGTL5000 codec, such as Apalis T30, Apalis TK1 or Colibri T30. + +endif -- cgit v1.2.3 From de5bfae2fd962a9da99f56382305ec7966a604b9 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sat, 23 Jan 2021 18:29:45 +0100 Subject: ASoC: cpcap: fix microphone timeslot mask The correct mask is 0x1f8 (Bit 3-8), but due to missing BIT() 0xf (Bit 0-3) was set instead. This means setting of CPCAP_BIT_MIC1_RX_TIMESLOT0 (Bit 3) still worked (part of both masks). On the other hand the code does not properly clear the other MIC timeslot bits. I think this is not a problem, since they are probably initialized to 0 and not touched by the driver anywhere else. But the mask also contains some wrong bits, that will be cleared. Bit 0 (CPCAP_BIT_SMB_CDC) should be safe, since the driver enforces it to be 0 anyways. Bit 1-2 are CPCAP_BIT_FS_INV and CPCAP_BIT_CLK_INV. This means enabling audio recording forces the codec into SND_SOC_DAIFMT_NB_NF mode, which is obviously bad. The bug probably remained undetected, because there are not many use cases for routing microphone to the CPU on platforms using cpcap and user base is small. I do remember having some issues with bad sound quality when testing voice recording back when I wrote the driver. It probably was this bug. Fixes: f6cdf2d3445d ("ASoC: cpcap: new codec") Reported-by: Dan Carpenter Signed-off-by: Sebastian Reichel Reviewed-by: Tony Lindgren Link: https://lore.kernel.org/r/20210123172945.3958622-1-sre@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/cpcap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index f046987ee4cd..c0425e3707d9 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1264,12 +1264,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream, if (direction == SNDRV_PCM_STREAM_CAPTURE) { mask = 0x0000; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2; - mask |= CPCAP_BIT_MIC2_TIMESLOT0; - mask |= CPCAP_BIT_MIC2_TIMESLOT1; - mask |= CPCAP_BIT_MIC2_TIMESLOT2; + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0); + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1); + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2); val = 0x0000; if (channels >= 2) val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0); -- cgit v1.2.3 From e8820dbddbcad7e91daacf7d42a49d1d04a4e489 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 1 Feb 2021 16:14:29 +0000 Subject: ASoC: codecs: add missing max_register in regmap config For some reason setting max_register was missed from regmap_config. Without this cat /sys/kernel/debug/regmap/sdw:0:217:2010:0:1/range actually throws below Warning. WARNING: CPU: 7 PID: 540 at drivers/base/regmap/regmap-debugfs.c:160 regmap_debugfs_get_dump_start.part.10+0x1e0/0x220 ... Call trace: regmap_debugfs_get_dump_start.part.10+0x1e0/0x220 regmap_reg_ranges_read_file+0xc0/0x2e0 full_proxy_read+0x64/0x98 vfs_read+0xa8/0x1e0 ksys_read+0x6c/0x100 __arm64_sys_read+0x1c/0x28 el0_svc_common.constprop.3+0x6c/0x190 do_el0_svc+0x24/0x90 el0_svc+0x14/0x20 el0_sync_handler+0x90/0xb8 el0_sync+0x158/0x180 ... Fixes: a0aab9e1404a ("ASoC: codecs: add wsa881x amplifier support") Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210201161429.28060-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wsa881x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 4530b74f5921..db87e07b11c9 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -640,6 +640,7 @@ static struct regmap_config wsa881x_regmap_config = { .val_bits = 8, .cache_type = REGCACHE_RBTREE, .reg_defaults = wsa881x_defaults, + .max_register = WSA881X_SPKR_STATUS3, .num_reg_defaults = ARRAY_SIZE(wsa881x_defaults), .volatile_reg = wsa881x_volatile_register, .readable_reg = wsa881x_readable_register, -- cgit v1.2.3 From 4841b8e6318a7f0ae57c4e5ec09032ea057c97a8 Mon Sep 17 00:00:00 2001 From: PeiSen Hou Date: Tue, 2 Feb 2021 10:30:22 +0100 Subject: ALSA: hda/realtek: modify EAPD in the ALC886 Modify 0x20 index 7 bit 5 to 1, make the 0x15 EAPD the same as 0x14. Signed-off-by: PeiSen Hou Cc: Link: https://lore.kernel.org/r/e62c5058957f48d8b8953e97135ff108@realtek.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 290645516313..52907506e16e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1905,6 +1905,7 @@ enum { ALC889_FIXUP_FRONT_HP_NO_PRESENCE, ALC889_FIXUP_VAIO_TT, ALC888_FIXUP_EEE1601, + ALC886_FIXUP_EAPD, ALC882_FIXUP_EAPD, ALC883_FIXUP_EAPD, ALC883_FIXUP_ACER_EAPD, @@ -2238,6 +2239,15 @@ static const struct hda_fixup alc882_fixups[] = { { } } }, + [ALC886_FIXUP_EAPD] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* change to EAPD mode */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 }, + { } + } + }, [ALC882_FIXUP_EAPD] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -2510,6 +2520,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), -- cgit v1.2.3 From da2a040ee7cfe1dd57d5bec7906cb979c5787a86 Mon Sep 17 00:00:00 2001 From: Jasmin Fazlic Date: Mon, 1 Feb 2021 15:28:52 +0100 Subject: ALSA: hdsp: hardware output loopback Output loopback is a feature where you can record what you hear. The HDSP series of the RME interfaces provides this functionality at the hardware level and this patch exposes controls to enable or disable it per output (playback) channel. This probably works on other cards but due to a lack of hardware it is only tested and enabled for the HDSP9632 card with this patch. Should this patch be accepted a separate patch will be posted to https://github.com/alsa-project/alsa-tools/tree/master/hdspmixer which adds "LPBK" buttons to each output in the playback strip for the user to be able to control this feature from the user land. Users from Windows tool TotalMixFX should be familiar with this. Signed-off-by: Jasmin Fazlic Link: https://lore.kernel.org/r/95cb3117-e85a-51a6-c2ce-bf736e70fc4c@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdsp.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index cea53a878c36..6d9029333a12 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -469,6 +469,7 @@ struct hdsp { unsigned char qs_out_channels; unsigned char ds_out_channels; unsigned char ss_out_channels; + u32 io_loopback; /* output loopback channel states*/ struct snd_dma_buffer capture_dma_buf; struct snd_dma_buffer playback_dma_buf; @@ -3253,6 +3254,60 @@ static const struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AnalogExtensionBoard); static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; + +static bool hdsp_loopback_get(struct hdsp *const hdsp, const u8 channel) +{ + return hdsp->io_loopback & (1 << channel); +} + +static int hdsp_loopback_set(struct hdsp *const hdsp, const u8 channel, const bool enable) +{ + if (hdsp_loopback_get(hdsp, channel) == enable) + return 0; + + hdsp->io_loopback ^= (1 << channel); + + hdsp_write(hdsp, HDSP_inputEnable + (4 * (hdsp->max_channels + channel)), enable); + + return 1; +} + +static int snd_hdsp_loopback_get(struct snd_kcontrol *const kcontrol, + struct snd_ctl_elem_value *const ucontrol) +{ + struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol); + const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id); + + if (channel >= hdsp->max_channels) + return -ENOENT; + + ucontrol->value.integer.value[0] = hdsp_loopback_get(hdsp, channel); + + return 0; +} + +static int snd_hdsp_loopback_put(struct snd_kcontrol *const kcontrol, + struct snd_ctl_elem_value *const ucontrol) +{ + struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol); + const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id); + const bool enable = ucontrol->value.integer.value[0] & 1; + + if (channel >= hdsp->max_channels) + return -ENOENT; + + return hdsp_loopback_set(hdsp, channel, enable); +} + +static struct snd_kcontrol_new snd_hdsp_loopback_control = { + .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, + .name = "Output Loopback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ctl_boolean_mono_info, + .get = snd_hdsp_loopback_get, + .put = snd_hdsp_loopback_put +}; + static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) { unsigned int idx; @@ -3297,6 +3352,17 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) } } + /* Output loopback controls for H9632 cards */ + if (hdsp->io_type == H9632) { + snd_hdsp_loopback_control.count = hdsp->max_channels; + kctl = snd_ctl_new1(&snd_hdsp_loopback_control, hdsp); + if (kctl == NULL) + return -ENOMEM; + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; + } + /* AEB control for H96xx card */ if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) @@ -4956,7 +5022,7 @@ static int snd_hdsp_enable_io (struct hdsp *hdsp) static void snd_hdsp_initialize_channels(struct hdsp *hdsp) { - int status, aebi_channels, aebo_channels; + int status, aebi_channels, aebo_channels, i; switch (hdsp->io_type) { case Digiface: @@ -4983,6 +5049,12 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels; hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels; hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels; + /* Disable loopback of output channels, as the set function + * only sets on a change we fake all bits (channels) as enabled. + */ + hdsp->io_loopback = 0xffffffff; + for (i = 0; i < hdsp->max_channels; ++i) + hdsp_loopback_set(hdsp, i, false); break; case Multiface: -- cgit v1.2.3 From 2d670ea2bd53a9792f453bb5b97cb8ef695988ff Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Wed, 27 Jan 2021 16:56:39 +0800 Subject: ALSA: jack: implement software jack injection via debugfs This change adds audio jack injection feature through debugfs, with this feature, we could validate alsa userspace changes by injecting plugin or plugout events to the non-phantom audio jacks. With this change, the sound core will build the folders $debugfs_mount_dir/sound/cardN if SND_DEBUG and DEBUG_FS are enabled. And if users also enable the SND_JACK_INJECTION_DEBUG, the jack injection nodes will be built in the folder cardN like below: $tree $debugfs_mount_dir/sound $debugfs_mount_dir/sound ├── card0 │   ├── HDMI_DP_pcm_10_Jack │   │   ├── jackin_inject │   │   ├── kctl_id │   │   ├── mask_bits │   │   ├── status │   │   ├── sw_inject_enable │   │   └── type ... │   └── HDMI_DP_pcm_9_Jack │   ├── jackin_inject │   ├── kctl_id │   ├── mask_bits │   ├── status │   ├── sw_inject_enable │   └── type └── card1 ├── HDMI_DP_pcm_5_Jack │   ├── jackin_inject │   ├── kctl_id │   ├── mask_bits │   ├── status │   ├── sw_inject_enable │   └── type ... ├── Headphone_Jack │   ├── jackin_inject │   ├── kctl_id │   ├── mask_bits │   ├── status │   ├── sw_inject_enable │   └── type └── Headset_Mic_Jack ├── jackin_inject ├── kctl_id ├── mask_bits ├── status ├── sw_inject_enable └── type The nodes kctl_id, mask_bits, status and type are read-only, users could check jack or jack_kctl's information through them. The nodes sw_inject_enable and jackin_inject are directly used for injection. The sw_inject_enable is read-write, users could check if software injection is enabled or not on this jack, and users could echo 1 or 0 to enable or disable software injection on this jack. Once the injection is enabled, the jack will not change by hardware events anymore, once the injection is disabled, the jack will restore the last reported hardware events to the jack. The jackin_inject is write-only, if the injection is enabled, users could echo 1 or 0 to this node to inject plugin or plugout events to this jack. For the detailed usage information on these nodes, please refer to Documentation/sound/designs/jack-injection.rst. Reviewed-by: Takashi Iwai Reviewed-by: Jaroslav Kysela Reviewed-by: Kai Vehmanen Signed-off-by: Hui Wang Link: https://lore.kernel.org/r/20210127085639.74954-2-hui.wang@canonical.com Signed-off-by: Takashi Iwai --- Documentation/sound/designs/index.rst | 1 + Documentation/sound/designs/jack-injection.rst | 166 ++++++++++++++ include/sound/core.h | 6 + include/sound/jack.h | 1 + sound/core/Kconfig | 9 + sound/core/init.c | 16 ++ sound/core/jack.c | 304 ++++++++++++++++++++++++- sound/core/sound.c | 13 ++ 8 files changed, 512 insertions(+), 4 deletions(-) create mode 100644 Documentation/sound/designs/jack-injection.rst diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst index f0749943ccb2..1eb08e7bae52 100644 --- a/Documentation/sound/designs/index.rst +++ b/Documentation/sound/designs/index.rst @@ -14,3 +14,4 @@ Designs and Implementations powersave oss-emulation seq-oss + jack-injection diff --git a/Documentation/sound/designs/jack-injection.rst b/Documentation/sound/designs/jack-injection.rst new file mode 100644 index 000000000000..f9790521523e --- /dev/null +++ b/Documentation/sound/designs/jack-injection.rst @@ -0,0 +1,166 @@ +============================ +ALSA Jack Software Injection +============================ + +Simple Introduction On Jack Injection +===================================== + +Here jack injection means users could inject plugin or plugout events +to the audio jacks through debugfs interface, it is helpful to +validate ALSA userspace changes. For example, we change the audio +profile switching code in the pulseaudio, and we want to verify if the +change works as expected and if the change introduce the regression, +in this case, we could inject plugin or plugout events to an audio +jack or to some audio jacks, we don't need to physically access the +machine and plug/unplug physical devices to the audio jack. + +In this design, an audio jack doesn't equal to a physical audio jack. +Sometimes a physical audio jack contains multi functions, and the +ALSA driver creates multi ``jack_kctl`` for a ``snd_jack``, here the +``snd_jack`` represents a physical audio jack and the ``jack_kctl`` +represents a function, for example a physical jack has two functions: +headphone and mic_in, the ALSA ASoC driver will build 2 ``jack_kctl`` +for this jack. The jack injection is implemented based on the +``jack_kctl`` instead of ``snd_jack``. + +To inject events to audio jacks, we need to enable the jack injection +via ``sw_inject_enable`` first, once it is enabled, this jack will not +change the state by hardware events anymore, we could inject plugin or +plugout events via ``jackin_inject`` and check the jack state via +``status``, after we finish our test, we need to disable the jack +injection via ``sw_inject_enable`` too, once it is disabled, the jack +state will be restored according to the last reported hardware events +and will change by future hardware events. + +The Layout of Jack Injection Interface +====================================== + +If users enable the SND_JACK_INJECTION_DEBUG in the kernel, the audio +jack injection interface will be created as below: +:: + + $debugfs_mount_dir/sound + |-- card0 + |-- |-- HDMI_DP_pcm_10_Jack + |-- |-- |-- jackin_inject + |-- |-- |-- kctl_id + |-- |-- |-- mask_bits + |-- |-- |-- status + |-- |-- |-- sw_inject_enable + |-- |-- |-- type + ... + |-- |-- HDMI_DP_pcm_9_Jack + |-- |-- jackin_inject + |-- |-- kctl_id + |-- |-- mask_bits + |-- |-- status + |-- |-- sw_inject_enable + |-- |-- type + |-- card1 + |-- HDMI_DP_pcm_5_Jack + |-- |-- jackin_inject + |-- |-- kctl_id + |-- |-- mask_bits + |-- |-- status + |-- |-- sw_inject_enable + |-- |-- type + ... + |-- Headphone_Jack + |-- |-- jackin_inject + |-- |-- kctl_id + |-- |-- mask_bits + |-- |-- status + |-- |-- sw_inject_enable + |-- |-- type + |-- Headset_Mic_Jack + |-- jackin_inject + |-- kctl_id + |-- mask_bits + |-- status + |-- sw_inject_enable + |-- type + +The Explanation Of The Nodes +====================================== + +kctl_id + read-only, get jack_kctl->kctl's id + :: + + sound/card1/Headphone_Jack# cat kctl_id + Headphone Jack + +mask_bits + read-only, get jack_kctl's supported events mask_bits + :: + + sound/card1/Headphone_Jack# cat mask_bits + 0x0001 HEADPHONE(0x0001) + +status + read-only, get jack_kctl's current status + +- headphone unplugged: + + :: + + sound/card1/Headphone_Jack# cat status + Unplugged + +- headphone plugged: + + :: + + sound/card1/Headphone_Jack# cat status + Plugged + +type + read-only, get snd_jack's supported events from type (all supported events on the physical audio jack) + :: + + sound/card1/Headphone_Jack# cat type + 0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000) + +sw_inject_enable + read-write, enable or disable injection + +- injection disabled: + + :: + + sound/card1/Headphone_Jack# cat sw_inject_enable + Jack: Headphone Jack Inject Enabled: 0 + +- injection enabled: + + :: + + sound/card1/Headphone_Jack# cat sw_inject_enable + Jack: Headphone Jack Inject Enabled: 1 + +- to enable jack injection: + + :: + + sound/card1/Headphone_Jack# echo 1 > sw_inject_enable + +- to disable jack injection: + + :: + + sound/card1/Headphone_Jack# echo 0 > sw_inject_enable + +jackin_inject + write-only, inject plugin or plugout + +- to inject plugin: + + :: + + sound/card1/Headphone_Jack# echo 1 > jackin_inject + +- to inject plugout: + + :: + + sound/card1/Headphone_Jack# echo 0 > jackin_inject diff --git a/include/sound/core.h b/include/sound/core.h index 0462c577d7a3..2e24f194ef70 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -122,6 +122,9 @@ struct snd_card { size_t total_pcm_alloc_bytes; /* total amount of allocated buffers */ struct mutex memory_mutex; /* protection for the above */ +#ifdef CONFIG_SND_DEBUG + struct dentry *debugfs_root; /* debugfs root for card */ +#endif #ifdef CONFIG_PM unsigned int power_state; /* power state */ @@ -180,6 +183,9 @@ static inline struct device *snd_card_get_device_link(struct snd_card *card) extern int snd_major; extern int snd_ecards_limit; extern struct class *sound_class; +#ifdef CONFIG_SND_DEBUG +extern struct dentry *sound_debugfs_root; +#endif void snd_request_card(int card); diff --git a/include/sound/jack.h b/include/sound/jack.h index 9eb2b5ec1ec4..1181f536557e 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -67,6 +67,7 @@ struct snd_jack { char name[100]; unsigned int key[6]; /* Keep in sync with definitions above */ #endif /* CONFIG_SND_JACK_INPUT_DEV */ + int hw_status_cache; void *private_data; void (*private_free)(struct snd_jack *); }; diff --git a/sound/core/Kconfig b/sound/core/Kconfig index d4554f376160..a4050f87f230 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -187,6 +187,15 @@ config SND_CTL_VALIDATION from the driver are in the proper ranges or the check of the invalid access at out-of-array areas. +config SND_JACK_INJECTION_DEBUG + bool "Sound jack injection interface via debugfs" + depends on SND_JACK && SND_DEBUG && DEBUG_FS + help + This option can be used to enable or disable sound jack + software injection. + Say Y if you are debugging via jack injection interface. + If unsure select "N". + config SND_VMASTER bool diff --git a/sound/core/init.c b/sound/core/init.c index 56834febc7a4..d4e78b176793 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,9 @@ int snd_card_new(struct device *parent, int idx, const char *xid, { struct snd_card *card; int err; +#ifdef CONFIG_SND_DEBUG + char name[8]; +#endif if (snd_BUG_ON(!card_ret)) return -EINVAL; @@ -244,6 +248,12 @@ int snd_card_new(struct device *parent, int idx, const char *xid, dev_err(parent, "unable to create card info\n"); goto __error_ctl; } + +#ifdef CONFIG_SND_DEBUG + sprintf(name, "card%d", idx); + card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root); +#endif + *card_ret = card; return 0; @@ -526,6 +536,12 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ wait_for_completion(&released); + +#ifdef CONFIG_SND_DEBUG + debugfs_remove(card->debugfs_root); + card->debugfs_root = NULL; +#endif + return 0; } EXPORT_SYMBOL(snd_card_free); diff --git a/sound/core/jack.c b/sound/core/jack.c index 503c8af79d55..32350c6aba84 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -16,6 +19,11 @@ struct snd_jack_kctl { struct snd_kcontrol *kctl; struct list_head list; /* list of controls belong to the same jack */ unsigned int mask_bits; /* only masked status bits are reported via kctl */ + struct snd_jack *jack; /* pointer to struct snd_jack */ + bool sw_inject_enable; /* allow to inject plug event via debugfs */ +#ifdef CONFIG_SND_JACK_INJECTION_DEBUG + struct dentry *jack_debugfs_root; /* jack_kctl debugfs root */ +#endif }; #ifdef CONFIG_SND_JACK_INPUT_DEV @@ -109,12 +117,291 @@ static int snd_jack_dev_register(struct snd_device *device) } #endif /* CONFIG_SND_JACK_INPUT_DEV */ +#ifdef CONFIG_SND_JACK_INJECTION_DEBUG +static void snd_jack_inject_report(struct snd_jack_kctl *jack_kctl, int status) +{ + struct snd_jack *jack; +#ifdef CONFIG_SND_JACK_INPUT_DEV + int i; +#endif + if (!jack_kctl) + return; + + jack = jack_kctl->jack; + + if (jack_kctl->sw_inject_enable) + snd_kctl_jack_report(jack->card, jack_kctl->kctl, + status & jack_kctl->mask_bits); + +#ifdef CONFIG_SND_JACK_INPUT_DEV + if (!jack->input_dev) + return; + + for (i = 0; i < ARRAY_SIZE(jack->key); i++) { + int testbit = ((SND_JACK_BTN_0 >> i) & jack_kctl->mask_bits); + + if (jack->type & testbit) + input_report_key(jack->input_dev, jack->key[i], + status & testbit); + } + + for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { + int testbit = ((1 << i) & jack_kctl->mask_bits); + + if (jack->type & testbit) + input_report_switch(jack->input_dev, + jack_switch_types[i], + status & testbit); + } + + input_sync(jack->input_dev); +#endif /* CONFIG_SND_JACK_INPUT_DEV */ +} + +static ssize_t sw_inject_enable_read(struct file *file, + char __user *to, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + int len, ret; + char buf[128]; + + len = scnprintf(buf, sizeof(buf), "%s: %s\t\t%s: %i\n", "Jack", jack_kctl->kctl->id.name, + "Inject Enabled", jack_kctl->sw_inject_enable); + ret = simple_read_from_buffer(to, count, ppos, buf, len); + + return ret; +} + +static ssize_t sw_inject_enable_write(struct file *file, + const char __user *from, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + int ret, err; + unsigned long enable; + char buf[8] = { 0 }; + + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count); + err = kstrtoul(buf, 0, &enable); + if (err) + return err; + + if (jack_kctl->sw_inject_enable == (!!enable)) + return ret; + + jack_kctl->sw_inject_enable = !!enable; + + if (!jack_kctl->sw_inject_enable) + snd_jack_report(jack_kctl->jack, jack_kctl->jack->hw_status_cache); + + return ret; +} + +static ssize_t jackin_inject_write(struct file *file, + const char __user *from, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + int ret, err; + unsigned long enable; + char buf[8] = { 0 }; + + if (!jack_kctl->sw_inject_enable) + return -EINVAL; + + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count); + err = kstrtoul(buf, 0, &enable); + if (err) + return err; + + snd_jack_inject_report(jack_kctl, !!enable ? jack_kctl->mask_bits : 0); + + return ret; +} + +static ssize_t jack_kctl_id_read(struct file *file, + char __user *to, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + char buf[64]; + int len, ret; + + len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->id.name); + ret = simple_read_from_buffer(to, count, ppos, buf, len); + + return ret; +} + +/* the bit definition is aligned with snd_jack_types in jack.h */ +static const char * const jack_events_name[] = { + "HEADPHONE(0x0001)", "MICROPHONE(0x0002)", "LINEOUT(0x0004)", + "MECHANICAL(0x0008)", "VIDEOOUT(0x0010)", "LINEIN(0x0020)", + "", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)", "BTN_3(0x0800)", + "BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)", "", +}; + +/* the recommended buffer size is 256 */ +static int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size) +{ + int i; + + scnprintf(buf, buf_size, "0x%04x", mask_bits); + + for (i = 0; i < ARRAY_SIZE(jack_events_name); i++) + if (mask_bits & (1 << i)) { + strlcat(buf, " ", buf_size); + strlcat(buf, jack_events_name[i], buf_size); + } + strlcat(buf, "\n", buf_size); + + return strlen(buf); +} + +static ssize_t jack_kctl_mask_bits_read(struct file *file, + char __user *to, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + char buf[256]; + int len, ret; + + len = parse_mask_bits(jack_kctl->mask_bits, buf, sizeof(buf)); + ret = simple_read_from_buffer(to, count, ppos, buf, len); + + return ret; +} + +static ssize_t jack_kctl_status_read(struct file *file, + char __user *to, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + char buf[16]; + int len, ret; + + len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->private_value ? + "Plugged" : "Unplugged"); + ret = simple_read_from_buffer(to, count, ppos, buf, len); + + return ret; +} + +#ifdef CONFIG_SND_JACK_INPUT_DEV +static ssize_t jack_type_read(struct file *file, + char __user *to, size_t count, loff_t *ppos) +{ + struct snd_jack_kctl *jack_kctl = file->private_data; + char buf[256]; + int len, ret; + + len = parse_mask_bits(jack_kctl->jack->type, buf, sizeof(buf)); + ret = simple_read_from_buffer(to, count, ppos, buf, len); + + return ret; +} + +static const struct file_operations jack_type_fops = { + .open = simple_open, + .read = jack_type_read, + .llseek = default_llseek, +}; +#endif + +static const struct file_operations sw_inject_enable_fops = { + .open = simple_open, + .read = sw_inject_enable_read, + .write = sw_inject_enable_write, + .llseek = default_llseek, +}; + +static const struct file_operations jackin_inject_fops = { + .open = simple_open, + .write = jackin_inject_write, + .llseek = default_llseek, +}; + +static const struct file_operations jack_kctl_id_fops = { + .open = simple_open, + .read = jack_kctl_id_read, + .llseek = default_llseek, +}; + +static const struct file_operations jack_kctl_mask_bits_fops = { + .open = simple_open, + .read = jack_kctl_mask_bits_read, + .llseek = default_llseek, +}; + +static const struct file_operations jack_kctl_status_fops = { + .open = simple_open, + .read = jack_kctl_status_read, + .llseek = default_llseek, +}; + +static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack, + struct snd_jack_kctl *jack_kctl) +{ + char *tname; + int i; + + /* Don't create injection interface for Phantom jacks */ + if (strstr(jack_kctl->kctl->id.name, "Phantom")) + return 0; + + tname = kstrdup(jack_kctl->kctl->id.name, GFP_KERNEL); + if (!tname) + return -ENOMEM; + + /* replace the chars which are not suitable for folder's name with _ */ + for (i = 0; tname[i]; i++) + if (!isalnum(tname[i])) + tname[i] = '_'; + + jack_kctl->jack_debugfs_root = debugfs_create_dir(tname, jack->card->debugfs_root); + kfree(tname); + + debugfs_create_file("sw_inject_enable", 0644, jack_kctl->jack_debugfs_root, jack_kctl, + &sw_inject_enable_fops); + + debugfs_create_file("jackin_inject", 0200, jack_kctl->jack_debugfs_root, jack_kctl, + &jackin_inject_fops); + + debugfs_create_file("kctl_id", 0444, jack_kctl->jack_debugfs_root, jack_kctl, + &jack_kctl_id_fops); + + debugfs_create_file("mask_bits", 0444, jack_kctl->jack_debugfs_root, jack_kctl, + &jack_kctl_mask_bits_fops); + + debugfs_create_file("status", 0444, jack_kctl->jack_debugfs_root, jack_kctl, + &jack_kctl_status_fops); + +#ifdef CONFIG_SND_JACK_INPUT_DEV + debugfs_create_file("type", 0444, jack_kctl->jack_debugfs_root, jack_kctl, + &jack_type_fops); +#endif + return 0; +} + +static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl) +{ + debugfs_remove(jack_kctl->jack_debugfs_root); + jack_kctl->jack_debugfs_root = NULL; +} +#else /* CONFIG_SND_JACK_INJECTION_DEBUG */ +static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack, + struct snd_jack_kctl *jack_kctl) +{ + return 0; +} + +static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl) +{ +} +#endif /* CONFIG_SND_JACK_INJECTION_DEBUG */ + static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl) { struct snd_jack_kctl *jack_kctl; jack_kctl = kctl->private_data; if (jack_kctl) { + snd_jack_debugfs_clear_inject_node(jack_kctl); list_del(&jack_kctl->list); kfree(jack_kctl); } @@ -122,7 +409,9 @@ static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl) static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl) { + jack_kctl->jack = jack; list_add_tail(&jack_kctl->list, &jack->kctl_list); + snd_jack_debugfs_add_inject_node(jack, jack_kctl); } static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask) @@ -340,6 +629,7 @@ EXPORT_SYMBOL(snd_jack_set_key); void snd_jack_report(struct snd_jack *jack, int status) { struct snd_jack_kctl *jack_kctl; + unsigned int mask_bits = 0; #ifdef CONFIG_SND_JACK_INPUT_DEV int i; #endif @@ -347,16 +637,21 @@ void snd_jack_report(struct snd_jack *jack, int status) if (!jack) return; + jack->hw_status_cache = status; + list_for_each_entry(jack_kctl, &jack->kctl_list, list) - snd_kctl_jack_report(jack->card, jack_kctl->kctl, - status & jack_kctl->mask_bits); + if (jack_kctl->sw_inject_enable) + mask_bits |= jack_kctl->mask_bits; + else + snd_kctl_jack_report(jack->card, jack_kctl->kctl, + status & jack_kctl->mask_bits); #ifdef CONFIG_SND_JACK_INPUT_DEV if (!jack->input_dev) return; for (i = 0; i < ARRAY_SIZE(jack->key); i++) { - int testbit = SND_JACK_BTN_0 >> i; + int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits); if (jack->type & testbit) input_report_key(jack->input_dev, jack->key[i], @@ -364,7 +659,8 @@ void snd_jack_report(struct snd_jack *jack, int status) } for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { - int testbit = 1 << i; + int testbit = ((1 << i) & ~mask_bits); + if (jack->type & testbit) input_report_switch(jack->input_dev, jack_switch_types[i], diff --git a/sound/core/sound.c b/sound/core/sound.c index b75f78f2c4b8..2f759febe365 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,11 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); int snd_ecards_limit; EXPORT_SYMBOL(snd_ecards_limit); +#ifdef CONFIG_SND_DEBUG +struct dentry *sound_debugfs_root; +EXPORT_SYMBOL_GPL(sound_debugfs_root); +#endif + static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; static DEFINE_MUTEX(sound_mutex); @@ -395,6 +401,10 @@ static int __init alsa_sound_init(void) unregister_chrdev(major, "alsa"); return -ENOMEM; } + +#ifdef CONFIG_SND_DEBUG + sound_debugfs_root = debugfs_create_dir("sound", NULL); +#endif #ifndef MODULE pr_info("Advanced Linux Sound Architecture Driver Initialized.\n"); #endif @@ -403,6 +413,9 @@ static int __init alsa_sound_init(void) static void __exit alsa_sound_exit(void) { +#ifdef CONFIG_SND_DEBUG + debugfs_remove(sound_debugfs_root); +#endif snd_info_done(); unregister_chrdev(major, "alsa"); } -- cgit v1.2.3 From e1711b1f9dfb712aa72ea25e03e0a3f6ef16c4fb Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 1 Feb 2021 11:23:45 +0200 Subject: ASoC: SOF: add be_hw_params_fixup() for ALH Fixup BE DAI links channel count to match topology settings. Normally the channel count of BE is equal to FE's so we don't have any issue. For some cases like DSM with 2-channel FE and 4-channel BE the mismatch of BE and topology will result in audio issues. Signed-off-by: Rander Wang Reviewed-by: Keyon Jie Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210201092345.1214232-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 0dc39fbcd81d..61c3fe17342d 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -707,7 +707,12 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa } break; case SOF_DAI_INTEL_ALH: - /* do nothing for ALH dai_link */ + /* + * Dai could run with different channel count compared with + * front end, so get dai channel count from topology + */ + channels->min = dai->dai_config->alh.channels; + channels->max = dai->dai_config->alh.channels; break; case SOF_DAI_IMX_ESAI: rate->min = dai->dai_config->esai.fsync_rate; -- cgit v1.2.3 From 1ecebae4733d8971059f0c514741868ce19f5d24 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Tue, 2 Feb 2021 11:35:57 +0800 Subject: ASoC: mt6359: reduce log verbosity for optional DT properties DT properties "dmic-mode" and "mic-type-X" are optional. Reduces the log verbosity and changes the message a bit to avoid misleading. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210202033557.1621029-1-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c index 6de0d744fa9e..6f4b1da52082 100644 --- a/sound/soc/codecs/mt6359.c +++ b/sound/soc/codecs/mt6359.c @@ -2754,7 +2754,8 @@ static int mt6359_parse_dt(struct mt6359_priv *priv) ret = of_property_read_u32(np, "mediatek,dmic-mode", &priv->dmic_one_wire_mode); if (ret) { - dev_warn(priv->dev, "%s() failed to read dmic-mode\n", + dev_info(priv->dev, + "%s() failed to read dmic-mode, use default (0)\n", __func__); priv->dmic_one_wire_mode = 0; } @@ -2762,24 +2763,27 @@ static int mt6359_parse_dt(struct mt6359_priv *priv) ret = of_property_read_u32(np, "mediatek,mic-type-0", &priv->mux_select[MUX_MIC_TYPE_0]); if (ret) { - dev_warn(priv->dev, "%s() failed to read mic-type-0\n", - __func__); + dev_info(priv->dev, + "%s() failed to read mic-type-0, use default (%d)\n", + __func__, MIC_TYPE_MUX_IDLE); priv->mux_select[MUX_MIC_TYPE_0] = MIC_TYPE_MUX_IDLE; } ret = of_property_read_u32(np, "mediatek,mic-type-1", &priv->mux_select[MUX_MIC_TYPE_1]); if (ret) { - dev_warn(priv->dev, "%s() failed to read mic-type-1\n", - __func__); + dev_info(priv->dev, + "%s() failed to read mic-type-1, use default (%d)\n", + __func__, MIC_TYPE_MUX_IDLE); priv->mux_select[MUX_MIC_TYPE_1] = MIC_TYPE_MUX_IDLE; } ret = of_property_read_u32(np, "mediatek,mic-type-2", &priv->mux_select[MUX_MIC_TYPE_2]); if (ret) { - dev_warn(priv->dev, "%s() failed to read mic-type-2\n", - __func__); + dev_info(priv->dev, + "%s() failed to read mic-type-2, use default (%d)\n", + __func__, MIC_TYPE_MUX_IDLE); priv->mux_select[MUX_MIC_TYPE_2] = MIC_TYPE_MUX_IDLE; } -- cgit v1.2.3 From 68be8ed6a4622d4eb6cf7632bc7cb78464c83c78 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Thu, 28 Jan 2021 19:27:14 +0800 Subject: ASoC: fsl_spdif: Utilize the defined parameter to clear code Utilize the defined parameter 'dev' to make the code cleaner. Signed-off-by: Tang Bin Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20210128112714.16324-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index b4d3b04694bf..174e558224d8 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1255,7 +1255,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, for (i = 0; i < STC_TXCLK_SRC_MAX; i++) { sprintf(tmp, "rxtx%d", i); - clk = devm_clk_get(&pdev->dev, tmp); + clk = devm_clk_get(dev, tmp); if (IS_ERR(clk)) { dev_err(dev, "no rxtx%d clock in devicetree\n", i); return PTR_ERR(clk); @@ -1277,14 +1277,14 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, break; } - dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate\n", + dev_dbg(dev, "use rxtx%d as tx clock source for %dHz sample rate\n", spdif_priv->txclk_src[index], rate[index]); - dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n", + dev_dbg(dev, "use txclk df %d for %dHz sample rate\n", spdif_priv->txclk_df[index], rate[index]); if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk)) - dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n", + dev_dbg(dev, "use sysclk df %d for %dHz sample rate\n", spdif_priv->sysclk_df[index], rate[index]); - dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n", + dev_dbg(dev, "the best rate for %dHz sample rate is %dHz\n", rate[index], spdif_priv->txrate[index]); return 0; -- cgit v1.2.3 From be6be67e135e59fb176b1e2e9d47a7436fb161d1 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Tue, 2 Feb 2021 17:31:23 +0100 Subject: ASoC: topology: KUnit: Convert from cpu to data format When creating topology templates and overriding data in specific test cases it should be done with cpu_to_le32 macro, so we operate on correct data on all architectures, as topology parser use le32_to_cpu to parse data from structures. Reported-by: kernel test robot Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20210202163123.3942040-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology-test.c | 66 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c index 36e2a3486dbf..ae3968161509 100644 --- a/sound/soc/soc-topology-test.c +++ b/sound/soc/soc-topology-test.c @@ -121,19 +121,19 @@ struct tplg_tmpl_001 { static struct tplg_tmpl_001 tplg_tmpl_empty = { .header = { - .magic = SND_SOC_TPLG_MAGIC, - .abi = 5, + .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), + .abi = cpu_to_le32(5), .version = 0, - .type = SND_SOC_TPLG_TYPE_MANIFEST, - .size = sizeof(struct snd_soc_tplg_hdr), + .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), + .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), .vendor_type = 0, - .payload_size = sizeof(struct snd_soc_tplg_manifest), + .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), .index = 0, - .count = 1, + .count = cpu_to_le32(1), }, .manifest = { - .size = sizeof(struct snd_soc_tplg_manifest), + .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), /* rest of fields is 0 */ }, }; @@ -149,60 +149,60 @@ struct tplg_tmpl_002 { static struct tplg_tmpl_002 tplg_tmpl_with_pcm = { .header = { - .magic = SND_SOC_TPLG_MAGIC, - .abi = 5, + .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), + .abi = cpu_to_le32(5), .version = 0, - .type = SND_SOC_TPLG_TYPE_MANIFEST, - .size = sizeof(struct snd_soc_tplg_hdr), + .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), + .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), .vendor_type = 0, - .payload_size = sizeof(struct snd_soc_tplg_manifest), + .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), .index = 0, - .count = 1, + .count = cpu_to_le32(1), }, .manifest = { - .size = sizeof(struct snd_soc_tplg_manifest), - .pcm_elems = 1, + .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), + .pcm_elems = cpu_to_le32(1), /* rest of fields is 0 */ }, .pcm_header = { - .magic = SND_SOC_TPLG_MAGIC, - .abi = 5, + .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), + .abi = cpu_to_le32(5), .version = 0, - .type = SND_SOC_TPLG_TYPE_PCM, - .size = sizeof(struct snd_soc_tplg_hdr), + .type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM), + .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), .vendor_type = 0, - .payload_size = sizeof(struct snd_soc_tplg_pcm), + .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), .index = 0, - .count = 1, + .count = cpu_to_le32(1), }, .pcm = { - .size = sizeof(struct snd_soc_tplg_pcm), + .size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), .pcm_name = "KUNIT Audio", .dai_name = "kunit-audio-dai", .pcm_id = 0, .dai_id = 0, - .playback = 1, - .capture = 1, + .playback = cpu_to_le32(1), + .capture = cpu_to_le32(1), .compress = 0, .stream = { [0] = { - .channels = 2, + .channels = cpu_to_le32(2), }, [1] = { - .channels = 2, + .channels = cpu_to_le32(2), }, }, .num_streams = 0, .caps = { [0] = { .name = "kunit-audio-playback", - .channels_min = 2, - .channels_max = 2, + .channels_min = cpu_to_le32(2), + .channels_max = cpu_to_le32(2), }, [1] = { .name = "kunit-audio-capture", - .channels_min = 2, - .channels_max = 2, + .channels_min = cpu_to_le32(2), + .channels_max = cpu_to_le32(2), }, }, .flag_mask = 0, @@ -460,7 +460,7 @@ static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test) * override abi * any value != magic number is wrong */ - data->header.magic = SND_SOC_TPLG_MAGIC + 1; + data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1); kunit_comp->fw.data = (u8 *)data; kunit_comp->fw.size = size; @@ -516,7 +516,7 @@ static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test) * override abi * any value != accepted range is wrong */ - data->header.abi = SND_SOC_TPLG_ABI_VERSION + 1; + data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1); kunit_comp->fw.data = (u8 *)data; kunit_comp->fw.size = size; @@ -572,7 +572,7 @@ static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test) * override size * any value != struct size is wrong */ - data->header.size = sizeof(struct snd_soc_tplg_hdr) + 1; + data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1); kunit_comp->fw.data = (u8 *)data; kunit_comp->fw.size = size; -- cgit v1.2.3 From e681b1a6d706b4e54c3847bb822531b4660234f3 Mon Sep 17 00:00:00 2001 From: Srinivasa Rao Mandadapu Date: Tue, 2 Feb 2021 11:57:27 +0530 Subject: ASoC: qcom: Fix typo error in HDMI regmap config callbacks Had a typo in lpass platform driver that resulted in crash during suspend/resume with an HDMI dongle connected. The regmap read/write/volatile regesters validation callbacks in lpass-cpu were using MI2S rdma_channels count instead of hdmi_rdma_channels. This typo error causing to read registers from the regmap beyond the length of the mapping created by ioremap(). This fix avoids the need for reducing number hdmi_rdma_channels, which is done in commit 7dfe20ee92f6 ("ASoC: qcom: Fix number of HDMI RDMA channels on sc7180"). So reverting the same. Fixes: 7cb37b7bd0d3c ("ASoC: qcom: Add support for lpass hdmi driver") Signed-off-by: Srinivasa Rao Mandadapu Link: https://lore.kernel.org/r/20210202062727.22469-1-srivasam@codeaurora.org Reviewed-by: Stephen Boyd Tested-by: Stephen Boyd Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 8 ++++---- sound/soc/qcom/lpass-sc7180.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 73ca24c0a08b..8e5415c9234f 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -594,7 +594,7 @@ static bool lpass_hdmi_regmap_writeable(struct device *dev, unsigned int reg) return true; } - for (i = 0; i < v->rdma_channels; ++i) { + for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACTL_REG(v, i)) return true; if (reg == LPAIF_HDMI_RDMABASE_REG(v, i)) @@ -640,7 +640,7 @@ static bool lpass_hdmi_regmap_readable(struct device *dev, unsigned int reg) if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v)) return true; - for (i = 0; i < v->rdma_channels; ++i) { + for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACTL_REG(v, i)) return true; if (reg == LPAIF_HDMI_RDMABASE_REG(v, i)) @@ -667,7 +667,7 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg) if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v)) return true; - for (i = 0; i < v->rdma_channels; ++i) { + for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACURR_REG(v, i)) return true; } @@ -817,7 +817,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) } lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant, - variant->hdmi_rdma_channels); + variant->hdmi_rdma_channels - 1); drvdata->hdmiif_map = devm_regmap_init_mmio(dev, drvdata->hdmiif, &lpass_hdmi_regmap_config); if (IS_ERR(drvdata->hdmiif_map)) { diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c index 735c9dac28f2..8c168d3c589e 100644 --- a/sound/soc/qcom/lpass-sc7180.c +++ b/sound/soc/qcom/lpass-sc7180.c @@ -171,7 +171,7 @@ static struct lpass_variant sc7180_data = { .rdma_channels = 5, .hdmi_rdma_reg_base = 0x64000, .hdmi_rdma_reg_stride = 0x1000, - .hdmi_rdma_channels = 3, + .hdmi_rdma_channels = 4, .dmactl_audif_start = 1, .wrdma_reg_base = 0x18000, .wrdma_reg_stride = 0x1000, -- cgit v1.2.3 From 3b85f5fc75d564a9eb4171dcb6b8687b080cd4d5 Mon Sep 17 00:00:00 2001 From: Olivia Mackintosh Date: Tue, 2 Feb 2021 13:42:26 +0000 Subject: ALSA: usb-audio: Add DJM450 to Pioneer format quirk Like the DJM-750, ensure that the format control message is passed to the device when opening a stream. It seems as though fmt->sync_ep is not always set when this function is called hence the passing of the value at the call site. If this can be fixed, fmt->sync_up should be used as the wvalue. There doesn't seem to be a "cpu_to_le24" type function defined hence for the open code but I did see a similar thing done in Bluez lib. Perhaps we can get these definitions defined in byteorder.h. See hci_cpu_to_le24 in include/net/bluetooth/hci.h:2543 for similar usage. Signed-off-by: Olivia Mackintosh Link: https://lore.kernel.org/r/20210202134225.3217-2-livvy@base.nu Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index e196e364cef1..9ba4682ebc48 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1470,6 +1470,23 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs, subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0; } +static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs, + u16 windex) +{ + unsigned int cur_rate = subs->data_endpoint->cur_rate; + u8 sr[3]; + // Convert to little endian + sr[0] = cur_rate & 0xff; + sr[1] = (cur_rate >> 8) & 0xff; + sr[2] = (cur_rate >> 16) & 0xff; + usb_set_interface(subs->dev, 0, 1); + // we should derive windex from fmt-sync_ep but it's not set + snd_usb_ctl_msg(subs->stream->chip->dev, + usb_rcvctrlpipe(subs->stream->chip->dev, 0), + 0x01, 0x22, 0x0100, windex, &sr, 0x0003); + return 0; +} + void snd_usb_set_format_quirk(struct snd_usb_substream *subs, const struct audioformat *fmt) { @@ -1483,6 +1500,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */ subs->stream_offset_adj = 2; break; + case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */ + pioneer_djm_set_format_quirk(subs, 0x0082); + break; } } -- cgit v1.2.3 From 9119e5661eab2c56a96b936cde49c6740dc49ff9 Mon Sep 17 00:00:00 2001 From: Olivia Mackintosh Date: Tue, 2 Feb 2021 13:42:28 +0000 Subject: ALSA: usb-audio: Add DJM-450 to the quirks table As with most Pioneer devices, the device descriptor is vendor specific and as such, the number of channels, the PCM format, endpoints and sample rate need to be specified. This device has 8 inputs and 8 outputs and a sample rate of 48000 only. The PCM format is S24_3LE like other devices. There seems to be an appetite for reducing duplication amongs these Pioneer patches but again, I feel this is a step to be taken after support has been added as it's not completely clear where the commonalities are. Signed-off-by: Olivia Mackintosh Link: https://lore.kernel.org/r/20210202134225.3217-3-livvy@base.nu Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 93d55cd1a5a4..1165a5ac60f2 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3817,6 +3817,63 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, +{ + /* + * Pioneer DJ DJM-450 + * PCM is 8 channels out @ 48 fixed (endpoint 0x01) + * and 8 channels in @ 48 fixed (endpoint 0x82). + */ + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0013), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, // outputs + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 48000 } + } + }, + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, // inputs + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x82, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_IMPLICIT_FB, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 48000 } + } + }, + { + .ifnum = -1 + } + } + } +}, #undef USB_DEVICE_VENDOR_SPEC #undef USB_AUDIO_DEVICE -- cgit v1.2.3 From 016f94feb57d73b2c375f1ccd665bb546d401162 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 Feb 2021 10:27:44 +0100 Subject: ALSA: hda: Drop power save deny list entry for Clevo W65_67SB As the runtime PM issue was addressed by the recent fix 4961167bf748 ("ALSA: hda/via: Apply the workaround generically for Clevo machines") for VIA codecs, we need no longer to keep the Clevo device off from the power saving as default. Drop the deny list entry accordingly. Depends: 4961167bf748 ("ALSA: hda/via: Apply the workaround generically for Clevo machines") Link: https://lore.kernel.org/r/20210202092744.20321-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6c439f377a7e..801c5dd25707 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2217,8 +2217,6 @@ static const struct snd_pci_quirk power_save_denylist[] = { /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0), /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ - SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0), - /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0), /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */ -- cgit v1.2.3 From 3c4ab49ec59b94651dea7c7b0104c781c79c62b5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 Feb 2021 23:56:29 +0100 Subject: ALSA: core: Fix the debugfs removal at snd_card_free() The commit 2d670ea2bd53 ("ALSA: jack: implement software jack injection via debugfs") introduced a debugfs root for each sound card object. The debugfs entry gets removed at the card removal, too, but it turned out that debugfs_remove() is called at a wrong place; it's after the card object gets freed, hence it leads to use-after-free. Fix it by moving the debugfs_remove() at the right place, the destructor of the card device. Fixes: 2d670ea2bd53 ("ALSA: jack: implement software jack injection via debugfs") Reported-and-tested-by: Chris Wilson Link: https://lore.kernel.org/r/161228343605.1150.8862281636043446562@build.alporthouse.com Link: https://lore.kernel.org/r/20210202225629.1965-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/init.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/core/init.c b/sound/core/init.c index d4e78b176793..84b573e9c1f9 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -487,6 +487,10 @@ static int snd_card_do_free(struct snd_card *card) dev_warn(card->dev, "unable to free card info\n"); /* Not fatal error */ } +#ifdef CONFIG_SND_DEBUG + debugfs_remove(card->debugfs_root); + card->debugfs_root = NULL; +#endif if (card->release_completion) complete(card->release_completion); kfree(card); @@ -537,11 +541,6 @@ int snd_card_free(struct snd_card *card) /* wait, until all devices are ready for the free operation */ wait_for_completion(&released); -#ifdef CONFIG_SND_DEBUG - debugfs_remove(card->debugfs_root); - card->debugfs_root = NULL; -#endif - return 0; } EXPORT_SYMBOL(snd_card_free); -- cgit v1.2.3 From e01a03db74a88084fb91a4ff18bb8d47a1e12f62 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Mon, 1 Feb 2021 16:01:21 +0800 Subject: ASoC: Intel: catpt: remove unneeded semicolon Eliminate the following coccicheck warning: ./sound/soc/intel/catpt/pcm.c:355:2-3: Unneeded semicolon Reported-by: Abaci Robot Signed-off-by: Yang Li Acked-by: Cezary Rojewski Link: https://lore.kernel.org/r/1612166481-121376-1-git-send-email-yang.lee@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/intel/catpt/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c index 9d304b3a817f..ebb27daeb1c7 100644 --- a/sound/soc/intel/catpt/pcm.c +++ b/sound/soc/intel/catpt/pcm.c @@ -352,7 +352,7 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, break; default: return 0; - }; + } list_for_each_entry(pos, &component->card->snd_card->controls, list) { if (pos->private_data == component && -- cgit v1.2.3 From e04e7b8ccd4912e6c823bf7e66f302a53396fb77 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 22 Jan 2021 10:13:32 +0900 Subject: ASoC: soc-pcm: tidyup pcm setting Current soc_new_pcm() setups pcm randomly. This patch tidyup it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878s8laigt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7079a301ec31..d5f1f653ec9b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2760,8 +2760,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) else rtd->close_delayed_work_func = snd_soc_close_delayed_work; - pcm->nonatomic = rtd->dai_link->nonatomic; rtd->pcm = pcm; + pcm->nonatomic = rtd->dai_link->nonatomic; pcm->private_data = rtd; if (rtd->dai_link->no_pcm || rtd->dai_link->params) { -- cgit v1.2.3 From 7fc6bebd5831a788a74e019e39c43c014a96a110 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 22 Jan 2021 10:13:38 +0900 Subject: ASoC: soc-pcm: add soc_get_playback_capture() and simplify soc_new_pcm() soc_new_pcm() implementation is very long / verbose / complex, thus, it is very difficult to read. If we read it carefully, we can notice that it is consisted by int soc_new_pcm(...) { (1) judging playback/caputre part (2) creating the PCM part (3) setup pcm/rtd part } This patch adds new soc_get_playback_capture() for (1) part and offload it from soc_new_pcm(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877do5aign.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d5f1f653ec9b..46818b3319f6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2631,15 +2631,11 @@ open_end: return ret; } -/* create a new pcm */ -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, + int *playback, int *capture) { struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai; - struct snd_soc_component *component; - struct snd_pcm *pcm; - char new_name[64]; - int ret = 0, playback = 0, capture = 0; int stream; int i; @@ -2655,12 +2651,11 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (snd_soc_dai_stream_valid(cpu_dai, stream)) { - playback = 1; + *playback = 1; break; } } - - if (!playback) { + if (!*playback) { dev_err(rtd->card->dev, "No CPU DAIs support playback for stream %s\n", rtd->dai_link->stream_name); @@ -2672,12 +2667,12 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (snd_soc_dai_stream_valid(cpu_dai, stream)) { - capture = 1; + *capture = 1; break; } } - if (!capture) { + if (!*capture) { dev_err(rtd->card->dev, "No CPU DAIs support capture for stream %s\n", rtd->dai_link->stream_name); @@ -2704,23 +2699,39 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) - playback = 1; + *playback = 1; if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) - capture = 1; + *capture = 1; } } if (rtd->dai_link->playback_only) { - playback = 1; - capture = 0; + *playback = 1; + *capture = 0; } if (rtd->dai_link->capture_only) { - playback = 0; - capture = 1; + *playback = 0; + *capture = 1; } + return 0; +} + +/* create a new pcm */ +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +{ + struct snd_soc_component *component; + struct snd_pcm *pcm; + char new_name[64]; + int ret = 0, playback = 0, capture = 0; + int i; + + ret = soc_get_playback_capture(rtd, &playback, &capture); + if (ret < 0) + return ret; + /* create the PCM */ if (rtd->dai_link->params) { snprintf(new_name, sizeof(new_name), "codec2codec(%s)", -- cgit v1.2.3 From 2b39123b134e10a3817156bd9b157c9b8f950d6f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 22 Jan 2021 10:13:43 +0900 Subject: ASoC: soc-pcm: add soc_create_pcm() and simplify soc_new_pcm() soc_new_pcm() implementation is very long / verbose / complex, thus, it is very difficult to read. If we read it carefully, we can notice that it is consisted by int soc_new_pcm(...) { (1) judging playback/caputre part (2) creating the PCM part (3) setup pcm/rtd part } This patch adds new soc_create_pcm() for (2) part and offload it from snd_pcm_new(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875z3paigi.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 46818b3319f6..10c5e0beecd8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2719,18 +2719,12 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, return 0; } -/* create a new pcm */ -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +static int soc_create_pcm(struct snd_pcm **pcm, + struct snd_soc_pcm_runtime *rtd, + int playback, int capture, int num) { - struct snd_soc_component *component; - struct snd_pcm *pcm; char new_name[64]; - int ret = 0, playback = 0, capture = 0; - int i; - - ret = soc_get_playback_capture(rtd, &playback, &capture); - if (ret < 0) - return ret; + int ret; /* create the PCM */ if (rtd->dai_link->params) { @@ -2738,13 +2732,13 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->dai_link->stream_name); ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, - playback, capture, &pcm); + playback, capture, pcm); } else if (rtd->dai_link->no_pcm) { snprintf(new_name, sizeof(new_name), "(%s)", rtd->dai_link->stream_name); ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, - playback, capture, &pcm); + playback, capture, pcm); } else { if (rtd->dai_link->dynamic) snprintf(new_name, sizeof(new_name), "%s (*)", @@ -2756,7 +2750,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num); ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, - capture, &pcm); + capture, pcm); } if (ret < 0) { dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n", @@ -2765,6 +2759,25 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) } dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); + return 0; +} + +/* create a new pcm */ +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +{ + struct snd_soc_component *component; + struct snd_pcm *pcm; + int ret = 0, playback = 0, capture = 0; + int i; + + ret = soc_get_playback_capture(rtd, &playback, &capture); + if (ret < 0) + return ret; + + ret = soc_create_pcm(&pcm, rtd, playback, capture, num); + if (ret < 0) + return ret; + /* DAPM dai link stream work */ if (rtd->dai_link->params) rtd->close_delayed_work_func = codec2codec_close_delayed_work; @@ -2825,8 +2838,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_soc_pcm_component_new(rtd); if (ret < 0) { - dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n", - new_name, rtd->dai_link->name, ret); + dev_err(rtd->dev, "ASoC: pcm constructor failed for dailink %s: %d\n", + rtd->dai_link->name, ret); return ret; } -- cgit v1.2.3 From 4b260f425497b105acc2baa9d97ef781ef0c667d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 22 Jan 2021 10:13:48 +0900 Subject: ASoC: soc-pcm: use snd_pcm_hardware at dpcm_runtime_merge_xxx() soc-pcm has dpcm_runtime_merge_xxx() functions, but uses parameters are very verbose. dpcm_runtime_merge_format(..., &runtime->hw.formats); dpcm_runtime_merge_chan(..., &runtime->hw.channels_min, &runtime->hw.channels_max); dpcm_runtime_merge_rate(..., &runtime->hw.rates, &runtime->hw.rate_min, &runtime->hw.rate_max); We want to replace it into dpcm_runtime_merge_format(..., runtime); dpcm_runtime_merge_chan(..., runtime); dpcm_runtime_merge_rate(..., runtime); This patch do it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/874kj9aigd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 10c5e0beecd8..2a625ce0bacb 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1526,9 +1526,10 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, } static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, - u64 *formats) + struct snd_pcm_runtime *runtime) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dpcm *dpcm; struct snd_soc_dai *dai; int stream = substream->stream; @@ -1556,16 +1557,16 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, codec_stream = snd_soc_dai_get_pcm_stream(dai, stream); - *formats &= codec_stream->formats; + hw->formats &= codec_stream->formats; } } } static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, - unsigned int *channels_min, - unsigned int *channels_max) + struct snd_pcm_runtime *runtime) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1594,10 +1595,10 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); - *channels_min = max(*channels_min, - cpu_stream->channels_min); - *channels_max = min(*channels_max, - cpu_stream->channels_max); + hw->channels_min = max(hw->channels_min, + cpu_stream->channels_min); + hw->channels_max = min(hw->channels_max, + cpu_stream->channels_max); } /* @@ -1607,20 +1608,19 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, if (be->num_codecs == 1) { codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream); - *channels_min = max(*channels_min, - codec_stream->channels_min); - *channels_max = min(*channels_max, - codec_stream->channels_max); + hw->channels_min = max(hw->channels_min, + codec_stream->channels_min); + hw->channels_max = min(hw->channels_max, + codec_stream->channels_max); } } } static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, - unsigned int *rates, - unsigned int *rate_min, - unsigned int *rate_max) + struct snd_pcm_runtime *runtime) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1648,9 +1648,9 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, pcm = snd_soc_dai_get_pcm_stream(dai, stream); - *rate_min = max(*rate_min, pcm->rate_min); - *rate_max = min_not_zero(*rate_max, pcm->rate_max); - *rates = snd_pcm_rate_mask_intersect(*rates, pcm->rates); + hw->rate_min = max(hw->rate_min, pcm->rate_min); + hw->rate_max = min_not_zero(hw->rate_max, pcm->rate_max); + hw->rates = snd_pcm_rate_mask_intersect(hw->rates, pcm->rates); } } } @@ -1675,11 +1675,9 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) substream->stream)); } - dpcm_runtime_merge_format(substream, &runtime->hw.formats); - dpcm_runtime_merge_chan(substream, &runtime->hw.channels_min, - &runtime->hw.channels_max); - dpcm_runtime_merge_rate(substream, &runtime->hw.rates, - &runtime->hw.rate_min, &runtime->hw.rate_max); + dpcm_runtime_merge_format(substream, runtime); + dpcm_runtime_merge_chan(substream, runtime); + dpcm_runtime_merge_rate(substream, runtime); } static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, -- cgit v1.2.3 From dd5abc7834ffae1ca6c399583353e00886817181 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 22 Jan 2021 10:13:53 +0900 Subject: ASoC: soc-pcm: fixup snd_pcm_limit_hw_rates() timing soc-pcm has snd_pcm_limit_hw_rates() which determine rate_min/rate_max. It updates runtime->hw.rate_min/max (A) based on hw->rates (B). int snd_pcm_limit_hw_rates(...) { int i; for (...) { (B) if (runtime->hw.rates & (1 << i)) { (A) runtime->hw.rate_min = ... break; } } for (...) { (B) if (runtime->hw.rates & (1 << i)) { (A) runtime->hw.rate_max = ... break; } } return 0; } This means, setup order is 1) set hw->rates 2) call snd_pcm_limit_hw_rates() 3) update hw->rate_min/max soc_pcm_init_runtime_hw() is calling it in good order static void soc_pcm_init_runtime_hw(xxx) { ... 1) hw->rates = snd_pcm_rate_mask_intersect(...); 2) snd_pcm_limit_hw_rates(...); 3) hw->rate_min = max(...); hw->rate_min = max(...); hw->rate_max = min_not_zero(...); hw->rate_max = min_not_zero(...); } But, dpcm_fe_dai_startup() is not. static int dpcm_fe_dai_startup(xxx) { ... 1) 3) dpcm_set_fe_runtime(...); 2) snd_pcm_limit_hw_rates(...); ... } More detail of dpcm_set_fe_runtime() is static void dpcm_set_fe_runtime() { ... for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ... 3) 1) dpcm_init_runtime_hw(...); } ... 3) 1) dpcm_runtime_merge_rate(...); } This patch fixup these into static void dpcm_set_fe_runtime() { ... for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ... 1) 2) 3) dpcm_init_runtime_hw(...); } ... 1) 2) 3) dpcm_runtime_merge_rate(...); } static int dpcm_fe_dai_startup(xxx) { ... dpcm_set_fe_runtime(...); - snd_pcm_limit_hw_rates(...); ... } Link: https://lore.kernel.org/r/87k15l7ewd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8735ytaig8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2a625ce0bacb..b79f064887d4 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1514,6 +1514,10 @@ unwind: static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, struct snd_soc_pcm_stream *stream) { + runtime->hw.rates = stream->rates; + + snd_pcm_limit_hw_rates(runtime); + runtime->hw.rate_min = stream->rate_min; runtime->hw.rate_max = min_not_zero(stream->rate_max, UINT_MAX); runtime->hw.channels_min = stream->channels_min; @@ -1522,7 +1526,6 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, runtime->hw.formats &= stream->formats; else runtime->hw.formats = stream->formats; - runtime->hw.rates = stream->rates; } static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, @@ -1648,9 +1651,12 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, pcm = snd_soc_dai_get_pcm_stream(dai, stream); + hw->rates = snd_pcm_rate_mask_intersect(hw->rates, pcm->rates); + + snd_pcm_limit_hw_rates(runtime); + hw->rate_min = max(hw->rate_min, pcm->rate_min); hw->rate_max = min_not_zero(hw->rate_max, pcm->rate_max); - hw->rates = snd_pcm_rate_mask_intersect(hw->rates, pcm->rates); } } } @@ -1738,7 +1744,6 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); - struct snd_pcm_runtime *runtime = fe_substream->runtime; int stream = fe_substream->stream, ret = 0; dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); @@ -1761,7 +1766,6 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; dpcm_set_fe_runtime(fe_substream); - snd_pcm_limit_hw_rates(runtime); ret = dpcm_apply_symmetry(fe_substream, stream); if (ret < 0) -- cgit v1.2.3 From 06e577b45db37e8a96ce04e7daa64480492b4ace Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 Jan 2021 22:49:53 +0100 Subject: mfd: arizona: Add MODULE_SOFTDEP("pre: arizona_ldo1") The (shared) probing code of the arizona-i2c and arizona-spi modules takes the following steps during init: 1. Call mfd_add_devices() for a set of early child-devices, this includes the arizona_ldo1 device which provides one of the core-regulators. 2. Bulk enable the core-regulators. 3. Read the device id. 4. Call mfd_add_devices() for the other child-devices. This sequence depends on 1. leading to not only the child-device being created, but also the driver for the child-device binding to it and registering its regulator. This requires the arizona_ldo1 driver to be loaded before the shared probing code runs. Add a softdep for this to both modules to ensure that this requirement is met. Note this mirrors the existing MODULE_SOFTDEP("pre: wm8994_regulator") in the wm8994 code, which has a similar init sequence. Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Signed-off-by: Hans de Goede Signed-off-by: Lee Jones --- drivers/mfd/arizona-i2c.c | 1 + drivers/mfd/arizona-spi.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 4b58e3ad6eb6..2a4a3a164d0a 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -115,6 +115,7 @@ static struct i2c_driver arizona_i2c_driver = { module_i2c_driver(arizona_i2c_driver); +MODULE_SOFTDEP("pre: arizona_ldo1"); MODULE_DESCRIPTION("Arizona I2C bus interface"); MODULE_AUTHOR("Mark Brown "); MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 2633e147b76c..704f214d2614 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -110,6 +110,7 @@ static struct spi_driver arizona_spi_driver = { module_spi_driver(arizona_spi_driver); +MODULE_SOFTDEP("pre: arizona_ldo1"); MODULE_DESCRIPTION("Arizona SPI bus interface"); MODULE_AUTHOR("Mark Brown "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 039da225d644e523a3bbec78ee258b25fe0676f9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 Jan 2021 22:49:54 +0100 Subject: mfd: arizona: Replace arizona_of_get_type() with device_get_match_data() Replace the custom arizona_of_get_type() function with the generic device_get_match_data() helper. Besides being a nice cleanup this also makes it easier to add support for binding to ACPI enumerated devices. While at it also fix a possible NULL pointer deref of the id argument to the probe functions (this could happen on e.g. manual driver binding through sysfs). Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Signed-off-by: Hans de Goede Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 11 ----------- drivers/mfd/arizona-i2c.c | 10 ++++++---- drivers/mfd/arizona-spi.c | 10 ++++++---- drivers/mfd/arizona.h | 9 --------- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 000cb82023e3..75f1bc671d59 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -797,17 +797,6 @@ const struct dev_pm_ops arizona_pm_ops = { EXPORT_SYMBOL_GPL(arizona_pm_ops); #ifdef CONFIG_OF -unsigned long arizona_of_get_type(struct device *dev) -{ - const struct of_device_id *id = of_match_device(arizona_of_match, dev); - - if (id) - return (unsigned long)id->data; - else - return 0; -} -EXPORT_SYMBOL_GPL(arizona_of_get_type); - static int arizona_of_get_core_pdata(struct arizona *arizona) { struct arizona_pdata *pdata = &arizona->pdata; diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 2a4a3a164d0a..5e83b730c4ce 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -23,14 +23,16 @@ static int arizona_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + const void *match_data; struct arizona *arizona; const struct regmap_config *regmap_config = NULL; - unsigned long type; + unsigned long type = 0; int ret; - if (i2c->dev.of_node) - type = arizona_of_get_type(&i2c->dev); - else + match_data = device_get_match_data(&i2c->dev); + if (match_data) + type = (unsigned long)match_data; + else if (id) type = id->driver_data; switch (type) { diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 704f214d2614..798b88295c77 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -23,14 +23,16 @@ static int arizona_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); + const void *match_data; struct arizona *arizona; const struct regmap_config *regmap_config = NULL; - unsigned long type; + unsigned long type = 0; int ret; - if (spi->dev.of_node) - type = arizona_of_get_type(&spi->dev); - else + match_data = device_get_match_data(&spi->dev); + if (match_data) + type = (unsigned long)match_data; + else if (id) type = id->driver_data; switch (type) { diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h index 995efc6d7f32..801cbbcd71cb 100644 --- a/drivers/mfd/arizona.h +++ b/drivers/mfd/arizona.h @@ -50,13 +50,4 @@ int arizona_dev_exit(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona); int arizona_irq_exit(struct arizona *arizona); -#ifdef CONFIG_OF -unsigned long arizona_of_get_type(struct device *dev); -#else -static inline unsigned long arizona_of_get_type(struct device *dev) -{ - return 0; -} -#endif - #endif -- cgit v1.2.3 From e933836744a2606e6cd42a6a83e5e43da2a60788 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 Jan 2021 22:49:55 +0100 Subject: mfd: arizona: Add support for ACPI enumeration of WM5102 connected over SPI The Intel Bay Trail (x86/ACPI) based Lenovo Yoga Tablet 2 series use a WM5102 codec connected over SPI. Add support for ACPI enumeration to arizona-spi so that arizona-spi can bind to the codec on these tablets. This is loosely based on an earlier attempt (for Android-x86) at this by Christian Hartmann, combined with insights in things like the speaker GPIO from the android-x86 android port for the Lenovo Yoga Tablet 2 1051F/L [1]. [1] https://github.com/Kitsune2222/Android_Yoga_Tablet_2-1051F_Kernel Cc: Christian Hartmann Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-spi.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 798b88295c77..24a2c75d691a 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -7,7 +7,10 @@ * Author: Mark Brown */ +#include #include +#include +#include #include #include #include @@ -15,11 +18,128 @@ #include #include #include +#include #include #include "arizona.h" +#ifdef CONFIG_ACPI +const struct acpi_gpio_params reset_gpios = { 1, 0, false }; +const struct acpi_gpio_params ldoena_gpios = { 2, 0, false }; + +static const struct acpi_gpio_mapping arizona_acpi_gpios[] = { + { "reset-gpios", &reset_gpios, 1, }, + { "wlf,ldoena-gpios", &ldoena_gpios, 1 }, + { } +}; + +/* + * The ACPI resources for the device only describe external GPIO-s. They do + * not provide mappings for the GPIO-s coming from the Arizona codec itself. + */ +static const struct gpiod_lookup arizona_soc_gpios[] = { + { "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH }, + { "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW }, +}; + +/* + * The AOSP 3.5 mm Headset: Accessory Specification gives the following values: + * Function A Play/Pause: 0 ohm + * Function D Voice assistant: 135 ohm + * Function B Volume Up 240 ohm + * Function C Volume Down 470 ohm + * Minimum Mic DC resistance 1000 ohm + * Minimum Ear speaker impedance 16 ohm + * Note the first max value below must be less then the min. speaker impedance, + * to allow CTIA/OMTP detection to work. The other max values are the closest + * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances. + */ +static const struct arizona_micd_range arizona_micd_aosp_ranges[] = { + { .max = 11, .key = KEY_PLAYPAUSE }, + { .max = 186, .key = KEY_VOICECOMMAND }, + { .max = 348, .key = KEY_VOLUMEUP }, + { .max = 752, .key = KEY_VOLUMEDOWN }, +}; + +static void arizona_spi_acpi_remove_lookup(void *lookup) +{ + gpiod_remove_lookup_table(lookup); +} + +static int arizona_spi_acpi_probe(struct arizona *arizona) +{ + struct gpiod_lookup_table *lookup; + acpi_status status; + int ret; + + /* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */ + devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios); + + /* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */ + lookup = devm_kzalloc(arizona->dev, + struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1), + GFP_KERNEL); + if (!lookup) + return -ENOMEM; + + lookup->dev_id = dev_name(arizona->dev); + memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios)); + + gpiod_add_lookup_table(lookup); + ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup); + if (ret) + return ret; + + /* Enable 32KHz clock from SoC to codec for jack-detect */ + status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL); + if (ACPI_FAILURE(status)) + dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status); + + /* + * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING + * The IRQ line will stay low when a new IRQ event happens between reading + * the IRQ status flags and acknowledging them. When the IRQ line stays + * low like this the IRQ will never trigger again when its type is set + * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this. + * + * Note theoretically it is possible that some boards are not capable + * of handling active low level interrupts. In that case setting the + * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need + * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING + * are a bug in the board's DSDT. + */ + arizona->pdata.irq_flags = IRQF_TRIGGER_LOW; + + /* Wait 200 ms after jack insertion */ + arizona->pdata.micd_detect_debounce = 200; + + /* Use standard AOSP values for headset-button mappings */ + arizona->pdata.micd_ranges = arizona_micd_aosp_ranges; + arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges); + + return 0; +} + +static const struct acpi_device_id arizona_acpi_match[] = { + { + .id = "WM510204", + .driver_data = WM5102, + }, + { + .id = "WM510205", + .driver_data = WM5102, + }, + { } +}; +MODULE_DEVICE_TABLE(acpi, arizona_acpi_match); +#else +static int arizona_spi_acpi_probe(struct arizona *arizona) +{ + return -ENODEV; +} +#endif + static int arizona_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -77,6 +197,12 @@ static int arizona_spi_probe(struct spi_device *spi) arizona->dev = &spi->dev; arizona->irq = spi->irq; + if (has_acpi_companion(&spi->dev)) { + ret = arizona_spi_acpi_probe(arizona); + if (ret) + return ret; + } + return arizona_dev_init(arizona); } @@ -104,6 +230,7 @@ static struct spi_driver arizona_spi_driver = { .name = "arizona", .pm = &arizona_pm_ops, .of_match_table = of_match_ptr(arizona_of_match), + .acpi_match_table = ACPI_PTR(arizona_acpi_match), }, .probe = arizona_spi_probe, .remove = arizona_spi_remove, -- cgit v1.2.3 From 8e59cf943fa7402f008de4b444beb0c5280317bc Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 3 Feb 2021 11:21:59 +0800 Subject: ASoC: mediatek: mt8192-mt6359: use asoc_substream_to_rtd() Uses asoc_substream_to_rtd() helper. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210203032201.2882158-2-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index cc0fc72305d2..f5c1c10408c9 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -39,7 +39,7 @@ struct mt8192_mt6359_priv { static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai; @@ -74,7 +74,7 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, static int mt8192_rt5682_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); @@ -362,7 +362,7 @@ static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); -- cgit v1.2.3 From 0840706d6c61658e51f42762c5b4f211b7596535 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 3 Feb 2021 11:22:00 +0800 Subject: ASoC: mediatek: mt8192: use asoc_substream_to_rtd() Uses asoc_substream_to_rtd() helper. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210203032201.2882158-3-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index e7fec2d75e3d..7a1724f5ff4c 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -42,7 +42,7 @@ static const struct snd_pcm_hardware mt8192_afe_hardware = { static int mt8192_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -59,7 +59,7 @@ static int mt8192_get_dai_fs(struct mtk_base_afe *afe, static int mt8192_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); -- cgit v1.2.3 From 4cceb42f4f401463b70d9e69c4771212707c51a8 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 3 Feb 2021 11:22:01 +0800 Subject: ASoC: mediatek: mt8192-mt6359: simplify ops for Capture1 DAI link 1. Uses rtd->dev to get the device. 2. Generalizes the variable name. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210203032201.2882158-4-tzungbi@google.com Signed-off-by: Mark Brown --- .../mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index f5c1c10408c9..f4b09672af8f 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -360,14 +360,8 @@ static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, } static int -mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream) +mt8192_mt6359_cap1_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_component *component = - snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); - int ret; - static const unsigned int channels[] = { 1, 2, 4 }; @@ -385,13 +379,15 @@ mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream) .mask = 0, }; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; + int ret; ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &constraints_channels); if (ret < 0) { - dev_err(afe->dev, "hw_constraint_list channels failed\n"); + dev_err(rtd->dev, "hw_constraint_list channels failed\n"); return ret; } @@ -399,15 +395,15 @@ mt8192_mt6359_rt1015_rt5682_cap1_startup(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); if (ret < 0) { - dev_err(afe->dev, "hw_constraint_list rate failed\n"); + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); return ret; } return 0; } -static const struct snd_soc_ops mt8192_mt6359_rt1015_rt5682_capture1_ops = { - .startup = mt8192_mt6359_rt1015_rt5682_cap1_startup, +static const struct snd_soc_ops mt8192_mt6359_capture1_ops = { + .startup = mt8192_mt6359_cap1_startup, }; /* FE */ @@ -720,7 +716,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8192_mt6359_rt1015_rt5682_capture1_ops, + .ops = &mt8192_mt6359_capture1_ops, SND_SOC_DAILINK_REG(capture1), }, { -- cgit v1.2.3 From 0dd4d3e8c3a8ab63e9368e01d7839afad7b804c7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 2 Feb 2021 11:20:16 -0800 Subject: ASoC: da7218: Drop CONFIG_OF ifdef This reverts commit a06cd8cf97a3 ("ASoC: da7218: skip of_device_id table when !CONFIG_OF") because we want to make of_match_device() stop using of_match_ptr() internally, confusing compilers and causing ifdef pollution. Reported-by: kernel test robot Cc: Geert Uytterhoeven Acked-by: Arnd Bergmann Cc: Mark Brown Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20210202192016.49028-1-swboyd@chromium.org Signed-off-by: Mark Brown --- sound/soc/codecs/da7218.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 0e5b91eb420b..ea426d986d4c 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -2278,14 +2278,12 @@ static irqreturn_t da7218_irq_thread(int irq, void *data) * DT */ -#ifdef CONFIG_OF static const struct of_device_id da7218_of_match[] = { { .compatible = "dlg,da7217", .data = (void *) DA7217_DEV_ID }, { .compatible = "dlg,da7218", .data = (void *) DA7218_DEV_ID }, { } }; MODULE_DEVICE_TABLE(of, da7218_of_match); -#endif static inline int da7218_of_get_id(struct device *dev) { @@ -3311,7 +3309,7 @@ MODULE_DEVICE_TABLE(i2c, da7218_i2c_id); static struct i2c_driver da7218_i2c_driver = { .driver = { .name = "da7218", - .of_match_table = of_match_ptr(da7218_of_match), + .of_match_table = da7218_of_match, }, .probe = da7218_i2c_probe, .id_table = da7218_i2c_id, -- cgit v1.2.3 From 036f90dd92bb0aac66fdeec8386401dd396c6079 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 5 Feb 2021 09:28:37 +0100 Subject: ALSA: usb-audio: Correct document for snd_usb_endpoint_free_all() The kerndoc comment for the new function snd_usb_endpoint_free_all() had a typo wrt the argument name. Fix it. Fixes: 00272c61827e ("ALSA: usb-audio: Avoid unnecessary interface re-setup") Reported-by: Pierre-Louis Bossart Cc: Link: https://lore.kernel.org/r/20210205082837.6327-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 8e568823c992..4d1c678a0d80 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1451,7 +1451,7 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep) /** * snd_usb_endpoint_free_all: Free the resources of an snd_usb_endpoint - * @card: The chip + * @chip: The chip * * This free all endpoints and those resources */ -- cgit v1.2.3 From f12bbc50f3b14c9b8ed902c6d1da980dd5addcce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Feb 2021 14:33:00 -0600 Subject: ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E We missed adding the TGL_HDMI quirk which is very much needed to expose the 4 display pipelines and will be required on TGL topologies. Fixes: 9ad9bc59dde10 ('ASoC: Intel: sof_sdw: set proper flags for Dell TGL-H SKU 0A5E') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210204203312.27112-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6d0d6ef711e0..29b6bba3d425 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -73,7 +73,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, -- cgit v1.2.3 From 45c92ec32b43c6cb42341ebf07577eefed9d87ec Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Feb 2021 14:33:01 -0600 Subject: ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A32 We missed adding the TGL_HDMI quirk which is very much needed to expose the 4 display pipelines and will be required on TGL topologies. Fixes: 488cdbd8931fe ('ASoC: Intel: sof_sdw: add quirk for new TigerLake-SDCA device') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210204203312.27112-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 29b6bba3d425..afdc336ec9bf 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -54,7 +54,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, -- cgit v1.2.3 From 5ab3ff4d66960be766a544886667e7c002f17fd6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Feb 2021 14:32:59 -0600 Subject: ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E We missed adding the TGL_HDMI quirk which is very much needed to expose the 4 display pipelines and will be required on TGL topologies. Fixes: e787f5b5b1406 ('ASoC: Intel: add support for new SoundWire hardware layout on TGL') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210204203312.27112-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index afdc336ec9bf..152ea166eeae 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -65,7 +65,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | SOF_RT715_DAI_ID_FIX), }, { -- cgit v1.2.3 From 737ee8bdf682cedb3c42b713d20ffa5c899591fb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Feb 2021 14:17:36 -0600 Subject: ASoC: rt700-sdw: use cancel_work_sync() in .remove as well as .suspend Make sure the workqueues are not running after the .remove() callback, which can lead to timeout errors. A previous fix to use cancel_work_sync was applied for the suspend case but the remove case is missing Fixes: 5f2df2a4583b ('ASoC: rt700: wait for the delayed work to finish when the system suspends') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20210204201739.25206-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index fb77e77a4ebd..45488325b635 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -462,8 +462,8 @@ static int rt700_sdw_remove(struct sdw_slave *slave) struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev); if (rt700 && rt700->hw_init) { - cancel_delayed_work(&rt700->jack_detect_work); - cancel_delayed_work(&rt700->jack_btn_check_work); + cancel_delayed_work_sync(&rt700->jack_detect_work); + cancel_delayed_work_sync(&rt700->jack_btn_check_work); } return 0; -- cgit v1.2.3 From 121871a75ae4032cf5e506ba5159761805709def Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Feb 2021 14:17:37 -0600 Subject: ASoC: rt711-sdw: use cancel_work_sync() for .remove Make sure the workqueues are not running after the .remove() callback, which can lead to timeout errors. A previous fix to use cancel_work_sync was applied for the suspend case but the remove case is missing Fixes: 501ef013390b ('ASoC: rt711: wait for the delayed work to finish when the system suspends') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20210204201739.25206-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index fc7df79c3b91..308e62564841 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -463,8 +463,8 @@ static int rt711_sdw_remove(struct sdw_slave *slave) struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev); if (rt711 && rt711->hw_init) { - cancel_delayed_work(&rt711->jack_detect_work); - cancel_delayed_work(&rt711->jack_btn_check_work); + cancel_delayed_work_sync(&rt711->jack_detect_work); + cancel_delayed_work_sync(&rt711->jack_btn_check_work); cancel_work_sync(&rt711->calibration_work); } -- cgit v1.2.3 From c792c3690b82c8d26c01494a51ebf66d9cae7e72 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Feb 2021 14:17:38 -0600 Subject: ASoC: rt5682-sdw: cancel_work_sync() in .remove and .suspend Follow pattern from other drivers and use cancel_work_sync() for both .remove() and .suspend(). Fixes: 03f6fc6de919 ('ASoC: rt5682: Add the soundwire support') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20210204201739.25206-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 4d707e854875..35c9d2be9eeb 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -703,7 +703,7 @@ static int rt5682_sdw_remove(struct sdw_slave *slave) struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); if (rt5682 && rt5682->hw_init) - cancel_delayed_work(&rt5682->jack_detect_work); + cancel_delayed_work_sync(&rt5682->jack_detect_work); return 0; } @@ -721,6 +721,8 @@ static int __maybe_unused rt5682_dev_suspend(struct device *dev) if (!rt5682->hw_init) return 0; + cancel_delayed_work_sync(&rt5682->jack_detect_work); + regcache_cache_only(rt5682->regmap, true); regcache_mark_dirty(rt5682->regmap); -- cgit v1.2.3 From 30fd8f65af78d0ac0859cf436beed14834b39802 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 4 Feb 2021 14:17:39 -0600 Subject: ASoC: rt5682: do nothing in rt5682_suspend/resume in sdw mode regcache sync will be done in sdw device suspend/resume functions. And we have different jack detection mechanism for SoundWire. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210204201739.25206-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 4d865edadd7e..fde5c4945e17 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2906,6 +2906,9 @@ static int rt5682_suspend(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + if (rt5682->is_sdw) + return 0; + regcache_cache_only(rt5682->regmap, true); regcache_mark_dirty(rt5682->regmap); return 0; @@ -2915,6 +2918,9 @@ static int rt5682_resume(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + if (rt5682->is_sdw) + return 0; + regcache_cache_only(rt5682->regmap, false); regcache_sync(rt5682->regmap); -- cgit v1.2.3 From df91785a22e2505d2ac668f1d3e6b6e6d8ba627a Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 5 Feb 2021 11:44:03 +0100 Subject: ASoC: dt-bindings: add mclk provider support to stm32 i2s Add master clock provider support to STM32 I2S. Reviewed-by: Rob Herring Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20210205104404.18786-2-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml index f32410890589..6feb5a09c184 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml @@ -54,6 +54,10 @@ properties: resets: maxItems: 1 + "#clock-cells": + description: Configure the I2S device as MCLK clock provider. + const: 0 + required: - compatible - "#sound-dai-cells" -- cgit v1.2.3 From 8a262e614ef8675cfde924c6ddf873a95db0be6a Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 5 Feb 2021 11:44:04 +0100 Subject: ASoC: stm32: i2s: add master clock provider Add master clock generation support in STM32 I2S driver. The master clock provided by I2S can be used to feed a codec. Signed-off-by: Olivier Moysan Link: https://lore.kernel.org/r/20210205104404.18786-3-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 310 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 266 insertions(+), 44 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 7c4d63c33f15..7d1672cf78cc 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -196,6 +197,9 @@ enum i2s_datlen { #define STM32_I2S_IS_MASTER(x) ((x)->ms_flg == I2S_MS_MASTER) #define STM32_I2S_IS_SLAVE(x) ((x)->ms_flg == I2S_MS_SLAVE) +#define STM32_I2S_NAME_LEN 32 +#define STM32_I2S_RATE_11K 11025 + /** * struct stm32_i2s_data - private data of I2S * @regmap_conf: I2S register map configuration pointer @@ -206,6 +210,7 @@ enum i2s_datlen { * @dma_data_rx: dma configuration data for tx channel * @substream: PCM substream data pointer * @i2sclk: kernel clock feeding the I2S clock generator + * @i2smclk: master clock from I2S mclk provider * @pclk: peripheral clock driving bus interface * @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz * @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz @@ -215,6 +220,9 @@ enum i2s_datlen { * @irq_lock: prevent race condition with IRQ * @mclk_rate: master clock frequency (Hz) * @fmt: DAI protocol + * @divider: prescaler division ratio + * @div: prescaler div field + * @odd: prescaler odd field * @refcount: keep count of opened streams on I2S * @ms_flg: master mode flag. */ @@ -227,6 +235,7 @@ struct stm32_i2s_data { struct snd_dmaengine_dai_dma_data dma_data_rx; struct snd_pcm_substream *substream; struct clk *i2sclk; + struct clk *i2smclk; struct clk *pclk; struct clk *x8kclk; struct clk *x11kclk; @@ -236,10 +245,210 @@ struct stm32_i2s_data { spinlock_t irq_lock; /* used to prevent race condition with IRQ */ unsigned int mclk_rate; unsigned int fmt; + unsigned int divider; + unsigned int div; + bool odd; int refcount; int ms_flg; }; +struct stm32_i2smclk_data { + struct clk_hw hw; + unsigned long freq; + struct stm32_i2s_data *i2s_data; +}; + +#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw) + +static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s, + unsigned long input_rate, + unsigned long output_rate) +{ + unsigned int ratio, div, divider = 1; + bool odd; + + ratio = DIV_ROUND_CLOSEST(input_rate, output_rate); + + /* Check the parity of the divider */ + odd = ratio & 0x1; + + /* Compute the div prescaler */ + div = ratio >> 1; + + /* If div is 0 actual divider is 1 */ + if (div) { + divider = ((2 * div) + odd); + dev_dbg(&i2s->pdev->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", + div, odd, divider); + } + + /* Division by three is not allowed by I2S prescaler */ + if ((div == 1 && odd) || div > I2S_CGFR_I2SDIV_MAX) { + dev_err(&i2s->pdev->dev, "Wrong divider setting\n"); + return -EINVAL; + } + + if (input_rate % divider) + dev_dbg(&i2s->pdev->dev, + "Rate not accurate. requested (%ld), actual (%ld)\n", + output_rate, input_rate / divider); + + i2s->div = div; + i2s->odd = odd; + i2s->divider = divider; + + return 0; +} + +static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s) +{ + u32 cgfr, cgfr_mask; + + cgfr = I2S_CGFR_I2SDIV_SET(i2s->div) | (i2s->odd << I2S_CGFR_ODD_SHIFT); + cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; + + return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, + cgfr_mask, cgfr); +} + +static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, + unsigned int rate) +{ + struct platform_device *pdev = i2s->pdev; + struct clk *parent_clk; + int ret; + + if (!(rate % STM32_I2S_RATE_11K)) + parent_clk = i2s->x11kclk; + else + parent_clk = i2s->x8kclk; + + ret = clk_set_parent(i2s->i2sclk, parent_clk); + if (ret) + dev_err(&pdev->dev, + "Error %d setting i2sclk parent clock\n", ret); + + return ret; +} + +static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct stm32_i2smclk_data *mclk = to_mclk_data(hw); + struct stm32_i2s_data *i2s = mclk->i2s_data; + int ret; + + ret = stm32_i2s_calc_clk_div(i2s, *prate, rate); + if (ret) + return ret; + + mclk->freq = *prate / i2s->divider; + + return mclk->freq; +} + +static unsigned long stm32_i2smclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct stm32_i2smclk_data *mclk = to_mclk_data(hw); + + return mclk->freq; +} + +static int stm32_i2smclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct stm32_i2smclk_data *mclk = to_mclk_data(hw); + struct stm32_i2s_data *i2s = mclk->i2s_data; + int ret; + + ret = stm32_i2s_calc_clk_div(i2s, parent_rate, rate); + if (ret) + return ret; + + ret = stm32_i2s_set_clk_div(i2s); + if (ret) + return ret; + + mclk->freq = rate; + + return 0; +} + +static int stm32_i2smclk_enable(struct clk_hw *hw) +{ + struct stm32_i2smclk_data *mclk = to_mclk_data(hw); + struct stm32_i2s_data *i2s = mclk->i2s_data; + + dev_dbg(&i2s->pdev->dev, "Enable master clock\n"); + + return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, + I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); +} + +static void stm32_i2smclk_disable(struct clk_hw *hw) +{ + struct stm32_i2smclk_data *mclk = to_mclk_data(hw); + struct stm32_i2s_data *i2s = mclk->i2s_data; + + dev_dbg(&i2s->pdev->dev, "Disable master clock\n"); + + regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0); +} + +static const struct clk_ops mclk_ops = { + .enable = stm32_i2smclk_enable, + .disable = stm32_i2smclk_disable, + .recalc_rate = stm32_i2smclk_recalc_rate, + .round_rate = stm32_i2smclk_round_rate, + .set_rate = stm32_i2smclk_set_rate, +}; + +static int stm32_i2s_add_mclk_provider(struct stm32_i2s_data *i2s) +{ + struct clk_hw *hw; + struct stm32_i2smclk_data *mclk; + struct device *dev = &i2s->pdev->dev; + const char *pname = __clk_get_name(i2s->i2sclk); + char *mclk_name, *p, *s = (char *)pname; + int ret, i = 0; + + mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL); + if (!mclk) + return -ENOMEM; + + mclk_name = devm_kcalloc(dev, sizeof(char), + STM32_I2S_NAME_LEN, GFP_KERNEL); + if (!mclk_name) + return -ENOMEM; + + /* + * Forge mclk clock name from parent clock name and suffix. + * String after "_" char is stripped in parent name. + */ + p = mclk_name; + while (*s && *s != '_' && (i < (STM32_I2S_NAME_LEN - 7))) { + *p++ = *s++; + i++; + } + strcat(p, "_mclk"); + + mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0); + mclk->i2s_data = i2s; + hw = &mclk->hw; + + dev_dbg(dev, "Register master clock %s\n", mclk_name); + ret = devm_clk_hw_register(&i2s->pdev->dev, hw); + if (ret) { + dev_err(dev, "mclk register fails with error %d\n", ret); + return ret; + } + i2s->i2smclk = hw->clk; + + /* register mclk provider */ + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); +} + static irqreturn_t stm32_i2s_isr(int irq, void *devid) { struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid; @@ -405,18 +614,46 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); + int ret = 0; - dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq); + dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz. mode: %s, dir: %s\n", + freq, STM32_I2S_IS_MASTER(i2s) ? "master" : "slave", + dir ? "output" : "input"); - if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) { - i2s->mclk_rate = freq; + /* MCLK generation is available only in master mode */ + if (dir == SND_SOC_CLOCK_OUT && STM32_I2S_IS_MASTER(i2s)) { + if (!i2s->i2smclk) { + dev_dbg(cpu_dai->dev, "No MCLK registered\n"); + return 0; + } - /* Enable master clock if master mode and mclk-fs are set */ - return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, - I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); + /* Assume shutdown if requested frequency is 0Hz */ + if (!freq) { + /* Release mclk rate only if rate was actually set */ + if (i2s->mclk_rate) { + clk_rate_exclusive_put(i2s->i2smclk); + i2s->mclk_rate = 0; + } + return regmap_update_bits(i2s->regmap, + STM32_I2S_CGFR_REG, + I2S_CGFR_MCKOE, 0); + } + /* If master clock is used, set parent clock now */ + ret = stm32_i2s_set_parent_clock(i2s, freq); + if (ret) + return ret; + ret = clk_set_rate_exclusive(i2s->i2smclk, freq); + if (ret) { + dev_err(cpu_dai->dev, "Could not set mclk rate\n"); + return ret; + } + ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, + I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); + if (!ret) + i2s->mclk_rate = freq; } - return 0; + return ret; } static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, @@ -424,11 +661,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, { struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); unsigned long i2s_clock_rate; - unsigned int tmp, div, real_div, nb_bits, frame_len; + unsigned int nb_bits, frame_len; unsigned int rate = params_rate(params); + u32 cgfr; int ret; - u32 cgfr, cgfr_mask; - bool odd; if (!(rate % 11025)) clk_set_parent(i2s->i2sclk, i2s->x11kclk); @@ -449,7 +685,10 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, * dsp mode : div = i2s_clk / (nb_bits x ws) */ if (i2s->mclk_rate) { - tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate); + ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, + i2s->mclk_rate); + if (ret) + return ret; } else { frame_len = 32; if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == @@ -462,34 +701,13 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, return ret; nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1); - tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate)); - } - - /* Check the parity of the divider */ - odd = tmp & 0x1; - - /* Compute the div prescaler */ - div = tmp >> 1; - - cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT); - cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; - - real_div = ((2 * div) + odd); - dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n", - i2s_clock_rate, rate); - dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", - div, odd, real_div); - - if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) { - dev_err(cpu_dai->dev, "Wrong divider setting\n"); - return -EINVAL; + ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, + (nb_bits * rate)); + if (ret) + return ret; } - if (!div && !odd) - dev_warn(cpu_dai->dev, "real divider forced to 1\n"); - - ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, - cgfr_mask, cgfr); + ret = stm32_i2s_set_clk_div(i2s); if (ret < 0) return ret; @@ -694,9 +912,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); unsigned long flags; - regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, - I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE); - clk_disable_unprepare(i2s->i2sclk); spin_lock_irqsave(&i2s->irq_lock, flags); @@ -861,6 +1076,13 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return PTR_ERR(i2s->x11kclk); } + /* Register mclk provider if requested */ + if (of_find_property(np, "#clock-cells", NULL)) { + ret = stm32_i2s_add_mclk_provider(i2s); + if (ret < 0) + return ret; + } + /* Get irqs */ irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -906,16 +1128,16 @@ static int stm32_i2s_probe(struct platform_device *pdev) if (!i2s) return -ENOMEM; - ret = stm32_i2s_parse_dt(pdev, i2s); - if (ret) - return ret; - i2s->pdev = pdev; i2s->ms_flg = I2S_MS_NOT_SET; spin_lock_init(&i2s->lock_fd); spin_lock_init(&i2s->irq_lock); platform_set_drvdata(pdev, i2s); + ret = stm32_i2s_parse_dt(pdev, i2s); + if (ret) + return ret; + ret = stm32_i2s_dais_init(pdev, i2s); if (ret) return ret; -- cgit v1.2.3 From 19657a609b68f37afede259a762765b77914557f Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Fri, 5 Feb 2021 16:16:52 +0800 Subject: ASoC: mediatek: mt8183-mt6358: set playback and capture constraints Sets playback and capture constraints to S16_LE, stereo, 48kHz. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/1612513012-27688-1-git-send-email-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- .../mt8183/mt8183-mt6358-ts3a227-max98357.c | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 3cf8aeab042c..271413e719e3 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -117,6 +117,45 @@ static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int +mt8183_mt6358_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000, + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const unsigned int channels[] = { + 2, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_pcm_runtime *runtime = substream->runtime; + + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + runtime->hw.channels_max = 2; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); + + return 0; +} + +static const struct snd_soc_ops mt8183_mt6358_ops = { + .startup = mt8183_mt6358_startup, +}; + static int mt8183_mt6358_ts3a227_max98357_bt_sco_startup( struct snd_pcm_substream *substream) @@ -356,6 +395,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, + .ops = &mt8183_mt6358_ops, SND_SOC_DAILINK_REG(playback1), }, { @@ -403,6 +443,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, + .ops = &mt8183_mt6358_ops, SND_SOC_DAILINK_REG(capture3), }, { -- cgit v1.2.3 From fb3c293b82c31a9a68fbcf4e7a45fadd8a47ea2b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 5 Feb 2021 15:45:59 +0100 Subject: ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode The commit f274baa49be6 ("ALSA: usb-audio: Allow non-vmalloc buffer for PCM buffers") introduced the mode to allocate coherent pages for PCM buffers, and it used bus->controller device as its DMA device. It turned out, however, that bus->sysdev is a more appropriate device to be used for DMA mapping in HCD code. This patch corrects the device reference accordingly. Note that, on most platforms, both point to the very same device, hence this patch doesn't change anything practically. But on platforms like xhcd-plat hcd, the change becomes effective. Fixes: f274baa49be6 ("ALSA: usb-audio: Allow non-vmalloc buffer for PCM buffers") Cc: Link: https://lore.kernel.org/r/20210205144559.29555-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 078bb4c94033..dcadf8f164b2 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1558,7 +1558,7 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs) { struct snd_pcm *pcm = subs->stream->pcm; struct snd_pcm_substream *s = pcm->streams[subs->direction].substream; - struct device *dev = subs->dev->bus->controller; + struct device *dev = subs->dev->bus->sysdev; if (snd_usb_use_vmalloc) snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC, -- cgit v1.2.3 From 5e3277ab3baff6db96ae44adf6f85d6f0f6502cc Mon Sep 17 00:00:00 2001 From: Jun Nie Date: Mon, 1 Feb 2021 21:29:41 +0800 Subject: ASoC: qcom: lpass: Fix i2s ctl register bit map Fix bitwidth mapping in i2s ctl register per APQ8016 document. Fixes: b5022a36d28f ("ASoC: qcom: lpass: Use regmap_field for i2sctl and dmactl registers") Reviewed-by: Srinivas Kandagatla Reviewed-by: Stephan Gerhold Signed-off-by: Jun Nie Link: https://lore.kernel.org/r/20210201132941.460360-1-jun.nie@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-apq8016.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index 8507ef8f6679..3efa133d1c64 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -250,7 +250,7 @@ static struct lpass_variant apq8016_data = { .micmode = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000), .micmono = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000), .wssrc = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000), - .bitwidth = REG_FIELD_ID(0x1000, 0, 0, 4, 0x1000), + .bitwidth = REG_FIELD_ID(0x1000, 0, 1, 4, 0x1000), .rdma_dyncclk = REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000), .rdma_bursten = REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000), -- cgit v1.2.3 From 500c9f8c58a7c8cd5d9c1483569c046cfcfc47a4 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 5 Feb 2021 15:26:25 +0800 Subject: ASoC: dmaengine_pcm: add peripheral configuration The commit e7bbb7acabf4 ("dmaengine: add peripheral configuration") adds peripheral configuration for dma_slave_config. This configuration is useful for some audio peripherals, for example, the peripheral supports multi fifos, we can let the DMA know which fifos are selected. So also add this configuration for snd_dmaengine_dai_dma_data. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1612509985-11063-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 5 +++++ sound/core/pcm_dmaengine.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 8c5e38180fb0..96666efddb39 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -66,6 +66,9 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) * @chan_name: Custom channel name to use when requesting DMA channel. * @fifo_size: FIFO size of the DAI controller in bytes * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size */ struct snd_dmaengine_dai_dma_data { dma_addr_t addr; @@ -76,6 +79,8 @@ struct snd_dmaengine_dai_dma_data { const char *chan_name; unsigned int fifo_size; unsigned int flags; + void *peripheral_config; + size_t peripheral_size; }; void snd_dmaengine_pcm_set_config_from_dai_data( diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 4d0e8fe535a1..1fc2fa077574 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -125,6 +125,8 @@ void snd_dmaengine_pcm_set_config_from_dai_data( } slave_config->slave_id = dma_data->slave_id; + slave_config->peripheral_config = dma_data->peripheral_config; + slave_config->peripheral_size = dma_data->peripheral_size; } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); -- cgit v1.2.3 From f08c74a3b52d126d053c741b906ee1ca2a4f3568 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Feb 2021 14:00:22 +0100 Subject: ASoC: dt-bindings: renesas, rsnd: Group tuples in playback/capture properties To improve human readability and enable automatic validation, the tuples in "playback" and "capture" properties in sound device nodes should be grouped using angle brackets. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210204130022.1646427-1-geert+renesas@glider.be Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/renesas,rsnd.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 0fd37aa84947..2e1046513603 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -404,7 +404,7 @@ examples: /* DAI base */ rcar_sound,dai { dai0 { - playback = <&ssi5 &src5>; + playback = <&ssi5>, <&src5>; capture = <&ssi6>; }; dai1 { @@ -430,8 +430,8 @@ examples: bitclock-master = <&rsnd_endpoint0>; frame-master = <&rsnd_endpoint0>; - playback = <&ssi0 &src0 &dvc0>; - capture = <&ssi1 &src1 &dvc1>; + playback = <&ssi0>, <&src0>, <&dvc0>; + capture = <&ssi1>, <&src1>, <&dvc1>; }; }; }; -- cgit v1.2.3 From a07df82c799013236aa90a140785775eda9f9523 Mon Sep 17 00:00:00 2001 From: Olivia Mackintosh Date: Fri, 5 Feb 2021 18:42:56 +0000 Subject: ALSA: usb-audio: Add DJM750 to Pioneer mixer quirk This allows for N different devices to use the pioneer mixer quirk for setting capture/record type and recording level. The impementation has not changed much with the exception of an additional mask on private_value to allow storing of a device index: DEVICE MASK 0xff000000 GROUP_MASK 0x00ff0000 VALUE_MASK 0x0000ffff This could be improved by changing the arrays of wValues for each channel to contain named definitions (e.g. SND_DJM_CAP_LINE). It would improve readability and perhaps would allow using the same array for multiple channels. The channel number can be specified on the control next to the wIndex. Feedback is very much appreciated as I'm not the most proficient C programmer but am learning as I go. Signed-off-by: Olivia Mackintosh Link: https://lore.kernel.org/r/20210205184256.10201-2-livvy@base.nu Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 336 ++++++++++++++++++++++++++++++----------------- 1 file changed, 216 insertions(+), 120 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index abad1d61a536..9d0ac2aa9044 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2603,141 +2603,221 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) } /* - * Pioneer DJ DJM-250MK2 and maybe other DJM models + * Pioneer DJ DJM Mixers * - * For playback, no duplicate mapping should be set. - * There are three mixer stereo channels (CH1, CH2, AUX) - * and three stereo sources (Playback 1-2, Playback 3-4, Playback 5-6). - * Each channel should be mapped just once to one source. - * If mapped multiple times, only one source will play on given channel - * (sources are not mixed together). + * These devices generally have options for soft-switching the playback and + * capture sources in addition to the recording level. Although different + * devices have different configurations, there seems to be canonical values + * for specific capture/playback types: See the definitions of these below. * - * For recording, duplicate mapping is OK. We will get the same signal multiple times. - * - * Channels 7-8 are in both directions fixed to FX SEND / FX RETURN. - * - * See also notes in the quirks-table.h file. + * The wValue is masked with the stereo channel number. e.g. Setting Ch2 to + * capture phono would be 0x0203. Capture, playback and capture level have + * different wIndexes. */ -struct snd_pioneer_djm_option { - const u16 wIndex; - const u16 wValue; +// Capture types +#define SND_DJM_CAP_LINE 0x00 +#define SND_DJM_CAP_CDLINE 0x01 +#define SND_DJM_CAP_PHONO 0x03 +#define SND_DJM_CAP_PFADER 0x06 +#define SND_DJM_CAP_XFADERA 0x07 +#define SND_DJM_CAP_XFADERB 0x08 +#define SND_DJM_CAP_MIC 0x09 +#define SND_DJM_CAP_AUX 0x0d +#define SND_DJM_CAP_RECOUT 0x0a +#define SND_DJM_CAP_NONE 0x0f +#define SND_DJM_CAP_CH1PFADER 0x11 +#define SND_DJM_CAP_CH2PFADER 0x12 + +// Playback types +#define SND_DJM_PB_CH1 0x00 +#define SND_DJM_PB_CH2 0x01 +#define SND_DJM_PB_AUX 0x04 + +#define SND_DJM_WINDEX_CAP 0x8002 +#define SND_DJM_WINDEX_CAPLVL 0x8003 +#define SND_DJM_WINDEX_PB 0x8016 + +// kcontrol->private_value layout +#define SND_DJM_VALUE_MASK 0x0000ffff +#define SND_DJM_GROUP_MASK 0x00ff0000 +#define SND_DJM_DEVICE_MASK 0xff000000 +#define SND_DJM_GROUP_SHIFT 16 +#define SND_DJM_DEVICE_SHIFT 24 + +// device table index +#define SND_DJM_250MK2_IDX 0x0 +#define SND_DJM_750_IDX 0x1 + + +#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ + .name = _name, \ + .options = snd_djm_opts_##suffix, \ + .noptions = ARRAY_SIZE(snd_djm_opts_##suffix), \ + .default_value = _default_value, \ + .wIndex = _windex } + +#define SND_DJM_DEVICE(suffix) { \ + .controls = snd_djm_ctls_##suffix, \ + .ncontrols = ARRAY_SIZE(snd_djm_ctls_##suffix) } + + +struct snd_djm_device { const char *name; + const struct snd_djm_ctl *controls; + size_t ncontrols; }; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_level[] = { - { .name = "-5 dB", .wValue = 0x0300, .wIndex = 0x8003 }, - { .name = "-10 dB", .wValue = 0x0200, .wIndex = 0x8003 }, - { .name = "-15 dB", .wValue = 0x0100, .wIndex = 0x8003 }, - { .name = "-19 dB", .wValue = 0x0000, .wIndex = 0x8003 } +struct snd_djm_ctl { + const char *name; + const u16 *options; + size_t noptions; + u16 default_value; + u16 wIndex; }; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch12[] = { - { .name = "CH1 Control Tone PHONO", .wValue = 0x0103, .wIndex = 0x8002 }, - { .name = "CH1 Control Tone LINE", .wValue = 0x0100, .wIndex = 0x8002 }, - { .name = "Post CH1 Fader", .wValue = 0x0106, .wIndex = 0x8002 }, - { .name = "Cross Fader A", .wValue = 0x0107, .wIndex = 0x8002 }, - { .name = "Cross Fader B", .wValue = 0x0108, .wIndex = 0x8002 }, - { .name = "MIC", .wValue = 0x0109, .wIndex = 0x8002 }, - { .name = "AUX", .wValue = 0x010d, .wIndex = 0x8002 }, - { .name = "REC OUT", .wValue = 0x010a, .wIndex = 0x8002 } +static const char *snd_djm_get_label_caplevel(u16 wvalue) +{ + switch (wvalue) { + case 0x0000: return "-19dB"; + case 0x0100: return "-15dB"; + case 0x0200: return "-10dB"; + case 0x0300: return "-5dB"; + default: return NULL; + } }; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch34[] = { - { .name = "CH2 Control Tone PHONO", .wValue = 0x0203, .wIndex = 0x8002 }, - { .name = "CH2 Control Tone LINE", .wValue = 0x0200, .wIndex = 0x8002 }, - { .name = "Post CH2 Fader", .wValue = 0x0206, .wIndex = 0x8002 }, - { .name = "Cross Fader A", .wValue = 0x0207, .wIndex = 0x8002 }, - { .name = "Cross Fader B", .wValue = 0x0208, .wIndex = 0x8002 }, - { .name = "MIC", .wValue = 0x0209, .wIndex = 0x8002 }, - { .name = "AUX", .wValue = 0x020d, .wIndex = 0x8002 }, - { .name = "REC OUT", .wValue = 0x020a, .wIndex = 0x8002 } +static const char *snd_djm_get_label_cap(u16 wvalue) +{ + switch (wvalue & 0x00ff) { + case SND_DJM_CAP_LINE: return "Control Tone LINE"; + case SND_DJM_CAP_CDLINE: return "Control Tone CD/LINE"; + case SND_DJM_CAP_PHONO: return "Control Tone PHONO"; + case SND_DJM_CAP_PFADER: return "Post Fader"; + case SND_DJM_CAP_XFADERA: return "Cross Fader A"; + case SND_DJM_CAP_XFADERB: return "Cross Fader B"; + case SND_DJM_CAP_MIC: return "Mic"; + case SND_DJM_CAP_RECOUT: return "Rec Out"; + case SND_DJM_CAP_AUX: return "Aux"; + case SND_DJM_CAP_NONE: return "None"; + case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1"; + case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; + default: return NULL; + } }; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch56[] = { - { .name = "REC OUT", .wValue = 0x030a, .wIndex = 0x8002 }, - { .name = "Post CH1 Fader", .wValue = 0x0311, .wIndex = 0x8002 }, - { .name = "Post CH2 Fader", .wValue = 0x0312, .wIndex = 0x8002 }, - { .name = "Cross Fader A", .wValue = 0x0307, .wIndex = 0x8002 }, - { .name = "Cross Fader B", .wValue = 0x0308, .wIndex = 0x8002 }, - { .name = "MIC", .wValue = 0x0309, .wIndex = 0x8002 }, - { .name = "AUX", .wValue = 0x030d, .wIndex = 0x8002 } +static const char *snd_djm_get_label_pb(u16 wvalue) +{ + switch (wvalue & 0x00ff) { + case SND_DJM_PB_CH1: return "Ch1"; + case SND_DJM_PB_CH2: return "Ch2"; + case SND_DJM_PB_AUX: return "Aux"; + default: return NULL; + } }; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_12[] = { - { .name = "CH1", .wValue = 0x0100, .wIndex = 0x8016 }, - { .name = "CH2", .wValue = 0x0101, .wIndex = 0x8016 }, - { .name = "AUX", .wValue = 0x0104, .wIndex = 0x8016 } +static const char *snd_djm_get_label(u16 wvalue, u16 windex) +{ + switch (windex) { + case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue); + case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(wvalue); + case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue); + default: return NULL; + } }; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_34[] = { - { .name = "CH1", .wValue = 0x0200, .wIndex = 0x8016 }, - { .name = "CH2", .wValue = 0x0201, .wIndex = 0x8016 }, - { .name = "AUX", .wValue = 0x0204, .wIndex = 0x8016 } -}; -static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_56[] = { - { .name = "CH1", .wValue = 0x0300, .wIndex = 0x8016 }, - { .name = "CH2", .wValue = 0x0301, .wIndex = 0x8016 }, - { .name = "AUX", .wValue = 0x0304, .wIndex = 0x8016 } +// DJM-250MK2 +static const u16 snd_djm_opts_cap_level[] = { + 0x0000, 0x0100, 0x0200, 0x0300 }; + +static const u16 snd_djm_opts_250mk2_cap1[] = { + 0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a }; + +static const u16 snd_djm_opts_250mk2_cap2[] = { + 0x0203, 0x0200, 0x0206, 0x0207, 0x0208, 0x0209, 0x020d, 0x020a }; + +static const u16 snd_djm_opts_250mk2_cap3[] = { + 0x030a, 0x0311, 0x0312, 0x0307, 0x0308, 0x0309, 0x030d }; + +static const u16 snd_djm_opts_250mk2_pb1[] = { 0x0100, 0x0101, 0x0104 }; +static const u16 snd_djm_opts_250mk2_pb2[] = { 0x0200, 0x0201, 0x0204 }; +static const u16 snd_djm_opts_250mk2_pb3[] = { 0x0300, 0x0301, 0x0304 }; + +static const struct snd_djm_ctl snd_djm_ctls_250mk2[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Ch1 Input", 250mk2_cap1, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", 250mk2_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", 250mk2_cap3, 0, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch1 Output", 250mk2_pb1, 0, SND_DJM_WINDEX_PB), + SND_DJM_CTL("Ch2 Output", 250mk2_pb2, 1, SND_DJM_WINDEX_PB), + SND_DJM_CTL("Ch3 Output", 250mk2_pb3, 2, SND_DJM_WINDEX_PB) }; -struct snd_pioneer_djm_option_group { - const char *name; - const struct snd_pioneer_djm_option *options; - const size_t count; - const u16 default_value; + +// DJM-750 +static const u16 snd_djm_opts_750_cap1[] = { + 0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f }; +static const u16 snd_djm_opts_750_cap2[] = { + 0x0200, 0x0201, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020f }; +static const u16 snd_djm_opts_750_cap3[] = { + 0x0300, 0x0301, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030f }; +static const u16 snd_djm_opts_750_cap4[] = { + 0x0401, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f }; + +static const struct snd_djm_ctl snd_djm_ctls_750[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Ch1 Input", 750_cap1, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", 750_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", 750_cap3, 0, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch4 Input", 750_cap4, 0, SND_DJM_WINDEX_CAP) }; -#define snd_pioneer_djm_option_group_item(_name, suffix, _default_value) { \ - .name = _name, \ - .options = snd_pioneer_djm_options_##suffix, \ - .count = ARRAY_SIZE(snd_pioneer_djm_options_##suffix), \ - .default_value = _default_value } - -static const struct snd_pioneer_djm_option_group snd_pioneer_djm_option_groups[] = { - snd_pioneer_djm_option_group_item("Master Capture Level Capture Switch", capture_level, 0), - snd_pioneer_djm_option_group_item("Capture 1-2 Capture Switch", capture_ch12, 2), - snd_pioneer_djm_option_group_item("Capture 3-4 Capture Switch", capture_ch34, 2), - snd_pioneer_djm_option_group_item("Capture 5-6 Capture Switch", capture_ch56, 0), - snd_pioneer_djm_option_group_item("Playback 1-2 Playback Switch", playback_12, 0), - snd_pioneer_djm_option_group_item("Playback 3-4 Playback Switch", playback_34, 1), - snd_pioneer_djm_option_group_item("Playback 5-6 Playback Switch", playback_56, 2) + +static const struct snd_djm_device snd_djm_devices[] = { + SND_DJM_DEVICE(250mk2), + SND_DJM_DEVICE(750) }; -// layout of the kcontrol->private_value: -#define SND_PIONEER_DJM_VALUE_MASK 0x0000ffff -#define SND_PIONEER_DJM_GROUP_MASK 0xffff0000 -#define SND_PIONEER_DJM_GROUP_SHIFT 16 -static int snd_pioneer_djm_controls_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info) +static int snd_djm_controls_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *info) { - u16 group_index = kctl->private_value >> SND_PIONEER_DJM_GROUP_SHIFT; - size_t count; + unsigned long private_value = kctl->private_value; + u8 device_idx = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; + u8 ctl_idx = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; const char *name; - const struct snd_pioneer_djm_option_group *group; + const struct snd_djm_ctl *ctl; + size_t noptions; + + if (ctl_idx >= device->ncontrols) + return -EINVAL; + + ctl = &device->controls[ctl_idx]; + noptions = ctl->noptions; + if (info->value.enumerated.item >= noptions) + info->value.enumerated.item = noptions - 1; - if (group_index >= ARRAY_SIZE(snd_pioneer_djm_option_groups)) + name = snd_djm_get_label(ctl->options[info->value.enumerated.item], + ctl->wIndex); + if (!name) return -EINVAL; - group = &snd_pioneer_djm_option_groups[group_index]; - count = group->count; - if (info->value.enumerated.item >= count) - info->value.enumerated.item = count - 1; - name = group->options[info->value.enumerated.item].name; strscpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name)); info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; info->count = 1; - info->value.enumerated.items = count; + info->value.enumerated.items = noptions; return 0; } -static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u16 group, u16 value) +static int snd_djm_controls_update(struct usb_mixer_interface *mixer, + u8 device_idx, u8 group, u16 value) { int err; + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; - if (group >= ARRAY_SIZE(snd_pioneer_djm_option_groups) - || value >= snd_pioneer_djm_option_groups[group].count) + if ((group >= device->ncontrols) || value >= device->controls[group].noptions) return -EINVAL; err = snd_usb_lock_shutdown(mixer->chip); @@ -2748,63 +2828,76 @@ static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u1 mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), USB_REQ_SET_FEATURE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - snd_pioneer_djm_option_groups[group].options[value].wValue, - snd_pioneer_djm_option_groups[group].options[value].wIndex, + device->controls[group].options[value], + device->controls[group].wIndex, NULL, 0); snd_usb_unlock_shutdown(mixer->chip); return err; } -static int snd_pioneer_djm_controls_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) +static int snd_djm_controls_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *elem) { - elem->value.enumerated.item[0] = kctl->private_value & SND_PIONEER_DJM_VALUE_MASK; + elem->value.enumerated.item[0] = kctl->private_value & SND_DJM_VALUE_MASK; return 0; } -static int snd_pioneer_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) +static int snd_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) { struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); struct usb_mixer_interface *mixer = list->mixer; unsigned long private_value = kctl->private_value; - u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT; + + u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; + u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; u16 value = elem->value.enumerated.item[0]; - kctl->private_value = (group << SND_PIONEER_DJM_GROUP_SHIFT) | value; + kctl->private_value = ((device << SND_DJM_DEVICE_SHIFT) | + (group << SND_DJM_GROUP_SHIFT) | + value); - return snd_pioneer_djm_controls_update(mixer, group, value); + return snd_djm_controls_update(mixer, device, group, value); } -static int snd_pioneer_djm_controls_resume(struct usb_mixer_elem_list *list) +static int snd_djm_controls_resume(struct usb_mixer_elem_list *list) { unsigned long private_value = list->kctl->private_value; - u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT; - u16 value = (private_value & SND_PIONEER_DJM_VALUE_MASK); + u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; + u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; + u16 value = (private_value & SND_DJM_VALUE_MASK); - return snd_pioneer_djm_controls_update(list->mixer, group, value); + return snd_djm_controls_update(list->mixer, device, group, value); } -static int snd_pioneer_djm_controls_create(struct usb_mixer_interface *mixer) +static int snd_djm_controls_create(struct usb_mixer_interface *mixer, + const u8 device_idx) { int err, i; - const struct snd_pioneer_djm_option_group *group; + u16 value; + + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; + struct snd_kcontrol_new knew = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .index = 0, - .info = snd_pioneer_djm_controls_info, - .get = snd_pioneer_djm_controls_get, - .put = snd_pioneer_djm_controls_put + .info = snd_djm_controls_info, + .get = snd_djm_controls_get, + .put = snd_djm_controls_put }; - for (i = 0; i < ARRAY_SIZE(snd_pioneer_djm_option_groups); i++) { - group = &snd_pioneer_djm_option_groups[i]; - knew.name = group->name; - knew.private_value = (i << SND_PIONEER_DJM_GROUP_SHIFT) | group->default_value; - err = snd_pioneer_djm_controls_update(mixer, i, group->default_value); + for (i = 0; i < device->ncontrols; i++) { + value = device->controls[i].default_value; + knew.name = device->controls[i].name; + knew.private_value = ( + (device_idx << SND_DJM_DEVICE_SHIFT) | + (i << SND_DJM_GROUP_SHIFT) | + value); + err = snd_djm_controls_update(mixer, device_idx, i, value); if (err) return err; - err = add_single_ctl_with_resume(mixer, 0, snd_pioneer_djm_controls_resume, + err = add_single_ctl_with_resume(mixer, 0, snd_djm_controls_resume, &knew, NULL); if (err) return err; @@ -2917,7 +3010,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) err = snd_bbfpro_controls_create(mixer); break; case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */ - err = snd_pioneer_djm_controls_create(mixer); + err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX); + break; + case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ + err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); break; } -- cgit v1.2.3 From fee03efc69345344c8851596d74d93199b175bfe Mon Sep 17 00:00:00 2001 From: Fabian Lesniak Date: Fri, 5 Feb 2021 22:51:16 +0100 Subject: ALSA: usb-audio: add mixer quirks for Pioneer DJM-900NXS2 This commit adds mixer quirks for the Pioneer DJM-900NXS2 mixer. This device has 6 capture channels, 5 of them allow setting the signal source. This adds controls for these, similar to the DJM-250Mk2. However, playpack channels are not controllable via software like on the 250Mk2, as they can only be set manually on the mixing console. Read-only controls showing the currently selected playback channels are omitted. Signed-off-by: Fabian Lesniak Link: https://lore.kernel.org/r/20210205215116.258724-2-fabian@lesniak-it.de Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 9d0ac2aa9044..08873d2afe4d 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2618,6 +2618,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) // Capture types #define SND_DJM_CAP_LINE 0x00 #define SND_DJM_CAP_CDLINE 0x01 +#define SND_DJM_CAP_DIGITAL 0x02 #define SND_DJM_CAP_PHONO 0x03 #define SND_DJM_CAP_PFADER 0x06 #define SND_DJM_CAP_XFADERA 0x07 @@ -2628,6 +2629,8 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) #define SND_DJM_CAP_NONE 0x0f #define SND_DJM_CAP_CH1PFADER 0x11 #define SND_DJM_CAP_CH2PFADER 0x12 +#define SND_DJM_CAP_CH3PFADER 0x13 +#define SND_DJM_CAP_CH4PFADER 0x14 // Playback types #define SND_DJM_PB_CH1 0x00 @@ -2648,6 +2651,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) // device table index #define SND_DJM_250MK2_IDX 0x0 #define SND_DJM_750_IDX 0x1 +#define SND_DJM_900NXS2_IDX 0x2 #define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ @@ -2692,6 +2696,7 @@ static const char *snd_djm_get_label_cap(u16 wvalue) switch (wvalue & 0x00ff) { case SND_DJM_CAP_LINE: return "Control Tone LINE"; case SND_DJM_CAP_CDLINE: return "Control Tone CD/LINE"; + case SND_DJM_CAP_DIGITAL: return "Control Tone DIGITAL"; case SND_DJM_CAP_PHONO: return "Control Tone PHONO"; case SND_DJM_CAP_PFADER: return "Post Fader"; case SND_DJM_CAP_XFADERA: return "Cross Fader A"; @@ -2702,6 +2707,8 @@ static const char *snd_djm_get_label_cap(u16 wvalue) case SND_DJM_CAP_NONE: return "None"; case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1"; case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; + case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3"; + case SND_DJM_CAP_CH4PFADER: return "Post Fader Ch4"; default: return NULL; } }; @@ -2774,9 +2781,32 @@ static const struct snd_djm_ctl snd_djm_ctls_750[] = { }; +// DJM-900NXS2 +static const u16 snd_djm_opts_900nxs2_cap1[] = { + 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a }; +static const u16 snd_djm_opts_900nxs2_cap2[] = { + 0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a }; +static const u16 snd_djm_opts_900nxs2_cap3[] = { + 0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a }; +static const u16 snd_djm_opts_900nxs2_cap4[] = { + 0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a }; +static const u16 snd_djm_opts_900nxs2_cap5[] = { + 0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 }; + +static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Ch1 Input", 900nxs2_cap1, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", 900nxs2_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", 900nxs2_cap3, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch4 Input", 900nxs2_cap4, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch5 Input", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP) +}; + + static const struct snd_djm_device snd_djm_devices[] = { SND_DJM_DEVICE(250mk2), - SND_DJM_DEVICE(750) + SND_DJM_DEVICE(750), + SND_DJM_DEVICE(900nxs2) }; @@ -3015,6 +3045,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); break; + case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ + err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX); + break; } return err; -- cgit v1.2.3 From c237813e3a1039331cf3d0bffba895b0ab52710a Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Sun, 7 Feb 2021 15:02:41 +0800 Subject: ALSA: azt3328: Assign boolean values to a bool variable Fix the following coccicheck warnings: ./sound/pci/azt3328.c:2451:2-16: WARNING: Assignment of 0/1 to bool variable. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Link: https://lore.kernel.org/r/1612681361-63404-1-git-send-email-jiapeng.chong@linux.alibaba.com Signed-off-by: Takashi Iwai --- sound/pci/azt3328.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index e3ea72a2116b..2ac594dcf21c 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2447,7 +2447,7 @@ snd_azf3328_create(struct snd_card *card, /* shutdown codecs to reduce power / noise */ /* have ...ctrl_codec_activity() act properly */ - codec->running = 1; + codec->running = true; snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); spin_lock_irq(codec->lock); -- cgit v1.2.3 From 45a2702ce10993eda7a5b12690294782d565519c Mon Sep 17 00:00:00 2001 From: Sathyanarayana Nujella Date: Fri, 5 Feb 2021 09:14:28 -0800 Subject: ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown During Coldboot stress tests, system encountered the following panic. Panic logs depicts rt5682_i2c_shutdown() happened first and then later jack detect handler workqueue function triggered. This situation causes panic as rt5682_i2c_shutdown() resets codec. Fix this panic by cancelling all jack detection delayed work. Panic log: [ 20.936124] sof_pci_shutdown [ 20.940248] snd_sof_device_shutdown [ 20.945023] snd_sof_shutdown [ 21.126849] rt5682_i2c_shutdown [ 21.286053] rt5682_jack_detect_handler [ 21.291235] BUG: kernel NULL pointer dereference, address: 000000000000037c [ 21.299302] #PF: supervisor read access in kernel mode [ 21.305254] #PF: error_code(0x0000) - not-present page [ 21.311218] PGD 0 P4D 0 [ 21.314155] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 21.319206] CPU: 2 PID: 123 Comm: kworker/2:3 Tainted: G U 5.4.68 #10 [ 21.333687] ACPI: Preparing to enter system sleep state S5 [ 21.337669] Workqueue: events_power_efficient rt5682_jack_detect_handler [snd_soc_rt5682] [ 21.337671] RIP: 0010:rt5682_jack_detect_handler+0x6c/0x279 [snd_soc_rt5682] Fixes: a50067d4f3c1d ('ASoC: rt5682: split i2c driver into separate module') Signed-off-by: Jairaj Arava Signed-off-by: Sathyanarayana Nujella Reviewed-by: Pierre-Louis Bossart Reviewed-by: Shuming Fan Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210205171428.2344210-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-i2c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 37d13120f5ba..93c1603b42f1 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -273,6 +273,9 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) { struct rt5682_priv *rt5682 = i2c_get_clientdata(client); + cancel_delayed_work_sync(&rt5682->jack_detect_work); + cancel_delayed_work_sync(&rt5682->jd_check_work); + rt5682_reset(rt5682); } -- cgit v1.2.3 From 9037c3bde65d339017ef41d81cb58069ffc321d4 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Mon, 8 Feb 2021 18:38:57 +0800 Subject: ASoC: SOF: debug: Fix a potential issue on string buffer termination The function simple_write_to_buffer() doesn't add string termination at the end of buf, we need to handle it on our own. This change refers to the function tokenize_input() in debug.c and the function sof_dfsentry_trace_filter_write() in trace.c. Fixes: 091c12e1f50c ("ASoC: SOF: debug: add new debugfs entries for IPC flood test") Reviewed-by: Kai Vehmanen Signed-off-by: Hui Wang Link: https://lore.kernel.org/r/20210208103857.75705-1-hui.wang@canonical.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 30213a1beaaa..715a374b33cf 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -352,7 +352,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, char *string; int ret; - string = kzalloc(count, GFP_KERNEL); + string = kzalloc(count+1, GFP_KERNEL); if (!string) return -ENOMEM; -- cgit v1.2.3 From 6e4ea8aace02479186b3fdaab48d7acfe06d8715 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Sun, 7 Feb 2021 23:06:57 +0530 Subject: ASoC: audio-graph: Rename functions needed for export Following functions are renamed for a better global visibility. graph_card_probe() --> audio_graph_card_probe() graph_parse_of() --> audio_graph_parse_of() graph_remove() --> audio_graph_remove() [exported as well] The references of these are updated in audio graph and Tegra audio graph card drivers. Signed-off-by: Sameer Pujar Cc: Kuninori Morimoto Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/1612719418-5858-2-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- include/sound/graph_card.h | 6 ++++-- sound/soc/generic/audio-graph-card.c | 17 +++++++++-------- sound/soc/tegra/tegra_audio_graph_card.c | 6 +++--- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index bbb5a137855c..013784467bec 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -9,8 +9,10 @@ #include -int graph_card_probe(struct snd_soc_card *card); +int audio_graph_card_probe(struct snd_soc_card *card); -int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); +int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); + +int audio_graph_remove(struct platform_device *pdev); #endif /* __GRAPH_CARD_H */ diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 16a04a678828..8c5cdcdc8713 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -532,7 +532,7 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, static void graph_get_dais_count(struct asoc_simple_priv *priv, struct link_info *li); -int graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) +int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) { struct snd_soc_card *card = simple_priv_to_card(priv); struct link_info li; @@ -608,7 +608,7 @@ err: return ret; } -EXPORT_SYMBOL_GPL(graph_parse_of); +EXPORT_SYMBOL_GPL(audio_graph_parse_of); static int graph_count_noml(struct asoc_simple_priv *priv, struct device_node *cpu_ep, @@ -705,7 +705,7 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv, li->link, li->dais, li->conf); } -int graph_card_probe(struct snd_soc_card *card) +int audio_graph_card_probe(struct snd_soc_card *card) { struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); int ret; @@ -720,7 +720,7 @@ int graph_card_probe(struct snd_soc_card *card) return 0; } -EXPORT_SYMBOL_GPL(graph_card_probe); +EXPORT_SYMBOL_GPL(audio_graph_card_probe); static int graph_probe(struct platform_device *pdev) { @@ -736,20 +736,21 @@ static int graph_probe(struct platform_device *pdev) card = simple_priv_to_card(priv); card->dapm_widgets = graph_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets); - card->probe = graph_card_probe; + card->probe = audio_graph_card_probe; if (of_device_get_match_data(dev)) priv->dpcm_selectable = 1; - return graph_parse_of(priv, dev); + return audio_graph_parse_of(priv, dev); } -static int graph_remove(struct platform_device *pdev) +int audio_graph_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); return asoc_simple_clean_reference(card); } +EXPORT_SYMBOL_GPL(audio_graph_remove); static const struct of_device_id graph_of_match[] = { { .compatible = "audio-graph-card", }, @@ -766,7 +767,7 @@ static struct platform_driver graph_card = { .of_match_table = graph_of_match, }, .probe = graph_probe, - .remove = graph_remove, + .remove = audio_graph_remove, }; module_platform_driver(graph_card); diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c index 9e43f16f9336..121e5721f61d 100644 --- a/sound/soc/tegra/tegra_audio_graph_card.c +++ b/sound/soc/tegra/tegra_audio_graph_card.c @@ -184,7 +184,7 @@ static int tegra_audio_graph_card_probe(struct snd_soc_card *card) return PTR_ERR(priv->clk_plla_out0); } - return graph_card_probe(card); + return audio_graph_card_probe(card); } static int tegra_audio_graph_probe(struct platform_device *pdev) @@ -201,12 +201,12 @@ static int tegra_audio_graph_probe(struct platform_device *pdev) card->probe = tegra_audio_graph_card_probe; - /* graph_parse_of() depends on below */ + /* audio_graph_parse_of() depends on below */ card->component_chaining = 1; priv->simple.ops = &tegra_audio_graph_ops; priv->simple.force_dpcm = 1; - return graph_parse_of(&priv->simple, dev); + return audio_graph_parse_of(&priv->simple, dev); } static const struct tegra_audio_cdata tegra210_data = { -- cgit v1.2.3 From 0d7475d2a5a90127a2f87961b99bcd8f95694dd9 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Sun, 7 Feb 2021 23:06:58 +0530 Subject: ASoC: tegra: Add driver remove() callback There is cleanup required, related to release of phandles, during driver removal and hence point remove callback to audio_graph_remove(). Fixes: 202e2f774543 ("ASoC: tegra: Add audio graph based card driver") Depends-on: "ASoC: audio-graph: Rename functions needed for export" Signed-off-by: Sameer Pujar Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/1612719418-5858-3-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_audio_graph_card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c index 121e5721f61d..ddedf18adde1 100644 --- a/sound/soc/tegra/tegra_audio_graph_card.c +++ b/sound/soc/tegra/tegra_audio_graph_card.c @@ -2,7 +2,7 @@ // // tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver // -// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. +// Copyright (c) 2020-2021 NVIDIA CORPORATION. All rights reserved. #include #include @@ -243,6 +243,7 @@ static struct platform_driver tegra_audio_graph_card = { .of_match_table = graph_of_tegra_match, }, .probe = tegra_audio_graph_probe, + .remove = audio_graph_remove, }; module_platform_driver(tegra_audio_graph_card); -- cgit v1.2.3 From 28785f548d18e6d52785a1172e5c176784ce74cd Mon Sep 17 00:00:00 2001 From: Sia Jee Heng Date: Thu, 4 Feb 2021 09:42:55 +0800 Subject: ASoC: codec: hdmi-codec: Support IEC958 encoded PCM format Existing hdmi-codec driver only support standard pcm format. Support of IEC958 encoded format pass from ALSA IEC958 plugin is needed so that the IEC958 encoded data can be streamed to the HDMI chip. Signed-off-by: Sia Jee Heng Link: https://lore.kernel.org/r/20210204014258.10197-2-jee.heng.sia@intel.com Signed-off-by: Mark Brown --- include/sound/hdmi-codec.h | 5 +++++ sound/soc/codecs/hdmi-codec.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index b55970859a13..4b3a1d374b90 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h @@ -34,6 +34,11 @@ struct hdmi_codec_daifmt { unsigned int frame_clk_inv:1; unsigned int bit_clk_master:1; unsigned int frame_clk_master:1; + /* bit_fmt could be standard PCM format or + * IEC958 encoded format. ALSA IEC958 plugin will pass + * IEC958_SUBFRAME format to the underneath driver. + */ + snd_pcm_format_t bit_fmt; }; /* diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 0f3ac22f2cf8..422539f933de 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -489,6 +489,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, hp.sample_rate = params_rate(params); hp.channels = params_channels(params); + cf->bit_fmt = params_format(params); return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data, cf, &hp); } @@ -617,7 +618,8 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = { SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\ + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) -- cgit v1.2.3 From 1c5f6e0714c16e3ad8732e49e07082772dcc6f87 Mon Sep 17 00:00:00 2001 From: Sia Jee Heng Date: Thu, 4 Feb 2021 09:42:58 +0800 Subject: ASoC: Intel: KMB: Support IEC958 encoded PCM format Support ALSA IEC958 plugin for KeemBay I2S driver. Bit manipulation needed as IEC958 format supported by ADV7511 HDMI chip is not compatible with the ALSA IEC958 plugin format. Signed-off-by: Sia Jee Heng Link: https://lore.kernel.org/r/20210204014258.10197-5-jee.heng.sia@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/keembay/kmb_platform.c | 73 +++++++++++++++++++++++++++++++++- sound/soc/intel/keembay/kmb_platform.h | 1 + 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 4961ba89c110..0fd1e8f62c89 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -5,6 +5,7 @@ // Intel KeemBay Platform driver. // +#include #include #include #include @@ -39,7 +40,8 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = { .rate_max = 48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = BUFFER_BYTES_MAX, @@ -50,6 +52,50 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = { .fifo_size = 16, }; +/* + * Convert to ADV7511 HDMI hardware format. + * ADV7511 HDMI chip need parity bit replaced by block start bit and + * with the preamble bits left out. + * ALSA IEC958 subframe format: + * bit 0-3 = preamble (0x8 = block start) + * 4-7 = AUX (=0) + * 8-27 = audio data (without AUX if 24bit sample) + * 28 = validity + * 29 = user data + * 30 = channel status + * 31 = parity + * + * ADV7511 IEC958 subframe format: + * bit 0-23 = audio data + * 24 = validity + * 25 = user data + * 26 = channel status + * 27 = block start + * 28-31 = 0 + * MSB to LSB bit reverse by software as hardware not supporting it. + */ +static void hdmi_reformat_iec958(struct snd_pcm_runtime *runtime, + struct kmb_i2s_info *kmb_i2s, + unsigned int tx_ptr) +{ + u32(*buf)[2] = (void *)runtime->dma_area; + unsigned long temp; + u32 i, j, sample; + + for (i = 0; i < kmb_i2s->fifo_th; i++) { + j = 0; + do { + temp = buf[tx_ptr][j]; + /* Replace parity with block start*/ + assign_bit(31, &temp, (BIT(3) & temp)); + sample = bitrev32(temp); + buf[tx_ptr][j] = sample << 4; + j++; + } while (j < 2); + tx_ptr++; + } +} + static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, struct snd_pcm_runtime *runtime, unsigned int tx_ptr, bool *period_elapsed) @@ -65,6 +111,8 @@ static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); } else { + if (kmb_i2s->iec958_fmt) + hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr); writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); } @@ -235,6 +283,7 @@ static int kmb_pcm_trigger(struct snd_soc_component *component, kmb_i2s->tx_substream = NULL; else kmb_i2s->rx_substream = NULL; + kmb_i2s->iec958_fmt = false; break; default: return -EINVAL; @@ -549,6 +598,9 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; + case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: + kmb_i2s->iec958_fmt = true; + fallthrough; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; kmb_i2s->ccr = 0x10; @@ -686,6 +738,24 @@ static struct snd_soc_dai_ops kmb_dai_ops = { .set_fmt = kmb_set_dai_fmt, }; +static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = { + { + .name = "intel_kmb_hdmi_i2s", + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE), + }, + .ops = &kmb_dai_ops, + .probe = kmb_probe, + }, +}; + static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = { { .name = "intel_kmb_i2s", @@ -740,6 +810,7 @@ static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = { static const struct of_device_id kmb_plat_of_match[] = { { .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai}, + { .compatible = "intel,keembay-hdmi-i2s", .data = &intel_kmb_hdmi_dai}, { .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai}, {} }; diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h index 67234caee814..29be2cd84ddb 100644 --- a/sound/soc/intel/keembay/kmb_platform.h +++ b/sound/soc/intel/keembay/kmb_platform.h @@ -150,6 +150,7 @@ struct kmb_i2s_info { struct snd_pcm_substream *rx_substream; unsigned int tx_ptr; unsigned int rx_ptr; + bool iec958_fmt; }; #endif /* KMB_PLATFORM_H_ */ -- cgit v1.2.3 From d5e16dc5fdad09d7b3133b6aaea7848bfb518e04 Mon Sep 17 00:00:00 2001 From: Sia Jee Heng Date: Thu, 4 Feb 2021 09:42:57 +0800 Subject: ASoC: Intel, Keembay-i2s: Add hdmi-i2s compatible string Add intel,keembay-hdmi-i2s compatible string to support the HDMI interface. Signed-off-by: Sia Jee Heng Link: https://lore.kernel.org/r/20210204014258.10197-4-jee.heng.sia@intel.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index dba25c33f0b0..6f71294909a5 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -18,6 +18,7 @@ properties: enum: - intel,keembay-i2s - intel,keembay-tdm + - intel,keembay-hdmi-i2s "#sound-dai-cells": const: 0 -- cgit v1.2.3 From 38d89a564847048c0f6fe53a829d15edb4f21da3 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sat, 6 Feb 2021 23:58:49 +0100 Subject: ASoC: fsl: constify static snd_soc_dai_ops structs The only usage of these is to assign their address to the 'ops' field in the snd_soc_dai_driver struct, which is a pointer to const. Make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20210206225849.51071-1-rikard.falkeborn@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 2 +- sound/soc/fsl/fsl_micfil.c | 2 +- sound/soc/fsl/fsl_xcvr.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 60951a8aabd3..636a702f37a6 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1530,7 +1530,7 @@ static int fsl_easrc_hw_free(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_dai_ops fsl_easrc_dai_ops = { +static const struct snd_soc_dai_ops fsl_easrc_dai_ops = { .startup = fsl_easrc_startup, .trigger = fsl_easrc_trigger, .hw_params = fsl_easrc_hw_params, diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 8aedf6590b28..5935af2e5ff4 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -381,7 +381,7 @@ static int fsl_micfil_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, return ret; } -static struct snd_soc_dai_ops fsl_micfil_dai_ops = { +static const struct snd_soc_dai_ops fsl_micfil_dai_ops = { .startup = fsl_micfil_startup, .trigger = fsl_micfil_trigger, .hw_params = fsl_micfil_hw_params, diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index dd228b421e2c..6dd0a5fcd455 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -857,7 +857,7 @@ static struct snd_kcontrol_new fsl_xcvr_tx_ctls[] = { }, }; -static struct snd_soc_dai_ops fsl_xcvr_dai_ops = { +static const struct snd_soc_dai_ops fsl_xcvr_dai_ops = { .prepare = fsl_xcvr_prepare, .startup = fsl_xcvr_startup, .shutdown = fsl_xcvr_shutdown, -- cgit v1.2.3 From 40bd053bc8e18b68e877bd4cdea1b6938ddf5fdd Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 6 Feb 2021 11:27:53 -0300 Subject: ASoC: fsl_esai: Remove unused 'imx' field The 'imx' field is not used anywhere, so get rid of it. Signed-off-by: Fabio Estevam Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20210206142753.536459-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index bac9f059c9fc..08056fa0a0fa 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -23,11 +23,9 @@ /** * struct fsl_esai_soc_data - soc specific data - * @imx: for imx platform * @reset_at_xrun: flags for enable reset operaton */ struct fsl_esai_soc_data { - bool imx; bool reset_at_xrun; }; @@ -86,17 +84,14 @@ struct fsl_esai { }; static struct fsl_esai_soc_data fsl_esai_vf610 = { - .imx = false, .reset_at_xrun = true, }; static struct fsl_esai_soc_data fsl_esai_imx35 = { - .imx = true, .reset_at_xrun = true, }; static struct fsl_esai_soc_data fsl_esai_imx6ull = { - .imx = true, .reset_at_xrun = false, }; -- cgit v1.2.3 From f9e5fd1b666e9d34c94b91808bda02c2d4d00776 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 5 Feb 2021 20:46:28 +0200 Subject: ALSA: hda: add link_power op to hdac_bus_ops The extended HDA bus (hdac_ext) provides interfaces for more fine-grained control of individual links than what plain HDA provides for. Links can be powered off when they are not used and if all links are released, controller can shut down the command DMA. These interfaces are currently not used by common HDA codec drivers. When a HDA codec is runtime suspended, it calls snd_hdac_codec_link_down(), but there is no link to the HDA extended bus, and on controller side the links are shut down only when all codecs are suspended. This patch adds link_power() to hdac_bus ops. Controllers using the HDA extended core, can use this to plug in snd_hdac_ext_bus_link_power() to implement more fine-grained control of link power. No change is needed for plain HDA controllers nor to existing HDA codec drivers. Co-developed-by: Ranjani Sridharan Signed-off-by: Ranjani Sridharan Signed-off-by: Kai Vehmanen Acked-by: Mark Brown Link: https://lore.kernel.org/r/20210205184630.1938761-2-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 14 +++++--------- include/sound/hdaudio_ext.h | 2 ++ sound/hda/ext/hdac_ext_controller.c | 37 +++++++++++++++++++++++++++++++++++++ sound/hda/hdac_bus.c | 23 +++++++++++++++++++++++ sound/hda/hdac_controller.c | 14 ++++++++++++++ 5 files changed, 81 insertions(+), 9 deletions(-) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 6eed61e6cf8a..22af68b01426 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -241,6 +241,8 @@ struct hdac_bus_ops { /* get a response from the last command */ int (*get_response)(struct hdac_bus *bus, unsigned int addr, unsigned int *res); + /* notify of codec link power-up/down */ + void (*link_power)(struct hdac_device *hdev, bool enable); }; /* @@ -378,15 +380,8 @@ void snd_hdac_bus_exit(struct hdac_bus *bus); int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, unsigned int cmd, unsigned int *res); -static inline void snd_hdac_codec_link_up(struct hdac_device *codec) -{ - set_bit(codec->addr, &codec->bus->codec_powered); -} - -static inline void snd_hdac_codec_link_down(struct hdac_device *codec) -{ - clear_bit(codec->addr, &codec->bus->codec_powered); -} +void snd_hdac_codec_link_up(struct hdac_device *codec); +void snd_hdac_codec_link_down(struct hdac_device *codec); int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, @@ -400,6 +395,7 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus); void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset); +void snd_hdac_bus_link_power(struct hdac_device *hdev, bool enable); void snd_hdac_bus_update_rirb(struct hdac_bus *bus); int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 7abf74c1c474..a125e3814b58 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -131,6 +131,8 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link); int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link); +void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable); + /* update register macro */ #define snd_hdac_updatel(addr, reg, mask, val) \ writel(((readl(addr + reg) & ~(mask)) | (val)), \ diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index b0c0ef824d7d..a9bd39b93697 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -332,3 +332,40 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put); + +static void hdac_ext_codec_link_up(struct hdac_device *codec) +{ + const char *devname = dev_name(&codec->dev); + struct hdac_ext_link *hlink = + snd_hdac_ext_bus_get_link(codec->bus, devname); + + if (hlink) + snd_hdac_ext_bus_link_get(codec->bus, hlink); +} + +static void hdac_ext_codec_link_down(struct hdac_device *codec) +{ + const char *devname = dev_name(&codec->dev); + struct hdac_ext_link *hlink = + snd_hdac_ext_bus_get_link(codec->bus, devname); + + if (hlink) + snd_hdac_ext_bus_link_put(codec->bus, hlink); +} + +void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable) +{ + struct hdac_bus *bus = codec->bus; + bool oldstate = test_bit(codec->addr, &bus->codec_powered); + + if (enable == oldstate) + return; + + snd_hdac_bus_link_power(codec, enable); + + if (enable) + hdac_ext_codec_link_up(codec); + else + hdac_ext_codec_link_down(codec); +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power); diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 9766f6af8743..71db8592b33d 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -17,6 +17,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work); static const struct hdac_bus_ops default_ops = { .command = snd_hdac_bus_send_cmd, .get_response = snd_hdac_bus_get_response, + .link_power = snd_hdac_bus_link_power, }; /** @@ -264,3 +265,25 @@ void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, } EXPORT_SYMBOL_GPL(snd_hdac_aligned_write); #endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ + +void snd_hdac_codec_link_up(struct hdac_device *codec) +{ + struct hdac_bus *bus = codec->bus; + + if (bus->ops->link_power) + bus->ops->link_power(codec, true); + else + snd_hdac_bus_link_power(codec, true); +} +EXPORT_SYMBOL_GPL(snd_hdac_codec_link_up); + +void snd_hdac_codec_link_down(struct hdac_device *codec) +{ + struct hdac_bus *bus = codec->bus; + + if (bus->ops->link_power) + bus->ops->link_power(codec, false); + else + snd_hdac_bus_link_power(codec, false); +} +EXPORT_SYMBOL_GPL(snd_hdac_codec_link_down); diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index b98449fd92f3..062da7a7a586 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -648,3 +648,17 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) snd_dma_free_pages(&bus->posbuf); } EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); + +/** + * snd_hdac_bus_link_power - power up/down codec link + * @codec: HD-audio device + * @enable: whether to power-up the link + */ +void snd_hdac_bus_link_power(struct hdac_device *codec, bool enable) +{ + if (enable) + set_bit(codec->addr, &codec->bus->codec_powered); + else + clear_bit(codec->addr, &codec->bus->codec_powered); +} +EXPORT_SYMBOL_GPL(snd_hdac_bus_link_power); -- cgit v1.2.3 From 87fc20e4a0cbc01fdfc23aeba93f8ce2fc3dccda Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 5 Feb 2021 20:46:29 +0200 Subject: ASoC: SOF: Intel: hda: use hdac_ext fine-grained link management Opt-in to use snd_hdac_ext_bus_link_power() to manage HDA link power up/down events. This allows to reduce power consumption in cases where some HDA codecs are suspended, but other child devices (HDA or non-HDA codecs) remain active and controller itself remains in active state. By using snd_hdac_ext_bus_link_power(), the individual HDA links can be powered off and if all HDA codecs are powered down, the command DMA can also be shut down. Signed-off-by: Kai Vehmanen Acked-by: Mark Brown Link: https://lore.kernel.org/r/20210205184630.1938761-3-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda-bus.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 789148e5584b..1ac6e79d7e62 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -19,13 +19,21 @@ #define sof_hda_ext_ops NULL #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +static const struct hdac_bus_ops bus_core_ops = { + .command = snd_hdac_bus_send_cmd, + .get_response = snd_hdac_bus_get_response, + .link_power = snd_hdac_ext_bus_link_power, +}; +#endif + /* * This can be used for both with/without hda link support. */ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - snd_hdac_ext_bus_init(bus, dev, NULL, sof_hda_ext_ops); + snd_hdac_ext_bus_init(bus, dev, &bus_core_ops, sof_hda_ext_ops); #else /* CONFIG_SND_SOC_SOF_HDA */ memset(bus, 0, sizeof(*bus)); bus->dev = dev; -- cgit v1.2.3 From c99fafdfccd75cb9bd91666a23ae022232afa3d5 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 5 Feb 2021 20:46:30 +0200 Subject: ASoC: SOF: Intel: hda: release display power at link_power The i915 display power is requested both by controller (for init and link reset) as well as by codec driver (for codec control). There's an additional constraint that on some platforms frequent changes to display power state may cause visible flicker. To avoid this, the SOF hda controller requests display power whenever it is active and only releases it when runtime suspended. This patch utilizes the new hdac_bus link_power op to plug into HDA link state changes. By monitoring link state changes, we can keep the controller side display power wakeref until the codec driver has completed its work, and only release the wakeref when codec driver is suspended. Signed-off-by: Kai Vehmanen Acked-by: Mark Brown Link: https://lore.kernel.org/r/20210205184630.1938761-4-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda-bus.c | 25 ++++++++++++++++++++++++- sound/soc/sof/intel/hda.h | 3 ++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index 1ac6e79d7e62..30025d3c16b6 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -9,6 +9,7 @@ #include #include +#include #include "../sof-priv.h" #include "hda.h" @@ -20,10 +21,32 @@ #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable) +{ + struct hdac_bus *bus = codec->bus; + bool oldstate = test_bit(codec->addr, &bus->codec_powered); + + snd_hdac_ext_bus_link_power(codec, enable); + + if (enable == oldstate) + return; + + /* + * Both codec driver and controller can hold references to + * display power. To avoid unnecessary power-up/down cycles, + * controller doesn't immediately release its reference. + * + * If the codec driver powers down the link, release + * the controller reference as well. + */ + if (codec->addr == HDA_IDISP_ADDR && !enable) + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); +} + static const struct hdac_bus_ops bus_core_ops = { .command = snd_hdac_bus_send_cmd, .get_response = snd_hdac_bus_get_response, - .link_power = snd_hdac_ext_bus_link_power, + .link_power = sof_hda_bus_link_power, }; #endif diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index a3b6f3e9121c..1d9b38e6ed40 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -388,7 +388,8 @@ #define SSP_SET_SFRM_SLAVE BIT(24) #define SSP_SET_SLAVE (SSP_SET_SCLK_SLAVE | SSP_SET_SFRM_SLAVE) -#define HDA_IDISP_CODEC(x) ((x) & BIT(2)) +#define HDA_IDISP_ADDR 2 +#define HDA_IDISP_CODEC(x) ((x) & BIT(HDA_IDISP_ADDR)) struct sof_intel_dsp_bdl { __le32 addr_l; -- cgit v1.2.3 From c50bfc8a6866775be39d7e747e83e8a5a9051e2e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Mon, 8 Feb 2021 00:47:36 +0900 Subject: ALSA: fireface: fix to parse sync status register of latter protocol Fireface UCX, UFX, and FF802 are categorized for latter protocol of the series. Current support for FF802 (and UFX) includes failure to parse sync status register and results in EIO. Further investigation figures out that the content of register differs depending on models. This commit adds tables specific to FF802 and UFX to fix it. Fixes: 062bb452b078b ("ALSA: fireface: add support for RME FireFace 802") Cc: Signed-off-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20210207154736.229551-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-latter.c | 118 +++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 18 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index 8d3b23778eb2..7ddb7b97f02d 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -15,6 +15,61 @@ #define LATTER_FETCH_MODE 0xffff00000010ULL #define LATTER_SYNC_STATUS 0x0000801c0000ULL +// The content of sync status register differs between models. +// +// Fireface UCX: +// 0xf0000000: (unidentified) +// 0x0f000000: effective rate of sampling clock +// 0x00f00000: detected rate of word clock on BNC interface +// 0x000f0000: detected rate of ADAT or S/PDIF on optical interface +// 0x0000f000: detected rate of S/PDIF on coaxial interface +// 0x00000e00: effective source of sampling clock +// 0x00000e00: Internal +// 0x00000800: (unidentified) +// 0x00000600: Word clock on BNC interface +// 0x00000400: ADAT on optical interface +// 0x00000200: S/PDIF on coaxial or optical interface +// 0x00000100: Optical interface is used for ADAT signal +// 0x00000080: (unidentified) +// 0x00000040: Synchronized to word clock on BNC interface +// 0x00000020: Synchronized to ADAT or S/PDIF on optical interface +// 0x00000010: Synchronized to S/PDIF on coaxial interface +// 0x00000008: (unidentified) +// 0x00000004: Lock word clock on BNC interface +// 0x00000002: Lock ADAT or S/PDIF on optical interface +// 0x00000001: Lock S/PDIF on coaxial interface +// +// Fireface 802 (and perhaps UFX): +// 0xf0000000: effective rate of sampling clock +// 0x0f000000: detected rate of ADAT-B on 2nd optical interface +// 0x00f00000: detected rate of ADAT-A on 1st optical interface +// 0x000f0000: detected rate of AES/EBU on XLR or coaxial interface +// 0x0000f000: detected rate of word clock on BNC interface +// 0x00000e00: effective source of sampling clock +// 0x00000e00: internal +// 0x00000800: ADAT-B +// 0x00000600: ADAT-A +// 0x00000400: AES/EBU +// 0x00000200: Word clock +// 0x00000080: Synchronized to ADAT-B on 2nd optical interface +// 0x00000040: Synchronized to ADAT-A on 1st optical interface +// 0x00000020: Synchronized to AES/EBU on XLR or 2nd optical interface +// 0x00000010: Synchronized to word clock on BNC interface +// 0x00000008: Lock ADAT-B on 2nd optical interface +// 0x00000004: Lock ADAT-A on 1st optical interface +// 0x00000002: Lock AES/EBU on XLR or 2nd optical interface +// 0x00000001: Lock word clock on BNC interface +// +// The pattern for rate bits: +// 0x00: 32.0 kHz +// 0x01: 44.1 kHz +// 0x02: 48.0 kHz +// 0x04: 64.0 kHz +// 0x05: 88.2 kHz +// 0x06: 96.0 kHz +// 0x08: 128.0 kHz +// 0x09: 176.4 kHz +// 0x0a: 192.0 kHz static int parse_clock_bits(u32 data, unsigned int *rate, enum snd_ff_clock_src *src, enum snd_ff_unit_version unit_version) @@ -23,35 +78,48 @@ static int parse_clock_bits(u32 data, unsigned int *rate, unsigned int rate; u32 flag; } *rate_entry, rate_entries[] = { - { 32000, 0x00000000, }, - { 44100, 0x01000000, }, - { 48000, 0x02000000, }, - { 64000, 0x04000000, }, - { 88200, 0x05000000, }, - { 96000, 0x06000000, }, - { 128000, 0x08000000, }, - { 176400, 0x09000000, }, - { 192000, 0x0a000000, }, + { 32000, 0x00, }, + { 44100, 0x01, }, + { 48000, 0x02, }, + { 64000, 0x04, }, + { 88200, 0x05, }, + { 96000, 0x06, }, + { 128000, 0x08, }, + { 176400, 0x09, }, + { 192000, 0x0a, }, }; static const struct { enum snd_ff_clock_src src; u32 flag; - } *clk_entry, clk_entries[] = { + } *clk_entry, *clk_entries, ucx_clk_entries[] = { { SND_FF_CLOCK_SRC_SPDIF, 0x00000200, }, { SND_FF_CLOCK_SRC_ADAT1, 0x00000400, }, { SND_FF_CLOCK_SRC_WORD, 0x00000600, }, { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, }, + }, ufx_ff802_clk_entries[] = { + { SND_FF_CLOCK_SRC_WORD, 0x00000200, }, + { SND_FF_CLOCK_SRC_SPDIF, 0x00000400, }, + { SND_FF_CLOCK_SRC_ADAT1, 0x00000600, }, + { SND_FF_CLOCK_SRC_ADAT2, 0x00000800, }, + { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, }, }; + u32 rate_bits; + unsigned int clk_entry_count; int i; - if (unit_version != SND_FF_UNIT_VERSION_UCX) { - // e.g. 0x00fe0f20 but expected 0x00eff002. - data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4); + if (unit_version == SND_FF_UNIT_VERSION_UCX) { + rate_bits = (data & 0x0f000000) >> 24; + clk_entries = ucx_clk_entries; + clk_entry_count = ARRAY_SIZE(ucx_clk_entries); + } else { + rate_bits = (data & 0xf0000000) >> 28; + clk_entries = ufx_ff802_clk_entries; + clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries); } for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) { rate_entry = rate_entries + i; - if ((data & 0x0f000000) == rate_entry->flag) { + if (rate_bits == rate_entry->flag) { *rate = rate_entry->rate; break; } @@ -59,14 +127,14 @@ static int parse_clock_bits(u32 data, unsigned int *rate, if (i == ARRAY_SIZE(rate_entries)) return -EIO; - for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) { + for (i = 0; i < clk_entry_count; ++i) { clk_entry = clk_entries + i; if ((data & 0x000e00) == clk_entry->flag) { *src = clk_entry->src; break; } } - if (i == ARRAY_SIZE(clk_entries)) + if (i == clk_entry_count) return -EIO; return 0; @@ -249,16 +317,22 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer char *const label; u32 locked_mask; u32 synced_mask; - } *clk_entry, clk_entries[] = { + } *clk_entry, *clk_entries, ucx_clk_entries[] = { { "S/PDIF", 0x00000001, 0x00000010, }, { "ADAT", 0x00000002, 0x00000020, }, { "WDClk", 0x00000004, 0x00000040, }, + }, ufx_ff802_clk_entries[] = { + { "WDClk", 0x00000001, 0x00000010, }, + { "AES/EBU", 0x00000002, 0x00000020, }, + { "ADAT-A", 0x00000004, 0x00000040, }, + { "ADAT-B", 0x00000008, 0x00000080, }, }; __le32 reg; u32 data; unsigned int rate; enum snd_ff_clock_src src; const char *label; + unsigned int clk_entry_count; int i; int err; @@ -270,7 +344,15 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer snd_iprintf(buffer, "External source detection:\n"); - for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) { + if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) { + clk_entries = ucx_clk_entries; + clk_entry_count = ARRAY_SIZE(ucx_clk_entries); + } else { + clk_entries = ufx_ff802_clk_entries; + clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries); + } + + for (i = 0; i < clk_entry_count; ++i) { clk_entry = clk_entries + i; snd_iprintf(buffer, "%s: ", clk_entry->label); if (data & clk_entry->locked_mask) { -- cgit v1.2.3 From d6cda4655e2a7612a1e48c49795a5330abc01c5a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:30:50 +0100 Subject: ALSA: usb-audio: Handle invalid running state at releasing EP When we stop an endpoint in release_urbs(), it ignores the inconsistent endpoint state and tries to release the resources. This shouldn't happen in theory, but it's still safer to abort the release and let the caller proper error handling. Also, stop_and_unlink_urbs() called from release_urbs() does two step works, and it's more straightforward to split this to two functions again, so that the call from the PCM trigger won't take the path with sleeping. This patch modifies the EP management code to adapt two points above. Fixes: d0f09d1e4a88 ("ALSA: usb-audio: Refactoring endpoint URB deactivation") Cc: Link: https://lore.kernel.org/r/20210206203052.15606-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 4d1c678a0d80..e102c024c21f 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -868,24 +868,22 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) } /* - * Stop and unlink active urbs. + * Stop active urbs * - * This function checks and clears EP_FLAG_RUNNING state. - * When @wait_sync is set, it waits until all pending URBs are killed. + * This function moves the EP to STOPPING state if it's being RUNNING. */ -static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force, - bool wait_sync) +static int stop_urbs(struct snd_usb_endpoint *ep, bool force) { unsigned int i; if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */ return -EBADFD; - if (atomic_read(&ep->running)) + if (!force && atomic_read(&ep->running)) return -EBUSY; if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags)) - goto out; + return 0; set_bit(EP_FLAG_STOPPING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); @@ -901,24 +899,25 @@ static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force, } } - out: - if (wait_sync) - return wait_clear_urbs(ep); return 0; } /* * release an endpoint's urbs */ -static void release_urbs(struct snd_usb_endpoint *ep, int force) +static int release_urbs(struct snd_usb_endpoint *ep, bool force) { - int i; + int i, err; /* route incoming urbs to nirvana */ snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); - /* stop urbs */ - stop_and_unlink_urbs(ep, force, true); + /* stop and unlink urbs */ + err = stop_urbs(ep, force); + if (err) + return err; + + wait_clear_urbs(ep); for (i = 0; i < ep->nurbs; i++) release_urb_ctx(&ep->urb[i]); @@ -928,6 +927,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) ep->syncbuf = NULL; ep->nurbs = 0; + return 0; } /* @@ -1118,7 +1118,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep) return 0; out_of_memory: - release_urbs(ep, 0); + release_urbs(ep, false); return -ENOMEM; } @@ -1162,7 +1162,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) return 0; out_of_memory: - release_urbs(ep, 0); + release_urbs(ep, false); return -ENOMEM; } @@ -1180,7 +1180,9 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, int err; /* release old buffers, if any */ - release_urbs(ep, 0); + err = release_urbs(ep, false); + if (err < 0) + return err; ep->datainterval = fmt->datainterval; ep->maxpacksize = fmt->maxpacksize; @@ -1433,7 +1435,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) WRITE_ONCE(ep->sync_source->sync_sink, NULL); if (!atomic_dec_return(&ep->running)) - stop_and_unlink_urbs(ep, false, false); + stop_urbs(ep, false); } /** @@ -1446,7 +1448,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) */ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep) { - release_urbs(ep, 1); + release_urbs(ep, true); } /** -- cgit v1.2.3 From 5c2b301476ec493be15546f05e23414e2aa9d472 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:30:51 +0100 Subject: ALSA: usb-audio: More strict state change in EP The endpoint management has bit flags to indicate the current state, and we're dealing two things: the running bit and the stopping bit. There is a thin window in transition from the running to the stopping in stop_urbs(), and as long as the bit flags are used, it's difficult to plug. This patch modifies the state management code to use the atomic int and follow the explicit three states, STOPPED, RUNNING and STOPPING. The state change is done via atomic_cmpxhg() for avoiding possible races, and check the state change more strictly. The unexpected state change is now handled as an error. Fixes: d0f09d1e4a88 ("ALSA: usb-audio: Refactoring endpoint URB deactivation") Cc: Link: https://lore.kernel.org/r/20210206203052.15606-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/card.h | 2 +- sound/usb/endpoint.c | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 37091b117614..a741e7da83a2 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -71,7 +71,7 @@ struct snd_usb_endpoint { unsigned char altsetting; /* corresponding alternate setting */ unsigned char ep_idx; /* endpoint array index */ - unsigned long flags; /* running bit flags */ + atomic_t state; /* running state */ void (*prepare_data_urb) (struct snd_usb_substream *subs, struct urb *urb); diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e102c024c21f..4390075b2c6f 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -21,8 +21,11 @@ #include "clock.h" #include "quirks.h" -#define EP_FLAG_RUNNING 1 -#define EP_FLAG_STOPPING 2 +enum { + EP_STATE_STOPPED, + EP_STATE_RUNNING, + EP_STATE_STOPPING, +}; /* interface refcounting */ struct snd_usb_iface_ref { @@ -115,6 +118,16 @@ static const char *usb_error_string(int err) } } +static inline bool ep_state_running(struct snd_usb_endpoint *ep) +{ + return atomic_read(&ep->state) == EP_STATE_RUNNING; +} + +static inline bool ep_state_update(struct snd_usb_endpoint *ep, int old, int new) +{ + return atomic_cmpxchg(&ep->state, old, new) == old; +} + /** * snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type * @@ -393,7 +406,7 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) */ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) { - while (test_bit(EP_FLAG_RUNNING, &ep->flags)) { + while (ep_state_running(ep)) { unsigned long flags; struct snd_usb_packet_info *packet; @@ -454,13 +467,13 @@ static void snd_complete_urb(struct urb *urb) if (unlikely(atomic_read(&ep->chip->shutdown))) goto exit_clear; - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear; if (usb_pipeout(ep->pipe)) { retire_outbound_urb(ep, ctx); /* can be stopped during retire callback */ - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear; if (snd_usb_endpoint_implicit_feedback_sink(ep)) { @@ -474,12 +487,12 @@ static void snd_complete_urb(struct urb *urb) prepare_outbound_urb(ep, ctx); /* can be stopped during prepare callback */ - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear; } else { retire_inbound_urb(ep, ctx); /* can be stopped during retire callback */ - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear; prepare_inbound_urb(ep, ctx); @@ -835,7 +848,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) unsigned long end_time = jiffies + msecs_to_jiffies(1000); int alive; - if (!test_bit(EP_FLAG_STOPPING, &ep->flags)) + if (atomic_read(&ep->state) != EP_STATE_STOPPING) return 0; do { @@ -850,10 +863,11 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) usb_audio_err(ep->chip, "timeout: still %d active urbs on EP #%x\n", alive, ep->ep_num); - clear_bit(EP_FLAG_STOPPING, &ep->flags); - ep->sync_sink = NULL; - snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); + if (ep_state_update(ep, EP_STATE_STOPPING, EP_STATE_STOPPED)) { + ep->sync_sink = NULL; + snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); + } return 0; } @@ -882,10 +896,9 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force) if (!force && atomic_read(&ep->running)) return -EBUSY; - if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags)) + if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING)) return 0; - set_bit(EP_FLAG_STOPPING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); ep->next_packet_head = 0; ep->next_packet_queued = 0; @@ -1362,7 +1375,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) * from that context. */ - set_bit(EP_FLAG_RUNNING, &ep->flags); + if (!ep_state_update(ep, EP_STATE_STOPPED, EP_STATE_RUNNING)) + goto __error; if (snd_usb_endpoint_implicit_feedback_sink(ep)) { for (i = 0; i < ep->nurbs; i++) { -- cgit v1.2.3 From 257d2d7e9e798305d65825cb82b0a7d1c0511e89 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:30:52 +0100 Subject: ALSA: usb-audio: Don't avoid stopping the stream at disconnection In the later patch, we're going to issue the PCM sync_stop calls at disconnection. But currently the USB-audio driver can't handle it because it has a check of shutdown flag for stopping the URBs. This is basically superfluous (the stopping URBs are safe at disconnection state), so let's drop the check. Fixes: dc5eafe7787c ("ALSA: usb-audio: Support PCM sync_stop") Cc: Link: https://lore.kernel.org/r/20210206203052.15606-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 3 --- sound/usb/pcm.c | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 4390075b2c6f..102d53515a76 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -890,9 +890,6 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force) { unsigned int i; - if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */ - return -EBADFD; - if (!force && atomic_read(&ep->running)) return -EBUSY; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index dcadf8f164b2..bf5a0f3c1fad 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -270,10 +270,7 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) { struct snd_usb_substream *subs = substream->runtime->private_data; - if (!snd_usb_lock_shutdown(subs->stream->chip)) { - sync_pending_stops(subs); - snd_usb_unlock_shutdown(subs->stream->chip); - } + sync_pending_stops(subs); return 0; } -- cgit v1.2.3 From 29bb274e94974669acb5186a75538f20df1508b6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:36:53 +0100 Subject: ALSA: pcm: Call sync_stop at disconnection The PCM core should perform the sync for the pending stop operations at disconnection. Otherwise it may lead to unexpected access. Currently the old user of sync_stop, USB-audio driver, has its own sync, so this isn't needed, but it's better to guarantee the sync in the PCM core level. This patch adds the missing sync_stop call at PCM disconnection callback. It also assures the IRQ sync if it's specified in the card. snd_pcm_sync_stop() is slightly modified to be called also for any PCM substream object now. Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") Cc: Link: https://lore.kernel.org/r/20210206203656.15959-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/init.c | 4 ++++ sound/core/pcm.c | 4 ++++ sound/core/pcm_local.h | 1 + sound/core/pcm_native.c | 16 ++++++++-------- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/sound/core/init.c b/sound/core/init.c index 84b573e9c1f9..45f4b01de23f 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -426,6 +427,9 @@ int snd_card_disconnect(struct snd_card *card) /* notify all devices that we are disconnected */ snd_device_disconnect_all(card); + if (card->sync_irq > 0) + synchronize_irq(card->sync_irq); + snd_info_card_disconnect(card); if (card->registered) { device_del(&card->card_dev); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index e5947281e5fc..50eb29fcdfe7 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1111,6 +1111,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) } } + for (cidx = 0; cidx < 2; cidx++) + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) + snd_pcm_sync_stop(substream, false); + pcm_call_notify(pcm, n_disconnect); for (cidx = 0; cidx < 2; cidx++) { snd_unregister_device(&pcm->streams[cidx].dev); diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h index 17a1a5d87098..b3e8be5aeafb 100644 --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h @@ -63,6 +63,7 @@ static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {} void __snd_pcm_xrun(struct snd_pcm_substream *substream); void snd_pcm_group_init(struct snd_pcm_group *group); +void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq); #ifdef CONFIG_SND_DMA_SGBUF struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 893c2abb2f63..1f5acf08cdcd 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -583,13 +583,13 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream, #endif } -static void snd_pcm_sync_stop(struct snd_pcm_substream *substream) +void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq) { - if (substream->runtime->stop_operating) { + if (substream->runtime && substream->runtime->stop_operating) { substream->runtime->stop_operating = false; - if (substream->ops->sync_stop) + if (substream->ops && substream->ops->sync_stop) substream->ops->sync_stop(substream); - else if (substream->pcm->card->sync_irq > 0) + else if (sync_irq && substream->pcm->card->sync_irq > 0) synchronize_irq(substream->pcm->card->sync_irq); } } @@ -686,7 +686,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, if (atomic_read(&substream->mmap_count)) return -EBADFD; - snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); params->rmask = ~0U; err = snd_pcm_hw_refine(substream, params); @@ -809,7 +809,7 @@ static int do_hw_free(struct snd_pcm_substream *substream) { int result = 0; - snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); if (substream->ops->hw_free) result = substream->ops->hw_free(substream); if (substream->managed_buffer_alloc) @@ -1736,7 +1736,7 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, snd_pcm_trigger_tstamp(substream); runtime->status->state = runtime->status->suspended_state; snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); - snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); } static const struct action_ops snd_pcm_action_resume = { @@ -1866,7 +1866,7 @@ static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, snd_pcm_state_t state) { int err; - snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); err = substream->ops->prepare(substream); if (err < 0) return err; -- cgit v1.2.3 From 2c87c1a49c9d113a9f3e8e951d7d64be5ff50ac1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:36:54 +0100 Subject: ALSA: pcm: Assure sync with the pending stop operation at suspend The current PCM code calls the sync_stop at the resume action due to the analogy to the PCM prepare call pattern. But, it makes little sense, as the sync should have been done rather at the suspend time, not at the resume time. This patch corrects the sync_stop call at suspend/resume to assure the sync before finishing the suspend. Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") Cc: Link: https://lore.kernel.org/r/20210206203656.15959-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 1f5acf08cdcd..cbbdb75c66ea 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1615,6 +1615,7 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, if (! snd_pcm_running(substream)) return 0; substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); + runtime->stop_operating = true; return 0; /* suspend unconditionally */ } @@ -1691,6 +1692,12 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) return err; } } + + for (stream = 0; stream < 2; stream++) + for (substream = pcm->streams[stream].substream; + substream; substream = substream->next) + snd_pcm_sync_stop(substream, false); + return 0; } EXPORT_SYMBOL(snd_pcm_suspend_all); @@ -1736,7 +1743,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, snd_pcm_trigger_tstamp(substream); runtime->status->state = runtime->status->suspended_state; snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); - snd_pcm_sync_stop(substream, true); } static const struct action_ops snd_pcm_action_resume = { -- cgit v1.2.3 From 700cb70730777c159a988e01daa93f20a1ae9b58 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:36:55 +0100 Subject: ALSA: pcm: Don't call sync_stop if it hasn't been stopped The PCM stop operation sets the stop_operating flag for indicating the sync_stop post-process. This flag is, however, set unconditionally even if the PCM trigger weren't issued. This may lead to inconsistency in the driver side. Correct the code to set stop_operating flag only after the trigger STOP is actually called. Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") Cc: Link: https://lore.kernel.org/r/20210206203656.15959-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index cbbdb75c66ea..0ae2475465ab 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1421,8 +1421,10 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { if (substream->runtime->trigger_master == substream && - snd_pcm_running(substream)) + snd_pcm_running(substream)) { substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); + substream->runtime->stop_operating = true; + } return 0; /* unconditonally stop all substreams */ } @@ -1435,7 +1437,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, runtime->status->state = state; snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP); } - runtime->stop_operating = true; wake_up(&runtime->sleep); wake_up(&runtime->tsleep); } -- cgit v1.2.3 From 8d19b4e0b377e226b98f26ded5f0c6463976e4fb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Feb 2021 21:36:56 +0100 Subject: ALSA: pcm: Use for_each_pcm_substream() macro There are a few places doing the same loop iterating all PCM substreams belonging to the PCM object. Introduce a local helper macro, for_each_pcm_substream(), to simplify the code. Link: https://lore.kernel.org/r/20210206203656.15959-5-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 29 +++++++++++++---------------- sound/core/pcm_local.h | 6 ++++++ sound/core/pcm_memory.c | 12 ++++-------- sound/core/pcm_native.c | 35 +++++++++++++++-------------------- 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 50eb29fcdfe7..b163164a83ec 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1095,25 +1095,22 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) mutex_lock(&pcm->open_mutex); wake_up(&pcm->open_wait); list_del_init(&pcm->list); - for (cidx = 0; cidx < 2; cidx++) { - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { - snd_pcm_stream_lock_irq(substream); - if (substream->runtime) { - if (snd_pcm_running(substream)) - snd_pcm_stop(substream, - SNDRV_PCM_STATE_DISCONNECTED); - /* to be sure, set the state unconditionally */ - substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; - wake_up(&substream->runtime->sleep); - wake_up(&substream->runtime->tsleep); - } - snd_pcm_stream_unlock_irq(substream); + + for_each_pcm_substream(pcm, cidx, substream) { + snd_pcm_stream_lock_irq(substream); + if (substream->runtime) { + if (snd_pcm_running(substream)) + snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); + /* to be sure, set the state unconditionally */ + substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + wake_up(&substream->runtime->sleep); + wake_up(&substream->runtime->tsleep); } + snd_pcm_stream_unlock_irq(substream); } - for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) - snd_pcm_sync_stop(substream, false); + for_each_pcm_substream(pcm, cidx, substream) + snd_pcm_sync_stop(substream, false); pcm_call_notify(pcm, n_disconnect); for (cidx = 0; cidx < 2; cidx++) { diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h index b3e8be5aeafb..e3b3558aeab6 100644 --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h @@ -72,4 +72,10 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, #define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime) +/* loop over all PCM substreams */ +#define for_each_pcm_substream(pcm, str, subs) \ + for ((str) = 0; (str) < 2; (str)++) \ + for ((subs) = (pcm)->streams[str].substream; (subs); \ + (subs) = (subs)->next) + #endif /* __SOUND_CORE_PCM_LOCAL_H */ diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index ee6e9c5eec45..289dd1fd8fe7 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -111,9 +111,8 @@ void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) struct snd_pcm_substream *substream; int stream; - for (stream = 0; stream < 2; stream++) - for (substream = pcm->streams[stream].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_free(substream); + for_each_pcm_substream(pcm, stream, substream) + snd_pcm_lib_preallocate_free(substream); } EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); @@ -246,11 +245,8 @@ static void preallocate_pages_for_all(struct snd_pcm *pcm, int type, struct snd_pcm_substream *substream; int stream; - for (stream = 0; stream < 2; stream++) - for (substream = pcm->streams[stream].substream; substream; - substream = substream->next) - preallocate_pages(substream, type, data, size, max, - managed); + for_each_pcm_substream(pcm, stream, substream) + preallocate_pages(substream, type, data, size, max, managed); } /** diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0ae2475465ab..17a85f4815d5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1674,30 +1674,25 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) if (! pcm) return 0; - for (stream = 0; stream < 2; stream++) { - for (substream = pcm->streams[stream].substream; - substream; substream = substream->next) { - /* FIXME: the open/close code should lock this as well */ - if (substream->runtime == NULL) - continue; + for_each_pcm_substream(pcm, stream, substream) { + /* FIXME: the open/close code should lock this as well */ + if (!substream->runtime) + continue; - /* - * Skip BE dai link PCM's that are internal and may - * not have their substream ops set. - */ - if (!substream->ops) - continue; + /* + * Skip BE dai link PCM's that are internal and may + * not have their substream ops set. + */ + if (!substream->ops) + continue; - err = snd_pcm_suspend(substream); - if (err < 0 && err != -EBUSY) - return err; - } + err = snd_pcm_suspend(substream); + if (err < 0 && err != -EBUSY) + return err; } - for (stream = 0; stream < 2; stream++) - for (substream = pcm->streams[stream].substream; - substream; substream = substream->next) - snd_pcm_sync_stop(substream, false); + for_each_pcm_substream(pcm, stream, substream) + snd_pcm_sync_stop(substream, false); return 0; } -- cgit v1.2.3 From bad929b81ce25bba1c3e9d91848ffdc166974256 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 23 Jan 2021 14:09:57 +0000 Subject: ASoC: codec/ingenic: Depend on MACH_INGENIC No need to show the options to build Ingenic-specific drivers on all MIPS kernel configurations if Ingenic SoCs support is not enabled. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210123140958.12895-2-paul@crapouillou.net Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index df34b3b3bb14..9e2a732bae27 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -712,7 +712,7 @@ config SND_SOC_CX2072X Enable support for Conexant CX20721 and CX20723 codec chips. config SND_SOC_JZ4740_CODEC - depends on MIPS || COMPILE_TEST + depends on MACH_INGENIC || COMPILE_TEST depends on OF select REGMAP_MMIO tristate "Ingenic JZ4740 internal CODEC" @@ -724,7 +724,7 @@ config SND_SOC_JZ4740_CODEC will be called snd-soc-jz4740-codec. config SND_SOC_JZ4725B_CODEC - depends on MIPS || COMPILE_TEST + depends on MACH_INGENIC || COMPILE_TEST depends on OF select REGMAP tristate "Ingenic JZ4725B internal CODEC" @@ -736,7 +736,7 @@ config SND_SOC_JZ4725B_CODEC will be called snd-soc-jz4725b-codec. config SND_SOC_JZ4770_CODEC - depends on MIPS || COMPILE_TEST + depends on MACH_INGENIC || COMPILE_TEST depends on OF select REGMAP tristate "Ingenic JZ4770 internal CODEC" -- cgit v1.2.3 From d9cd22e9c87cb61488d00f7279cfb2abf5238879 Mon Sep 17 00:00:00 2001 From: Christophe Branchereau Date: Sat, 23 Jan 2021 14:09:58 +0000 Subject: ASoC: codec: Add driver for JZ4760 internal codec Add support for the internal codec found in the JZ4760 SoC from Ingenic. Signed-off-by: Christophe Branchereau Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210123140958.12895-3-paul@crapouillou.net Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 13 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/jz4760.c | 889 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 904 insertions(+) create mode 100644 sound/soc/codecs/jz4760.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9e2a732bae27..f9ce7bb654a5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_ISABELLE imply SND_SOC_JZ4740_CODEC imply SND_SOC_JZ4725B_CODEC + imply SND_SOC_JZ4760_CODEC imply SND_SOC_JZ4770_CODEC imply SND_SOC_LM4857 imply SND_SOC_LM49453 @@ -735,6 +736,18 @@ config SND_SOC_JZ4725B_CODEC This driver can also be built as a module. If so, the module will be called snd-soc-jz4725b-codec. +config SND_SOC_JZ4760_CODEC + depends on MACH_INGENIC || COMPILE_TEST + depends on OF + select REGMAP + tristate "Ingenic JZ4760 internal CODEC" + help + Enable support for the internal CODEC found in the JZ4760 SoC + from Ingenic. + + This driver can also be built as a module. If so, the module + will be called snd-soc-jz4760-codec. + config SND_SOC_JZ4770_CODEC depends on MACH_INGENIC || COMPILE_TEST depends on OF diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 628b0c9b3e2a..d5c7eb3544a5 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -101,6 +101,7 @@ snd-soc-inno-rk3036-objs := inno_rk3036.o snd-soc-isabelle-objs := isabelle.o snd-soc-jz4740-codec-objs := jz4740.o snd-soc-jz4725b-codec-objs := jz4725b.o +snd-soc-jz4760-codec-objs := jz4760.o snd-soc-jz4770-codec-objs := jz4770.o snd-soc-l3-objs := l3.o snd-soc-lm4857-objs := lm4857.o @@ -416,6 +417,7 @@ obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o +obj-$(CONFIG_SND_SOC_JZ4760_CODEC) += snd-soc-jz4760-codec.o obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += snd-soc-jz4770-codec.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o diff --git a/sound/soc/codecs/jz4760.c b/sound/soc/codecs/jz4760.c new file mode 100644 index 000000000000..e8f28ccc145a --- /dev/null +++ b/sound/soc/codecs/jz4760.c @@ -0,0 +1,889 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Ingenic JZ4760 CODEC driver +// +// Copyright (C) 2021, Christophe Branchereau +// Copyright (C) 2021, Paul Cercueil + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ICDC_RGADW_OFFSET 0x00 +#define ICDC_RGDATA_OFFSET 0x04 + +/* ICDC internal register access control register(RGADW) */ +#define ICDC_RGADW_RGWR BIT(16) +#define ICDC_RGADW_RGADDR_MASK GENMASK(14, 8) +#define ICDC_RGADW_RGDIN_MASK GENMASK(7, 0) + +/* ICDC internal register data output register (RGDATA)*/ +#define ICDC_RGDATA_IRQ BIT(8) +#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, 0) + +/* Internal register space, accessed through regmap */ +enum { + JZ4760_CODEC_REG_SR, + JZ4760_CODEC_REG_AICR, + JZ4760_CODEC_REG_CR1, + JZ4760_CODEC_REG_CR2, + JZ4760_CODEC_REG_CR3, + JZ4760_CODEC_REG_CR4, + JZ4760_CODEC_REG_CCR1, + JZ4760_CODEC_REG_CCR2, + JZ4760_CODEC_REG_PMR1, + JZ4760_CODEC_REG_PMR2, + JZ4760_CODEC_REG_ICR, + JZ4760_CODEC_REG_IFR, + JZ4760_CODEC_REG_GCR1, + JZ4760_CODEC_REG_GCR2, + JZ4760_CODEC_REG_GCR3, + JZ4760_CODEC_REG_GCR4, + JZ4760_CODEC_REG_GCR5, + JZ4760_CODEC_REG_GCR6, + JZ4760_CODEC_REG_GCR7, + JZ4760_CODEC_REG_GCR8, + JZ4760_CODEC_REG_GCR9, + JZ4760_CODEC_REG_AGC1, + JZ4760_CODEC_REG_AGC2, + JZ4760_CODEC_REG_AGC3, + JZ4760_CODEC_REG_AGC4, + JZ4760_CODEC_REG_AGC5, + JZ4760_CODEC_REG_MIX1, + JZ4760_CODEC_REG_MIX2, +}; + +#define REG_AICR_DAC_ADWL_MASK GENMASK(7, 6) +#define REG_AICR_DAC_SERIAL BIT(3) +#define REG_AICR_DAC_I2S BIT(1) + +#define REG_AICR_ADC_ADWL_MASK GENMASK(5, 4) + +#define REG_AICR_ADC_SERIAL BIT(2) +#define REG_AICR_ADC_I2S BIT(0) + +#define REG_CR1_HP_LOAD BIT(7) +#define REG_CR1_HP_MUTE BIT(5) +#define REG_CR1_LO_MUTE_OFFSET 4 +#define REG_CR1_BTL_MUTE_OFFSET 3 +#define REG_CR1_OUTSEL_OFFSET 0 +#define REG_CR1_OUTSEL_MASK GENMASK(1, REG_CR1_OUTSEL_OFFSET) + +#define REG_CR2_DAC_MONO BIT(7) +#define REG_CR2_DAC_MUTE BIT(5) +#define REG_CR2_DAC_NOMAD BIT(1) +#define REG_CR2_DAC_RIGHT_ONLY BIT(0) + +#define REG_CR3_ADC_INSEL_OFFSET 2 +#define REG_CR3_ADC_INSEL_MASK GENMASK(3, REG_CR3_ADC_INSEL_OFFSET) +#define REG_CR3_MICSTEREO_OFFSET 1 +#define REG_CR3_MICDIFF_OFFSET 0 + +#define REG_CR4_ADC_HPF_OFFSET 7 +#define REG_CR4_ADC_RIGHT_ONLY BIT(0) + +#define REG_CCR1_CRYSTAL_MASK GENMASK(3, 0) + +#define REG_CCR2_DAC_FREQ_MASK GENMASK(7, 4) +#define REG_CCR2_ADC_FREQ_MASK GENMASK(3, 0) + +#define REG_PMR1_SB BIT(7) +#define REG_PMR1_SB_SLEEP BIT(6) +#define REG_PMR1_SB_AIP_OFFSET 5 +#define REG_PMR1_SB_LINE_OFFSET 4 +#define REG_PMR1_SB_MIC1_OFFSET 3 +#define REG_PMR1_SB_MIC2_OFFSET 2 +#define REG_PMR1_SB_BYPASS_OFFSET 1 +#define REG_PMR1_SB_MICBIAS_OFFSET 0 + +#define REG_PMR2_SB_ADC_OFFSET 4 +#define REG_PMR2_SB_HP_OFFSET 3 +#define REG_PMR2_SB_BTL_OFFSET 2 +#define REG_PMR2_SB_LOUT_OFFSET 1 +#define REG_PMR2_SB_DAC_OFFSET 0 + +#define REG_ICR_INT_FORM_MASK GENMASK(7, 6) +#define REG_ICR_ALL_MASK GENMASK(5, 0) +#define REG_ICR_JACK_MASK BIT(5) +#define REG_ICR_SCMC_MASK BIT(4) +#define REG_ICR_RUP_MASK BIT(3) +#define REG_ICR_RDO_MASK BIT(2) +#define REG_ICR_GUP_MASK BIT(1) +#define REG_ICR_GDO_MASK BIT(0) + +#define REG_IFR_ALL_MASK GENMASK(5, 0) +#define REG_IFR_JACK BIT(6) +#define REG_IFR_JACK_EVENT BIT(5) +#define REG_IFR_SCMC BIT(4) +#define REG_IFR_RUP BIT(3) +#define REG_IFR_RDO BIT(2) +#define REG_IFR_GUP BIT(1) +#define REG_IFR_GDO BIT(0) + +#define REG_GCR_GAIN_OFFSET 0 +#define REG_GCR_GAIN_MAX 0x1f + +#define REG_GCR_RL BIT(7) + +#define REG_GCR_GIM1_MASK GENMASK(5, 3) +#define REG_GCR_GIM2_MASK GENMASK(2, 0) +#define REG_GCR_GIM_GAIN_MAX 7 + +#define REG_AGC1_EN BIT(7) +#define REG_AGC1_TARGET_MASK GENMASK(5, 2) + +#define REG_AGC2_NG_THR_MASK GENMASK(6, 4) +#define REG_AGC2_HOLD_MASK GENMASK(3, 0) + +#define REG_AGC3_ATK_MASK GENMASK(7, 4) +#define REG_AGC3_DCY_MASK GENMASK(3, 0) + +#define REG_AGC4_AGC_MAX_MASK GENMASK(4, 0) + +#define REG_AGC5_AGC_MIN_MASK GENMASK(4, 0) + +#define REG_MIX1_MIX_REC_MASK GENMASK(7, 6) +#define REG_MIX1_GIMIX_MASK GENMASK(4, 0) + +#define REG_MIX2_DAC_MIX_MASK GENMASK(7, 6) +#define REG_MIX2_GOMIX_MASK GENMASK(4, 0) + +/* codec private data */ +struct jz_codec { + struct device *dev; + struct regmap *regmap; + void __iomem *base; + struct clk *clk; +}; + +static int jz4760_codec_set_bias_level(struct snd_soc_component *codec, + enum snd_soc_bias_level level) +{ + struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); + struct regmap *regmap = jz_codec->regmap; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + /* Reset all interrupt flags. */ + regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK); + + regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB); + msleep(250); + regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP); + msleep(400); + break; + case SND_SOC_BIAS_STANDBY: + regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP); + regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB); + break; + default: + break; + } + + return 0; +} + +static int jz4760_codec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *codec = dai->component; + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec); + int ret; + + /* + * SYSCLK output from the codec to the AIC is required to keep the + * DMA transfer going during playback when all audible outputs have + * been disabled. + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK"); + return 0; +} + +static void jz4760_codec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *codec = dai->component; + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dapm_disable_pin(dapm, "SYSCLK"); +} + + +static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct snd_soc_component *codec = dai->component; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + /* do nothing */ + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction) +{ + struct snd_soc_component *codec = dai->component; + struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); + unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP; + unsigned int val, reg; + int change, err; + + change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2, + REG_CR2_DAC_MUTE, + mute ? REG_CR2_DAC_MUTE : 0); + if (change == 1) { + regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val); + + if (val & BIT(REG_PMR2_SB_DAC_OFFSET)) + return 1; + + err = regmap_read_poll_timeout(jz_codec->regmap, + JZ4760_CODEC_REG_IFR, + val, val & gain_bit, + 1000, 1 * USEC_PER_SEC); + if (err) { + dev_err(jz_codec->dev, + "Timeout while setting digital mute: %d", err); + return err; + } + + /* clear GUP/GDO flag */ + regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit); + } + + regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, ®); + + return 0; +} + +/* unit: 0.01dB */ +static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100); +static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0); +static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100); +static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0); + +/* Unconditional controls. */ +static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = { + /* record gain control */ + SOC_DOUBLE_R_TLV("PCM Capture Volume", + JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8, + REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv), + + SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume", + JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3, + REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv), + + SOC_SINGLE("High-Pass Filter Capture Switch", + JZ4760_CODEC_REG_CR4, + REG_CR4_ADC_HPF_OFFSET, 1, 0), +}; + +static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Volume", + .info = snd_soc_info_volsw, + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE, + .tlv.p = dac_tlv, + .get = snd_soc_dapm_get_volsw, + .put = snd_soc_dapm_put_volsw, + .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6, + JZ4760_CODEC_REG_GCR5, + REG_GCR_GAIN_OFFSET, + REG_GCR_GAIN_MAX, 1), + }, +}; + +static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Volume", + .info = snd_soc_info_volsw, + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE, + .tlv.p = out_tlv, + .get = snd_soc_dapm_get_volsw, + .put = snd_soc_dapm_put_volsw, + .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2, + JZ4760_CODEC_REG_GCR1, + REG_GCR_GAIN_OFFSET, + REG_GCR_GAIN_MAX, 1), + }, +}; + +static int hpout_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); + struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); + unsigned int val; + int err; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* unmute HP */ + regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1, + REG_CR1_HP_MUTE); + break; + + case SND_SOC_DAPM_POST_PMU: + /* wait for ramp-up complete (RUP) */ + err = regmap_read_poll_timeout(jz_codec->regmap, + JZ4760_CODEC_REG_IFR, + val, val & REG_IFR_RUP, + 1000, 1 * USEC_PER_SEC); + if (err) { + dev_err(jz_codec->dev, "RUP timeout: %d", err); + return err; + } + + /* clear RUP flag */ + regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR, + REG_IFR_RUP); + + break; + + case SND_SOC_DAPM_POST_PMD: + /* mute HP */ + regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1, + REG_CR1_HP_MUTE); + + err = regmap_read_poll_timeout(jz_codec->regmap, + JZ4760_CODEC_REG_IFR, + val, val & REG_IFR_RDO, + 1000, 1 * USEC_PER_SEC); + if (err) { + dev_err(jz_codec->dev, "RDO timeout: %d", err); + return err; + } + + /* clear RDO flag */ + regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR, + REG_IFR_RDO); + + break; + } + + return 0; +} + +static const char * const jz4760_codec_hp_texts[] = { + "PCM", "Line In", "Mic 1", "Mic 2" +}; + +static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 }; + +static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum, + JZ4760_CODEC_REG_CR1, + REG_CR1_OUTSEL_OFFSET, + REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET, + jz4760_codec_hp_texts, + jz4760_codec_hp_values); +static const struct snd_kcontrol_new jz4760_codec_hp_source = + SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum); + +static const char * const jz4760_codec_cap_texts[] = { + "Line In", "Mic 1", "Mic 2" +}; + +static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 }; + +static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum, + JZ4760_CODEC_REG_CR3, + REG_CR3_ADC_INSEL_OFFSET, + REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET, + jz4760_codec_cap_texts, + jz4760_codec_cap_values); +static const struct snd_kcontrol_new jz4760_codec_cap_source = + SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum); + +static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = { + SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3, + REG_CR3_MICSTEREO_OFFSET, 1, 0), +}; + +static const struct snd_kcontrol_new jz4760_codec_line_out_switch = + SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1, + REG_CR1_LO_MUTE_OFFSET, 0, 0); +static const struct snd_kcontrol_new jz4760_codec_btl_out_switch = + SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1, + REG_CR1_BTL_MUTE_OFFSET, 0, 0); + +static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = { + SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2, + REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2, + REG_PMR2_SB_LOUT_OFFSET, 1, + &jz4760_codec_line_out_switch), + + SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2, + REG_PMR2_SB_BTL_OFFSET, 1, + &jz4760_codec_btl_out_switch), + + SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1, + REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0), + + SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0, + &jz4760_codec_hp_source), + + SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0, + &jz4760_codec_cap_source), + + SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1, + REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0), + + SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1, + REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0), + + SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3, + REG_CR3_MICDIFF_OFFSET, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0, + jz4760_codec_mic_controls, + ARRAY_SIZE(jz4760_codec_mic_controls)), + + SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1, + REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0), + + SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2, + REG_PMR2_SB_ADC_OFFSET, 1), + + SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2, + REG_PMR2_SB_DAC_OFFSET, 1), + + SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0, + jz4760_codec_pcm_playback_controls, + ARRAY_SIZE(jz4760_codec_pcm_playback_controls)), + + SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0, + jz4760_codec_hp_playback_controls, + ARRAY_SIZE(jz4760_codec_hp_playback_controls)), + + SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1, + REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0), + + SND_SOC_DAPM_INPUT("MIC1P"), + SND_SOC_DAPM_INPUT("MIC1N"), + SND_SOC_DAPM_INPUT("MIC2P"), + SND_SOC_DAPM_INPUT("MIC2N"), + + SND_SOC_DAPM_INPUT("LLINEIN"), + SND_SOC_DAPM_INPUT("RLINEIN"), + + SND_SOC_DAPM_OUTPUT("LHPOUT"), + SND_SOC_DAPM_OUTPUT("RHPOUT"), + + SND_SOC_DAPM_OUTPUT("LOUT"), + SND_SOC_DAPM_OUTPUT("ROUT"), + + SND_SOC_DAPM_OUTPUT("BTLP"), + SND_SOC_DAPM_OUTPUT("BTLN"), + + SND_SOC_DAPM_OUTPUT("SYSCLK"), +}; + +/* Unconditional routes. */ +static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = { + { "Mic 1", NULL, "MIC1P" }, + { "Mic Diff", NULL, "MIC1N" }, + { "Mic 1", NULL, "Mic Diff" }, + { "Mic 2", NULL, "MIC2P" }, + { "Mic Diff", NULL, "MIC2N" }, + { "Mic 2", NULL, "Mic Diff" }, + + { "Line In", NULL, "LLINEIN" }, + { "Line In", NULL, "RLINEIN" }, + + { "Mic", "Stereo Capture Switch", "Mic 1" }, + { "Mic", "Stereo Capture Switch", "Mic 2" }, + { "Headphones Source", "Mic 1", "Mic" }, + { "Headphones Source", "Mic 2", "Mic" }, + { "Capture Source", "Mic 1", "Mic" }, + { "Capture Source", "Mic 2", "Mic" }, + + { "Capture Source", "Line In", "Line In" }, + { "Capture Source", "Mic 1", "Mic 1" }, + { "Capture Source", "Mic 2", "Mic 2" }, + { "ADC", NULL, "Capture Source" }, + + { "Line In Bypass", NULL, "Line In" }, + + { "Headphones Source", "Mic 1", "Mic 1" }, + { "Headphones Source", "Mic 2", "Mic 2" }, + { "Headphones Source", "Line In", "Line In Bypass" }, + { "Headphones Source", "PCM", "Headphones Playback" }, + { "HP Out", NULL, "Headphones Source" }, + + { "LHPOUT", NULL, "HP Out" }, + { "RHPOUT", NULL, "HP Out" }, + { "Line Out", "Switch", "HP Out" }, + + { "LOUT", NULL, "Line Out" }, + { "ROUT", NULL, "Line Out" }, + { "BTL Out", "Switch", "Line Out" }, + + { "BTLP", NULL, "BTL Out"}, + { "BTLN", NULL, "BTL Out"}, + + { "PCM Playback", "Volume", "DAC" }, + { "Headphones Playback", "Volume", "PCM Playback" }, + + { "SYSCLK", NULL, "DAC" }, +}; + +static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec) +{ + struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); + struct regmap *regmap = jz_codec->regmap; + + /* Collect updates for later sending. */ + regcache_cache_only(regmap, true); + + /* default Amp output to PCM */ + regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK); + + /* Disable stereo mic */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3, + BIT(REG_CR3_MICSTEREO_OFFSET)); + + /* Set mic 1 as default source for ADC */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3, + REG_CR3_ADC_INSEL_MASK); + + /* ADC/DAC: serial + i2s */ + regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR, + REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S | + REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S); + + /* The generated IRQ is a high level */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK); + regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK, + REG_ICR_JACK_MASK | REG_ICR_RUP_MASK | + REG_ICR_RDO_MASK | REG_ICR_GUP_MASK | + REG_ICR_GDO_MASK); + + /* 12M oscillator */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK); + + /* 0: 16ohm/220uF, 1: 10kohm/1uF */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD); + + /* default to NOMAD */ + regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2, + REG_CR2_DAC_NOMAD); + + /* disable automatic gain */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN); + + /* Independent L/R DAC gain control */ + regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5, + REG_GCR_RL); + + /* Send collected updates. */ + regcache_cache_only(regmap, false); + regcache_sync(regmap); +} + +static int jz4760_codec_codec_probe(struct snd_soc_component *codec) +{ + struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); + + clk_prepare_enable(jz_codec->clk); + + jz4760_codec_codec_init_regs(codec); + + return 0; +} + +static void jz4760_codec_codec_remove(struct snd_soc_component *codec) +{ + struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec); + + clk_disable_unprepare(jz_codec->clk); +} + +static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = { + .probe = jz4760_codec_codec_probe, + .remove = jz4760_codec_codec_remove, + .set_bias_level = jz4760_codec_set_bias_level, + .controls = jz4760_codec_snd_controls, + .num_controls = ARRAY_SIZE(jz4760_codec_snd_controls), + .dapm_widgets = jz4760_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(jz4760_codec_dapm_widgets), + .dapm_routes = jz4760_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(jz4760_codec_dapm_routes), + .suspend_bias_off = 1, + .use_pmdown_time = 1, +}; + +static const unsigned int jz4760_codec_sample_rates[] = { + 96000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, + 11025, 9600, 8000, +}; + +static int jz4760_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component); + unsigned int rate, bit_width; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + bit_width = 0; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + bit_width = 1; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + bit_width = 2; + break; + case SNDRV_PCM_FORMAT_S24_3LE: + bit_width = 3; + break; + default: + return -EINVAL; + } + + for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) { + if (jz4760_codec_sample_rates[rate] == params_rate(params)) + break; + } + + if (rate == ARRAY_SIZE(jz4760_codec_sample_rates)) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR, + REG_AICR_DAC_ADWL_MASK, + FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width)); + regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2, + REG_CCR2_DAC_FREQ_MASK, + FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate)); + } else { + regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR, + REG_AICR_ADC_ADWL_MASK, + FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width)); + regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2, + REG_CCR2_ADC_FREQ_MASK, + FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate)); + } + + return 0; +} + +static const struct snd_soc_dai_ops jz4760_codec_dai_ops = { + .startup = jz4760_codec_startup, + .shutdown = jz4760_codec_shutdown, + .hw_params = jz4760_codec_hw_params, + .trigger = jz4760_codec_pcm_trigger, + .mute_stream = jz4760_codec_mute_stream, + .no_capture_mute = 1, +}; + +#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S18_3LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE) + +static struct snd_soc_dai_driver jz4760_codec_dai = { + .name = "jz4760-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = JZ_CODEC_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = JZ_CODEC_FORMATS, + }, + .ops = &jz4760_codec_dai_ops, +}; + +static bool jz4760_codec_volatile(struct device *dev, unsigned int reg) +{ + return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR; +} + +static bool jz4760_codec_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case JZ4760_CODEC_REG_SR: + return false; + default: + return true; + } +} + +static int jz4760_codec_io_wait(struct jz_codec *codec) +{ + u32 reg; + + return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg, + !(reg & ICDC_RGADW_RGWR), + 1000, 1 * USEC_PER_SEC); +} + +static int jz4760_codec_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct jz_codec *codec = context; + unsigned int i; + u32 tmp; + int ret; + + ret = jz4760_codec_io_wait(codec); + if (ret) + return ret; + + tmp = readl(codec->base + ICDC_RGADW_OFFSET); + tmp &= ~ICDC_RGADW_RGADDR_MASK; + tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg); + writel(tmp, codec->base + ICDC_RGADW_OFFSET); + + /* wait 6+ cycles */ + for (i = 0; i < 6; i++) + *val = readl(codec->base + ICDC_RGDATA_OFFSET) & + ICDC_RGDATA_RGDOUT_MASK; + + return 0; +} + +static int jz4760_codec_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct jz_codec *codec = context; + int ret; + + ret = jz4760_codec_io_wait(codec); + if (ret) + return ret; + + writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val, + codec->base + ICDC_RGADW_OFFSET); + + ret = jz4760_codec_io_wait(codec); + if (ret) + return ret; + + return 0; +} + +static const u8 jz4760_codec_reg_defaults[] = { + 0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00, + 0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44, + 0x1F, 0x00, 0x00, 0x00 +}; + +static struct regmap_config jz4760_codec_regmap_config = { + .reg_bits = 7, + .val_bits = 8, + + .max_register = JZ4760_CODEC_REG_MIX2, + .volatile_reg = jz4760_codec_volatile, + .writeable_reg = jz4760_codec_writeable, + + .reg_read = jz4760_codec_reg_read, + .reg_write = jz4760_codec_reg_write, + + .reg_defaults_raw = jz4760_codec_reg_defaults, + .num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static int jz4760_codec_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct jz_codec *codec; + int ret; + + codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + codec->dev = dev; + + codec->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(codec->base)) { + ret = PTR_ERR(codec->base); + dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret); + return ret; + } + + codec->regmap = devm_regmap_init(dev, NULL, codec, + &jz4760_codec_regmap_config); + if (IS_ERR(codec->regmap)) + return PTR_ERR(codec->regmap); + + codec->clk = devm_clk_get(dev, "aic"); + if (IS_ERR(codec->clk)) + return PTR_ERR(codec->clk); + + platform_set_drvdata(pdev, codec); + + ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev, + &jz4760_codec_dai, 1); + if (ret) { + dev_err(dev, "Failed to register codec: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct of_device_id jz4760_codec_of_matches[] = { + { .compatible = "ingenic,jz4760-codec", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches); + +static struct platform_driver jz4760_codec_driver = { + .probe = jz4760_codec_probe, + .driver = { + .name = "jz4760-codec", + .of_match_table = jz4760_codec_of_matches, + }, +}; +module_platform_driver(jz4760_codec_driver); + +MODULE_DESCRIPTION("JZ4760 SoC internal codec driver"); +MODULE_AUTHOR("Christophe Branchereau "); +MODULE_AUTHOR("Paul Cercueil "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 45a90d4aba1781aa382d4aeedebcac7cc78e1927 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 23 Jan 2021 14:09:56 +0000 Subject: ASoC: Add compatible strings for JZ4760(B) SoC Add the ingenic,jz4760b-codec and ingenic,jz4760-codec compatible strings. In the process, convert the previous compatible strings to use an enum instead. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210123140958.12895-1-paul@crapouillou.net Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ingenic,codec.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/ingenic,codec.yaml b/Documentation/devicetree/bindings/sound/ingenic,codec.yaml index eb4be86464bb..97d5f3819b27 100644 --- a/Documentation/devicetree/bindings/sound/ingenic,codec.yaml +++ b/Documentation/devicetree/bindings/sound/ingenic,codec.yaml @@ -15,9 +15,14 @@ properties: compatible: oneOf: - - const: ingenic,jz4770-codec - - const: ingenic,jz4725b-codec - - const: ingenic,jz4740-codec + - enum: + - ingenic,jz4770-codec + - ingenic,jz4760-codec + - ingenic,jz4725b-codec + - ingenic,jz4740-codec + - items: + - const: ingenic,jz4760b-codec + - const: ingenic,jz4760-codec reg: maxItems: 1 -- cgit v1.2.3 From 8ade6d8b02b1ead741bd4f6c42921035caab6560 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 Jan 2021 22:49:56 +0100 Subject: ASoC: Intel: Add DMI quirk table to soc_intel_is_byt_cr() Some Bay Trail systems: 1. Use a non CR version of the Bay Trail SoC 2. Contain at least 6 interrupt resources so that the platform_get_resource(pdev, IORESOURCE_IRQ, 5) check to workaround non CR systems which list their IPC IRQ at index 0 despite being non CR does not work 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5 Add a DMI quirk table to check for the few known models with this issue, so that the right IPC IRQ index is used on these systems. Reviewed-by: Andy Shevchenko Acked-by: Pierre-Louis Bossart Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210120214957.140232-5-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-intel-quirks.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h index b07df3059926..a93987ab7f4d 100644 --- a/sound/soc/intel/common/soc-intel-quirks.h +++ b/sound/soc/intel/common/soc-intel-quirks.h @@ -11,6 +11,7 @@ #if IS_ENABLED(CONFIG_X86) +#include #include #include #include @@ -38,12 +39,36 @@ SOC_INTEL_IS_CPU(cml, KABYLAKE_L); static inline bool soc_intel_is_byt_cr(struct platform_device *pdev) { + /* + * List of systems which: + * 1. Use a non CR version of the Bay Trail SoC + * 2. Contain at least 6 interrupt resources so that the + * platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below + * succeeds + * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5 + * + * This needs to be here so that it can be shared between the SST and + * SOF drivers. We rely on the compiler to optimize this out in files + * where soc_intel_is_byt_cr is not used. + */ + static const struct dmi_system_id force_bytcr_table[] = { + { /* Lenovo Yoga Tablet 2 series */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"), + }, + }, + {} + }; struct device *dev = &pdev->dev; int status = 0; if (!soc_intel_is_byt()) return false; + if (dmi_check_system(force_bytcr_table)) + return true; + if (iosf_mbi_available()) { u32 bios_status; -- cgit v1.2.3 From 9a87fc1e061900e81ab13d823e85012a78849244 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 22:49:57 +0100 Subject: ASoC: Intel: bytcr_wm5102: Add machine driver for BYT/WM5102 Add a new ASoc Machine driver for Intel Baytrail platforms with a Wolfson Microelectronics WM5102 codec. This is based on a past contributions [1] from Paulo Sergio Travaglia based on the Levono kernel [2] combined with insights in things like the speaker GPIO from the android-x86 android port for the Lenovo Yoga Tablet 2 1051F/L [3]. [1] https://patchwork.kernel.org/project/alsa-devel/patch/593313f5.3636c80a.50e05.47e9@mx.google.com/ [2] https://github.com/lenovo-yt2-dev/android_kernel_lenovo_baytrail/blob/cm-12.1/sound/soc/intel/board/byt_bl_wm5102.c [3] https://github.com/Kitsune2222/Android_Yoga_Tablet_2-1051F_Kernel The original machine driver from the Android ports was a crude modified copy of bytcr_rt5640.c adjusted to work with the WM5102 codec. This version has been extensively reworked to: 1. Remove all rt5640 related quirk handling. to the best of my knowledge this setup is only used on the Lenovo Yoga Tablet 2 series (8, 10 and 13 inch models) which all use the same setup. So there is no need to deal with all the variations with which we need to deal on rt5640 boards. 2. Rework clock handling, properly turn off the FLL and the platform-clock when they are no longer necessary and don't reconfigure the FLL unnecessarily when it is already running. This fixes a number of: "Timed out waiting for lock" warnings being logged. 3. Add the GPIO controlled Speaker-VDD regulator as a DAPM_SUPPLY This only adds the machine driver and ACPI hooks, the BYT-CR detection quirk which these devices need will be added in a separate patch. BugLink: https://github.com/thesofproject/linux/issues/2485 Co-authored-by: Pierre-Louis Bossart Signed-off-by: Pierre-Louis Bossart Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Reviewed-by: Charles Keepax Link: https://lore.kernel.org/r/20210120214957.140232-6-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 12 + sound/soc/intel/boards/Makefile | 2 + sound/soc/intel/boards/bytcr_wm5102.c | 465 ++++++++++++++++++++++ sound/soc/intel/common/soc-acpi-intel-byt-match.c | 16 + 4 files changed, 495 insertions(+) create mode 100644 sound/soc/intel/boards/bytcr_wm5102.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index b58b9b60d37e..d1d28129a32b 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -111,6 +111,18 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_BYTCR_WM5102_MACH + tristate "Baytrail and Baytrail-CR with WM5102 codec" + depends on MFD_ARIZONA && MFD_WM5102 && SPI_MASTER && ACPI + depends on X86_INTEL_LPSS || COMPILE_TEST + select SND_SOC_ACPI + select SND_SOC_WM5102 + help + This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR + platforms with WM5102 audio codec. + Say Y if you have such a device. + If unsure select "N". + config SND_SOC_INTEL_CHT_BSW_RT5672_MACH tristate "Cherrytrail & Braswell with RT5672 codec" depends on I2C && ACPI diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 5f03e484b215..616c5fbab7d5 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -10,6 +10,7 @@ snd-soc-sst-sof-wm8804-objs := sof_wm8804.o snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o +snd-soc-sst-bytcr-wm5102-objs := bytcr_wm5102.o snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o @@ -51,6 +52,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o +obj-$(CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH) += snd-soc-sst-bytcr-wm5102.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c new file mode 100644 index 000000000000..f38850eb2eaf --- /dev/null +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * bytcr_wm5102.c - ASoc Machine driver for Intel Baytrail platforms with a + * Wolfson Microelectronics WM5102 codec + * + * Copyright (C) 2020 Hans de Goede + * Loosely based on bytcr_rt5640.c which is: + * Copyright (C) 2014-2020 Intel Corp + * Author: Subhransu S. Prusty + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../codecs/wm5102.h" +#include "../atom/sst-atom-controls.h" + +#define MCLK_FREQ 25000000 + +#define WM5102_MAX_SYSCLK_4K 49152000 /* max sysclk for 4K family */ +#define WM5102_MAX_SYSCLK_11025 45158400 /* max sysclk for 11.025K family */ + +struct byt_wm5102_private { + struct clk *mclk; + struct gpio_desc *spkvdd_en_gpio; +}; + +static int byt_wm5102_spkvdd_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); + + gpiod_set_value_cansleep(priv->spkvdd_en_gpio, + !!SND_SOC_DAPM_EVENT_ON(event)); + + return 0; +} + +static int byt_wm5102_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, int rate) +{ + struct snd_soc_component *codec_component = codec_dai->component; + int sr_mult = ((rate % 4000) == 0) ? + (WM5102_MAX_SYSCLK_4K / rate) : + (WM5102_MAX_SYSCLK_11025 / rate); + int ret; + + /* Reset FLL1 */ + snd_soc_dai_set_pll(codec_dai, WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0); + snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0); + + /* Configure the FLL1 PLL before selecting it */ + ret = snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_CLK_SRC_MCLK1, + MCLK_FREQ, rate * sr_mult); + if (ret) { + dev_err(codec_component->dev, "Error setting PLL: %d\n", ret); + return ret; + } + + ret = snd_soc_component_set_sysclk(codec_component, ARIZONA_CLK_SYSCLK, + ARIZONA_CLK_SRC_FLL1, rate * sr_mult, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(codec_component->dev, "Error setting SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, ARIZONA_CLK_SYSCLK, + rate * 512, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(codec_component->dev, "Error setting clock: %d\n", ret); + return ret; + } + + return 0; +} + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); + int ret; + + codec_dai = snd_soc_card_get_codec_dai(card, "wm5102-aif1"); + if (!codec_dai) { + dev_err(card->dev, "Error codec DAI not found\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_ON(event)) { + ret = clk_prepare_enable(priv->mclk); + if (ret) { + dev_err(card->dev, "Error enabling MCLK: %d\n", ret); + return ret; + } + ret = byt_wm5102_prepare_and_enable_pll1(codec_dai, 48000); + if (ret) { + dev_err(card->dev, "Error setting codec sysclk: %d\n", ret); + return ret; + } + } else { + /* + * The WM5102 has a separate 32KHz clock for jack-detect + * so we can disable the PLL, followed by disabling the + * platform clock which is the source-clock for the PLL. + */ + snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0); + clk_disable_unprepare(priv->mclk); + } + + return 0; +} + +static const struct snd_soc_dapm_widget byt_wm5102_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Internal Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("Speaker VDD", SND_SOC_NOPM, 0, 0, + byt_wm5102_spkvdd_power_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +}; + +static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = { + {"Headphone", NULL, "Platform Clock"}, + {"Headset Mic", NULL, "Platform Clock"}, + {"Internal Mic", NULL, "Platform Clock"}, + {"Speaker", NULL, "Platform Clock"}, + + {"Speaker", NULL, "SPKOUTLP"}, + {"Speaker", NULL, "SPKOUTLN"}, + {"Speaker", NULL, "SPKOUTRP"}, + {"Speaker", NULL, "SPKOUTRN"}, + {"Speaker", NULL, "Speaker VDD"}, + + {"Headphone", NULL, "HPOUT1L"}, + {"Headphone", NULL, "HPOUT1R"}, + + {"Internal Mic", NULL, "MICBIAS3"}, + {"IN3L", NULL, "Internal Mic"}, + + /* + * The Headset Mix uses MICBIAS1 or 2 depending on if a CTIA/OMTP Headset + * is connected, as the MICBIAS is applied after the CTIA/OMTP cross-switch. + */ + {"Headset Mic", NULL, "MICBIAS1"}, + {"Headset Mic", NULL, "MICBIAS2"}, + {"IN1L", NULL, "Headset Mic"}, + + {"AIF1 Playback", NULL, "ssp0 Tx"}, + {"ssp0 Tx", NULL, "modem_out"}, + + {"modem_in", NULL, "ssp0 Rx"}, + {"ssp0 Rx", NULL, "AIF1 Capture"}, +}; + +static const struct snd_kcontrol_new byt_wm5102_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Internal Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_card *card = runtime->card; + struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); + int ret; + + card->dapm.idle_bias_off = true; + + ret = snd_soc_add_card_controls(card, byt_wm5102_controls, + ARRAY_SIZE(byt_wm5102_controls)); + if (ret) { + dev_err(card->dev, "Error adding card controls: %d\n", ret); + return ret; + } + + /* + * The firmware might enable the clock at boot (this information + * may or may not be reflected in the enable clock register). + * To change the rate we must disable the clock first to cover these + * cases. Due to common clock framework restrictions that do not allow + * to disable a clock that has not been enabled, we need to enable + * the clock first. + */ + ret = clk_prepare_enable(priv->mclk); + if (!ret) + clk_disable_unprepare(priv->mclk); + + ret = clk_set_rate(priv->mclk, MCLK_FREQ); + if (ret) { + dev_err(card->dev, "Error setting MCLK rate: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_pcm_stream byt_wm5102_dai_params = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, +}; + +static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + int ret; + + /* The DSP will covert the FE rate to 48k, stereo */ + rate->min = 48000; + rate->max = 48000; + channels->min = 2; + channels->max = 2; + + /* set SSP0 to 16-bit */ + params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); + + /* + * Default mode for SSP configuration is TDM 4 slot, override config + * with explicit setting to I2S 2ch 16-bit. The word length is set with + * dai_set_tdm_slot() since there is no other API exposed + */ + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); + if (ret) { + dev_err(rtd->dev, "Error setting format to I2S: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16); + if (ret) { + dev_err(rtd->dev, "Error setting I2S config: %d\n", ret); + return ret; + } + + return 0; +} + +static int byt_wm5102_aif1_startup(struct snd_pcm_substream *substream) +{ + return snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, 48000); +} + +static const struct snd_soc_ops byt_wm5102_aif1_ops = { + .startup = byt_wm5102_aif1_startup, +}; + +SND_SOC_DAILINK_DEF(dummy, + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +SND_SOC_DAILINK_DEF(media, + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); + +SND_SOC_DAILINK_DEF(deepbuffer, + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); + +SND_SOC_DAILINK_DEF(ssp0_port, + DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); + +SND_SOC_DAILINK_DEF(ssp0_codec, + DAILINK_COMP_ARRAY(COMP_CODEC( + /* + * Note there is no need to overwrite the codec-name as is done in + * other bytcr machine drivers, because the codec is a MFD child-dev. + */ + "wm5102-codec", + "wm5102-aif1"))); + +SND_SOC_DAILINK_DEF(platform, + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); + +static struct snd_soc_dai_link byt_wm5102_dais[] = { + [MERR_DPCM_AUDIO] = { + .name = "Baytrail Audio Port", + .stream_name = "Baytrail Audio", + .nonatomic = true, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &byt_wm5102_aif1_ops, + SND_SOC_DAILINK_REG(media, dummy, platform), + + }, + [MERR_DPCM_DEEP_BUFFER] = { + .name = "Deep-Buffer Audio Port", + .stream_name = "Deep-Buffer Audio", + .nonatomic = true, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &byt_wm5102_aif1_ops, + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), + }, + /* back ends */ + { + /* + * This must be named SSP2-Codec even though this machine driver + * always uses SSP0. Most machine drivers support both and dynamically + * update the dailink to point to SSP0 or SSP2, while keeping the name + * as "SSP2-Codec". The SOF tplg files hardcode the "SSP2-Codec" even + * in the byt-foo-ssp0.tplg versions because the other machine-drivers + * use "SSP2-Codec" even when SSP0 is used. + */ + .name = "SSP2-Codec", + .id = 0, + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .be_hw_params_fixup = byt_wm5102_codec_fixup, + .nonatomic = true, + .dpcm_playback = 1, + .dpcm_capture = 1, + .init = byt_wm5102_init, + SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform), + }, +}; + +/* use space before codec name to simplify card ID, and simplify driver name */ +#define SOF_CARD_NAME "bytcht wm5102" /* card name will be 'sof-bytcht wm5102' */ +#define SOF_DRIVER_NAME "SOF" + +#define CARD_NAME "bytcr-wm5102" +#define DRIVER_NAME NULL /* card name will be used for driver name */ + +/* SoC card */ +static struct snd_soc_card byt_wm5102_card = { + .owner = THIS_MODULE, + .dai_link = byt_wm5102_dais, + .num_links = ARRAY_SIZE(byt_wm5102_dais), + .dapm_widgets = byt_wm5102_widgets, + .num_dapm_widgets = ARRAY_SIZE(byt_wm5102_widgets), + .dapm_routes = byt_wm5102_audio_map, + .num_dapm_routes = ARRAY_SIZE(byt_wm5102_audio_map), + .fully_routed = true, +}; + +static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) +{ + char codec_name[SND_ACPI_I2C_ID_LEN]; + struct device *dev = &pdev->dev; + struct byt_wm5102_private *priv; + struct snd_soc_acpi_mach *mach; + const char *platform_name; + struct acpi_device *adev; + struct device *codec_dev; + bool sof_parent; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_ATOMIC); + if (!priv) + return -ENOMEM; + + /* Get MCLK */ + priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3"); + if (IS_ERR(priv->mclk)) + return dev_err_probe(dev, PTR_ERR(priv->mclk), "getting pmc_plt_clk_3\n"); + + /* + * Get speaker VDD enable GPIO: + * 1. Get codec-device-name + * 2. Get codec-device + * 3. Get GPIO from codec-device + */ + mach = dev->platform_data; + adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); + if (!adev) { + dev_err(dev, "Error cannot find acpi-dev for codec\n"); + return -ENOENT; + } + snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev)); + put_device(&adev->dev); + + codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name); + if (!codec_dev) + return -EPROBE_DEFER; + + /* Note no devm_ here since we call gpiod_get on codec_dev rather then dev */ + priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW); + put_device(codec_dev); + + if (IS_ERR(priv->spkvdd_en_gpio)) + return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n"); + + /* override platform name, if required */ + byt_wm5102_card.dev = dev; + platform_name = mach->mach_params.platform; + ret = snd_soc_fixup_dai_links_platform_name(&byt_wm5102_card, platform_name); + if (ret) + goto out_put_gpio; + + /* set card and driver name and pm-ops */ + sof_parent = snd_soc_acpi_sof_parent(dev); + if (sof_parent) { + byt_wm5102_card.name = SOF_CARD_NAME; + byt_wm5102_card.driver_name = SOF_DRIVER_NAME; + dev->driver->pm = &snd_soc_pm_ops; + } else { + byt_wm5102_card.name = CARD_NAME; + byt_wm5102_card.driver_name = DRIVER_NAME; + } + + snd_soc_card_set_drvdata(&byt_wm5102_card, priv); + ret = devm_snd_soc_register_card(dev, &byt_wm5102_card); + if (ret) { + dev_err_probe(dev, ret, "registering card\n"); + goto out_put_gpio; + } + + platform_set_drvdata(pdev, &byt_wm5102_card); + return 0; + +out_put_gpio: + gpiod_put(priv->spkvdd_en_gpio); + return ret; +} + +static int snd_byt_wm5102_mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); + + gpiod_put(priv->spkvdd_en_gpio); + return 0; +} + +static struct platform_driver snd_byt_wm5102_mc_driver = { + .driver = { + .name = "bytcr_wm5102", + }, + .probe = snd_byt_wm5102_mc_probe, + .remove = snd_byt_wm5102_mc_remove, +}; + +module_platform_driver(snd_byt_wm5102_mc_driver); + +MODULE_DESCRIPTION("ASoC Baytrail with WM5102 codec machine driver"); +MODULE_AUTHOR("Hans de Goede "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:bytcr_wm5102"); diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index 31e60df131c3..d1febbb53b70 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -154,6 +154,22 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = { .sof_fw_filename = "sof-byt.ri", .sof_tplg_filename = "sof-byt-rt5651.tplg", }, + { + .id = "WM510204", + .drv_name = "bytcr_wm5102", + .fw_filename = "intel/fw_sst_0f28.bin", + .board = "bytcr_wm5102", + .sof_fw_filename = "sof-byt.ri", + .sof_tplg_filename = "sof-byt-wm5102.tplg", + }, + { + .id = "WM510205", + .drv_name = "bytcr_wm5102", + .fw_filename = "intel/fw_sst_0f28.bin", + .board = "bytcr_wm5102", + .sof_fw_filename = "sof-byt.ri", + .sof_tplg_filename = "sof-byt-wm5102.tplg", + }, { .id = "DLGS7212", .drv_name = "bytcht_da7213", -- cgit v1.2.3 From 5427c7d6296ee574037c4a6649ac45a9474d1f13 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 8 Feb 2021 14:59:19 +0100 Subject: ALSA: hda: intel-dsp-config: Add SND_INTEL_BYT_PREFER_SOF Kconfig option The kernel has 2 drivers for the Low Power Engine audio-block on Bay- and Cherry-Trail SoCs. The old SST driver and the new SOF driver. If both drivers are enabled then the kernel will default to using the old SST driver, unless told otherwise through the snd_intel_dspcfg.dsp_driver module-parameter. Add a boolean SND_INTEL_BYT_PREFER_SOF Kconfig option, which when set to Y will make the kernel default to the new SOF driver instead. The option defaults to n, preserving the current behavior. Making this configurable will help distributions such as Fedora: https://fedoraproject.org/w/index.php?title=Changes/SofDefaultForIntelLpe to test using SOF on BYT/CHT during the transition phase where we have both drivers (eventually the old driver and this option will be removed). Note that this drops the acpi_config_table[] containing 2 entries per ACPI hardware-id if both drivers are enabled. snd_intel_acpi_dsp_find_config() will always return the first hit, so we only need a single entry with the flags value set depending on the Kconfig settings. Suggested-by: Takashi Iwai Signed-off-by: Hans de Goede Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208135919.135600-1-hdegoede@redhat.com Signed-off-by: Takashi Iwai --- sound/hda/Kconfig | 14 ++++++++++++++ sound/hda/intel-dsp-config.c | 29 ++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 3bc9224d5e4f..9ed5cfa3c18c 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -46,3 +46,17 @@ config SND_INTEL_DSP_CONFIG select SND_INTEL_NHLT if ACPI # this config should be selected only for Intel DSP platforms. # A fallback is provided so that the code compiles in all cases. + +config SND_INTEL_BYT_PREFER_SOF + bool "Prefer SOF driver over SST on BY/CHT platforms" + depends on SND_SST_ATOM_HIFI2_PLATFORM_ACPI && SND_SOC_SOF_BAYTRAIL + default n + help + The kernel has 2 drivers for the Low Power Engine audio-block on + Bay- and Cherry-Trail SoCs. The old SST driver and the new SOF + driver. If both drivers are enabled then the kernel will default + to using the old SST driver, unless told otherwise through the + snd_intel_dspcfg.dsp_driver module-parameter. + + Set this option to Y to make the kernel default to the new SOF + driver instead. diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index c45686172517..68bb977c6a37 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -452,35 +452,30 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) } EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe); +/* Should we default to SOF or SST for BYT/CHT ? */ +#if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \ + !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) +#define FLAG_SST_OR_SOF_BYT FLAG_SOF +#else +#define FLAG_SST_OR_SOF_BYT FLAG_SST +#endif + /* * configuration table * - the order of similar ACPI ID entries is important! * - the first successful match will win */ static const struct config_entry acpi_config_table[] = { +#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \ + IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) /* BayTrail */ -#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) - { - .flags = FLAG_SST, - .acpi_hid = "80860F28", - }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) { - .flags = FLAG_SOF, + .flags = FLAG_SST_OR_SOF_BYT, .acpi_hid = "80860F28", }, -#endif /* CherryTrail */ -#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) - { - .flags = FLAG_SST, - .acpi_hid = "808622A8", - }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) { - .flags = FLAG_SOF, + .flags = FLAG_SST_OR_SOF_BYT, .acpi_hid = "808622A8", }, #endif -- cgit v1.2.3 From 2c28156d88aa36ee8d45a3e68cc7eaa7d919dd96 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 10 Feb 2021 09:37:13 +0100 Subject: ALSA: core - add missing compress device type to /proc/asound/devices Signed-off-by: Jaroslav Kysela Acked-by: Vinod Koul Link: https://lore.kernel.org/r/20210210083713.1034201-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/core/sound.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/core/sound.c b/sound/core/sound.c index 2f759febe365..af89e51dd44a 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -343,6 +343,8 @@ static const char *snd_device_type_name(int type) return "sequencer"; case SNDRV_DEVICE_TYPE_TIMER: return "timer"; + case SNDRV_DEVICE_TYPE_COMPRESS: + return "compress"; default: return "?"; } -- cgit v1.2.3 From bd8036eb15263a720b8f846861c180b27d050a09 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:18:53 -0600 Subject: ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk The UpExtreme board supports the community key and was missed in previous contributions. Add it to make sure the open firmware is picked by default without needing a symlink on the target. Fixes: 46207ca24545 ('ASoC: SOF: pci: change the default firmware path when the community key is used') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210208231853.58761-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-pci-dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 215711ac7450..9adf50b20a73 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -65,6 +65,13 @@ static const struct dmi_system_id community_key_platforms[] = { DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), } }, + { + .ident = "Up Extreme", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_BOARD_NAME, "UP-WHL01"), + } + }, { .ident = "Google Chromebooks", .matches = { -- cgit v1.2.3 From ae4fc532244b3bb4d86c397418d980b0c6be1dfd Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Mon, 8 Feb 2021 17:40:42 -0600 Subject: ASoC: dapm: use component prefix when checking widget names On a TigerLake SoundWire platform, we see these warnings: [ 27.360086] rt5682 sdw:0:25d:5682:0: ASoC: DAPM unknown pin MICBIAS [ 27.360092] rt5682 sdw:0:25d:5682:0: ASoC: DAPM unknown pin Vref2 This is root-caused to the addition of a component prefix in the machine driver. The tests in soc-dapm should account for a prefix instead of reporting an invalid issue. Reported-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Signed-off-by: Shuming Fan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208234043.59750-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2b75d0139e47..b005f9eadd71 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2528,9 +2528,20 @@ static struct snd_soc_dapm_widget *dapm_find_widget( { struct snd_soc_dapm_widget *w; struct snd_soc_dapm_widget *fallback = NULL; + char prefixed_pin[80]; + const char *pin_name; + const char *prefix = soc_dapm_prefix(dapm); + + if (prefix) { + snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s", + prefix, pin); + pin_name = prefixed_pin; + } else { + pin_name = pin; + } for_each_card_widgets(dapm->card, w) { - if (!strcmp(w->name, pin)) { + if (!strcmp(w->name, pin_name)) { if (w->dapm == dapm) return w; else -- cgit v1.2.3 From 1183c350011a6f6b551c200b9206bf1808c22a4c Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 8 Feb 2021 17:40:43 -0600 Subject: ASoC: Intel: boards: max98373: get dapm from cpu_dai There is a prefix on max98373 codec, and the prefix will be added to the pin name However, there is no prefix on the "Right Spk" and "Left Spk" widgets. To avoid getting a redundant prefix, we should get dapm from cpu_dai component. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208234043.59750-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_maxim_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index c2a9757181fe..437d20562753 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -63,6 +63,7 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; int j; int ret = 0; @@ -70,10 +71,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) return 0; + cpu_dai = asoc_rtd_to_cpu(rtd, 0); for_each_rtd_codec_dais(rtd, j, codec_dai) { - struct snd_soc_component *component = codec_dai->component; struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); + snd_soc_component_get_dapm(cpu_dai->component); char pin_name[MAX_98373_PIN_NAME]; snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", -- cgit v1.2.3 From a8f50cd9be7cc4c57f29c1390568225ebee90eda Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Mon, 8 Feb 2021 17:21:45 -0600 Subject: ASoC: SOF: add missing pm debug Type is not part of debugging parse code. Add it so unknown types don't show up while debugging Reviewed-by: Ranjani Sridharan Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208232149.58899-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index fc13bb06dbf3..1bc3d6282f16 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -106,6 +106,8 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) str2 = "CLK_REQ"; break; case SOF_IPC_PM_CORE_ENABLE: str2 = "CORE_ENABLE"; break; + case SOF_IPC_PM_GATE: + str2 = "GATE"; break; default: str2 = "unknown type"; break; } -- cgit v1.2.3 From ce1f55bac5534aa518e26b94728173ee45f91a8c Mon Sep 17 00:00:00 2001 From: Curtis Malainey Date: Mon, 8 Feb 2021 17:21:46 -0600 Subject: ASoC: SOF: fix string format for errors These are negative error return values, printing them as hex is annoying and not beneficial. Switch back to signed type to make error lookup simpler. Reviewed-by: Kai Vehmanen Reviewed-by: Daniel Baluta Reviewed-by: Guennadi Liakhovetski Signed-off-by: Curtis Malainey Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208232149.58899-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-compress.c | 2 +- sound/soc/sof/intel/hda-dsp.c | 2 +- sound/soc/sof/intel/hda-loader.c | 6 +++--- sound/soc/sof/intel/hda-pcm.c | 2 +- sound/soc/sof/intel/hda-trace.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-compress.c index c6cf7b313934..fe2f3f7d236b 100644 --- a/sound/soc/sof/intel/hda-compress.c +++ b/sound/soc/sof/intel/hda-compress.c @@ -82,7 +82,7 @@ int hda_probe_compr_set_params(struct snd_sof_dev *sdev, ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL); if (ret < 0) { - dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret); + dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); return ret; } diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index e92e9750b720..72c0b8e9a196 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -732,7 +732,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) ret = snd_hdac_ext_bus_link_power_up(hlink); if (ret < 0) { dev_dbg(sdev->dev, - "error %x in %s: failed to power up links", + "error %d in %s: failed to power up links", ret, __func__); return ret; } diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index d744952f6954..fc25ee8f68dc 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -47,7 +47,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig /* allocate DMA buffer */ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab); if (ret < 0) { - dev_err(sdev->dev, "error: memory alloc failed: %x\n", ret); + dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret); goto error; } @@ -58,13 +58,13 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig if (direction == SNDRV_PCM_STREAM_CAPTURE) { ret = hda_dsp_iccmax_stream_hw_params(sdev, dsp_stream, dmab, NULL); if (ret < 0) { - dev_err(sdev->dev, "error: iccmax stream prepare failed: %x\n", ret); + dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret); goto error; } } else { ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL); if (ret < 0) { - dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret); + dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); goto error; } hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size); diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 689934131a68..df00db8369c7 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -111,7 +111,7 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, ret = hda_dsp_stream_hw_params(sdev, stream, dmab, params); if (ret < 0) { - dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret); + dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); return ret; } diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index 81d76d3debc6..29e3da3c63db 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -32,7 +32,7 @@ static int hda_dsp_trace_prepare(struct snd_sof_dev *sdev) ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL); if (ret < 0) - dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret); + dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret); return ret; } @@ -59,7 +59,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag) */ ret = hda_dsp_trace_prepare(sdev); if (ret < 0) { - dev_err(sdev->dev, "error: hdac trace init failed: %x\n", ret); + dev_err(sdev->dev, "error: hdac trace init failed: %d\n", ret); hda_dsp_stream_put(sdev, SNDRV_PCM_STREAM_CAPTURE, *stream_tag); hda->dtrace_stream = NULL; *stream_tag = 0; -- cgit v1.2.3 From 3be46fa21088740ae5790d84b882e5a3c98fce41 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 8 Feb 2021 17:21:47 -0600 Subject: ASoC: SOF: remove unused functions hda_dsp_dump_skl() is never used and hda_dsp_get_status_skl() is only called from that function. Remove both functions. Reviewed-by: Ranjani Sridharan Reviewed-by: Keyon Jie Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208232149.58899-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 50 ----------------------------------------------- sound/soc/sof/intel/hda.h | 1 - 2 files changed, 51 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 447163494b05..57853ef89cd1 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -317,26 +317,6 @@ static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { {HDA_DSP_ROM_NULL_FW_ENTRY, "error: null FW entry point"}, }; -static void hda_dsp_get_status_skl(struct snd_sof_dev *sdev) -{ - u32 status; - int i; - - status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_ADSP_FW_STATUS_SKL); - - for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) { - if (status == hda_dsp_rom_msg[i].code) { - dev_err(sdev->dev, "%s - code %8.8x\n", - hda_dsp_rom_msg[i].msg, status); - return; - } - } - - /* not for us, must be generic sof message */ - dev_dbg(sdev->dev, "unknown ROM status value %8.8x\n", status); -} - static void hda_dsp_get_status(struct snd_sof_dev *sdev) { u32 status; @@ -385,36 +365,6 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev, stack_words * sizeof(u32)); } -void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags) -{ - struct sof_ipc_dsp_oops_xtensa xoops; - struct sof_ipc_panic_info panic_info; - u32 stack[HDA_DSP_STACK_DUMP_SIZE]; - u32 status, panic; - - /* try APL specific status message types first */ - hda_dsp_get_status_skl(sdev); - - /* now try generic SOF status messages */ - status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_ADSP_ERROR_CODE_SKL); - - /*TODO: Check: there is no define in spec, but it is used in the code*/ - panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_ADSP_ERROR_CODE_SKL + 0x4); - - if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) { - hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, - HDA_DSP_STACK_DUMP_SIZE); - snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, - stack, HDA_DSP_STACK_DUMP_SIZE); - } else { - dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n", - status, panic); - hda_dsp_get_status_skl(sdev); - } -} - /* dump the first 8 dwords representing the extended ROM status */ static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags) { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 8e39d1e16178..d979411b4041 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -517,7 +517,6 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); -void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); void hda_ipc_dump(struct snd_sof_dev *sdev); void hda_ipc_irq_dump(struct snd_sof_dev *sdev); -- cgit v1.2.3 From f1bb023525fd654121f18f6e2587eeee84c9db04 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 8 Feb 2021 17:21:48 -0600 Subject: ASoC: SOF: HDA: (cosmetic) simplify hda_dsp_d0i3_work() Simplify hda_dsp_d0i3_work() by returning immediately from it if D0i3 cannot be set. Reviewed-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Reviewed-by: Libin Yang Reviewed-by: Keyon Jie Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208232149.58899-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 72c0b8e9a196..5788fe356960 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -934,19 +934,15 @@ void hda_dsp_d0i3_work(struct work_struct *work) d0i3_work.work); struct hdac_bus *bus = &hdev->hbus.core; struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev); - struct sof_dsp_power_state target_state; + struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + .substate = SOF_HDA_DSP_PM_D0I3, + }; int ret; - target_state.state = SOF_DSP_PM_D0; - /* DSP can enter D0I3 iff only D0I3-compatible streams are active */ - if (snd_sof_dsp_only_d0i3_compatible_stream_active(sdev)) - target_state.substate = SOF_HDA_DSP_PM_D0I3; - else - target_state.substate = SOF_HDA_DSP_PM_D0I0; - - /* remain in D0I0 */ - if (target_state.substate == SOF_HDA_DSP_PM_D0I0) + if (!snd_sof_dsp_only_d0i3_compatible_stream_active(sdev)) + /* remain in D0I0 */ return; /* This can fail but error cannot be propagated */ -- cgit v1.2.3 From cc11626dd9f894d93ed15d78b04452ca9acbb52b Mon Sep 17 00:00:00 2001 From: Fred Oh Date: Mon, 8 Feb 2021 17:21:49 -0600 Subject: ASoC: SOF: ext_manifest: use explicit number for elem_type Use explicit number to define elem_type enum instead of using SOF_IPC_EXT_*. Reviewed-by: Guennadi Liakhovetski Reviewed-by: Karol Trzciński Reviewed-by: Kai Vehmanen Signed-off-by: Fred Oh Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208232149.58899-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ext_manifest.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 7abc4f0bd3ad..2a7e055584f9 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -58,9 +58,9 @@ struct sof_ext_man_header { /* Extended manifest elements types */ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, - SOF_EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, - SOF_EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, - SOF_EXT_MAN_ELEM_DBG_ABI = SOF_IPC_EXT_USER_ABI_INFO, + SOF_EXT_MAN_ELEM_WINDOW = 1, + SOF_EXT_MAN_ELEM_CC_VERSION = 2, + SOF_EXT_MAN_ELEM_DBG_ABI = 4, SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, }; -- cgit v1.2.3 From 3d09cf8d0d791a41a75123e135f604d59f4aa870 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:26 -0600 Subject: ASoC: Intel: sof_sdw: reorganize quirks by generation The quirk table is a mess, let's reorganize it by generation before making sure that the quirks are consistent for each generation. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 73 +++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 152ea166eeae..8bd1d6c84f19 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -48,37 +48,14 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id) } static const struct dmi_system_id sof_sdw_quirk_table[] = { + /* CometLake devices */ { .callback = sof_sdw_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") - }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | - SOF_RT715_DAI_ID_FIX | - SOF_SDW_FOUR_SPK), - }, - { - .callback = sof_sdw_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") - }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | - SOF_RT715_DAI_ID_FIX), - }, - { - .callback = sof_sdw_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | - SOF_RT715_DAI_ID_FIX | - SOF_SDW_FOUR_SPK), + .driver_data = (void *)SOF_SDW_PCH_DMIC, }, { .callback = sof_sdw_quirk_cb, @@ -109,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, - { + { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), @@ -119,6 +96,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, + /* IceLake devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), + }, + .driver_data = (void *)SOF_SDW_PCH_DMIC, + }, + /* TigerLake devices */ { .callback = sof_sdw_quirk_cb, .matches = { @@ -133,18 +120,23 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { { .callback = sof_sdw_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") }, - .driver_data = (void *)SOF_SDW_PCH_DMIC, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX), }, { .callback = sof_sdw_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") }, - .driver_data = (void *)SOF_SDW_PCH_DMIC, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), }, { .callback = sof_sdw_quirk_cb, @@ -164,7 +156,18 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, - + /* TigerLake-SDCA devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), + }, {} }; -- cgit v1.2.3 From 8caf37e2be761688c396c609880936a807af490f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:27 -0600 Subject: ASoC: Intel: sof-sdw: indent and add quirks consistently Use the same style for all quirks to avoid misses and errors Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 8bd1d6c84f19..99c0e4b12d1c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -113,9 +113,10 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Tiger Lake Client Platform"), }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | - SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | - SOF_SSP_PORT(SOF_I2S_SSP2)), + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD1 | + SOF_SDW_PCH_DMIC | + SOF_SSP_PORT(SOF_I2S_SSP2)), }, { .callback = sof_sdw_quirk_cb, @@ -144,7 +145,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, { @@ -153,7 +155,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, /* TigerLake-SDCA devices */ -- cgit v1.2.3 From d92e279dee56b4b65c1af21f972413f172a9734a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:28 -0600 Subject: ASoC: Intel: sof_sdw: add quirk for HP Spectre x360 convertible This set of devices has SoundWire support along with DMICs. The DMI information was provided by users for 3 separate skus. BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 99c0e4b12d1c..0e83db947a57 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -159,6 +159,22 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, + { + /* + * this entry covers multiple HP SKUs. The family name + * does not seem robust enough, so we use a partial + * match that ignores the product name suffix + * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx) + */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | + SOF_RT711_JD_SRC_JD2), + }, /* TigerLake-SDCA devices */ { .callback = sof_sdw_quirk_cb, -- cgit v1.2.3 From 209b0b0d8d5a469a2892ad51cb448811d00b4ff4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:29 -0600 Subject: ASoC: Intel: sof_sdw: add mic:dmic and cfg-mics component strings UCM needs to know which microphone is used (dmic or RT715-based), let's add the information in the component string. Note the slight change from HDAudio platforms where 'cfg-dmics' was used. 'cfg-mics' is used here with the intent that this component string describes either the number of PCH-attached microphones or the number of RT715-attached ones (the assumption is that the two configurations are mutually exclusive). Suggested-by: Jaroslav Kysela Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0e83db947a57..d1251a6ac3af 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1222,6 +1222,15 @@ static int mc_probe(struct platform_device *pdev) if (!card->components) return -ENOMEM; + if (mach->mach_params.dmic_num) { + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:dmic cfg-mics:%d", + card->components, + mach->mach_params.dmic_num); + if (!card->components) + return -ENOMEM; + } + card->long_name = sdw_card_long_name; /* Register the card */ -- cgit v1.2.3 From f88dcb9b98d3f86ead04d2453475267910448bb8 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 8 Feb 2021 17:33:30 -0600 Subject: ASoC: Intel: sof_sdw: detect DMIC number based on mach params Current driver create DMIC dai based on quirk for each platforms, so we need to add quirk for new platforms. Now driver reports DMIC number to machine driver and machine driver can create DMIC dai based on this information. The old check is reserved for some platforms may be failed to set the DMIC number in BIOS. Reviewed-by: Bard Liao Signed-off-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208233336.59449-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index d1251a6ac3af..06f07dd45fb4 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -955,7 +955,7 @@ static int sof_card_dai_links_create(struct device *dev, ctx->idisp_codec = true; /* enable dmic01 & dmic16k */ - dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0; + dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0; comp_num += dmic_num; dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, -- cgit v1.2.3 From 3827b7ca399245e609b3ca717550b0638d1f69cd Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 8 Feb 2021 17:33:31 -0600 Subject: ASoC: intel: sof_sdw: add trace for dai links We create dai links dynamically, so it is not easy to know what dai links are created. So adding trace for dai link name and id. Reviewed-by: Rander Wang Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208233336.59449-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 06f07dd45fb4..8adce6417b02 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -476,15 +476,14 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, return 0; } -static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id, - char *name, int playback, int capture, - struct snd_soc_dai_link_component *cpus, - int cpus_num, - struct snd_soc_dai_link_component *codecs, - int codecs_num, +static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int be_id, char *name, int playback, int capture, + struct snd_soc_dai_link_component *cpus, int cpus_num, + struct snd_soc_dai_link_component *codecs, int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd), const struct snd_soc_ops *ops) { + dev_dbg(dev, "create dai link %s, id %d\n", name, be_id); dai_links->id = be_id; dai_links->name = name; dai_links->platforms = platform_component; @@ -822,7 +821,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); capture = (stream == SNDRV_PCM_STREAM_CAPTURE); - init_dai_link(dai_links + *be_index, *be_index, name, + init_dai_link(dev, dai_links + *be_index, *be_index, name, playback, capture, cpus + *cpu_id, cpu_dai_num, codecs, codec_num, @@ -1061,7 +1060,7 @@ SSP: playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; - init_dai_link(links + link_id, be_id, name, + init_dai_link(dev, links + link_id, be_id, name, playback, capture, cpus + cpu_id, 1, ssp_components, 1, @@ -1078,7 +1077,7 @@ DMIC: /* dmic */ if (dmic_num > 0) { cpus[cpu_id].dai_name = "DMIC01 Pin"; - init_dai_link(links + link_id, be_id, "dmic01", + init_dai_link(dev, links + link_id, be_id, "dmic01", 0, 1, // DMIC only supports capture cpus + cpu_id, 1, dmic_component, 1, @@ -1086,7 +1085,7 @@ DMIC: INC_ID(be_id, cpu_id, link_id); cpus[cpu_id].dai_name = "DMIC16k Pin"; - init_dai_link(links + link_id, be_id, "dmic16k", + init_dai_link(dev, links + link_id, be_id, "dmic16k", 0, 1, // DMIC only supports capture cpus + cpu_id, 1, dmic_component, 1, @@ -1129,7 +1128,7 @@ DMIC: return -ENOMEM; cpus[cpu_id].dai_name = cpu_name; - init_dai_link(links + link_id, be_id, name, + init_dai_link(dev, links + link_id, be_id, name, 1, 0, // HDMI only supports playback cpus + cpu_id, 1, idisp_components + i, 1, -- cgit v1.2.3 From 717a8fdd150c495cc202880cf6955294c7acae4f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:32 -0600 Subject: ASoC: Intel: soc-acpi: add ACPI matching table for HP Spectre x360 This device only has a single amplifier on link1, so we need a dedicated entry to find a match. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210208233336.59449-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index e3ddbf05bf72..40f31c8a3aba 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -205,6 +205,20 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = { {} }; +static const struct snd_soc_acpi_link_adr tgl_hp[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_0_adr), + .adr_d = rt711_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1308_1_single_adr), + .adr_d = rt1308_1_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = { { .mask = BIT(0), @@ -383,6 +397,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg", }, + { + .link_mask = 0x3, /* rt711 on link 0 and 1 rt1308 on link 1 */ + .links = tgl_hp, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg", + }, { .link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */ .links = tgl_rvp, -- cgit v1.2.3 From 6f5d506d7ff1d9b1ffac0130f2958b9da41175f4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:33 -0600 Subject: ASoC: SOF: Intel: SoundWire: refine ACPI match We have existing platforms where the wrong machine is selected. We need to make sure the number of devices reported on a link matches what we expect for a link descriptor. This helps avoid using the TGL-RVP configuration for an HP platform or vice-versa, depending on the order in which they are inserted in the table. Co-developed-by: Bard Liao Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210208233336.59449-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 59 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 447163494b05..db868376039a 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1071,32 +1071,63 @@ static bool link_slaves_found(struct snd_sof_dev *sdev, struct sdw_intel_slave_id *ids = sdw->ids; int num_slaves = sdw->num_slaves; unsigned int part_id, link_id, unique_id, mfg_id; - int i, j; + int i, j, k; for (i = 0; i < link->num_adr; i++) { u64 adr = link->adr_d[i].adr; + int reported_part_count = 0; mfg_id = SDW_MFG_ID(adr); part_id = SDW_PART_ID(adr); link_id = SDW_DISCO_LINK_ID(adr); + + for (j = 0; j < num_slaves; j++) { + /* find out how many identical parts were reported on that link */ + if (ids[j].link_id == link_id && + ids[j].id.part_id == part_id && + ids[j].id.mfg_id == mfg_id) + reported_part_count++; + } + for (j = 0; j < num_slaves; j++) { + int expected_part_count = 0; + if (ids[j].link_id != link_id || ids[j].id.part_id != part_id || ids[j].id.mfg_id != mfg_id) continue; - /* - * we have to check unique id - * if there is more than one - * Slave on the link - */ - unique_id = SDW_UNIQUE_ID(adr); - if (link->num_adr == 1 || - ids[j].id.unique_id == SDW_IGNORED_UNIQUE_ID || - ids[j].id.unique_id == unique_id) { - dev_dbg(bus->dev, - "found %x at link %d\n", - part_id, link_id); - break; + + /* find out how many identical parts are expected */ + for (k = 0; k < link->num_adr; k++) { + u64 adr2 = link->adr_d[i].adr; + unsigned int part_id2, link_id2, mfg_id2; + + mfg_id2 = SDW_MFG_ID(adr2); + part_id2 = SDW_PART_ID(adr2); + link_id2 = SDW_DISCO_LINK_ID(adr2); + + if (link_id2 == link_id && + part_id2 == part_id && + mfg_id2 == mfg_id) + expected_part_count++; + } + + if (reported_part_count == expected_part_count) { + /* + * we have to check unique id + * if there is more than one + * Slave on the link + */ + unique_id = SDW_UNIQUE_ID(adr); + if (reported_part_count == 1 || + ids[j].id.unique_id == unique_id) { + dev_dbg(bus->dev, "found %x at link %d\n", + part_id, link_id); + break; + } + } else { + dev_dbg(bus->dev, "part %x reported %d expected %d on link %d, skipping\n", + part_id, reported_part_count, expected_part_count, link_id); } } if (j == num_slaves) { -- cgit v1.2.3 From 7aecf59770920cce5ff6e94b3809574364178126 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:34 -0600 Subject: ASoC: SOF: Intel: detect DMIC number in SoundWire mixed config The pinmux allows for 2 SoundWire links to be enabled along with DMICs. This was the default configuration on the TGL-RVP. One issue with this configuration is that we don't have a means to automatically detect how many DMICs are used, which in turn requires the user to manually rename the topology file required on a platform. This was borderline acceptable for Intel RVPs, but now that this configuration is present in HP devices we need to automate the process. This patch makes use of the NHLT information and will pass the DMIC number to the machine driver as a parameter. A follow-up patch will expose the DMIC number to userspace/UCM with the configuration strings. The Google devices do make use of DMICs instead of SoundWire link 2 and 3, but their topology is unique enough that they do not need any NHTL support or topology renaming. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 133 +++++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 48 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index db868376039a..7ae2c2c451ef 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -285,11 +285,13 @@ static char *hda_model; module_param(hda_model, charp, 0444); MODULE_PARM_DESC(hda_model, "Use the given HDA board model."); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) static int hda_dmic_num = -1; module_param_named(dmic_num, hda_dmic_num, int, 0444); MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI); module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444); MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver"); @@ -555,7 +557,7 @@ static int hda_init(struct snd_sof_dev *sdev) return ret; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) static int check_nhlt_dmic(struct snd_sof_dev *sdev) { @@ -598,6 +600,53 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, return tplg_filename; } +static int dmic_topology_fixup(struct snd_sof_dev *sdev, + const char **tplg_filename, + const char *idisp_str, + int *dmic_found) +{ + const char *default_tplg_filename = *tplg_filename; + const char *fixed_tplg_filename; + const char *dmic_str; + int dmic_num; + + /* first check NHLT for DMICs */ + dmic_num = check_nhlt_dmic(sdev); + + /* allow for module parameter override */ + if (hda_dmic_num != -1) + dmic_num = hda_dmic_num; + + switch (dmic_num) { + case 1: + dmic_str = "-1ch"; + break; + case 2: + dmic_str = "-2ch"; + break; + case 3: + dmic_str = "-3ch"; + break; + case 4: + dmic_str = "-4ch"; + break; + default: + dmic_num = 0; + dmic_str = ""; + break; + } + + fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename, + idisp_str, dmic_str); + if (!fixed_tplg_filename) + return -ENOMEM; + + dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num); + *dmic_found = dmic_num; + *tplg_filename = fixed_tplg_filename; + + return 0; +} #endif static int hda_init_caps(struct snd_sof_dev *sdev) @@ -963,9 +1012,9 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) struct snd_sof_pdata *pdata = sdev->pdata; const char *tplg_filename; const char *idisp_str; - const char *dmic_str; int dmic_num = 0; int codec_num = 0; + int ret; int i; /* codec detection */ @@ -990,10 +1039,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) if (!pdata->machine && codec_num <= 2) { hda_mach = snd_soc_acpi_intel_hda_machines; - /* topology: use the info from hda_machines */ - pdata->tplg_filename = - hda_mach->sof_tplg_filename; - dev_info(bus->dev, "using HDA machine driver %s now\n", hda_mach->drv_name); @@ -1002,42 +1047,13 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) else idisp_str = ""; - /* first check NHLT for DMICs */ - dmic_num = check_nhlt_dmic(sdev); - - /* allow for module parameter override */ - if (hda_dmic_num != -1) - dmic_num = hda_dmic_num; - - switch (dmic_num) { - case 1: - dmic_str = "-1ch"; - break; - case 2: - dmic_str = "-2ch"; - break; - case 3: - dmic_str = "-3ch"; - break; - case 4: - dmic_str = "-4ch"; - break; - default: - dmic_num = 0; - dmic_str = ""; - break; - } - - tplg_filename = pdata->tplg_filename; - tplg_filename = fixup_tplg_name(sdev, tplg_filename, - idisp_str, dmic_str); - if (!tplg_filename) - return -EINVAL; - - dev_info(bus->dev, - "DMICs detected in NHLT tables: %d\n", - dmic_num); + /* topology: use the info from hda_machines */ + tplg_filename = hda_mach->sof_tplg_filename; + ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num); + if (ret < 0) + return ret; + hda_mach->mach_params.dmic_num = dmic_num; pdata->machine = hda_mach; pdata->tplg_filename = tplg_filename; } @@ -1049,7 +1065,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) &pdata->machine->mach_params; mach_params->codec_mask = bus->codec_mask; mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; - mach_params->dmic_num = dmic_num; } return 0; @@ -1144,7 +1159,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) { struct snd_sof_pdata *pdata = sdev->pdata; const struct snd_soc_acpi_link_adr *link; - struct hdac_bus *bus = sof_to_bus(sdev); struct snd_soc_acpi_mach *mach; struct sof_intel_hda_dev *hdev; u32 link_mask; @@ -1192,10 +1206,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) break; } if (mach && mach->link_mask) { - dev_dbg(bus->dev, - "SoundWire machine driver %s topology %s\n", - mach->drv_name, - mach->sof_tplg_filename); + int dmic_num = 0; + pdata->machine = mach; mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; @@ -1205,6 +1217,31 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) else pdata->fw_filename = pdata->desc->default_fw_filename; pdata->tplg_filename = mach->sof_tplg_filename; + + /* + * DMICs use up to 4 pins and are typically pin-muxed with SoundWire + * link 2 and 3, thus we only try to enable dmics if all conditions + * are true: + * a) link 2 and 3 are not used by SoundWire + * b) the NHLT table reports the presence of microphones + */ + if (!(mach->link_mask & GENMASK(3, 2))) { + const char *tplg_filename = mach->sof_tplg_filename; + int ret; + + ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num); + + if (ret < 0) + return ret; + + pdata->tplg_filename = tplg_filename; + } + mach->mach_params.dmic_num = dmic_num; + + dev_dbg(sdev->dev, + "SoundWire machine driver %s topology %s\n", + mach->drv_name, + pdata->tplg_filename); } else { dev_info(sdev->dev, "No SoundWire machine driver found\n"); -- cgit v1.2.3 From b9088535e1021f11500f8417598b6af1f381f7dc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 8 Feb 2021 17:33:35 -0600 Subject: ASoC: SOF: Intel: HDA: don't keep a temporary variable fixup_tplg_name() doesn't need to keep the string, allocated for filename - it's temporary. Reviewed-by: Kai Vehmanen Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210208233336.59449-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7ae2c2c451ef..bd1cbef90278 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -581,22 +581,22 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, const char *dmic_str) { const char *tplg_filename = NULL; - char *filename; - char *split_ext; + char *filename, *tmp; + const char *split_ext; - filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL); + filename = kstrdup(sof_tplg_filename, GFP_KERNEL); if (!filename) return NULL; /* this assumes a .tplg extension */ - split_ext = strsep(&filename, "."); - if (split_ext) { + tmp = filename; + split_ext = strsep(&tmp, "."); + if (split_ext) tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s%s%s.tplg", split_ext, idisp_str, dmic_str); - if (!tplg_filename) - return NULL; - } + kfree(filename); + return tplg_filename; } -- cgit v1.2.3 From 026370cb5bd7ef7999bc4379ab89ffd7a73874f2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:36 -0600 Subject: ASoC: SOF: Intel: hda: add dev_dbg() when DMIC number is overridden It's useful for debug and system integration to show cases where we ignore the number of microphones reported by NHLT. Suggested-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index bd1cbef90278..0251bf83d0fe 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -614,8 +614,12 @@ static int dmic_topology_fixup(struct snd_sof_dev *sdev, dmic_num = check_nhlt_dmic(sdev); /* allow for module parameter override */ - if (hda_dmic_num != -1) + if (hda_dmic_num != -1) { + dev_dbg(sdev->dev, + "overriding DMICs detected in NHLT tables %d by kernel param %d\n", + dmic_num, hda_dmic_num); dmic_num = hda_dmic_num; + } switch (dmic_num) { case 1: -- cgit v1.2.3 From b6eabd247db8bb2d013fb9a9451ecb04a44ee58f Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 8 Feb 2021 16:12:45 +0800 Subject: ASoC: soc-pcm: change error message to debug message This log message should be a debug message, because it doesn't return directly but continue next loop. Signed-off-by: Shengjiu Wang Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/1612771965-5776-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b79f064887d4..8d55f39d4014 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1344,8 +1344,8 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, /* is there a valid BE rtd for this widget */ be = dpcm_get_be(card, widget, stream); if (!be) { - dev_err(fe->dev, "ASoC: no BE found for %s\n", - widget->name); + dev_dbg(fe->dev, "ASoC: no BE found for %s\n", + widget->name); continue; } -- cgit v1.2.3 From 271d9373db1c76f239fe3124e552b6b58b2af984 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 10 Feb 2021 12:52:37 +0200 Subject: ASoC: SOF: fix runtime pm usage mismatch after probe errors With current delayed probe implementation, sof_probe_complete is not called in case of errors. And as this function is responsible for decrementing runtime pm usage counter, this will result in following problem: - probe driver in conditions where probe will fail (to force the condition on Intel SOF systems, set "snd_sof_intel_hda_common.codec_mask=0") - unload driver (runtime-pm usage_count is leaked) - fix the issue by installing missing fw, modifying module parameters, etc actions - try to load driver again -> success, probe ok -> device never enters runtime suspend Fix the issue by storing result of delayed probe to a state variable and providing new snd_sof_device_probe_completed() to be queried from SOF PCI/ACPI/OF drivers. If probe never completed successfully, runtime PM was not set up and thus at remove(), we should not increment usage count anymore. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210210105237.2179273-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 10 ++++++++++ sound/soc/sof/sof-pci-dev.c | 3 ++- sound/soc/sof/sof-priv.h | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 8d13eb13fe08..6d8f7d9fd192 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -246,6 +246,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) if (plat_data->sof_probe_complete) plat_data->sof_probe_complete(sdev->dev); + sdev->probe_completed = true; + return 0; fw_trace_err: @@ -340,6 +342,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) } EXPORT_SYMBOL(snd_sof_device_probe); +bool snd_sof_device_probe_completed(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + return sdev->probe_completed; +} +EXPORT_SYMBOL(snd_sof_device_probe_completed); + int snd_sof_device_remove(struct device *dev) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 388772f9c4d2..84990cc8aa7d 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -447,7 +447,8 @@ static void sof_pci_remove(struct pci_dev *pci) snd_sof_device_remove(&pci->dev); /* follow recommendation in pci-driver.c to increment usage counter */ - if (!(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) + if (snd_sof_device_probe_completed(&pci->dev) && + !(sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME)) pm_runtime_get_noresume(&pci->dev); /* release pci regions and disable device */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 682c4b6d01ef..ad0d7ba2708c 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -389,6 +389,7 @@ struct snd_sof_dev { /* work queue in case the probe is implemented in two steps */ struct work_struct probe_work; + bool probe_completed; /* DSP HW differentiation */ struct snd_sof_pdata *pdata; @@ -464,6 +465,7 @@ struct snd_sof_dev { int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data); int snd_sof_device_remove(struct device *dev); int snd_sof_device_shutdown(struct device *dev); +bool snd_sof_device_probe_completed(struct device *dev); int snd_sof_runtime_suspend(struct device *dev); int snd_sof_runtime_resume(struct device *dev); -- cgit v1.2.3 From 056a3da5d07fc5d3ceacfa2cdf013c9d8df630bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Feb 2021 09:31:39 +0100 Subject: ALSA: hda/hdmi: Drop bogus check at closing a stream Some users reported the kernel WARNING with stack traces from hdmi_pcm_close(), and it's the line checking the per_cvt->assigned flag. This used to be a valid check in the past because the flag was turned on/off only at opening and closing a PCM stream. Meanwhile, since the introduction of the silent-stream mode, this flag may be turned on/off at the monitor connection/disconnection time, which isn't always associated with the PCM open/close. Hence this may lead to the inconsistent per_cvt->assigned flag at closing. As the check itself became almost useless and confuses users as if it were a serious problem, just drop the check. Fixes: b1a5039759cb ("ALSA: hda/hdmi: fix silent stream for first playback to DP") Cc: BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=210987 Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210211083139.29531-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 97adff0cbcab..e405be7929e3 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2130,7 +2130,6 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, goto unlock; } per_cvt = get_cvt(spec, cvt_idx); - snd_BUG_ON(!per_cvt->assigned); per_cvt->assigned = 0; hinfo->nid = 0; -- cgit v1.2.3 From 1e30f642cf2939bbdac82ea0dd3071232670b5ab Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Wed, 10 Feb 2021 12:13:39 +0530 Subject: ASoC: simple-card-utils: Fix device module clock If "clocks = <&xxx>" is specified from the CPU or Codec component device node, the clock is not getting enabled. Thus audio playback or capture fails. Fix this by populating "simple_dai->clk" field when clocks property is specified from device node as well. Also tidy up by re-organising conditional statements of parsing logic. Fixes: bb6fc620c2ed ("ASoC: simple-card-utils: add asoc_simple_card_parse_clk()") Cc: Kuninori Morimoto Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1612939421-19900-2-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 6cada4c1e283..ab31045cfc95 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -172,16 +172,15 @@ int asoc_simple_parse_clk(struct device *dev, * or device's module clock. */ clk = devm_get_clk_from_child(dev, node, NULL); - if (!IS_ERR(clk)) { - simple_dai->sysclk = clk_get_rate(clk); + if (IS_ERR(clk)) + clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); + if (!IS_ERR(clk)) { simple_dai->clk = clk; - } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { + simple_dai->sysclk = clk_get_rate(clk); + } else if (!of_property_read_u32(node, "system-clock-frequency", + &val)) { simple_dai->sysclk = val; - } else { - clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); - if (!IS_ERR(clk)) - simple_dai->sysclk = clk_get_rate(clk); } if (of_property_read_bool(node, "system-clock-direction-out")) -- cgit v1.2.3 From 0be0f142b8323378df6358c36dd15494134f5b94 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Wed, 10 Feb 2021 12:13:40 +0530 Subject: ASoC: audio-graph-card: Drop device node clocks property An endpoint is not a device and it is recommended to use clocks property in the device node. Hence reverting the original change. Fixes: 531e5b7abbde ("ASoC: audio-graph-card: Add clocks property to endpoint node") Suggested-by: Rob Herring Cc: Kuninori Morimoto Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1612939421-19900-3-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/audio-graph-port.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml index 08ed8f52c962..766e9109b2f7 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml @@ -33,9 +33,6 @@ properties: properties: remote-endpoint: maxItems: 1 - clocks: - maxItems: 1 - description: Describes the clock used by audio component. mclk-fs: description: | Multiplication factor between stream rate and codec mclk. -- cgit v1.2.3 From f133de9e32374841c5ed1ad5cf18ed14098a0f4c Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:29 +0000 Subject: ASoC: qcom: dt-bindings: add bindings for lpass rx macro codec This binding is for LPASS has internal codec RX macro which is for connecting with SoundWire RX codecs like WCD938x. Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210211122735.5691-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-rx-macro.yaml | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml new file mode 100644 index 000000000000..443d556caa69 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,lpass-rx-macro.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LPASS(Low Power Audio Subsystem) RX Macro audio codec DT bindings + +maintainers: + - Srinivas Kandagatla + +properties: + compatible: + const: qcom,sm8250-lpass-rx-macro + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + '#clock-cells': + const: 0 + + clocks: + maxItems: 5 + + clock-names: + items: + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + + clock-output-names: + items: + - const: mclk + +required: + - compatible + - reg + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + #include + codec@3200000 { + compatible = "qcom,sm8250-lpass-rx-macro"; + reg = <0x3200000 0x1000>; + #sound-dai-cells = <1>; + #clock-cells = <0>; + clocks = <&audiocc 0>, + <&audiocc 1>, + <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", "npl", "macro", "dcodec", "fsgen"; + clock-output-names = "mclk"; + }; -- cgit v1.2.3 From af3d54b99764f0bdd83fcbd1895d23b83f8276be Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:30 +0000 Subject: ASoC: codecs: lpass-rx-macro: add support for lpass rx macro LPASS RX Codec Macro is available in Qualcomm LPASS (Low Power Audio SubSystem). This is used for connecting with SoundWire devices like WCD938x Codecs to provide headphone/ear/lineout functionality. Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210211122735.5691-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/lpass-rx-macro.c | 1994 +++++++++++++++++++++++++++++++++++++ 3 files changed, 2001 insertions(+) create mode 100644 sound/soc/codecs/lpass-rx-macro.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f9ce7bb654a5..5fb5a5a2c605 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -228,6 +228,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_UDA1380 imply SND_SOC_WCD9335 imply SND_SOC_WCD934X + imply SND_SOC_LPASS_RX_MACRO imply SND_SOC_WL1273 imply SND_SOC_WM0010 imply SND_SOC_WM1250_EV1 @@ -1833,4 +1834,8 @@ config SND_SOC_LPASS_VA_MACRO depends on COMMON_CLK tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)" +config SND_SOC_LPASS_RX_MACRO + depends on COMMON_CLK + tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)" + endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d5c7eb3544a5..004ffcbe0b98 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -107,6 +107,7 @@ snd-soc-l3-objs := l3.o snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o snd-soc-lochnagar-sc-objs := lochnagar-sc.o +snd-soc-lpass-rx-macro-objs := lpass-rx-macro.o snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o snd-soc-lpass-va-macro-objs := lpass-va-macro.o snd-soc-madera-objs := madera.o @@ -625,6 +626,7 @@ obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO) += snd-soc-lpass-wsa-macro.o obj-$(CONFIG_SND_SOC_LPASS_VA_MACRO) += snd-soc-lpass-va-macro.o +obj-$(CONFIG_SND_SOC_LPASS_RX_MACRO) += snd-soc-lpass-rx-macro.o # Mux obj-$(CONFIG_SND_SOC_SIMPLE_MUX) += snd-soc-simple-mux.o diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c new file mode 100644 index 000000000000..1c114a46c44a --- /dev/null +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -0,0 +1,1994 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CDC_RX_TOP_TOP_CFG0 (0x0000) +#define CDC_RX_TOP_SWR_CTRL (0x0008) +#define CDC_RX_TOP_DEBUG (0x000C) +#define CDC_RX_TOP_DEBUG_BUS (0x0010) +#define CDC_RX_TOP_DEBUG_EN0 (0x0014) +#define CDC_RX_TOP_DEBUG_EN1 (0x0018) +#define CDC_RX_TOP_DEBUG_EN2 (0x001C) +#define CDC_RX_TOP_HPHL_COMP_WR_LSB (0x0020) +#define CDC_RX_TOP_HPHL_COMP_WR_MSB (0x0024) +#define CDC_RX_TOP_HPHL_COMP_LUT (0x0028) +#define CDC_RX_TOP_HPH_LUT_BYPASS_MASK BIT(7) +#define CDC_RX_TOP_HPHL_COMP_RD_LSB (0x002C) +#define CDC_RX_TOP_HPHL_COMP_RD_MSB (0x0030) +#define CDC_RX_TOP_HPHR_COMP_WR_LSB (0x0034) +#define CDC_RX_TOP_HPHR_COMP_WR_MSB (0x0038) +#define CDC_RX_TOP_HPHR_COMP_LUT (0x003C) +#define CDC_RX_TOP_HPHR_COMP_RD_LSB (0x0040) +#define CDC_RX_TOP_HPHR_COMP_RD_MSB (0x0044) +#define CDC_RX_TOP_DSD0_DEBUG_CFG0 (0x0070) +#define CDC_RX_TOP_DSD0_DEBUG_CFG1 (0x0074) +#define CDC_RX_TOP_DSD0_DEBUG_CFG2 (0x0078) +#define CDC_RX_TOP_DSD0_DEBUG_CFG3 (0x007C) +#define CDC_RX_TOP_DSD1_DEBUG_CFG0 (0x0080) +#define CDC_RX_TOP_DSD1_DEBUG_CFG1 (0x0084) +#define CDC_RX_TOP_DSD1_DEBUG_CFG2 (0x0088) +#define CDC_RX_TOP_DSD1_DEBUG_CFG3 (0x008C) +#define CDC_RX_TOP_RX_I2S_CTL (0x0090) +#define CDC_RX_TOP_TX_I2S2_CTL (0x0094) +#define CDC_RX_TOP_I2S_CLK (0x0098) +#define CDC_RX_TOP_I2S_RESET (0x009C) +#define CDC_RX_TOP_I2S_MUX (0x00A0) +#define CDC_RX_CLK_RST_CTRL_MCLK_CONTROL (0x0100) +#define CDC_RX_CLK_MCLK_EN_MASK BIT(0) +#define CDC_RX_CLK_MCLK_ENABLE BIT(0) +#define CDC_RX_CLK_MCLK2_EN_MASK BIT(1) +#define CDC_RX_CLK_MCLK2_ENABLE BIT(1) +#define CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL (0x0104) +#define CDC_RX_FS_MCLK_CNT_EN_MASK BIT(0) +#define CDC_RX_FS_MCLK_CNT_ENABLE BIT(0) +#define CDC_RX_FS_MCLK_CNT_CLR_MASK BIT(1) +#define CDC_RX_FS_MCLK_CNT_CLR BIT(1) +#define CDC_RX_CLK_RST_CTRL_SWR_CONTROL (0x0108) +#define CDC_RX_SWR_CLK_EN_MASK BIT(0) +#define CDC_RX_SWR_RESET_MASK BIT(1) +#define CDC_RX_SWR_RESET BIT(1) +#define CDC_RX_CLK_RST_CTRL_DSD_CONTROL (0x010C) +#define CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL (0x0110) +#define CDC_RX_SOFTCLIP_CRC (0x0140) +#define CDC_RX_SOFTCLIP_CLK_EN_MASK BIT(0) +#define CDC_RX_SOFTCLIP_SOFTCLIP_CTRL (0x0144) +#define CDC_RX_SOFTCLIP_EN_MASK BIT(0) +#define CDC_RX_INP_MUX_RX_INT0_CFG0 (0x0180) +#define CDC_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(3, 0) +#define CDC_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(7, 4) +#define CDC_RX_INP_MUX_RX_INT0_CFG1 (0x0184) +#define CDC_RX_INTX_2_SEL_MASK GENMASK(3, 0) +#define CDC_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(7, 4) +#define CDC_RX_INP_MUX_RX_INT1_CFG0 (0x0188) +#define CDC_RX_INP_MUX_RX_INT1_CFG1 (0x018C) +#define CDC_RX_INP_MUX_RX_INT2_CFG0 (0x0190) +#define CDC_RX_INP_MUX_RX_INT2_CFG1 (0x0194) +#define CDC_RX_INP_MUX_RX_MIX_CFG4 (0x0198) +#define CDC_RX_INP_MUX_RX_MIX_CFG5 (0x019C) +#define CDC_RX_INP_MUX_SIDETONE_SRC_CFG0 (0x01A0) +#define CDC_RX_CLSH_CRC (0x0200) +#define CDC_RX_CLSH_CLK_EN_MASK BIT(0) +#define CDC_RX_CLSH_DLY_CTRL (0x0204) +#define CDC_RX_CLSH_DECAY_CTRL (0x0208) +#define CDC_RX_CLSH_DECAY_RATE_MASK GENMASK(2, 0) +#define CDC_RX_CLSH_HPH_V_PA (0x020C) +#define CDC_RX_CLSH_HPH_V_PA_MIN_MASK GENMASK(5, 0) +#define CDC_RX_CLSH_EAR_V_PA (0x0210) +#define CDC_RX_CLSH_HPH_V_HD (0x0214) +#define CDC_RX_CLSH_EAR_V_HD (0x0218) +#define CDC_RX_CLSH_K1_MSB (0x021C) +#define CDC_RX_CLSH_K1_MSB_COEFF_MASK GENMASK(3, 0) +#define CDC_RX_CLSH_K1_LSB (0x0220) +#define CDC_RX_CLSH_K2_MSB (0x0224) +#define CDC_RX_CLSH_K2_LSB (0x0228) +#define CDC_RX_CLSH_IDLE_CTRL (0x022C) +#define CDC_RX_CLSH_IDLE_HPH (0x0230) +#define CDC_RX_CLSH_IDLE_EAR (0x0234) +#define CDC_RX_CLSH_TEST0 (0x0238) +#define CDC_RX_CLSH_TEST1 (0x023C) +#define CDC_RX_CLSH_OVR_VREF (0x0240) +#define CDC_RX_CLSH_CLSG_CTL (0x0244) +#define CDC_RX_CLSH_CLSG_CFG1 (0x0248) +#define CDC_RX_CLSH_CLSG_CFG2 (0x024C) +#define CDC_RX_BCL_VBAT_PATH_CTL (0x0280) +#define CDC_RX_BCL_VBAT_CFG (0x0284) +#define CDC_RX_BCL_VBAT_ADC_CAL1 (0x0288) +#define CDC_RX_BCL_VBAT_ADC_CAL2 (0x028C) +#define CDC_RX_BCL_VBAT_ADC_CAL3 (0x0290) +#define CDC_RX_BCL_VBAT_PK_EST1 (0x0294) +#define CDC_RX_BCL_VBAT_PK_EST2 (0x0298) +#define CDC_RX_BCL_VBAT_PK_EST3 (0x029C) +#define CDC_RX_BCL_VBAT_RF_PROC1 (0x02A0) +#define CDC_RX_BCL_VBAT_RF_PROC2 (0x02A4) +#define CDC_RX_BCL_VBAT_TAC1 (0x02A8) +#define CDC_RX_BCL_VBAT_TAC2 (0x02AC) +#define CDC_RX_BCL_VBAT_TAC3 (0x02B0) +#define CDC_RX_BCL_VBAT_TAC4 (0x02B4) +#define CDC_RX_BCL_VBAT_GAIN_UPD1 (0x02B8) +#define CDC_RX_BCL_VBAT_GAIN_UPD2 (0x02BC) +#define CDC_RX_BCL_VBAT_GAIN_UPD3 (0x02C0) +#define CDC_RX_BCL_VBAT_GAIN_UPD4 (0x02C4) +#define CDC_RX_BCL_VBAT_GAIN_UPD5 (0x02C8) +#define CDC_RX_BCL_VBAT_DEBUG1 (0x02CC) +#define CDC_RX_BCL_VBAT_GAIN_UPD_MON (0x02D0) +#define CDC_RX_BCL_VBAT_GAIN_MON_VAL (0x02D4) +#define CDC_RX_BCL_VBAT_BAN (0x02D8) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD1 (0x02DC) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD2 (0x02E0) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD3 (0x02E4) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD4 (0x02E8) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD5 (0x02EC) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD6 (0x02F0) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD7 (0x02F4) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD8 (0x02F8) +#define CDC_RX_BCL_VBAT_BCL_GAIN_UPD9 (0x02FC) +#define CDC_RX_BCL_VBAT_ATTN1 (0x0300) +#define CDC_RX_BCL_VBAT_ATTN2 (0x0304) +#define CDC_RX_BCL_VBAT_ATTN3 (0x0308) +#define CDC_RX_BCL_VBAT_DECODE_CTL1 (0x030C) +#define CDC_RX_BCL_VBAT_DECODE_CTL2 (0x0310) +#define CDC_RX_BCL_VBAT_DECODE_CFG1 (0x0314) +#define CDC_RX_BCL_VBAT_DECODE_CFG2 (0x0318) +#define CDC_RX_BCL_VBAT_DECODE_CFG3 (0x031C) +#define CDC_RX_BCL_VBAT_DECODE_CFG4 (0x0320) +#define CDC_RX_BCL_VBAT_DECODE_ST (0x0324) +#define CDC_RX_INTR_CTRL_CFG (0x0340) +#define CDC_RX_INTR_CTRL_CLR_COMMIT (0x0344) +#define CDC_RX_INTR_CTRL_PIN1_MASK0 (0x0360) +#define CDC_RX_INTR_CTRL_PIN1_STATUS0 (0x0368) +#define CDC_RX_INTR_CTRL_PIN1_CLEAR0 (0x0370) +#define CDC_RX_INTR_CTRL_PIN2_MASK0 (0x0380) +#define CDC_RX_INTR_CTRL_PIN2_STATUS0 (0x0388) +#define CDC_RX_INTR_CTRL_PIN2_CLEAR0 (0x0390) +#define CDC_RX_INTR_CTRL_LEVEL0 (0x03C0) +#define CDC_RX_INTR_CTRL_BYPASS0 (0x03C8) +#define CDC_RX_INTR_CTRL_SET0 (0x03D0) +#define CDC_RX_RXn_RX_PATH_CTL(n) (0x0400 + 0x80 * n) +#define CDC_RX_RX0_RX_PATH_CTL (0x0400) +#define CDC_RX_PATH_RESET_EN_MASK BIT(6) +#define CDC_RX_PATH_CLK_EN_MASK BIT(5) +#define CDC_RX_PATH_CLK_ENABLE BIT(5) +#define CDC_RX_PATH_PGA_MUTE_MASK BIT(4) +#define CDC_RX_PATH_PGA_MUTE_ENABLE BIT(4) +#define CDC_RX_PATH_PCM_RATE_MASK GENMASK(3, 0) +#define CDC_RX_RXn_RX_PATH_CFG0(n) (0x0404 + 0x80 * n) +#define CDC_RX_RXn_COMP_EN_MASK BIT(1) +#define CDC_RX_RX0_RX_PATH_CFG0 (0x0404) +#define CDC_RX_RXn_CLSH_EN_MASK BIT(6) +#define CDC_RX_DLY_ZN_EN_MASK BIT(3) +#define CDC_RX_DLY_ZN_ENABLE BIT(3) +#define CDC_RX_RXn_HD2_EN_MASK BIT(2) +#define CDC_RX_RXn_RX_PATH_CFG1(n) (0x0408 + 0x80 * n) +#define CDC_RX_RXn_SIDETONE_EN_MASK BIT(4) +#define CDC_RX_RX0_RX_PATH_CFG1 (0x0408) +#define CDC_RX_RX0_HPH_L_EAR_SEL_MASK BIT(1) +#define CDC_RX_RXn_RX_PATH_CFG2(n) (0x040C + 0x80 * n) +#define CDC_RX_RXn_HPF_CUT_FREQ_MASK GENMASK(1, 0) +#define CDC_RX_RX0_RX_PATH_CFG2 (0x040C) +#define CDC_RX_RXn_RX_PATH_CFG3(n) (0x0410 + 0x80 * n) +#define CDC_RX_RX0_RX_PATH_CFG3 (0x0410) +#define CDC_RX_DC_COEFF_SEL_MASK GENMASK(1, 0) +#define CDC_RX_DC_COEFF_SEL_TWO 0x2 +#define CDC_RX_RXn_RX_VOL_CTL(n) (0x0414 + 0x80 * n) +#define CDC_RX_RX0_RX_VOL_CTL (0x0414) +#define CDC_RX_RXn_RX_PATH_MIX_CTL(n) (0x0418 + 0x80 * n) +#define CDC_RX_RXn_MIX_PCM_RATE_MASK GENMASK(3, 0) +#define CDC_RX_RXn_MIX_RESET_MASK BIT(6) +#define CDC_RX_RXn_MIX_RESET BIT(6) +#define CDC_RX_RXn_MIX_CLK_EN_MASK BIT(5) +#define CDC_RX_RX0_RX_PATH_MIX_CTL (0x0418) +#define CDC_RX_RX0_RX_PATH_MIX_CFG (0x041C) +#define CDC_RX_RXn_RX_VOL_MIX_CTL(n) (0x0420 + 0x80 * n) +#define CDC_RX_RX0_RX_VOL_MIX_CTL (0x0420) +#define CDC_RX_RX0_RX_PATH_SEC1 (0x0424) +#define CDC_RX_RX0_RX_PATH_SEC2 (0x0428) +#define CDC_RX_RX0_RX_PATH_SEC3 (0x042C) +#define CDC_RX_RX0_RX_PATH_SEC4 (0x0430) +#define CDC_RX_RX0_RX_PATH_SEC7 (0x0434) +#define CDC_RX_DSM_OUT_DELAY_SEL_MASK GENMASK(2, 0) +#define CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE 0x2 +#define CDC_RX_RX0_RX_PATH_MIX_SEC0 (0x0438) +#define CDC_RX_RX0_RX_PATH_MIX_SEC1 (0x043C) +#define CDC_RX_RXn_RX_PATH_DSM_CTL(n) (0x0440 + 0x80 * n) +#define CDC_RX_RXn_DSM_CLK_EN_MASK BIT(0) +#define CDC_RX_RX0_RX_PATH_DSM_CTL (0x0440) +#define CDC_RX_RX0_RX_PATH_DSM_DATA1 (0x0444) +#define CDC_RX_RX0_RX_PATH_DSM_DATA2 (0x0448) +#define CDC_RX_RX0_RX_PATH_DSM_DATA3 (0x044C) +#define CDC_RX_RX0_RX_PATH_DSM_DATA4 (0x0450) +#define CDC_RX_RX0_RX_PATH_DSM_DATA5 (0x0454) +#define CDC_RX_RX0_RX_PATH_DSM_DATA6 (0x0458) +#define CDC_RX_RX1_RX_PATH_CTL (0x0480) +#define CDC_RX_RX1_RX_PATH_CFG0 (0x0484) +#define CDC_RX_RX1_RX_PATH_CFG1 (0x0488) +#define CDC_RX_RX1_RX_PATH_CFG2 (0x048C) +#define CDC_RX_RX1_RX_PATH_CFG3 (0x0490) +#define CDC_RX_RX1_RX_VOL_CTL (0x0494) +#define CDC_RX_RX1_RX_PATH_MIX_CTL (0x0498) +#define CDC_RX_RX1_RX_PATH_MIX_CFG (0x049C) +#define CDC_RX_RX1_RX_VOL_MIX_CTL (0x04A0) +#define CDC_RX_RX1_RX_PATH_SEC1 (0x04A4) +#define CDC_RX_RX1_RX_PATH_SEC2 (0x04A8) +#define CDC_RX_RX1_RX_PATH_SEC3 (0x04AC) +#define CDC_RX_RXn_HD2_ALPHA_MASK GENMASK(5, 2) +#define CDC_RX_RX1_RX_PATH_SEC4 (0x04B0) +#define CDC_RX_RX1_RX_PATH_SEC7 (0x04B4) +#define CDC_RX_RX1_RX_PATH_MIX_SEC0 (0x04B8) +#define CDC_RX_RX1_RX_PATH_MIX_SEC1 (0x04BC) +#define CDC_RX_RX1_RX_PATH_DSM_CTL (0x04C0) +#define CDC_RX_RX1_RX_PATH_DSM_DATA1 (0x04C4) +#define CDC_RX_RX1_RX_PATH_DSM_DATA2 (0x04C8) +#define CDC_RX_RX1_RX_PATH_DSM_DATA3 (0x04CC) +#define CDC_RX_RX1_RX_PATH_DSM_DATA4 (0x04D0) +#define CDC_RX_RX1_RX_PATH_DSM_DATA5 (0x04D4) +#define CDC_RX_RX1_RX_PATH_DSM_DATA6 (0x04D8) +#define CDC_RX_RX2_RX_PATH_CTL (0x0500) +#define CDC_RX_RX2_RX_PATH_CFG0 (0x0504) +#define CDC_RX_RX2_CLSH_EN_MASK BIT(4) +#define CDC_RX_RX2_DLY_Z_EN_MASK BIT(3) +#define CDC_RX_RX2_RX_PATH_CFG1 (0x0508) +#define CDC_RX_RX2_RX_PATH_CFG2 (0x050C) +#define CDC_RX_RX2_RX_PATH_CFG3 (0x0510) +#define CDC_RX_RX2_RX_VOL_CTL (0x0514) +#define CDC_RX_RX2_RX_PATH_MIX_CTL (0x0518) +#define CDC_RX_RX2_RX_PATH_MIX_CFG (0x051C) +#define CDC_RX_RX2_RX_VOL_MIX_CTL (0x0520) +#define CDC_RX_RX2_RX_PATH_SEC0 (0x0524) +#define CDC_RX_RX2_RX_PATH_SEC1 (0x0528) +#define CDC_RX_RX2_RX_PATH_SEC2 (0x052C) +#define CDC_RX_RX2_RX_PATH_SEC3 (0x0530) +#define CDC_RX_RX2_RX_PATH_SEC4 (0x0534) +#define CDC_RX_RX2_RX_PATH_SEC5 (0x0538) +#define CDC_RX_RX2_RX_PATH_SEC6 (0x053C) +#define CDC_RX_RX2_RX_PATH_SEC7 (0x0540) +#define CDC_RX_RX2_RX_PATH_MIX_SEC0 (0x0544) +#define CDC_RX_RX2_RX_PATH_MIX_SEC1 (0x0548) +#define CDC_RX_RX2_RX_PATH_DSM_CTL (0x054C) +#define CDC_RX_IDLE_DETECT_PATH_CTL (0x0780) +#define CDC_RX_IDLE_DETECT_CFG0 (0x0784) +#define CDC_RX_IDLE_DETECT_CFG1 (0x0788) +#define CDC_RX_IDLE_DETECT_CFG2 (0x078C) +#define CDC_RX_IDLE_DETECT_CFG3 (0x0790) +#define CDC_RX_COMPANDERn_CTL0(n) (0x0800 + 0x40 * n) +#define CDC_RX_COMPANDERn_CLK_EN_MASK BIT(0) +#define CDC_RX_COMPANDERn_SOFT_RST_MASK BIT(1) +#define CDC_RX_COMPANDERn_HALT_MASK BIT(2) +#define CDC_RX_COMPANDER0_CTL0 (0x0800) +#define CDC_RX_COMPANDER0_CTL1 (0x0804) +#define CDC_RX_COMPANDER0_CTL2 (0x0808) +#define CDC_RX_COMPANDER0_CTL3 (0x080C) +#define CDC_RX_COMPANDER0_CTL4 (0x0810) +#define CDC_RX_COMPANDER0_CTL5 (0x0814) +#define CDC_RX_COMPANDER0_CTL6 (0x0818) +#define CDC_RX_COMPANDER0_CTL7 (0x081C) +#define CDC_RX_COMPANDER1_CTL0 (0x0840) +#define CDC_RX_COMPANDER1_CTL1 (0x0844) +#define CDC_RX_COMPANDER1_CTL2 (0x0848) +#define CDC_RX_COMPANDER1_CTL3 (0x084C) +#define CDC_RX_COMPANDER1_CTL4 (0x0850) +#define CDC_RX_COMPANDER1_CTL5 (0x0854) +#define CDC_RX_COMPANDER1_CTL6 (0x0858) +#define CDC_RX_COMPANDER1_CTL7 (0x085C) +#define CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK BIT(5) +#define CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL (0x0A00) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL (0x0A04) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL (0x0A08) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL (0x0A0C) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL (0x0A10) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL (0x0A14) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL (0x0A18) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL (0x0A1C) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL (0x0A20) +#define CDC_RX_SIDETONE_IIR0_IIR_CTL (0x0A24) +#define CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL (0x0A28) +#define CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL (0x0A2C) +#define CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL (0x0A30) +#define CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL (0x0A80) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL (0x0A84) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL (0x0A88) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL (0x0A8C) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL (0x0A90) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL (0x0A94) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL (0x0A98) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL (0x0A9C) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL (0x0AA0) +#define CDC_RX_SIDETONE_IIR1_IIR_CTL (0x0AA4) +#define CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL (0x0AA8) +#define CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL (0x0AAC) +#define CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL (0x0AB0) +#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0 (0x0B00) +#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1 (0x0B04) +#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2 (0x0B08) +#define CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3 (0x0B0C) +#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0 (0x0B10) +#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1 (0x0B14) +#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2 (0x0B18) +#define CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3 (0x0B1C) +#define CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL (0x0B40) +#define CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1 (0x0B44) +#define CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL (0x0B50) +#define CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1 (0x0B54) +#define CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL (0x0C00) +#define CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 (0x0C04) +#define CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL (0x0C40) +#define CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0 (0x0C44) +#define CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL (0x0C80) +#define CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0 (0x0C84) +#define CDC_RX_EC_ASRC0_CLK_RST_CTL (0x0D00) +#define CDC_RX_EC_ASRC0_CTL0 (0x0D04) +#define CDC_RX_EC_ASRC0_CTL1 (0x0D08) +#define CDC_RX_EC_ASRC0_FIFO_CTL (0x0D0C) +#define CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB (0x0D10) +#define CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB (0x0D14) +#define CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB (0x0D18) +#define CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB (0x0D1C) +#define CDC_RX_EC_ASRC0_STATUS_FIFO (0x0D20) +#define CDC_RX_EC_ASRC1_CLK_RST_CTL (0x0D40) +#define CDC_RX_EC_ASRC1_CTL0 (0x0D44) +#define CDC_RX_EC_ASRC1_CTL1 (0x0D48) +#define CDC_RX_EC_ASRC1_FIFO_CTL (0x0D4C) +#define CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB (0x0D50) +#define CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB (0x0D54) +#define CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB (0x0D58) +#define CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB (0x0D5C) +#define CDC_RX_EC_ASRC1_STATUS_FIFO (0x0D60) +#define CDC_RX_EC_ASRC2_CLK_RST_CTL (0x0D80) +#define CDC_RX_EC_ASRC2_CTL0 (0x0D84) +#define CDC_RX_EC_ASRC2_CTL1 (0x0D88) +#define CDC_RX_EC_ASRC2_FIFO_CTL (0x0D8C) +#define CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB (0x0D90) +#define CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB (0x0D94) +#define CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB (0x0D98) +#define CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB (0x0D9C) +#define CDC_RX_EC_ASRC2_STATUS_FIFO (0x0DA0) +#define CDC_RX_DSD0_PATH_CTL (0x0F00) +#define CDC_RX_DSD0_CFG0 (0x0F04) +#define CDC_RX_DSD0_CFG1 (0x0F08) +#define CDC_RX_DSD0_CFG2 (0x0F0C) +#define CDC_RX_DSD1_PATH_CTL (0x0F80) +#define CDC_RX_DSD1_CFG0 (0x0F84) +#define CDC_RX_DSD1_CFG1 (0x0F88) +#define CDC_RX_DSD1_CFG2 (0x0F8C) +#define RX_MAX_OFFSET (0x0F8C) + +#define MCLK_FREQ 9600000 + +#define RX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\ + SNDRV_PCM_RATE_384000) +/* Fractional Rates */ +#define RX_MACRO_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) + +#define RX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +#define RX_MACRO_ECHO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_48000) +#define RX_MACRO_ECHO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define RX_MACRO_MAX_DMA_CH_PER_PORT 2 + +#define RX_MACRO_EC_MIX_TX0_MASK 0xf0 +#define RX_MACRO_EC_MIX_TX1_MASK 0x0f +#define RX_MACRO_EC_MIX_TX2_MASK 0x0f + +#define COMP_MAX_COEFF 25 +#define RX_NUM_CLKS_MAX 5 + +struct comp_coeff_val { + u8 lsb; + u8 msb; +}; + +enum { + HPH_ULP, + HPH_LOHIFI, + HPH_MODE_MAX, +}; + +static const struct comp_coeff_val comp_coeff_table[HPH_MODE_MAX][COMP_MAX_COEFF] = { + { + {0x40, 0x00}, + {0x4C, 0x00}, + {0x5A, 0x00}, + {0x6B, 0x00}, + {0x7F, 0x00}, + {0x97, 0x00}, + {0xB3, 0x00}, + {0xD5, 0x00}, + {0xFD, 0x00}, + {0x2D, 0x01}, + {0x66, 0x01}, + {0xA7, 0x01}, + {0xF8, 0x01}, + {0x57, 0x02}, + {0xC7, 0x02}, + {0x4B, 0x03}, + {0xE9, 0x03}, + {0xA3, 0x04}, + {0x7D, 0x05}, + {0x90, 0x06}, + {0xD1, 0x07}, + {0x49, 0x09}, + {0x00, 0x0B}, + {0x01, 0x0D}, + {0x59, 0x0F}, + }, + { + {0x40, 0x00}, + {0x4C, 0x00}, + {0x5A, 0x00}, + {0x6B, 0x00}, + {0x80, 0x00}, + {0x98, 0x00}, + {0xB4, 0x00}, + {0xD5, 0x00}, + {0xFE, 0x00}, + {0x2E, 0x01}, + {0x66, 0x01}, + {0xA9, 0x01}, + {0xF8, 0x01}, + {0x56, 0x02}, + {0xC4, 0x02}, + {0x4F, 0x03}, + {0xF0, 0x03}, + {0xAE, 0x04}, + {0x8B, 0x05}, + {0x8E, 0x06}, + {0xBC, 0x07}, + {0x56, 0x09}, + {0x0F, 0x0B}, + {0x13, 0x0D}, + {0x6F, 0x0F}, + }, +}; + +struct rx_macro_reg_mask_val { + u16 reg; + u8 mask; + u8 val; +}; + +enum { + INTERP_HPHL, + INTERP_HPHR, + INTERP_AUX, + INTERP_MAX +}; + +enum { + RX_MACRO_RX0, + RX_MACRO_RX1, + RX_MACRO_RX2, + RX_MACRO_RX3, + RX_MACRO_RX4, + RX_MACRO_RX5, + RX_MACRO_PORTS_MAX +}; + +enum { + RX_MACRO_COMP1, /* HPH_L */ + RX_MACRO_COMP2, /* HPH_R */ + RX_MACRO_COMP_MAX +}; + +enum { + RX_MACRO_EC0_MUX = 0, + RX_MACRO_EC1_MUX, + RX_MACRO_EC2_MUX, + RX_MACRO_EC_MUX_MAX, +}; + +enum { + INTn_1_INP_SEL_ZERO = 0, + INTn_1_INP_SEL_DEC0, + INTn_1_INP_SEL_DEC1, + INTn_1_INP_SEL_IIR0, + INTn_1_INP_SEL_IIR1, + INTn_1_INP_SEL_RX0, + INTn_1_INP_SEL_RX1, + INTn_1_INP_SEL_RX2, + INTn_1_INP_SEL_RX3, + INTn_1_INP_SEL_RX4, + INTn_1_INP_SEL_RX5, +}; + +enum { + INTn_2_INP_SEL_ZERO = 0, + INTn_2_INP_SEL_RX0, + INTn_2_INP_SEL_RX1, + INTn_2_INP_SEL_RX2, + INTn_2_INP_SEL_RX3, + INTn_2_INP_SEL_RX4, + INTn_2_INP_SEL_RX5, +}; + +enum { + INTERP_MAIN_PATH, + INTERP_MIX_PATH, +}; + +struct interp_sample_rate { + int sample_rate; + int rate_val; +}; + +static struct interp_sample_rate sr_val_tbl[] = { + {8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5}, + {192000, 0x6}, {384000, 0x7}, {44100, 0x9}, {88200, 0xA}, + {176400, 0xB}, {352800, 0xC}, +}; + +enum { + RX_MACRO_AIF_INVALID = 0, + RX_MACRO_AIF1_PB, + RX_MACRO_AIF2_PB, + RX_MACRO_AIF3_PB, + RX_MACRO_AIF4_PB, + RX_MACRO_AIF_ECHO, + RX_MACRO_MAX_DAIS, +}; + +enum { + RX_MACRO_AIF1_CAP = 0, + RX_MACRO_AIF2_CAP, + RX_MACRO_AIF3_CAP, + RX_MACRO_MAX_AIF_CAP_DAIS +}; + +struct rx_macro { + struct device *dev; + int comp_enabled[RX_MACRO_COMP_MAX]; + /* Main path clock users count */ + int main_clk_users[INTERP_MAX]; + int rx_port_value[RX_MACRO_PORTS_MAX]; + u16 prim_int_users[INTERP_MAX]; + int rx_mclk_users; + bool reset_swr; + int clsh_users; + int rx_mclk_cnt; + bool is_ear_mode_on; + bool hph_pwr_mode; + bool hph_hd2_mode; + struct snd_soc_component *component; + unsigned long active_ch_mask[RX_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[RX_MACRO_MAX_DAIS]; + u16 bit_width[RX_MACRO_MAX_DAIS]; + int is_softclip_on; + int is_aux_hpf_on; + int softclip_clk_users; + + struct regmap *regmap; + struct clk_bulk_data clks[RX_NUM_CLKS_MAX]; + struct clk_hw hw; +}; +#define to_rx_macro(_hw) container_of(_hw, struct rx_macro, hw) + +static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); + +static const char *const rx_macro_hph_pwr_mode_text[] = { + "ULP", "LOHIFI" +}; + +static const struct soc_enum rx_macro_hph_pwr_mode_enum = + SOC_ENUM_SINGLE_EXT(2, rx_macro_hph_pwr_mode_text); + +static const struct reg_default rx_defaults[] = { + /* RX Macro */ + { CDC_RX_TOP_TOP_CFG0, 0x00 }, + { CDC_RX_TOP_SWR_CTRL, 0x00 }, + { CDC_RX_TOP_DEBUG, 0x00 }, + { CDC_RX_TOP_DEBUG_BUS, 0x00 }, + { CDC_RX_TOP_DEBUG_EN0, 0x00 }, + { CDC_RX_TOP_DEBUG_EN1, 0x00 }, + { CDC_RX_TOP_DEBUG_EN2, 0x00 }, + { CDC_RX_TOP_HPHL_COMP_WR_LSB, 0x00 }, + { CDC_RX_TOP_HPHL_COMP_WR_MSB, 0x00 }, + { CDC_RX_TOP_HPHL_COMP_LUT, 0x00 }, + { CDC_RX_TOP_HPHL_COMP_RD_LSB, 0x00 }, + { CDC_RX_TOP_HPHL_COMP_RD_MSB, 0x00 }, + { CDC_RX_TOP_HPHR_COMP_WR_LSB, 0x00 }, + { CDC_RX_TOP_HPHR_COMP_WR_MSB, 0x00 }, + { CDC_RX_TOP_HPHR_COMP_LUT, 0x00 }, + { CDC_RX_TOP_HPHR_COMP_RD_LSB, 0x00 }, + { CDC_RX_TOP_HPHR_COMP_RD_MSB, 0x00 }, + { CDC_RX_TOP_DSD0_DEBUG_CFG0, 0x11 }, + { CDC_RX_TOP_DSD0_DEBUG_CFG1, 0x20 }, + { CDC_RX_TOP_DSD0_DEBUG_CFG2, 0x00 }, + { CDC_RX_TOP_DSD0_DEBUG_CFG3, 0x00 }, + { CDC_RX_TOP_DSD1_DEBUG_CFG0, 0x11 }, + { CDC_RX_TOP_DSD1_DEBUG_CFG1, 0x20 }, + { CDC_RX_TOP_DSD1_DEBUG_CFG2, 0x00 }, + { CDC_RX_TOP_DSD1_DEBUG_CFG3, 0x00 }, + { CDC_RX_TOP_RX_I2S_CTL, 0x0C }, + { CDC_RX_TOP_TX_I2S2_CTL, 0x0C }, + { CDC_RX_TOP_I2S_CLK, 0x0C }, + { CDC_RX_TOP_I2S_RESET, 0x00 }, + { CDC_RX_TOP_I2S_MUX, 0x00 }, + { CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 }, + { CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 }, + { CDC_RX_CLK_RST_CTRL_SWR_CONTROL, 0x00 }, + { CDC_RX_CLK_RST_CTRL_DSD_CONTROL, 0x00 }, + { CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL, 0x08 }, + { CDC_RX_SOFTCLIP_CRC, 0x00 }, + { CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x38 }, + { CDC_RX_INP_MUX_RX_INT0_CFG0, 0x00 }, + { CDC_RX_INP_MUX_RX_INT0_CFG1, 0x00 }, + { CDC_RX_INP_MUX_RX_INT1_CFG0, 0x00 }, + { CDC_RX_INP_MUX_RX_INT1_CFG1, 0x00 }, + { CDC_RX_INP_MUX_RX_INT2_CFG0, 0x00 }, + { CDC_RX_INP_MUX_RX_INT2_CFG1, 0x00 }, + { CDC_RX_INP_MUX_RX_MIX_CFG4, 0x00 }, + { CDC_RX_INP_MUX_RX_MIX_CFG5, 0x00 }, + { CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0x00 }, + { CDC_RX_CLSH_CRC, 0x00 }, + { CDC_RX_CLSH_DLY_CTRL, 0x03 }, + { CDC_RX_CLSH_DECAY_CTRL, 0x02 }, + { CDC_RX_CLSH_HPH_V_PA, 0x1C }, + { CDC_RX_CLSH_EAR_V_PA, 0x39 }, + { CDC_RX_CLSH_HPH_V_HD, 0x0C }, + { CDC_RX_CLSH_EAR_V_HD, 0x0C }, + { CDC_RX_CLSH_K1_MSB, 0x01 }, + { CDC_RX_CLSH_K1_LSB, 0x00 }, + { CDC_RX_CLSH_K2_MSB, 0x00 }, + { CDC_RX_CLSH_K2_LSB, 0x80 }, + { CDC_RX_CLSH_IDLE_CTRL, 0x00 }, + { CDC_RX_CLSH_IDLE_HPH, 0x00 }, + { CDC_RX_CLSH_IDLE_EAR, 0x00 }, + { CDC_RX_CLSH_TEST0, 0x07 }, + { CDC_RX_CLSH_TEST1, 0x00 }, + { CDC_RX_CLSH_OVR_VREF, 0x00 }, + { CDC_RX_CLSH_CLSG_CTL, 0x02 }, + { CDC_RX_CLSH_CLSG_CFG1, 0x9A }, + { CDC_RX_CLSH_CLSG_CFG2, 0x10 }, + { CDC_RX_BCL_VBAT_PATH_CTL, 0x00 }, + { CDC_RX_BCL_VBAT_CFG, 0x10 }, + { CDC_RX_BCL_VBAT_ADC_CAL1, 0x00 }, + { CDC_RX_BCL_VBAT_ADC_CAL2, 0x00 }, + { CDC_RX_BCL_VBAT_ADC_CAL3, 0x04 }, + { CDC_RX_BCL_VBAT_PK_EST1, 0xE0 }, + { CDC_RX_BCL_VBAT_PK_EST2, 0x01 }, + { CDC_RX_BCL_VBAT_PK_EST3, 0x40 }, + { CDC_RX_BCL_VBAT_RF_PROC1, 0x2A }, + { CDC_RX_BCL_VBAT_RF_PROC1, 0x00 }, + { CDC_RX_BCL_VBAT_TAC1, 0x00 }, + { CDC_RX_BCL_VBAT_TAC2, 0x18 }, + { CDC_RX_BCL_VBAT_TAC3, 0x18 }, + { CDC_RX_BCL_VBAT_TAC4, 0x03 }, + { CDC_RX_BCL_VBAT_GAIN_UPD1, 0x01 }, + { CDC_RX_BCL_VBAT_GAIN_UPD2, 0x00 }, + { CDC_RX_BCL_VBAT_GAIN_UPD3, 0x00 }, + { CDC_RX_BCL_VBAT_GAIN_UPD4, 0x64 }, + { CDC_RX_BCL_VBAT_GAIN_UPD5, 0x01 }, + { CDC_RX_BCL_VBAT_DEBUG1, 0x00 }, + { CDC_RX_BCL_VBAT_GAIN_UPD_MON, 0x00 }, + { CDC_RX_BCL_VBAT_GAIN_MON_VAL, 0x00 }, + { CDC_RX_BCL_VBAT_BAN, 0x0C }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD1, 0x00 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD2, 0x77 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD3, 0x01 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD4, 0x00 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD5, 0x4B }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD6, 0x00 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD7, 0x01 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD8, 0x00 }, + { CDC_RX_BCL_VBAT_BCL_GAIN_UPD9, 0x00 }, + { CDC_RX_BCL_VBAT_ATTN1, 0x04 }, + { CDC_RX_BCL_VBAT_ATTN2, 0x08 }, + { CDC_RX_BCL_VBAT_ATTN3, 0x0C }, + { CDC_RX_BCL_VBAT_DECODE_CTL1, 0xE0 }, + { CDC_RX_BCL_VBAT_DECODE_CTL2, 0x00 }, + { CDC_RX_BCL_VBAT_DECODE_CFG1, 0x00 }, + { CDC_RX_BCL_VBAT_DECODE_CFG2, 0x00 }, + { CDC_RX_BCL_VBAT_DECODE_CFG3, 0x00 }, + { CDC_RX_BCL_VBAT_DECODE_CFG4, 0x00 }, + { CDC_RX_BCL_VBAT_DECODE_ST, 0x00 }, + { CDC_RX_INTR_CTRL_CFG, 0x00 }, + { CDC_RX_INTR_CTRL_CLR_COMMIT, 0x00 }, + { CDC_RX_INTR_CTRL_PIN1_MASK0, 0xFF }, + { CDC_RX_INTR_CTRL_PIN1_STATUS0, 0x00 }, + { CDC_RX_INTR_CTRL_PIN1_CLEAR0, 0x00 }, + { CDC_RX_INTR_CTRL_PIN2_MASK0, 0xFF }, + { CDC_RX_INTR_CTRL_PIN2_STATUS0, 0x00 }, + { CDC_RX_INTR_CTRL_PIN2_CLEAR0, 0x00 }, + { CDC_RX_INTR_CTRL_LEVEL0, 0x00 }, + { CDC_RX_INTR_CTRL_BYPASS0, 0x00 }, + { CDC_RX_INTR_CTRL_SET0, 0x00 }, + { CDC_RX_RX0_RX_PATH_CTL, 0x04 }, + { CDC_RX_RX0_RX_PATH_CFG0, 0x00 }, + { CDC_RX_RX0_RX_PATH_CFG1, 0x64 }, + { CDC_RX_RX0_RX_PATH_CFG2, 0x8F }, + { CDC_RX_RX0_RX_PATH_CFG3, 0x00 }, + { CDC_RX_RX0_RX_VOL_CTL, 0x00 }, + { CDC_RX_RX0_RX_PATH_MIX_CTL, 0x04 }, + { CDC_RX_RX0_RX_PATH_MIX_CFG, 0x7E }, + { CDC_RX_RX0_RX_VOL_MIX_CTL, 0x00 }, + { CDC_RX_RX0_RX_PATH_SEC1, 0x08 }, + { CDC_RX_RX0_RX_PATH_SEC2, 0x00 }, + { CDC_RX_RX0_RX_PATH_SEC3, 0x00 }, + { CDC_RX_RX0_RX_PATH_SEC4, 0x00 }, + { CDC_RX_RX0_RX_PATH_SEC7, 0x00 }, + { CDC_RX_RX0_RX_PATH_MIX_SEC0, 0x08 }, + { CDC_RX_RX0_RX_PATH_MIX_SEC1, 0x00 }, + { CDC_RX_RX0_RX_PATH_DSM_CTL, 0x08 }, + { CDC_RX_RX0_RX_PATH_DSM_DATA1, 0x00 }, + { CDC_RX_RX0_RX_PATH_DSM_DATA2, 0x00 }, + { CDC_RX_RX0_RX_PATH_DSM_DATA3, 0x00 }, + { CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55 }, + { CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55 }, + { CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55 }, + { CDC_RX_RX1_RX_PATH_CTL, 0x04 }, + { CDC_RX_RX1_RX_PATH_CFG0, 0x00 }, + { CDC_RX_RX1_RX_PATH_CFG1, 0x64 }, + { CDC_RX_RX1_RX_PATH_CFG2, 0x8F }, + { CDC_RX_RX1_RX_PATH_CFG3, 0x00 }, + { CDC_RX_RX1_RX_VOL_CTL, 0x00 }, + { CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04 }, + { CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E }, + { CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00 }, + { CDC_RX_RX1_RX_PATH_SEC1, 0x08 }, + { CDC_RX_RX1_RX_PATH_SEC2, 0x00 }, + { CDC_RX_RX1_RX_PATH_SEC3, 0x00 }, + { CDC_RX_RX1_RX_PATH_SEC4, 0x00 }, + { CDC_RX_RX1_RX_PATH_SEC7, 0x00 }, + { CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08 }, + { CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00 }, + { CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08 }, + { CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00 }, + { CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00 }, + { CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00 }, + { CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55 }, + { CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55 }, + { CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55 }, + { CDC_RX_RX2_RX_PATH_CTL, 0x04 }, + { CDC_RX_RX2_RX_PATH_CFG0, 0x00 }, + { CDC_RX_RX2_RX_PATH_CFG1, 0x64 }, + { CDC_RX_RX2_RX_PATH_CFG2, 0x8F }, + { CDC_RX_RX2_RX_PATH_CFG3, 0x00 }, + { CDC_RX_RX2_RX_VOL_CTL, 0x00 }, + { CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04 }, + { CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E }, + { CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00 }, + { CDC_RX_RX2_RX_PATH_SEC0, 0x04 }, + { CDC_RX_RX2_RX_PATH_SEC1, 0x08 }, + { CDC_RX_RX2_RX_PATH_SEC2, 0x00 }, + { CDC_RX_RX2_RX_PATH_SEC3, 0x00 }, + { CDC_RX_RX2_RX_PATH_SEC4, 0x00 }, + { CDC_RX_RX2_RX_PATH_SEC5, 0x00 }, + { CDC_RX_RX2_RX_PATH_SEC6, 0x00 }, + { CDC_RX_RX2_RX_PATH_SEC7, 0x00 }, + { CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08 }, + { CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00 }, + { CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00 }, + { CDC_RX_IDLE_DETECT_PATH_CTL, 0x00 }, + { CDC_RX_IDLE_DETECT_CFG0, 0x07 }, + { CDC_RX_IDLE_DETECT_CFG1, 0x3C }, + { CDC_RX_IDLE_DETECT_CFG2, 0x00 }, + { CDC_RX_IDLE_DETECT_CFG3, 0x00 }, + { CDC_RX_COMPANDER0_CTL0, 0x60 }, + { CDC_RX_COMPANDER0_CTL1, 0xDB }, + { CDC_RX_COMPANDER0_CTL2, 0xFF }, + { CDC_RX_COMPANDER0_CTL3, 0x35 }, + { CDC_RX_COMPANDER0_CTL4, 0xFF }, + { CDC_RX_COMPANDER0_CTL5, 0x00 }, + { CDC_RX_COMPANDER0_CTL6, 0x01 }, + { CDC_RX_COMPANDER0_CTL7, 0x28 }, + { CDC_RX_COMPANDER1_CTL0, 0x60 }, + { CDC_RX_COMPANDER1_CTL1, 0xDB }, + { CDC_RX_COMPANDER1_CTL2, 0xFF }, + { CDC_RX_COMPANDER1_CTL3, 0x35 }, + { CDC_RX_COMPANDER1_CTL4, 0xFF }, + { CDC_RX_COMPANDER1_CTL5, 0x00 }, + { CDC_RX_COMPANDER1_CTL6, 0x01 }, + { CDC_RX_COMPANDER1_CTL7, 0x28 }, + { CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_CTL, 0x40 }, + { CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_CTL, 0x40 }, + { CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL, 0x00 }, + { CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0x00 }, + { CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0x00 }, + { CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 0x04 }, + { CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1, 0x00 }, + { CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, 0x04 }, + { CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1, 0x00 }, + { CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL, 0x00 }, + { CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0, 0x01 }, + { CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL, 0x00 }, + { CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0, 0x01 }, + { CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL, 0x00 }, + { CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0, 0x01 }, + { CDC_RX_EC_ASRC0_CLK_RST_CTL, 0x00 }, + { CDC_RX_EC_ASRC0_CTL0, 0x00 }, + { CDC_RX_EC_ASRC0_CTL1, 0x00 }, + { CDC_RX_EC_ASRC0_FIFO_CTL, 0xA8 }, + { CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB, 0x00 }, + { CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB, 0x00 }, + { CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB, 0x00 }, + { CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB, 0x00 }, + { CDC_RX_EC_ASRC0_STATUS_FIFO, 0x00 }, + { CDC_RX_EC_ASRC1_CLK_RST_CTL, 0x00 }, + { CDC_RX_EC_ASRC1_CTL0, 0x00 }, + { CDC_RX_EC_ASRC1_CTL1, 0x00 }, + { CDC_RX_EC_ASRC1_FIFO_CTL, 0xA8 }, + { CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB, 0x00 }, + { CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB, 0x00 }, + { CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB, 0x00 }, + { CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB, 0x00 }, + { CDC_RX_EC_ASRC1_STATUS_FIFO, 0x00 }, + { CDC_RX_EC_ASRC2_CLK_RST_CTL, 0x00 }, + { CDC_RX_EC_ASRC2_CTL0, 0x00 }, + { CDC_RX_EC_ASRC2_CTL1, 0x00 }, + { CDC_RX_EC_ASRC2_FIFO_CTL, 0xA8 }, + { CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB, 0x00 }, + { CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB, 0x00 }, + { CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB, 0x00 }, + { CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB, 0x00 }, + { CDC_RX_EC_ASRC2_STATUS_FIFO, 0x00 }, + { CDC_RX_DSD0_PATH_CTL, 0x00 }, + { CDC_RX_DSD0_CFG0, 0x00 }, + { CDC_RX_DSD0_CFG1, 0x62 }, + { CDC_RX_DSD0_CFG2, 0x96 }, + { CDC_RX_DSD1_PATH_CTL, 0x00 }, + { CDC_RX_DSD1_CFG0, 0x00 }, + { CDC_RX_DSD1_CFG1, 0x62 }, + { CDC_RX_DSD1_CFG2, 0x96 }, +}; + +static bool rx_is_wronly_register(struct device *dev, + unsigned int reg) +{ + switch (reg) { + case CDC_RX_BCL_VBAT_GAIN_UPD_MON: + case CDC_RX_INTR_CTRL_CLR_COMMIT: + case CDC_RX_INTR_CTRL_PIN1_CLEAR0: + case CDC_RX_INTR_CTRL_PIN2_CLEAR0: + return true; + } + + return false; +} + +static bool rx_is_volatile_register(struct device *dev, unsigned int reg) +{ + /* Update volatile list for rx/tx macros */ + switch (reg) { + case CDC_RX_TOP_HPHL_COMP_RD_LSB: + case CDC_RX_TOP_HPHL_COMP_WR_LSB: + case CDC_RX_TOP_HPHL_COMP_RD_MSB: + case CDC_RX_TOP_HPHL_COMP_WR_MSB: + case CDC_RX_TOP_HPHR_COMP_RD_LSB: + case CDC_RX_TOP_HPHR_COMP_WR_LSB: + case CDC_RX_TOP_HPHR_COMP_RD_MSB: + case CDC_RX_TOP_HPHR_COMP_WR_MSB: + case CDC_RX_TOP_DSD0_DEBUG_CFG2: + case CDC_RX_TOP_DSD1_DEBUG_CFG2: + case CDC_RX_BCL_VBAT_GAIN_MON_VAL: + case CDC_RX_BCL_VBAT_DECODE_ST: + case CDC_RX_INTR_CTRL_PIN1_STATUS0: + case CDC_RX_INTR_CTRL_PIN2_STATUS0: + case CDC_RX_COMPANDER0_CTL6: + case CDC_RX_COMPANDER1_CTL6: + case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB: + case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB: + case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB: + case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB: + case CDC_RX_EC_ASRC0_STATUS_FIFO: + case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB: + case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB: + case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB: + case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB: + case CDC_RX_EC_ASRC1_STATUS_FIFO: + case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB: + case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB: + case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB: + case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB: + case CDC_RX_EC_ASRC2_STATUS_FIFO: + return true; + } + return false; +} + +static bool rx_is_rw_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_RX_TOP_TOP_CFG0: + case CDC_RX_TOP_SWR_CTRL: + case CDC_RX_TOP_DEBUG: + case CDC_RX_TOP_DEBUG_BUS: + case CDC_RX_TOP_DEBUG_EN0: + case CDC_RX_TOP_DEBUG_EN1: + case CDC_RX_TOP_DEBUG_EN2: + case CDC_RX_TOP_HPHL_COMP_WR_LSB: + case CDC_RX_TOP_HPHL_COMP_WR_MSB: + case CDC_RX_TOP_HPHL_COMP_LUT: + case CDC_RX_TOP_HPHR_COMP_WR_LSB: + case CDC_RX_TOP_HPHR_COMP_WR_MSB: + case CDC_RX_TOP_HPHR_COMP_LUT: + case CDC_RX_TOP_DSD0_DEBUG_CFG0: + case CDC_RX_TOP_DSD0_DEBUG_CFG1: + case CDC_RX_TOP_DSD0_DEBUG_CFG3: + case CDC_RX_TOP_DSD1_DEBUG_CFG0: + case CDC_RX_TOP_DSD1_DEBUG_CFG1: + case CDC_RX_TOP_DSD1_DEBUG_CFG3: + case CDC_RX_TOP_RX_I2S_CTL: + case CDC_RX_TOP_TX_I2S2_CTL: + case CDC_RX_TOP_I2S_CLK: + case CDC_RX_TOP_I2S_RESET: + case CDC_RX_TOP_I2S_MUX: + case CDC_RX_CLK_RST_CTRL_MCLK_CONTROL: + case CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL: + case CDC_RX_CLK_RST_CTRL_SWR_CONTROL: + case CDC_RX_CLK_RST_CTRL_DSD_CONTROL: + case CDC_RX_CLK_RST_CTRL_ASRC_SHARE_CONTROL: + case CDC_RX_SOFTCLIP_CRC: + case CDC_RX_SOFTCLIP_SOFTCLIP_CTRL: + case CDC_RX_INP_MUX_RX_INT0_CFG0: + case CDC_RX_INP_MUX_RX_INT0_CFG1: + case CDC_RX_INP_MUX_RX_INT1_CFG0: + case CDC_RX_INP_MUX_RX_INT1_CFG1: + case CDC_RX_INP_MUX_RX_INT2_CFG0: + case CDC_RX_INP_MUX_RX_INT2_CFG1: + case CDC_RX_INP_MUX_RX_MIX_CFG4: + case CDC_RX_INP_MUX_RX_MIX_CFG5: + case CDC_RX_INP_MUX_SIDETONE_SRC_CFG0: + case CDC_RX_CLSH_CRC: + case CDC_RX_CLSH_DLY_CTRL: + case CDC_RX_CLSH_DECAY_CTRL: + case CDC_RX_CLSH_HPH_V_PA: + case CDC_RX_CLSH_EAR_V_PA: + case CDC_RX_CLSH_HPH_V_HD: + case CDC_RX_CLSH_EAR_V_HD: + case CDC_RX_CLSH_K1_MSB: + case CDC_RX_CLSH_K1_LSB: + case CDC_RX_CLSH_K2_MSB: + case CDC_RX_CLSH_K2_LSB: + case CDC_RX_CLSH_IDLE_CTRL: + case CDC_RX_CLSH_IDLE_HPH: + case CDC_RX_CLSH_IDLE_EAR: + case CDC_RX_CLSH_TEST0: + case CDC_RX_CLSH_TEST1: + case CDC_RX_CLSH_OVR_VREF: + case CDC_RX_CLSH_CLSG_CTL: + case CDC_RX_CLSH_CLSG_CFG1: + case CDC_RX_CLSH_CLSG_CFG2: + case CDC_RX_BCL_VBAT_PATH_CTL: + case CDC_RX_BCL_VBAT_CFG: + case CDC_RX_BCL_VBAT_ADC_CAL1: + case CDC_RX_BCL_VBAT_ADC_CAL2: + case CDC_RX_BCL_VBAT_ADC_CAL3: + case CDC_RX_BCL_VBAT_PK_EST1: + case CDC_RX_BCL_VBAT_PK_EST2: + case CDC_RX_BCL_VBAT_PK_EST3: + case CDC_RX_BCL_VBAT_RF_PROC1: + case CDC_RX_BCL_VBAT_RF_PROC2: + case CDC_RX_BCL_VBAT_TAC1: + case CDC_RX_BCL_VBAT_TAC2: + case CDC_RX_BCL_VBAT_TAC3: + case CDC_RX_BCL_VBAT_TAC4: + case CDC_RX_BCL_VBAT_GAIN_UPD1: + case CDC_RX_BCL_VBAT_GAIN_UPD2: + case CDC_RX_BCL_VBAT_GAIN_UPD3: + case CDC_RX_BCL_VBAT_GAIN_UPD4: + case CDC_RX_BCL_VBAT_GAIN_UPD5: + case CDC_RX_BCL_VBAT_DEBUG1: + case CDC_RX_BCL_VBAT_BAN: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD1: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD2: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD3: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD4: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD5: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD6: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD7: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD8: + case CDC_RX_BCL_VBAT_BCL_GAIN_UPD9: + case CDC_RX_BCL_VBAT_ATTN1: + case CDC_RX_BCL_VBAT_ATTN2: + case CDC_RX_BCL_VBAT_ATTN3: + case CDC_RX_BCL_VBAT_DECODE_CTL1: + case CDC_RX_BCL_VBAT_DECODE_CTL2: + case CDC_RX_BCL_VBAT_DECODE_CFG1: + case CDC_RX_BCL_VBAT_DECODE_CFG2: + case CDC_RX_BCL_VBAT_DECODE_CFG3: + case CDC_RX_BCL_VBAT_DECODE_CFG4: + case CDC_RX_INTR_CTRL_CFG: + case CDC_RX_INTR_CTRL_PIN1_MASK0: + case CDC_RX_INTR_CTRL_PIN2_MASK0: + case CDC_RX_INTR_CTRL_LEVEL0: + case CDC_RX_INTR_CTRL_BYPASS0: + case CDC_RX_INTR_CTRL_SET0: + case CDC_RX_RX0_RX_PATH_CTL: + case CDC_RX_RX0_RX_PATH_CFG0: + case CDC_RX_RX0_RX_PATH_CFG1: + case CDC_RX_RX0_RX_PATH_CFG2: + case CDC_RX_RX0_RX_PATH_CFG3: + case CDC_RX_RX0_RX_VOL_CTL: + case CDC_RX_RX0_RX_PATH_MIX_CTL: + case CDC_RX_RX0_RX_PATH_MIX_CFG: + case CDC_RX_RX0_RX_VOL_MIX_CTL: + case CDC_RX_RX0_RX_PATH_SEC1: + case CDC_RX_RX0_RX_PATH_SEC2: + case CDC_RX_RX0_RX_PATH_SEC3: + case CDC_RX_RX0_RX_PATH_SEC4: + case CDC_RX_RX0_RX_PATH_SEC7: + case CDC_RX_RX0_RX_PATH_MIX_SEC0: + case CDC_RX_RX0_RX_PATH_MIX_SEC1: + case CDC_RX_RX0_RX_PATH_DSM_CTL: + case CDC_RX_RX0_RX_PATH_DSM_DATA1: + case CDC_RX_RX0_RX_PATH_DSM_DATA2: + case CDC_RX_RX0_RX_PATH_DSM_DATA3: + case CDC_RX_RX0_RX_PATH_DSM_DATA4: + case CDC_RX_RX0_RX_PATH_DSM_DATA5: + case CDC_RX_RX0_RX_PATH_DSM_DATA6: + case CDC_RX_RX1_RX_PATH_CTL: + case CDC_RX_RX1_RX_PATH_CFG0: + case CDC_RX_RX1_RX_PATH_CFG1: + case CDC_RX_RX1_RX_PATH_CFG2: + case CDC_RX_RX1_RX_PATH_CFG3: + case CDC_RX_RX1_RX_VOL_CTL: + case CDC_RX_RX1_RX_PATH_MIX_CTL: + case CDC_RX_RX1_RX_PATH_MIX_CFG: + case CDC_RX_RX1_RX_VOL_MIX_CTL: + case CDC_RX_RX1_RX_PATH_SEC1: + case CDC_RX_RX1_RX_PATH_SEC2: + case CDC_RX_RX1_RX_PATH_SEC3: + case CDC_RX_RX1_RX_PATH_SEC4: + case CDC_RX_RX1_RX_PATH_SEC7: + case CDC_RX_RX1_RX_PATH_MIX_SEC0: + case CDC_RX_RX1_RX_PATH_MIX_SEC1: + case CDC_RX_RX1_RX_PATH_DSM_CTL: + case CDC_RX_RX1_RX_PATH_DSM_DATA1: + case CDC_RX_RX1_RX_PATH_DSM_DATA2: + case CDC_RX_RX1_RX_PATH_DSM_DATA3: + case CDC_RX_RX1_RX_PATH_DSM_DATA4: + case CDC_RX_RX1_RX_PATH_DSM_DATA5: + case CDC_RX_RX1_RX_PATH_DSM_DATA6: + case CDC_RX_RX2_RX_PATH_CTL: + case CDC_RX_RX2_RX_PATH_CFG0: + case CDC_RX_RX2_RX_PATH_CFG1: + case CDC_RX_RX2_RX_PATH_CFG2: + case CDC_RX_RX2_RX_PATH_CFG3: + case CDC_RX_RX2_RX_VOL_CTL: + case CDC_RX_RX2_RX_PATH_MIX_CTL: + case CDC_RX_RX2_RX_PATH_MIX_CFG: + case CDC_RX_RX2_RX_VOL_MIX_CTL: + case CDC_RX_RX2_RX_PATH_SEC0: + case CDC_RX_RX2_RX_PATH_SEC1: + case CDC_RX_RX2_RX_PATH_SEC2: + case CDC_RX_RX2_RX_PATH_SEC3: + case CDC_RX_RX2_RX_PATH_SEC4: + case CDC_RX_RX2_RX_PATH_SEC5: + case CDC_RX_RX2_RX_PATH_SEC6: + case CDC_RX_RX2_RX_PATH_SEC7: + case CDC_RX_RX2_RX_PATH_MIX_SEC0: + case CDC_RX_RX2_RX_PATH_MIX_SEC1: + case CDC_RX_RX2_RX_PATH_DSM_CTL: + case CDC_RX_IDLE_DETECT_PATH_CTL: + case CDC_RX_IDLE_DETECT_CFG0: + case CDC_RX_IDLE_DETECT_CFG1: + case CDC_RX_IDLE_DETECT_CFG2: + case CDC_RX_IDLE_DETECT_CFG3: + case CDC_RX_COMPANDER0_CTL0: + case CDC_RX_COMPANDER0_CTL1: + case CDC_RX_COMPANDER0_CTL2: + case CDC_RX_COMPANDER0_CTL3: + case CDC_RX_COMPANDER0_CTL4: + case CDC_RX_COMPANDER0_CTL5: + case CDC_RX_COMPANDER0_CTL7: + case CDC_RX_COMPANDER1_CTL0: + case CDC_RX_COMPANDER1_CTL1: + case CDC_RX_COMPANDER1_CTL2: + case CDC_RX_COMPANDER1_CTL3: + case CDC_RX_COMPANDER1_CTL4: + case CDC_RX_COMPANDER1_CTL5: + case CDC_RX_COMPANDER1_CTL7: + case CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B5_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B6_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B7_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_B8_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL: + case CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B5_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B6_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B7_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_B8_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_COEF_B1_CTL: + case CDC_RX_SIDETONE_IIR1_IIR_COEF_B2_CTL: + case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0: + case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1: + case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2: + case CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3: + case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0: + case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1: + case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2: + case CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3: + case CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL: + case CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CFG1: + case CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL: + case CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CFG1: + case CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL: + case CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0: + case CDC_RX_EC_REF_HQ1_EC_REF_HQ_PATH_CTL: + case CDC_RX_EC_REF_HQ1_EC_REF_HQ_CFG0: + case CDC_RX_EC_REF_HQ2_EC_REF_HQ_PATH_CTL: + case CDC_RX_EC_REF_HQ2_EC_REF_HQ_CFG0: + case CDC_RX_EC_ASRC0_CLK_RST_CTL: + case CDC_RX_EC_ASRC0_CTL0: + case CDC_RX_EC_ASRC0_CTL1: + case CDC_RX_EC_ASRC0_FIFO_CTL: + case CDC_RX_EC_ASRC1_CLK_RST_CTL: + case CDC_RX_EC_ASRC1_CTL0: + case CDC_RX_EC_ASRC1_CTL1: + case CDC_RX_EC_ASRC1_FIFO_CTL: + case CDC_RX_EC_ASRC2_CLK_RST_CTL: + case CDC_RX_EC_ASRC2_CTL0: + case CDC_RX_EC_ASRC2_CTL1: + case CDC_RX_EC_ASRC2_FIFO_CTL: + case CDC_RX_DSD0_PATH_CTL: + case CDC_RX_DSD0_CFG0: + case CDC_RX_DSD0_CFG1: + case CDC_RX_DSD0_CFG2: + case CDC_RX_DSD1_PATH_CTL: + case CDC_RX_DSD1_CFG0: + case CDC_RX_DSD1_CFG1: + case CDC_RX_DSD1_CFG2: + return true; + } + + return false; +} + +static bool rx_is_writeable_register(struct device *dev, unsigned int reg) +{ + bool ret; + + ret = rx_is_rw_register(dev, reg); + if (!ret) + return rx_is_wronly_register(dev, reg); + + return ret; +} + +static bool rx_is_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_RX_TOP_HPHL_COMP_RD_LSB: + case CDC_RX_TOP_HPHL_COMP_RD_MSB: + case CDC_RX_TOP_HPHR_COMP_RD_LSB: + case CDC_RX_TOP_HPHR_COMP_RD_MSB: + case CDC_RX_TOP_DSD0_DEBUG_CFG2: + case CDC_RX_TOP_DSD1_DEBUG_CFG2: + case CDC_RX_BCL_VBAT_GAIN_MON_VAL: + case CDC_RX_BCL_VBAT_DECODE_ST: + case CDC_RX_INTR_CTRL_PIN1_STATUS0: + case CDC_RX_INTR_CTRL_PIN2_STATUS0: + case CDC_RX_COMPANDER0_CTL6: + case CDC_RX_COMPANDER1_CTL6: + case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_LSB: + case CDC_RX_EC_ASRC0_STATUS_FMIN_CNTR_MSB: + case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_LSB: + case CDC_RX_EC_ASRC0_STATUS_FMAX_CNTR_MSB: + case CDC_RX_EC_ASRC0_STATUS_FIFO: + case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_LSB: + case CDC_RX_EC_ASRC1_STATUS_FMIN_CNTR_MSB: + case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_LSB: + case CDC_RX_EC_ASRC1_STATUS_FMAX_CNTR_MSB: + case CDC_RX_EC_ASRC1_STATUS_FIFO: + case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_LSB: + case CDC_RX_EC_ASRC2_STATUS_FMIN_CNTR_MSB: + case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_LSB: + case CDC_RX_EC_ASRC2_STATUS_FMAX_CNTR_MSB: + case CDC_RX_EC_ASRC2_STATUS_FIFO: + return true; + } + + return rx_is_rw_register(dev, reg); +} + +static const struct regmap_config rx_regmap_config = { + .name = "rx_macro", + .reg_bits = 16, + .val_bits = 32, /* 8 but with 32 bit read/write */ + .reg_stride = 4, + .cache_type = REGCACHE_FLAT, + .reg_defaults = rx_defaults, + .num_reg_defaults = ARRAY_SIZE(rx_defaults), + .max_register = RX_MAX_OFFSET, + .writeable_reg = rx_is_writeable_register, + .volatile_reg = rx_is_volatile_register, + .readable_reg = rx_is_readable_register, +}; + +static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, + int rate_reg_val, u32 sample_rate) +{ + + u8 int_1_mix1_inp; + u32 j, port; + u16 int_mux_cfg0, int_mux_cfg1; + u16 int_fs_reg; + u8 inp0_sel, inp1_sel, inp2_sel; + struct snd_soc_component *component = dai->component; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + for_each_set_bit(port, &rx->active_ch_mask[dai->id], RX_MACRO_PORTS_MAX) { + int_1_mix1_inp = port; + int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0; + /* + * Loop through all interpolator MUX inputs and find out + * to which interpolator input, the rx port + * is connected + */ + for (j = 0; j < INTERP_MAX; j++) { + int_mux_cfg1 = int_mux_cfg0 + 4; + + inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_RX_INTX_1_MIX_INP0_SEL_MASK); + inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_RX_INTX_1_MIX_INP1_SEL_MASK); + inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1, + CDC_RX_INTX_1_MIX_INP2_SEL_MASK); + + if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || + (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) { + int_fs_reg = CDC_RX_RXn_RX_PATH_CTL(j); + /* sample_rate is in Hz */ + snd_soc_component_update_bits(component, int_fs_reg, + CDC_RX_PATH_PCM_RATE_MASK, + rate_reg_val); + } + int_mux_cfg0 += 8; + } + } + + return 0; +} + +static int rx_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai, + int rate_reg_val, u32 sample_rate) +{ + + u8 int_2_inp; + u32 j, port; + u16 int_mux_cfg1, int_fs_reg; + u8 int_mux_cfg1_val; + struct snd_soc_component *component = dai->component; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + for_each_set_bit(port, &rx->active_ch_mask[dai->id], RX_MACRO_PORTS_MAX) { + int_2_inp = port; + + int_mux_cfg1 = CDC_RX_INP_MUX_RX_INT0_CFG1; + for (j = 0; j < INTERP_MAX; j++) { + int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1, + CDC_RX_INTX_2_SEL_MASK); + + if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) { + int_fs_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j); + snd_soc_component_update_bits(component, int_fs_reg, + CDC_RX_RXn_MIX_PCM_RATE_MASK, + rate_reg_val); + } + int_mux_cfg1 += 8; + } + } + return 0; +} + +static int rx_macro_set_interpolator_rate(struct snd_soc_dai *dai, + u32 sample_rate) +{ + int rate_val = 0; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++) + if (sample_rate == sr_val_tbl[i].sample_rate) + rate_val = sr_val_tbl[i].rate_val; + + ret = rx_macro_set_prim_interpolator_rate(dai, rate_val, sample_rate); + if (ret) + return ret; + + ret = rx_macro_set_mix_interpolator_rate(dai, rate_val, sample_rate); + if (ret) + return ret; + + return ret; +} + +static int rx_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + int ret; + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = rx_macro_set_interpolator_rate(dai, params_rate(params)); + if (ret) { + dev_err(component->dev, "%s: cannot set sample rate: %u\n", + __func__, params_rate(params)); + return ret; + } + rx->bit_width[dai->id] = params_width(params); + break; + default: + break; + } + return 0; +} + +static int rx_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + u16 val, mask = 0, cnt = 0, temp; + + switch (dai->id) { + case RX_MACRO_AIF1_PB: + case RX_MACRO_AIF2_PB: + case RX_MACRO_AIF3_PB: + case RX_MACRO_AIF4_PB: + for_each_set_bit(temp, &rx->active_ch_mask[dai->id], + RX_MACRO_PORTS_MAX) { + mask |= (1 << temp); + if (++cnt == RX_MACRO_MAX_DMA_CH_PER_PORT) + break; + } + /* + * CDC_DMA_RX_0 port drives RX0/RX1 -- ch_mask 0x1/0x2/0x3 + * CDC_DMA_RX_1 port drives RX2/RX3 -- ch_mask 0x1/0x2/0x3 + * CDC_DMA_RX_2 port drives RX4 -- ch_mask 0x1 + * CDC_DMA_RX_3 port drives RX5 -- ch_mask 0x1 + * AIFn can pair to any CDC_DMA_RX_n port. + * In general, below convention is used:: + * CDC_DMA_RX_0(AIF1)/CDC_DMA_RX_1(AIF2)/ + * CDC_DMA_RX_2(AIF3)/CDC_DMA_RX_3(AIF4) + */ + if (mask & 0x0C) + mask = mask >> 2; + if ((mask & 0x10) || (mask & 0x20)) + mask = 0x1; + *rx_slot = mask; + *rx_num = rx->active_ch_cnt[dai->id]; + break; + case RX_MACRO_AIF_ECHO: + val = snd_soc_component_read(component, CDC_RX_INP_MUX_RX_MIX_CFG4); + if (val & RX_MACRO_EC_MIX_TX0_MASK) { + mask |= 0x1; + cnt++; + } + if (val & RX_MACRO_EC_MIX_TX1_MASK) { + mask |= 0x2; + cnt++; + } + val = snd_soc_component_read(component, + CDC_RX_INP_MUX_RX_MIX_CFG5); + if (val & RX_MACRO_EC_MIX_TX2_MASK) { + mask |= 0x4; + cnt++; + } + *tx_slot = mask; + *tx_num = cnt; + break; + default: + dev_err(component->dev, "%s: Invalid AIF\n", __func__); + break; + } + return 0; +} + +static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *component = dai->component; + uint16_t j, reg, mix_reg, dsm_reg; + u16 int_mux_cfg0, int_mux_cfg1; + u8 int_mux_cfg0_val, int_mux_cfg1_val; + + switch (dai->id) { + case RX_MACRO_AIF1_PB: + case RX_MACRO_AIF2_PB: + case RX_MACRO_AIF3_PB: + case RX_MACRO_AIF4_PB: + for (j = 0; j < INTERP_MAX; j++) { + reg = CDC_RX_RXn_RX_PATH_CTL(j); + mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j); + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j); + + if (mute) { + snd_soc_component_update_bits(component, reg, + CDC_RX_PATH_PGA_MUTE_MASK, + CDC_RX_PATH_PGA_MUTE_ENABLE); + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_PATH_PGA_MUTE_MASK, + CDC_RX_PATH_PGA_MUTE_ENABLE); + } else { + snd_soc_component_update_bits(component, reg, + CDC_RX_PATH_PGA_MUTE_MASK, 0x0); + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_PATH_PGA_MUTE_MASK, 0x0); + } + + if (j == INTERP_AUX) + dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL; + + int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1); + + if (snd_soc_component_read(component, dsm_reg) & 0x01) { + if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0)) + snd_soc_component_update_bits(component, reg, 0x20, 0x20); + if (int_mux_cfg1_val & 0x0F) { + snd_soc_component_update_bits(component, reg, 0x20, 0x20); + snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20); + } + } + } + break; + default: + break; + } + return 0; +} + +static struct snd_soc_dai_ops rx_macro_dai_ops = { + .hw_params = rx_macro_hw_params, + .get_channel_map = rx_macro_get_channel_map, + .mute_stream = rx_macro_digital_mute, +}; + +static struct snd_soc_dai_driver rx_macro_dai[] = { + { + .name = "rx_macro_rx1", + .id = RX_MACRO_AIF1_PB, + .playback = { + .stream_name = "RX_MACRO_AIF1 Playback", + .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES, + .formats = RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx2", + .id = RX_MACRO_AIF2_PB, + .playback = { + .stream_name = "RX_MACRO_AIF2 Playback", + .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES, + .formats = RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx3", + .id = RX_MACRO_AIF3_PB, + .playback = { + .stream_name = "RX_MACRO_AIF3 Playback", + .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES, + .formats = RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &rx_macro_dai_ops, + }, + { + .name = "rx_macro_rx4", + .id = RX_MACRO_AIF4_PB, + .playback = { + .stream_name = "RX_MACRO_AIF4 Playback", + .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES, + .formats = RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &rx_macro_dai_ops, + }, + { + .name = "rx_macro_echo", + .id = RX_MACRO_AIF_ECHO, + .capture = { + .stream_name = "RX_AIF_ECHO Capture", + .rates = RX_MACRO_ECHO_RATES, + .formats = RX_MACRO_ECHO_FORMATS, + .rate_max = 48000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 3, + }, + .ops = &rx_macro_dai_ops, + }, +}; + +static void rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable) +{ + struct regmap *regmap = rx->regmap; + + if (mclk_enable) { + if (rx->rx_mclk_users == 0) { + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, + CDC_RX_CLK_MCLK_EN_MASK | + CDC_RX_CLK_MCLK2_EN_MASK, + CDC_RX_CLK_MCLK_ENABLE | + CDC_RX_CLK_MCLK2_ENABLE); + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_RX_FS_MCLK_CNT_CLR_MASK, 0x00); + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_RX_FS_MCLK_CNT_EN_MASK, + CDC_RX_FS_MCLK_CNT_ENABLE); + regcache_mark_dirty(regmap); + regcache_sync(regmap); + } + rx->rx_mclk_users++; + } else { + if (rx->rx_mclk_users <= 0) { + dev_err(rx->dev, "%s: clock already disabled\n", __func__); + rx->rx_mclk_users = 0; + return; + } + rx->rx_mclk_users--; + if (rx->rx_mclk_users == 0) { + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_RX_FS_MCLK_CNT_EN_MASK, 0x0); + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_RX_FS_MCLK_CNT_CLR_MASK, + CDC_RX_FS_MCLK_CNT_CLR); + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, + CDC_RX_CLK_MCLK_EN_MASK | + CDC_RX_CLK_MCLK2_EN_MASK, 0x0); + } + } +} + +static inline void rx_macro_enable_clsh_block(struct rx_macro *rx, bool enable) +{ + if ((enable && ++rx->clsh_users == 1) || (!enable && --rx->clsh_users == 0)) + snd_soc_component_update_bits(rx->component, CDC_RX_CLSH_CRC, + CDC_RX_CLSH_CLK_EN_MASK, enable); + if (rx->clsh_users < 0) + rx->clsh_users = 0; +} + +static int rx_macro_get_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rx->comp_enabled[comp]; + return 0; +} + +static int rx_macro_set_compander(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int comp = ((struct soc_mixer_control *) kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + rx->comp_enabled[comp] = value; + + return 0; +} + +static int rx_macro_get_ear_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rx->is_ear_mode_on; + return 0; +} + +static int rx_macro_put_ear_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + rx->is_ear_mode_on = (!ucontrol->value.integer.value[0] ? false : true); + return 0; +} + +static int rx_macro_get_hph_hd2_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rx->hph_hd2_mode; + return 0; +} + +static int rx_macro_put_hph_hd2_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + rx->hph_hd2_mode = ucontrol->value.integer.value[0]; + return 0; +} + +static int rx_macro_get_hph_pwr_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rx->hph_pwr_mode; + return 0; +} + +static int rx_macro_put_hph_pwr_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + rx->hph_pwr_mode = ucontrol->value.integer.value[0]; + return 0; +} + +static int rx_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rx->is_softclip_on; + + return 0; +} + +static int rx_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + rx->is_softclip_on = ucontrol->value.integer.value[0]; + + return 0; +} + +static int rx_macro_aux_hpf_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rx->is_aux_hpf_on; + + return 0; +} + +static int rx_macro_aux_hpf_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + rx->is_aux_hpf_on = ucontrol->value.integer.value[0]; + + return 0; +} + +static const struct snd_kcontrol_new rx_macro_snd_controls[] = { + SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_RX_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_RX_RX2_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", CDC_RX_RX0_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_RX_RX1_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_RX_RX2_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + + SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0, + rx_macro_get_compander, rx_macro_set_compander), + SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, RX_MACRO_COMP2, 1, 0, + rx_macro_get_compander, rx_macro_set_compander), + + SOC_SINGLE_EXT("RX_EAR Mode Switch", SND_SOC_NOPM, 0, 1, 0, + rx_macro_get_ear_mode, rx_macro_put_ear_mode), + + SOC_SINGLE_EXT("RX_HPH HD2 Mode Switch", SND_SOC_NOPM, 0, 1, 0, + rx_macro_get_hph_hd2_mode, rx_macro_put_hph_hd2_mode), + + SOC_ENUM_EXT("RX_HPH PWR Mode", rx_macro_hph_pwr_mode_enum, + rx_macro_get_hph_pwr_mode, rx_macro_put_hph_pwr_mode), + + SOC_SINGLE_EXT("RX_Softclip Switch", SND_SOC_NOPM, 0, 1, 0, + rx_macro_soft_clip_enable_get, + rx_macro_soft_clip_enable_put), + SOC_SINGLE_EXT("AUX_HPF Switch", SND_SOC_NOPM, 0, 1, 0, + rx_macro_aux_hpf_mode_get, + rx_macro_aux_hpf_mode_put), +}; + +static int rx_macro_component_probe(struct snd_soc_component *component) +{ + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + snd_soc_component_init_regmap(component, rx->regmap); + + snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_SEC7, + CDC_RX_DSM_OUT_DELAY_SEL_MASK, + CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); + snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_SEC7, + CDC_RX_DSM_OUT_DELAY_SEL_MASK, + CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); + snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_SEC7, + CDC_RX_DSM_OUT_DELAY_SEL_MASK, + CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); + snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_CFG3, + CDC_RX_DC_COEFF_SEL_MASK, + CDC_RX_DC_COEFF_SEL_TWO); + snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_CFG3, + CDC_RX_DC_COEFF_SEL_MASK, + CDC_RX_DC_COEFF_SEL_TWO); + snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_CFG3, + CDC_RX_DC_COEFF_SEL_MASK, + CDC_RX_DC_COEFF_SEL_TWO); + + rx->component = component; + + return 0; +} + +static int swclk_gate_enable(struct clk_hw *hw) +{ + struct rx_macro *rx = to_rx_macro(hw); + + rx_macro_mclk_enable(rx, true); + if (rx->reset_swr) + regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + CDC_RX_SWR_RESET_MASK, + CDC_RX_SWR_RESET); + + regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + CDC_RX_SWR_CLK_EN_MASK, 1); + + if (rx->reset_swr) + regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + CDC_RX_SWR_RESET_MASK, 0); + rx->reset_swr = false; + + return 0; +} + +static void swclk_gate_disable(struct clk_hw *hw) +{ + struct rx_macro *rx = to_rx_macro(hw); + + regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, + CDC_RX_SWR_CLK_EN_MASK, 0); + + rx_macro_mclk_enable(rx, false); +} + +static int swclk_gate_is_enabled(struct clk_hw *hw) +{ + struct rx_macro *rx = to_rx_macro(hw); + int ret, val; + + regmap_read(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, &val); + ret = val & BIT(0); + + return ret; +} + +static unsigned long swclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate / 2; +} + +static const struct clk_ops swclk_gate_ops = { + .prepare = swclk_gate_enable, + .unprepare = swclk_gate_disable, + .is_enabled = swclk_gate_is_enabled, + .recalc_rate = swclk_recalc_rate, + +}; + +static struct clk *rx_macro_register_mclk_output(struct rx_macro *rx) +{ + struct device *dev = rx->dev; + struct device_node *np = dev->of_node; + const char *parent_clk_name = NULL; + const char *clk_name = "lpass-rx-mclk"; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + parent_clk_name = __clk_get_name(rx->clks[2].clk); + + init.name = clk_name; + init.ops = &swclk_gate_ops; + init.flags = 0; + init.parent_names = &parent_clk_name; + init.num_parents = 1; + rx->hw.init = &init; + hw = &rx->hw; + ret = clk_hw_register(rx->dev, hw); + if (ret) + return ERR_PTR(ret); + + of_clk_add_provider(np, of_clk_src_simple_get, hw->clk); + + return NULL; +} + +static const struct snd_soc_component_driver rx_macro_component_drv = { + .name = "RX-MACRO", + .probe = rx_macro_component_probe, + .controls = rx_macro_snd_controls, + .num_controls = ARRAY_SIZE(rx_macro_snd_controls), +}; + +static int rx_macro_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rx_macro *rx; + void __iomem *base; + int ret; + + rx = devm_kzalloc(dev, sizeof(*rx), GFP_KERNEL); + if (!rx) + return -ENOMEM; + + rx->clks[0].id = "macro"; + rx->clks[1].id = "dcodec"; + rx->clks[2].id = "mclk"; + rx->clks[3].id = "npl"; + rx->clks[4].id = "fsgen"; + + ret = devm_clk_bulk_get(dev, RX_NUM_CLKS_MAX, rx->clks); + if (ret) { + dev_err(dev, "Error getting RX Clocks (%d)\n", ret); + return ret; + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + rx->regmap = devm_regmap_init_mmio(dev, base, &rx_regmap_config); + + dev_set_drvdata(dev, rx); + + rx->reset_swr = true; + rx->dev = dev; + + /* set MCLK and NPL rates */ + clk_set_rate(rx->clks[2].clk, MCLK_FREQ); + clk_set_rate(rx->clks[3].clk, MCLK_FREQ); + + ret = clk_bulk_prepare_enable(RX_NUM_CLKS_MAX, rx->clks); + if (ret) + return ret; + + rx_macro_register_mclk_output(rx); + + ret = devm_snd_soc_register_component(dev, &rx_macro_component_drv, + rx_macro_dai, + ARRAY_SIZE(rx_macro_dai)); + if (ret) + clk_bulk_disable_unprepare(RX_NUM_CLKS_MAX, rx->clks); + + return ret; +} + +static int rx_macro_remove(struct platform_device *pdev) +{ + struct rx_macro *rx = dev_get_drvdata(&pdev->dev); + + of_clk_del_provider(pdev->dev.of_node); + clk_bulk_disable_unprepare(RX_NUM_CLKS_MAX, rx->clks); + return 0; +} + +static const struct of_device_id rx_macro_dt_match[] = { + { .compatible = "qcom,sm8250-lpass-rx-macro" }, + { } +}; + +static struct platform_driver rx_macro_driver = { + .driver = { + .name = "rx_macro", + .owner = THIS_MODULE, + .of_match_table = rx_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = rx_macro_probe, + .remove = rx_macro_remove, +}; + +module_platform_driver(rx_macro_driver); + +MODULE_DESCRIPTION("RX macro driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4f692926f562ff48abfcca6b16f36ff8d57473b6 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:31 +0000 Subject: ASoC: codecs: lpass-rx-macro: add dapm widgets and route This patch adds dapm widgets and routes on this codec Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210211122735.5691-4-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 1341 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1341 insertions(+) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 1c114a46c44a..2cf6eb9238a7 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -583,12 +583,210 @@ struct rx_macro { static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); +static const char * const rx_int_mix_mux_text[] = { + "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5" +}; + +static const char * const rx_prim_mix_text[] = { + "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2", + "RX3", "RX4", "RX5" +}; + +static const char * const rx_sidetone_mix_text[] = { + "ZERO", "SRC0", "SRC1", "SRC_SUM" +}; + +static const char * const iir_inp_mux_text[] = { + "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", + "RX0", "RX1", "RX2", "RX3", "RX4", "RX5" +}; + +static const char * const rx_int_dem_inp_mux_text[] = { + "NORMAL_DSM_OUT", "CLSH_DSM_OUT", +}; + +static const char * const rx_int0_1_interp_mux_text[] = { + "ZERO", "RX INT0_1 MIX1", +}; + +static const char * const rx_int1_1_interp_mux_text[] = { + "ZERO", "RX INT1_1 MIX1", +}; + +static const char * const rx_int2_1_interp_mux_text[] = { + "ZERO", "RX INT2_1 MIX1", +}; + +static const char * const rx_int0_2_interp_mux_text[] = { + "ZERO", "RX INT0_2 MUX", +}; + +static const char * const rx_int1_2_interp_mux_text[] = { + "ZERO", "RX INT1_2 MUX", +}; + +static const char * const rx_int2_2_interp_mux_text[] = { + "ZERO", "RX INT2_2 MUX", +}; + +static const char *const rx_macro_mux_text[] = { + "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB" +}; + static const char *const rx_macro_hph_pwr_mode_text[] = { "ULP", "LOHIFI" }; +static const char * const rx_echo_mux_text[] = { + "ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2" +}; + static const struct soc_enum rx_macro_hph_pwr_mode_enum = SOC_ENUM_SINGLE_EXT(2, rx_macro_hph_pwr_mode_text); +static const struct soc_enum rx_mix_tx2_mux_enum = + SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG5, 0, 4, rx_echo_mux_text); +static const struct soc_enum rx_mix_tx1_mux_enum = + SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG4, 0, 4, rx_echo_mux_text); +static const struct soc_enum rx_mix_tx0_mux_enum = + SOC_ENUM_SINGLE(CDC_RX_INP_MUX_RX_MIX_CFG4, 4, 4, rx_echo_mux_text); + +static SOC_ENUM_SINGLE_DECL(rx_int0_2_enum, CDC_RX_INP_MUX_RX_INT0_CFG1, 0, + rx_int_mix_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_2_enum, CDC_RX_INP_MUX_RX_INT1_CFG1, 0, + rx_int_mix_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_2_enum, CDC_RX_INP_MUX_RX_INT2_CFG1, 0, + rx_int_mix_mux_text); + +static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT0_CFG0, 0, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT0_CFG0, 4, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int0_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT0_CFG1, 4, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT1_CFG0, 0, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT1_CFG0, 4, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT1_CFG1, 4, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp0_enum, CDC_RX_INP_MUX_RX_INT2_CFG0, 0, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp1_enum, CDC_RX_INP_MUX_RX_INT2_CFG0, 4, + rx_prim_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_1_mix_inp2_enum, CDC_RX_INP_MUX_RX_INT2_CFG1, 4, + rx_prim_mix_text); + +static SOC_ENUM_SINGLE_DECL(rx_int0_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, + rx_sidetone_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4, + rx_sidetone_mix_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_mix2_inp_enum, CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6, + rx_sidetone_mix_text); +static SOC_ENUM_SINGLE_DECL(iir0_inp0_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG0, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir0_inp1_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG1, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir0_inp2_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG2, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir0_inp3_enum, CDC_RX_IIR_INP_MUX_IIR0_MIX_CFG3, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir1_inp0_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG0, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir1_inp1_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG1, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir1_inp2_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG2, 0, + iir_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(iir1_inp3_enum, CDC_RX_IIR_INP_MUX_IIR1_MIX_CFG3, 0, + iir_inp_mux_text); + +static SOC_ENUM_SINGLE_DECL(rx_int0_1_interp_enum, SND_SOC_NOPM, 0, + rx_int0_1_interp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_1_interp_enum, SND_SOC_NOPM, 0, + rx_int1_1_interp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_1_interp_enum, SND_SOC_NOPM, 0, + rx_int2_1_interp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int0_2_interp_enum, SND_SOC_NOPM, 0, + rx_int0_2_interp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_2_interp_enum, SND_SOC_NOPM, 0, + rx_int1_2_interp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int2_2_interp_enum, SND_SOC_NOPM, 0, + rx_int2_2_interp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int0_dem_inp_enum, CDC_RX_RX0_RX_PATH_CFG1, 0, + rx_int_dem_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_int1_dem_inp_enum, CDC_RX_RX1_RX_PATH_CFG1, 0, + rx_int_dem_inp_mux_text); + +static SOC_ENUM_SINGLE_DECL(rx_macro_rx0_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_macro_rx1_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_macro_rx2_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_macro_rx3_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_macro_rx4_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_macro_rx5_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); + +static const struct snd_kcontrol_new rx_mix_tx1_mux = + SOC_DAPM_ENUM("RX MIX TX1_MUX Mux", rx_mix_tx1_mux_enum); +static const struct snd_kcontrol_new rx_mix_tx2_mux = + SOC_DAPM_ENUM("RX MIX TX2_MUX Mux", rx_mix_tx2_mux_enum); +static const struct snd_kcontrol_new rx_int0_2_mux = + SOC_DAPM_ENUM("rx_int0_2", rx_int0_2_enum); +static const struct snd_kcontrol_new rx_int1_2_mux = + SOC_DAPM_ENUM("rx_int1_2", rx_int1_2_enum); +static const struct snd_kcontrol_new rx_int2_2_mux = + SOC_DAPM_ENUM("rx_int2_2", rx_int2_2_enum); +static const struct snd_kcontrol_new rx_int0_1_mix_inp0_mux = + SOC_DAPM_ENUM("rx_int0_1_mix_inp0", rx_int0_1_mix_inp0_enum); +static const struct snd_kcontrol_new rx_int0_1_mix_inp1_mux = + SOC_DAPM_ENUM("rx_int0_1_mix_inp1", rx_int0_1_mix_inp1_enum); +static const struct snd_kcontrol_new rx_int0_1_mix_inp2_mux = + SOC_DAPM_ENUM("rx_int0_1_mix_inp2", rx_int0_1_mix_inp2_enum); +static const struct snd_kcontrol_new rx_int1_1_mix_inp0_mux = + SOC_DAPM_ENUM("rx_int1_1_mix_inp0", rx_int1_1_mix_inp0_enum); +static const struct snd_kcontrol_new rx_int1_1_mix_inp1_mux = + SOC_DAPM_ENUM("rx_int1_1_mix_inp1", rx_int1_1_mix_inp1_enum); +static const struct snd_kcontrol_new rx_int1_1_mix_inp2_mux = + SOC_DAPM_ENUM("rx_int1_1_mix_inp2", rx_int1_1_mix_inp2_enum); +static const struct snd_kcontrol_new rx_int2_1_mix_inp0_mux = + SOC_DAPM_ENUM("rx_int2_1_mix_inp0", rx_int2_1_mix_inp0_enum); +static const struct snd_kcontrol_new rx_int2_1_mix_inp1_mux = + SOC_DAPM_ENUM("rx_int2_1_mix_inp1", rx_int2_1_mix_inp1_enum); +static const struct snd_kcontrol_new rx_int2_1_mix_inp2_mux = + SOC_DAPM_ENUM("rx_int2_1_mix_inp2", rx_int2_1_mix_inp2_enum); +static const struct snd_kcontrol_new rx_int0_mix2_inp_mux = + SOC_DAPM_ENUM("rx_int0_mix2_inp", rx_int0_mix2_inp_enum); +static const struct snd_kcontrol_new rx_int1_mix2_inp_mux = + SOC_DAPM_ENUM("rx_int1_mix2_inp", rx_int1_mix2_inp_enum); +static const struct snd_kcontrol_new rx_int2_mix2_inp_mux = + SOC_DAPM_ENUM("rx_int2_mix2_inp", rx_int2_mix2_inp_enum); +static const struct snd_kcontrol_new iir0_inp0_mux = + SOC_DAPM_ENUM("iir0_inp0", iir0_inp0_enum); +static const struct snd_kcontrol_new iir0_inp1_mux = + SOC_DAPM_ENUM("iir0_inp1", iir0_inp1_enum); +static const struct snd_kcontrol_new iir0_inp2_mux = + SOC_DAPM_ENUM("iir0_inp2", iir0_inp2_enum); +static const struct snd_kcontrol_new iir0_inp3_mux = + SOC_DAPM_ENUM("iir0_inp3", iir0_inp3_enum); +static const struct snd_kcontrol_new iir1_inp0_mux = + SOC_DAPM_ENUM("iir1_inp0", iir1_inp0_enum); +static const struct snd_kcontrol_new iir1_inp1_mux = + SOC_DAPM_ENUM("iir1_inp1", iir1_inp1_enum); +static const struct snd_kcontrol_new iir1_inp2_mux = + SOC_DAPM_ENUM("iir1_inp2", iir1_inp2_enum); +static const struct snd_kcontrol_new iir1_inp3_mux = + SOC_DAPM_ENUM("iir1_inp3", iir1_inp3_enum); +static const struct snd_kcontrol_new rx_int0_1_interp_mux = + SOC_DAPM_ENUM("rx_int0_1_interp", rx_int0_1_interp_enum); +static const struct snd_kcontrol_new rx_int1_1_interp_mux = + SOC_DAPM_ENUM("rx_int1_1_interp", rx_int1_1_interp_enum); +static const struct snd_kcontrol_new rx_int2_1_interp_mux = + SOC_DAPM_ENUM("rx_int2_1_interp", rx_int2_1_interp_enum); +static const struct snd_kcontrol_new rx_int0_2_interp_mux = + SOC_DAPM_ENUM("rx_int0_2_interp", rx_int0_2_interp_enum); +static const struct snd_kcontrol_new rx_int1_2_interp_mux = + SOC_DAPM_ENUM("rx_int1_2_interp", rx_int1_2_interp_enum); +static const struct snd_kcontrol_new rx_int2_2_interp_mux = + SOC_DAPM_ENUM("rx_int2_2_interp", rx_int2_2_interp_enum); +static const struct snd_kcontrol_new rx_mix_tx0_mux = + SOC_DAPM_ENUM("RX MIX TX0_MUX Mux", rx_mix_tx0_mux_enum); static const struct reg_default rx_defaults[] = { /* RX Macro */ @@ -1257,6 +1455,41 @@ static const struct regmap_config rx_regmap_config = { .readable_reg = rx_is_readable_register, }; +static int rx_macro_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned short look_ahead_dly_reg; + unsigned int val; + + val = ucontrol->value.enumerated.item[0]; + + if (e->reg == CDC_RX_RX0_RX_PATH_CFG1) + look_ahead_dly_reg = CDC_RX_RX0_RX_PATH_CFG0; + else if (e->reg == CDC_RX_RX1_RX_PATH_CFG1) + look_ahead_dly_reg = CDC_RX_RX1_RX_PATH_CFG0; + + /* Set Look Ahead Delay */ + if (val) + snd_soc_component_update_bits(component, look_ahead_dly_reg, + CDC_RX_DLY_ZN_EN_MASK, + CDC_RX_DLY_ZN_ENABLE); + else + snd_soc_component_update_bits(component, look_ahead_dly_reg, + CDC_RX_DLY_ZN_EN_MASK, 0); + /* Set DEM INP Select */ + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); +} + +static const struct snd_kcontrol_new rx_int0_dem_inp_mux = + SOC_DAPM_ENUM_EXT("rx_int0_dem_inp", rx_int0_dem_inp_enum, + snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); +static const struct snd_kcontrol_new rx_int1_dem_inp_mux = + SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_int1_dem_inp_enum, + snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); + static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, int rate_reg_val, u32 sample_rate) { @@ -1615,6 +1848,248 @@ static void rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable) } } +static int rx_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + int ret = 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + rx_macro_mclk_enable(rx, true); + break; + case SND_SOC_DAPM_POST_PMD: + rx_macro_mclk_enable(rx, false); + break; + default: + dev_err(component->dev, "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + +static bool rx_macro_adie_lb(struct snd_soc_component *component, + int interp_idx) +{ + u16 int_mux_cfg0, int_mux_cfg1; + u8 int_n_inp0, int_n_inp1, int_n_inp2; + + int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + + int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_RX_INTX_1_MIX_INP0_SEL_MASK); + int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0, + CDC_RX_INTX_1_MIX_INP1_SEL_MASK); + int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1, + CDC_RX_INTX_1_MIX_INP2_SEL_MASK); + + if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || + int_n_inp0 == INTn_1_INP_SEL_DEC1 || + int_n_inp0 == INTn_1_INP_SEL_IIR0 || + int_n_inp0 == INTn_1_INP_SEL_IIR1) + return true; + + if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || + int_n_inp1 == INTn_1_INP_SEL_DEC1 || + int_n_inp1 == INTn_1_INP_SEL_IIR0 || + int_n_inp1 == INTn_1_INP_SEL_IIR1) + return true; + + if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || + int_n_inp2 == INTn_1_INP_SEL_DEC1 || + int_n_inp2 == INTn_1_INP_SEL_IIR0 || + int_n_inp2 == INTn_1_INP_SEL_IIR1) + return true; + + return false; +} + +static int rx_macro_enable_interp_clk(struct snd_soc_component *component, + int event, int interp_idx); +static int rx_macro_enable_main_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 gain_reg, reg; + + reg = CDC_RX_RXn_RX_PATH_CTL(w->shift); + gain_reg = CDC_RX_RXn_RX_VOL_CTL(w->shift); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + rx_macro_enable_interp_clk(component, event, w->shift); + if (rx_macro_adie_lb(component, w->shift)) + snd_soc_component_update_bits(component, reg, + CDC_RX_PATH_CLK_EN_MASK, + CDC_RX_PATH_CLK_ENABLE); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_write(component, gain_reg, + snd_soc_component_read(component, gain_reg)); + break; + case SND_SOC_DAPM_POST_PMD: + rx_macro_enable_interp_clk(component, event, w->shift); + break; + } + + return 0; +} + +static int rx_macro_config_compander(struct snd_soc_component *component, + struct rx_macro *rx, + int comp, int event) +{ + u8 pcm_rate, val; + + /* AUX does not have compander */ + if (comp == INTERP_AUX) + return 0; + + pcm_rate = snd_soc_component_read(component, CDC_RX_RXn_RX_PATH_CTL(comp)) & 0x0F; + if (pcm_rate < 0x06) + val = 0x03; + else if (pcm_rate < 0x08) + val = 0x01; + else if (pcm_rate < 0x0B) + val = 0x02; + else + val = 0x00; + + if (SND_SOC_DAPM_EVENT_ON(event)) + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp), + CDC_RX_DC_COEFF_SEL_MASK, val); + + if (SND_SOC_DAPM_EVENT_OFF(event)) + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp), + CDC_RX_DC_COEFF_SEL_MASK, 0x3); + if (!rx->comp_enabled[comp]) + return 0; + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Compander Clock */ + snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), + CDC_RX_COMPANDERn_CLK_EN_MASK, 0x1); + snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), + CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x1); + snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), + CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x0); + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp), + CDC_RX_RXn_COMP_EN_MASK, 0x1); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), + CDC_RX_COMPANDERn_HALT_MASK, 0x1); + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp), + CDC_RX_RXn_COMP_EN_MASK, 0x0); + snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), + CDC_RX_COMPANDERn_CLK_EN_MASK, 0x0); + snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), + CDC_RX_COMPANDERn_HALT_MASK, 0x0); + } + + return 0; +} + +static int rx_macro_load_compander_coeff(struct snd_soc_component *component, + struct rx_macro *rx, + int comp, int event) +{ + u16 comp_coeff_lsb_reg, comp_coeff_msb_reg; + int i; + int hph_pwr_mode = HPH_LOHIFI; + + if (!rx->comp_enabled[comp]) + return 0; + + if (comp == INTERP_HPHL) { + comp_coeff_lsb_reg = CDC_RX_TOP_HPHL_COMP_WR_LSB; + comp_coeff_msb_reg = CDC_RX_TOP_HPHL_COMP_WR_MSB; + } else if (comp == INTERP_HPHR) { + comp_coeff_lsb_reg = CDC_RX_TOP_HPHR_COMP_WR_LSB; + comp_coeff_msb_reg = CDC_RX_TOP_HPHR_COMP_WR_MSB; + } else { + /* compander coefficients are loaded only for hph path */ + return 0; + } + + hph_pwr_mode = rx->hph_pwr_mode; + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Load Compander Coeff */ + for (i = 0; i < COMP_MAX_COEFF; i++) { + snd_soc_component_write(component, comp_coeff_lsb_reg, + comp_coeff_table[hph_pwr_mode][i].lsb); + snd_soc_component_write(component, comp_coeff_msb_reg, + comp_coeff_table[hph_pwr_mode][i].msb); + } + } + + return 0; +} + +static void rx_macro_enable_softclip_clk(struct snd_soc_component *component, + struct rx_macro *rx, bool enable) +{ + if (enable) { + if (rx->softclip_clk_users == 0) + snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_CRC, + CDC_RX_SOFTCLIP_CLK_EN_MASK, 1); + rx->softclip_clk_users++; + } else { + rx->softclip_clk_users--; + if (rx->softclip_clk_users == 0) + snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_CRC, + CDC_RX_SOFTCLIP_CLK_EN_MASK, 0); + } +} + +static int rx_macro_config_softclip(struct snd_soc_component *component, + struct rx_macro *rx, int event) +{ + + if (!rx->is_softclip_on) + return 0; + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Enable Softclip clock */ + rx_macro_enable_softclip_clk(component, rx, true); + /* Enable Softclip control */ + snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, + CDC_RX_SOFTCLIP_EN_MASK, 0x01); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_write_field(component, CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, + CDC_RX_SOFTCLIP_EN_MASK, 0x0); + rx_macro_enable_softclip_clk(component, rx, false); + } + + return 0; +} + +static int rx_macro_config_aux_hpf(struct snd_soc_component *component, + struct rx_macro *rx, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Update Aux HPF control */ + if (!rx->is_aux_hpf_on) + snd_soc_component_update_bits(component, + CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x00); + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + /* Reset to default (HPF=ON) */ + snd_soc_component_update_bits(component, + CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04); + } + + return 0; +} + static inline void rx_macro_enable_clsh_block(struct rx_macro *rx, bool enable) { if ((enable && ++rx->clsh_users == 1) || (!enable && --rx->clsh_users == 0)) @@ -1624,6 +2099,106 @@ static inline void rx_macro_enable_clsh_block(struct rx_macro *rx, bool enable) rx->clsh_users = 0; } +static int rx_macro_config_classh(struct snd_soc_component *component, + struct rx_macro *rx, + int interp_n, int event) +{ + if (SND_SOC_DAPM_EVENT_OFF(event)) { + rx_macro_enable_clsh_block(rx, false); + return 0; + } + + if (!SND_SOC_DAPM_EVENT_ON(event)) + return 0; + + rx_macro_enable_clsh_block(rx, true); + if (interp_n == INTERP_HPHL || + interp_n == INTERP_HPHR) { + /* + * These K1 values depend on the Headphone Impedance + * For now it is assumed to be 16 ohm + */ + snd_soc_component_write(component, CDC_RX_CLSH_K1_LSB, 0xc0); + snd_soc_component_write_field(component, CDC_RX_CLSH_K1_MSB, + CDC_RX_CLSH_K1_MSB_COEFF_MASK, 0); + } + switch (interp_n) { + case INTERP_HPHL: + if (rx->is_ear_mode_on) + snd_soc_component_update_bits(component, + CDC_RX_CLSH_HPH_V_PA, + CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x39); + else + snd_soc_component_update_bits(component, + CDC_RX_CLSH_HPH_V_PA, + CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x1c); + snd_soc_component_update_bits(component, + CDC_RX_CLSH_DECAY_CTRL, + CDC_RX_CLSH_DECAY_RATE_MASK, 0x0); + snd_soc_component_write_field(component, + CDC_RX_RX0_RX_PATH_CFG0, + CDC_RX_RXn_CLSH_EN_MASK, 0x1); + break; + case INTERP_HPHR: + if (rx->is_ear_mode_on) + snd_soc_component_update_bits(component, + CDC_RX_CLSH_HPH_V_PA, + CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x39); + else + snd_soc_component_update_bits(component, + CDC_RX_CLSH_HPH_V_PA, + CDC_RX_CLSH_HPH_V_PA_MIN_MASK, 0x1c); + snd_soc_component_update_bits(component, + CDC_RX_CLSH_DECAY_CTRL, + CDC_RX_CLSH_DECAY_RATE_MASK, 0x0); + snd_soc_component_update_bits(component, + CDC_RX_RX1_RX_PATH_CFG0, + CDC_RX_RXn_CLSH_EN_MASK, 0x1); + break; + case INTERP_AUX: + snd_soc_component_update_bits(component, + CDC_RX_RX2_RX_PATH_CFG0, + CDC_RX_RX2_DLY_Z_EN_MASK, 1); + snd_soc_component_write_field(component, + CDC_RX_RX2_RX_PATH_CFG0, + CDC_RX_RX2_CLSH_EN_MASK, 1); + break; + } + + return 0; +} + +static void rx_macro_hd2_control(struct snd_soc_component *component, + u16 interp_idx, int event) +{ + u16 hd2_scale_reg, hd2_enable_reg; + + switch (interp_idx) { + case INTERP_HPHL: + hd2_scale_reg = CDC_RX_RX0_RX_PATH_SEC3; + hd2_enable_reg = CDC_RX_RX0_RX_PATH_CFG0; + break; + case INTERP_HPHR: + hd2_scale_reg = CDC_RX_RX1_RX_PATH_SEC3; + hd2_enable_reg = CDC_RX_RX1_RX_PATH_CFG0; + break; + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_component_update_bits(component, hd2_scale_reg, + CDC_RX_RXn_HD2_ALPHA_MASK, 0x14); + snd_soc_component_write_field(component, hd2_enable_reg, + CDC_RX_RXn_HD2_EN_MASK, 1); + } + + if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_write_field(component, hd2_enable_reg, + CDC_RX_RXn_HD2_EN_MASK, 0); + snd_soc_component_update_bits(component, hd2_scale_reg, + CDC_RX_RXn_HD2_ALPHA_MASK, 0x0); + } +} + static int rx_macro_get_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1649,6 +2224,91 @@ static int rx_macro_set_compander(struct snd_kcontrol *kcontrol, return 0; } +static int rx_macro_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = + rx->rx_port_value[widget->shift]; + return 0; +} + +static int rx_macro_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + u32 rx_port_value = ucontrol->value.integer.value[0]; + u32 aif_rst; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + aif_rst = rx->rx_port_value[widget->shift]; + if (!rx_port_value) { + if (aif_rst == 0) { + dev_err(component->dev, "%s:AIF reset already\n", __func__); + return 0; + } + if (aif_rst > RX_MACRO_AIF4_PB) { + dev_err(component->dev, "%s: Invalid AIF reset\n", __func__); + return 0; + } + } + rx->rx_port_value[widget->shift] = rx_port_value; + + switch (rx_port_value) { + case 0: + if (rx->active_ch_cnt[aif_rst]) { + clear_bit(widget->shift, + &rx->active_ch_mask[aif_rst]); + rx->active_ch_cnt[aif_rst]--; + } + break; + case 1: + case 2: + case 3: + case 4: + set_bit(widget->shift, + &rx->active_ch_mask[rx_port_value]); + rx->active_ch_cnt[rx_port_value]++; + break; + default: + dev_err(component->dev, + "%s:Invalid AIF_ID for RX_MACRO MUX %d\n", + __func__, rx_port_value); + goto err; + } + + snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, + rx_port_value, e, update); + return 0; +err: + return -EINVAL; +} + +static const struct snd_kcontrol_new rx_macro_rx0_mux = + SOC_DAPM_ENUM_EXT("rx_macro_rx0", rx_macro_rx0_enum, + rx_macro_mux_get, rx_macro_mux_put); +static const struct snd_kcontrol_new rx_macro_rx1_mux = + SOC_DAPM_ENUM_EXT("rx_macro_rx1", rx_macro_rx1_enum, + rx_macro_mux_get, rx_macro_mux_put); +static const struct snd_kcontrol_new rx_macro_rx2_mux = + SOC_DAPM_ENUM_EXT("rx_macro_rx2", rx_macro_rx2_enum, + rx_macro_mux_get, rx_macro_mux_put); +static const struct snd_kcontrol_new rx_macro_rx3_mux = + SOC_DAPM_ENUM_EXT("rx_macro_rx3", rx_macro_rx3_enum, + rx_macro_mux_get, rx_macro_mux_put); +static const struct snd_kcontrol_new rx_macro_rx4_mux = + SOC_DAPM_ENUM_EXT("rx_macro_rx4", rx_macro_rx4_enum, + rx_macro_mux_get, rx_macro_mux_put); +static const struct snd_kcontrol_new rx_macro_rx5_mux = + SOC_DAPM_ENUM_EXT("rx_macro_rx5", rx_macro_rx5_enum, + rx_macro_mux_get, rx_macro_mux_put); + static int rx_macro_get_ear_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1753,6 +2413,189 @@ static int rx_macro_aux_hpf_mode_put(struct snd_kcontrol *kcontrol, return 0; } +static int rx_macro_hphdelay_lutbypass(struct snd_soc_component *component, + struct rx_macro *rx, + u16 interp_idx, int event) +{ + u16 hph_lut_bypass_reg; + u16 hph_comp_ctrl7; + + switch (interp_idx) { + case INTERP_HPHL: + hph_lut_bypass_reg = CDC_RX_TOP_HPHL_COMP_LUT; + hph_comp_ctrl7 = CDC_RX_COMPANDER0_CTL7; + break; + case INTERP_HPHR: + hph_lut_bypass_reg = CDC_RX_TOP_HPHR_COMP_LUT; + hph_comp_ctrl7 = CDC_RX_COMPANDER1_CTL7; + break; + default: + return -EINVAL; + } + + if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) { + if (interp_idx == INTERP_HPHL) { + if (rx->is_ear_mode_on) + snd_soc_component_write_field(component, + CDC_RX_RX0_RX_PATH_CFG1, + CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x1); + else + snd_soc_component_write_field(component, + hph_lut_bypass_reg, + CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 1); + } else { + snd_soc_component_write_field(component, hph_lut_bypass_reg, + CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 1); + } + if (rx->hph_pwr_mode) + snd_soc_component_write_field(component, hph_comp_ctrl7, + CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK, 0x0); + } + + if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) { + snd_soc_component_write_field(component, + CDC_RX_RX0_RX_PATH_CFG1, + CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x0); + snd_soc_component_update_bits(component, hph_lut_bypass_reg, + CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 0); + snd_soc_component_write_field(component, hph_comp_ctrl7, + CDC_RX_COMPANDER1_HPH_LOW_PWR_MODE_MASK, 0x1); + } + + return 0; +} + +static int rx_macro_enable_interp_clk(struct snd_soc_component *component, + int event, int interp_idx) +{ + u16 main_reg, dsm_reg, rx_cfg2_reg; + struct rx_macro *rx = snd_soc_component_get_drvdata(component); + + main_reg = CDC_RX_RXn_RX_PATH_CTL(interp_idx); + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(interp_idx); + if (interp_idx == INTERP_AUX) + dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL; + rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(interp_idx); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + if (rx->main_clk_users[interp_idx] == 0) { + /* Main path PGA mute enable */ + snd_soc_component_write_field(component, main_reg, + CDC_RX_PATH_PGA_MUTE_MASK, 0x1); + snd_soc_component_write_field(component, dsm_reg, + CDC_RX_RXn_DSM_CLK_EN_MASK, 0x1); + snd_soc_component_update_bits(component, rx_cfg2_reg, + CDC_RX_RXn_HPF_CUT_FREQ_MASK, 0x03); + rx_macro_load_compander_coeff(component, rx, interp_idx, event); + if (rx->hph_hd2_mode) + rx_macro_hd2_control(component, interp_idx, event); + rx_macro_hphdelay_lutbypass(component, rx, interp_idx, event); + rx_macro_config_compander(component, rx, interp_idx, event); + if (interp_idx == INTERP_AUX) { + rx_macro_config_softclip(component, rx, event); + rx_macro_config_aux_hpf(component, rx, event); + } + rx_macro_config_classh(component, rx, interp_idx, event); + } + rx->main_clk_users[interp_idx]++; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + rx->main_clk_users[interp_idx]--; + if (rx->main_clk_users[interp_idx] <= 0) { + rx->main_clk_users[interp_idx] = 0; + /* Main path PGA mute enable */ + snd_soc_component_write_field(component, main_reg, + CDC_RX_PATH_PGA_MUTE_MASK, 0x1); + /* Clk Disable */ + snd_soc_component_write_field(component, dsm_reg, + CDC_RX_RXn_DSM_CLK_EN_MASK, 0); + snd_soc_component_write_field(component, main_reg, + CDC_RX_PATH_CLK_EN_MASK, 0); + /* Reset enable and disable */ + snd_soc_component_write_field(component, main_reg, + CDC_RX_PATH_RESET_EN_MASK, 1); + snd_soc_component_write_field(component, main_reg, + CDC_RX_PATH_RESET_EN_MASK, 0); + /* Reset rate to 48K*/ + snd_soc_component_update_bits(component, main_reg, + CDC_RX_PATH_PCM_RATE_MASK, + 0x04); + snd_soc_component_update_bits(component, rx_cfg2_reg, + CDC_RX_RXn_HPF_CUT_FREQ_MASK, 0x00); + rx_macro_config_classh(component, rx, interp_idx, event); + rx_macro_config_compander(component, rx, interp_idx, event); + if (interp_idx == INTERP_AUX) { + rx_macro_config_softclip(component, rx, event); + rx_macro_config_aux_hpf(component, rx, event); + } + rx_macro_hphdelay_lutbypass(component, rx, interp_idx, event); + if (rx->hph_hd2_mode) + rx_macro_hd2_control(component, interp_idx, event); + } + } + + return rx->main_clk_users[interp_idx]; +} + +static int rx_macro_enable_mix_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 gain_reg, mix_reg; + + gain_reg = CDC_RX_RXn_RX_VOL_MIX_CTL(w->shift); + mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(w->shift); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + rx_macro_enable_interp_clk(component, event, w->shift); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_write(component, gain_reg, + snd_soc_component_read(component, gain_reg)); + break; + case SND_SOC_DAPM_POST_PMD: + /* Clk Disable */ + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_RXn_MIX_CLK_EN_MASK, 0x00); + rx_macro_enable_interp_clk(component, event, w->shift); + /* Reset enable and disable */ + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_RXn_MIX_RESET_MASK, + CDC_RX_RXn_MIX_RESET); + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_RXn_MIX_RESET_MASK, 0x00); + break; + } + + return 0; +} + +static int rx_macro_enable_rx_path_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + rx_macro_enable_interp_clk(component, event, w->shift); + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift), + CDC_RX_RXn_SIDETONE_EN_MASK, 1); + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CTL(w->shift), + CDC_RX_PATH_CLK_EN_MASK, 1); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift), + CDC_RX_RXn_SIDETONE_EN_MASK, 0); + rx_macro_enable_interp_clk(component, event, w->shift); + break; + default: + break; + }; + return 0; +} + static const struct snd_kcontrol_new rx_macro_snd_controls[] = { SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, -84, 40, digital_gain), @@ -1789,6 +2632,500 @@ static const struct snd_kcontrol_new rx_macro_snd_controls[] = { rx_macro_aux_hpf_mode_put), }; +static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u16 val, ec_hq_reg; + int ec_tx; + + val = snd_soc_component_read(component, + CDC_RX_INP_MUX_RX_MIX_CFG4); + if (!(strcmp(w->name, "RX MIX TX0 MUX"))) + ec_tx = ((val & 0xf0) >> 0x4) - 1; + else if (!(strcmp(w->name, "RX MIX TX1 MUX"))) + ec_tx = (val & 0x0f) - 1; + + val = snd_soc_component_read(component, + CDC_RX_INP_MUX_RX_MIX_CFG5); + if (!(strcmp(w->name, "RX MIX TX2 MUX"))) + ec_tx = (val & 0x0f) - 1; + + if (ec_tx < 0 || (ec_tx >= RX_MACRO_EC_MUX_MAX)) { + dev_err(component->dev, "%s: EC mix control not set correctly\n", + __func__); + return -EINVAL; + } + ec_hq_reg = CDC_RX_EC_REF_HQ0_EC_REF_HQ_PATH_CTL + + 0x40 * ec_tx; + snd_soc_component_update_bits(component, ec_hq_reg, 0x01, 0x01); + ec_hq_reg = CDC_RX_EC_REF_HQ0_EC_REF_HQ_CFG0 + + 0x40 * ec_tx; + /* default set to 48k */ + snd_soc_component_update_bits(component, ec_hq_reg, 0x1E, 0x08); + + return 0; +} + +static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("RX AIF1 PB", "RX_MACRO_AIF1 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF2 PB", "RX_MACRO_AIF2 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF3 PB", "RX_MACRO_AIF3 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("RX AIF4 PB", "RX_MACRO_AIF4 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MUX("RX_MACRO RX0 MUX", SND_SOC_NOPM, RX_MACRO_RX0, 0, + &rx_macro_rx0_mux), + SND_SOC_DAPM_MUX("RX_MACRO RX1 MUX", SND_SOC_NOPM, RX_MACRO_RX1, 0, + &rx_macro_rx1_mux), + SND_SOC_DAPM_MUX("RX_MACRO RX2 MUX", SND_SOC_NOPM, RX_MACRO_RX2, 0, + &rx_macro_rx2_mux), + SND_SOC_DAPM_MUX("RX_MACRO RX3 MUX", SND_SOC_NOPM, RX_MACRO_RX3, 0, + &rx_macro_rx3_mux), + SND_SOC_DAPM_MUX("RX_MACRO RX4 MUX", SND_SOC_NOPM, RX_MACRO_RX4, 0, + &rx_macro_rx4_mux), + SND_SOC_DAPM_MUX("RX_MACRO RX5 MUX", SND_SOC_NOPM, RX_MACRO_RX5, 0, + &rx_macro_rx5_mux), + + SND_SOC_DAPM_MIXER("RX_RX0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX3", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX4", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX_RX5", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("IIR0 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp0_mux), + SND_SOC_DAPM_MUX("IIR0 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp1_mux), + SND_SOC_DAPM_MUX("IIR0 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp2_mux), + SND_SOC_DAPM_MUX("IIR0 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp3_mux), + SND_SOC_DAPM_MUX("IIR1 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp0_mux), + SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux), + SND_SOC_DAPM_MUX("IIR1 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp2_mux), + SND_SOC_DAPM_MUX("IIR1 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp3_mux), + + SND_SOC_DAPM_MUX_E("RX MIX TX0 MUX", SND_SOC_NOPM, + RX_MACRO_EC0_MUX, 0, + &rx_mix_tx0_mux, rx_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX MIX TX1 MUX", SND_SOC_NOPM, + RX_MACRO_EC1_MUX, 0, + &rx_mix_tx1_mux, rx_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX MIX TX2 MUX", SND_SOC_NOPM, + RX_MACRO_EC2_MUX, 0, + &rx_mix_tx2_mux, rx_macro_enable_echo, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIXER("SRC0", CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, + 4, 0, NULL, 0), + SND_SOC_DAPM_MIXER("SRC1", CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, + 4, 0, NULL, 0), + + SND_SOC_DAPM_MUX("RX INT0 DEM MUX", SND_SOC_NOPM, 0, 0, + &rx_int0_dem_inp_mux), + SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, + &rx_int1_dem_inp_mux), + + SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0, + &rx_int0_2_mux, rx_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0, + &rx_int1_2_mux, rx_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_AUX, 0, + &rx_int2_2_mux, rx_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp0_mux), + SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp1_mux), + SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int0_1_mix_inp2_mux), + SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp0_mux), + SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp1_mux), + SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int1_1_mix_inp2_mux), + SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP0", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp0_mux), + SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP1", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp1_mux), + SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP2", SND_SOC_NOPM, 0, 0, &rx_int2_1_mix_inp2_mux), + + SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0, + &rx_int0_1_interp_mux, rx_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0, + &rx_int1_1_interp_mux, rx_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_AUX, 0, + &rx_int2_1_interp_mux, rx_macro_enable_main_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("RX INT0_2 INTERP", SND_SOC_NOPM, 0, 0, + &rx_int0_2_interp_mux), + SND_SOC_DAPM_MUX("RX INT1_2 INTERP", SND_SOC_NOPM, 0, 0, + &rx_int1_2_interp_mux), + SND_SOC_DAPM_MUX("RX INT2_2 INTERP", SND_SOC_NOPM, 0, 0, + &rx_int2_2_interp_mux), + + SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL, + 0, &rx_int0_mix2_inp_mux, rx_macro_enable_rx_path_clk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR, + 0, &rx_int1_mix2_inp_mux, rx_macro_enable_rx_path_clk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_AUX, + 0, &rx_int2_mix2_inp_mux, rx_macro_enable_rx_path_clk, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("HPHL_OUT"), + SND_SOC_DAPM_OUTPUT("HPHR_OUT"), + SND_SOC_DAPM_OUTPUT("AUX_OUT"), + + SND_SOC_DAPM_INPUT("RX_TX DEC0_INP"), + SND_SOC_DAPM_INPUT("RX_TX DEC1_INP"), + SND_SOC_DAPM_INPUT("RX_TX DEC2_INP"), + SND_SOC_DAPM_INPUT("RX_TX DEC3_INP"), + + SND_SOC_DAPM_SUPPLY_S("RX_MCLK", 0, SND_SOC_NOPM, 0, 0, + rx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route rx_audio_map[] = { + {"RX AIF1 PB", NULL, "RX_MCLK"}, + {"RX AIF2 PB", NULL, "RX_MCLK"}, + {"RX AIF3 PB", NULL, "RX_MCLK"}, + {"RX AIF4 PB", NULL, "RX_MCLK"}, + + {"RX_MACRO RX0 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX1 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX2 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX3 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX4 MUX", "AIF1_PB", "RX AIF1 PB"}, + {"RX_MACRO RX5 MUX", "AIF1_PB", "RX AIF1 PB"}, + + {"RX_MACRO RX0 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX1 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX2 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX3 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX4 MUX", "AIF2_PB", "RX AIF2 PB"}, + {"RX_MACRO RX5 MUX", "AIF2_PB", "RX AIF2 PB"}, + + {"RX_MACRO RX0 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX1 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX2 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX3 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX4 MUX", "AIF3_PB", "RX AIF3 PB"}, + {"RX_MACRO RX5 MUX", "AIF3_PB", "RX AIF3 PB"}, + + {"RX_MACRO RX0 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX1 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX2 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX3 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX4 MUX", "AIF4_PB", "RX AIF4 PB"}, + {"RX_MACRO RX5 MUX", "AIF4_PB", "RX AIF4 PB"}, + + {"RX_RX0", NULL, "RX_MACRO RX0 MUX"}, + {"RX_RX1", NULL, "RX_MACRO RX1 MUX"}, + {"RX_RX2", NULL, "RX_MACRO RX2 MUX"}, + {"RX_RX3", NULL, "RX_MACRO RX3 MUX"}, + {"RX_RX4", NULL, "RX_MACRO RX4 MUX"}, + {"RX_RX5", NULL, "RX_MACRO RX5 MUX"}, + + {"RX INT0_1 MIX1 INP0", "RX0", "RX_RX0"}, + {"RX INT0_1 MIX1 INP0", "RX1", "RX_RX1"}, + {"RX INT0_1 MIX1 INP0", "RX2", "RX_RX2"}, + {"RX INT0_1 MIX1 INP0", "RX3", "RX_RX3"}, + {"RX INT0_1 MIX1 INP0", "RX4", "RX_RX4"}, + {"RX INT0_1 MIX1 INP0", "RX5", "RX_RX5"}, + {"RX INT0_1 MIX1 INP0", "IIR0", "IIR0"}, + {"RX INT0_1 MIX1 INP0", "IIR1", "IIR1"}, + {"RX INT0_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT0_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT0_1 MIX1 INP1", "RX0", "RX_RX0"}, + {"RX INT0_1 MIX1 INP1", "RX1", "RX_RX1"}, + {"RX INT0_1 MIX1 INP1", "RX2", "RX_RX2"}, + {"RX INT0_1 MIX1 INP1", "RX3", "RX_RX3"}, + {"RX INT0_1 MIX1 INP1", "RX4", "RX_RX4"}, + {"RX INT0_1 MIX1 INP1", "RX5", "RX_RX5"}, + {"RX INT0_1 MIX1 INP1", "IIR0", "IIR0"}, + {"RX INT0_1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX INT0_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT0_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT0_1 MIX1 INP2", "RX0", "RX_RX0"}, + {"RX INT0_1 MIX1 INP2", "RX1", "RX_RX1"}, + {"RX INT0_1 MIX1 INP2", "RX2", "RX_RX2"}, + {"RX INT0_1 MIX1 INP2", "RX3", "RX_RX3"}, + {"RX INT0_1 MIX1 INP2", "RX4", "RX_RX4"}, + {"RX INT0_1 MIX1 INP2", "RX5", "RX_RX5"}, + {"RX INT0_1 MIX1 INP2", "IIR0", "IIR0"}, + {"RX INT0_1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX INT0_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT0_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"}, + + {"RX INT1_1 MIX1 INP0", "RX0", "RX_RX0"}, + {"RX INT1_1 MIX1 INP0", "RX1", "RX_RX1"}, + {"RX INT1_1 MIX1 INP0", "RX2", "RX_RX2"}, + {"RX INT1_1 MIX1 INP0", "RX3", "RX_RX3"}, + {"RX INT1_1 MIX1 INP0", "RX4", "RX_RX4"}, + {"RX INT1_1 MIX1 INP0", "RX5", "RX_RX5"}, + {"RX INT1_1 MIX1 INP0", "IIR0", "IIR0"}, + {"RX INT1_1 MIX1 INP0", "IIR1", "IIR1"}, + {"RX INT1_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT1_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT1_1 MIX1 INP1", "RX0", "RX_RX0"}, + {"RX INT1_1 MIX1 INP1", "RX1", "RX_RX1"}, + {"RX INT1_1 MIX1 INP1", "RX2", "RX_RX2"}, + {"RX INT1_1 MIX1 INP1", "RX3", "RX_RX3"}, + {"RX INT1_1 MIX1 INP1", "RX4", "RX_RX4"}, + {"RX INT1_1 MIX1 INP1", "RX5", "RX_RX5"}, + {"RX INT1_1 MIX1 INP1", "IIR0", "IIR0"}, + {"RX INT1_1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX INT1_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT1_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT1_1 MIX1 INP2", "RX0", "RX_RX0"}, + {"RX INT1_1 MIX1 INP2", "RX1", "RX_RX1"}, + {"RX INT1_1 MIX1 INP2", "RX2", "RX_RX2"}, + {"RX INT1_1 MIX1 INP2", "RX3", "RX_RX3"}, + {"RX INT1_1 MIX1 INP2", "RX4", "RX_RX4"}, + {"RX INT1_1 MIX1 INP2", "RX5", "RX_RX5"}, + {"RX INT1_1 MIX1 INP2", "IIR0", "IIR0"}, + {"RX INT1_1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX INT1_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT1_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"}, + + {"RX INT2_1 MIX1 INP0", "RX0", "RX_RX0"}, + {"RX INT2_1 MIX1 INP0", "RX1", "RX_RX1"}, + {"RX INT2_1 MIX1 INP0", "RX2", "RX_RX2"}, + {"RX INT2_1 MIX1 INP0", "RX3", "RX_RX3"}, + {"RX INT2_1 MIX1 INP0", "RX4", "RX_RX4"}, + {"RX INT2_1 MIX1 INP0", "RX5", "RX_RX5"}, + {"RX INT2_1 MIX1 INP0", "IIR0", "IIR0"}, + {"RX INT2_1 MIX1 INP0", "IIR1", "IIR1"}, + {"RX INT2_1 MIX1 INP0", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT2_1 MIX1 INP0", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT2_1 MIX1 INP1", "RX0", "RX_RX0"}, + {"RX INT2_1 MIX1 INP1", "RX1", "RX_RX1"}, + {"RX INT2_1 MIX1 INP1", "RX2", "RX_RX2"}, + {"RX INT2_1 MIX1 INP1", "RX3", "RX_RX3"}, + {"RX INT2_1 MIX1 INP1", "RX4", "RX_RX4"}, + {"RX INT2_1 MIX1 INP1", "RX5", "RX_RX5"}, + {"RX INT2_1 MIX1 INP1", "IIR0", "IIR0"}, + {"RX INT2_1 MIX1 INP1", "IIR1", "IIR1"}, + {"RX INT2_1 MIX1 INP1", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT2_1 MIX1 INP1", "DEC1", "RX_TX DEC1_INP"}, + {"RX INT2_1 MIX1 INP2", "RX0", "RX_RX0"}, + {"RX INT2_1 MIX1 INP2", "RX1", "RX_RX1"}, + {"RX INT2_1 MIX1 INP2", "RX2", "RX_RX2"}, + {"RX INT2_1 MIX1 INP2", "RX3", "RX_RX3"}, + {"RX INT2_1 MIX1 INP2", "RX4", "RX_RX4"}, + {"RX INT2_1 MIX1 INP2", "RX5", "RX_RX5"}, + {"RX INT2_1 MIX1 INP2", "IIR0", "IIR0"}, + {"RX INT2_1 MIX1 INP2", "IIR1", "IIR1"}, + {"RX INT2_1 MIX1 INP2", "DEC0", "RX_TX DEC0_INP"}, + {"RX INT2_1 MIX1 INP2", "DEC1", "RX_TX DEC1_INP"}, + + {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP0"}, + {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP1"}, + {"RX INT0_1 MIX1", NULL, "RX INT0_1 MIX1 INP2"}, + {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP0"}, + {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP1"}, + {"RX INT1_1 MIX1", NULL, "RX INT1_1 MIX1 INP2"}, + {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP0"}, + {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP1"}, + {"RX INT2_1 MIX1", NULL, "RX INT2_1 MIX1 INP2"}, + + {"RX MIX TX0 MUX", "RX_MIX0", "RX INT0 SEC MIX"}, + {"RX MIX TX0 MUX", "RX_MIX1", "RX INT1 SEC MIX"}, + {"RX MIX TX0 MUX", "RX_MIX2", "RX INT2 SEC MIX"}, + {"RX MIX TX1 MUX", "RX_MIX0", "RX INT0 SEC MIX"}, + {"RX MIX TX1 MUX", "RX_MIX1", "RX INT1 SEC MIX"}, + {"RX MIX TX1 MUX", "RX_MIX2", "RX INT2 SEC MIX"}, + {"RX MIX TX2 MUX", "RX_MIX0", "RX INT0 SEC MIX"}, + {"RX MIX TX2 MUX", "RX_MIX1", "RX INT1 SEC MIX"}, + {"RX MIX TX2 MUX", "RX_MIX2", "RX INT2 SEC MIX"}, + {"RX AIF_ECHO", NULL, "RX MIX TX0 MUX"}, + {"RX AIF_ECHO", NULL, "RX MIX TX1 MUX"}, + {"RX AIF_ECHO", NULL, "RX MIX TX2 MUX"}, + {"RX AIF_ECHO", NULL, "RX_MCLK"}, + + /* Mixing path INT0 */ + {"RX INT0_2 MUX", "RX0", "RX_RX0"}, + {"RX INT0_2 MUX", "RX1", "RX_RX1"}, + {"RX INT0_2 MUX", "RX2", "RX_RX2"}, + {"RX INT0_2 MUX", "RX3", "RX_RX3"}, + {"RX INT0_2 MUX", "RX4", "RX_RX4"}, + {"RX INT0_2 MUX", "RX5", "RX_RX5"}, + {"RX INT0_2 INTERP", NULL, "RX INT0_2 MUX"}, + {"RX INT0 SEC MIX", NULL, "RX INT0_2 INTERP"}, + + /* Mixing path INT1 */ + {"RX INT1_2 MUX", "RX0", "RX_RX0"}, + {"RX INT1_2 MUX", "RX1", "RX_RX1"}, + {"RX INT1_2 MUX", "RX2", "RX_RX2"}, + {"RX INT1_2 MUX", "RX3", "RX_RX3"}, + {"RX INT1_2 MUX", "RX4", "RX_RX4"}, + {"RX INT1_2 MUX", "RX5", "RX_RX5"}, + {"RX INT1_2 INTERP", NULL, "RX INT1_2 MUX"}, + {"RX INT1 SEC MIX", NULL, "RX INT1_2 INTERP"}, + + /* Mixing path INT2 */ + {"RX INT2_2 MUX", "RX0", "RX_RX0"}, + {"RX INT2_2 MUX", "RX1", "RX_RX1"}, + {"RX INT2_2 MUX", "RX2", "RX_RX2"}, + {"RX INT2_2 MUX", "RX3", "RX_RX3"}, + {"RX INT2_2 MUX", "RX4", "RX_RX4"}, + {"RX INT2_2 MUX", "RX5", "RX_RX5"}, + {"RX INT2_2 INTERP", NULL, "RX INT2_2 MUX"}, + {"RX INT2 SEC MIX", NULL, "RX INT2_2 INTERP"}, + + {"RX INT0_1 INTERP", NULL, "RX INT0_1 MIX1"}, + {"RX INT0 SEC MIX", NULL, "RX INT0_1 INTERP"}, + {"RX INT0 MIX2", NULL, "RX INT0 SEC MIX"}, + {"RX INT0 MIX2", NULL, "RX INT0 MIX2 INP"}, + {"RX INT0 DEM MUX", "CLSH_DSM_OUT", "RX INT0 MIX2"}, + {"HPHL_OUT", NULL, "RX INT0 DEM MUX"}, + {"HPHL_OUT", NULL, "RX_MCLK"}, + + {"RX INT1_1 INTERP", NULL, "RX INT1_1 MIX1"}, + {"RX INT1 SEC MIX", NULL, "RX INT1_1 INTERP"}, + {"RX INT1 MIX2", NULL, "RX INT1 SEC MIX"}, + {"RX INT1 MIX2", NULL, "RX INT1 MIX2 INP"}, + {"RX INT1 DEM MUX", "CLSH_DSM_OUT", "RX INT1 MIX2"}, + {"HPHR_OUT", NULL, "RX INT1 DEM MUX"}, + {"HPHR_OUT", NULL, "RX_MCLK"}, + + {"RX INT2_1 INTERP", NULL, "RX INT2_1 MIX1"}, + + {"RX INT2 SEC MIX", NULL, "RX INT2_1 INTERP"}, + {"RX INT2 MIX2", NULL, "RX INT2 SEC MIX"}, + {"RX INT2 MIX2", NULL, "RX INT2 MIX2 INP"}, + {"AUX_OUT", NULL, "RX INT2 MIX2"}, + {"AUX_OUT", NULL, "RX_MCLK"}, + + {"IIR0", NULL, "RX_MCLK"}, + {"IIR0", NULL, "IIR0 INP0 MUX"}, + {"IIR0 INP0 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP0 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP0 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP0 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP0 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP0 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP0 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP0 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP0 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP0 MUX", "RX5", "RX_RX5"}, + {"IIR0", NULL, "IIR0 INP1 MUX"}, + {"IIR0 INP1 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP1 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP1 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP1 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP1 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP1 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP1 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP1 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP1 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP1 MUX", "RX5", "RX_RX5"}, + {"IIR0", NULL, "IIR0 INP2 MUX"}, + {"IIR0 INP2 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP2 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP2 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP2 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP2 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP2 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP2 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP2 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP2 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP2 MUX", "RX5", "RX_RX5"}, + {"IIR0", NULL, "IIR0 INP3 MUX"}, + {"IIR0 INP3 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR0 INP3 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR0 INP3 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR0 INP3 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR0 INP3 MUX", "RX0", "RX_RX0"}, + {"IIR0 INP3 MUX", "RX1", "RX_RX1"}, + {"IIR0 INP3 MUX", "RX2", "RX_RX2"}, + {"IIR0 INP3 MUX", "RX3", "RX_RX3"}, + {"IIR0 INP3 MUX", "RX4", "RX_RX4"}, + {"IIR0 INP3 MUX", "RX5", "RX_RX5"}, + + {"IIR1", NULL, "RX_MCLK"}, + {"IIR1", NULL, "IIR1 INP0 MUX"}, + {"IIR1 INP0 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP0 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP0 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP0 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP0 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP0 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP0 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP0 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP0 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP0 MUX", "RX5", "RX_RX5"}, + {"IIR1", NULL, "IIR1 INP1 MUX"}, + {"IIR1 INP1 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP1 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP1 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP1 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP1 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP1 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP1 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP1 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP1 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP1 MUX", "RX5", "RX_RX5"}, + {"IIR1", NULL, "IIR1 INP2 MUX"}, + {"IIR1 INP2 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP2 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP2 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP2 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP2 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP2 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP2 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP2 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP2 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP2 MUX", "RX5", "RX_RX5"}, + {"IIR1", NULL, "IIR1 INP3 MUX"}, + {"IIR1 INP3 MUX", "DEC0", "RX_TX DEC0_INP"}, + {"IIR1 INP3 MUX", "DEC1", "RX_TX DEC1_INP"}, + {"IIR1 INP3 MUX", "DEC2", "RX_TX DEC2_INP"}, + {"IIR1 INP3 MUX", "DEC3", "RX_TX DEC3_INP"}, + {"IIR1 INP3 MUX", "RX0", "RX_RX0"}, + {"IIR1 INP3 MUX", "RX1", "RX_RX1"}, + {"IIR1 INP3 MUX", "RX2", "RX_RX2"}, + {"IIR1 INP3 MUX", "RX3", "RX_RX3"}, + {"IIR1 INP3 MUX", "RX4", "RX_RX4"}, + {"IIR1 INP3 MUX", "RX5", "RX_RX5"}, + + {"SRC0", NULL, "IIR0"}, + {"SRC1", NULL, "IIR1"}, + {"RX INT0 MIX2 INP", "SRC0", "SRC0"}, + {"RX INT0 MIX2 INP", "SRC1", "SRC1"}, + {"RX INT1 MIX2 INP", "SRC0", "SRC0"}, + {"RX INT1 MIX2 INP", "SRC1", "SRC1"}, + {"RX INT2 MIX2 INP", "SRC0", "SRC0"}, + {"RX INT2 MIX2 INP", "SRC1", "SRC1"}, +}; + static int rx_macro_component_probe(struct snd_soc_component *component) { struct rx_macro *rx = snd_soc_component_get_drvdata(component); @@ -1908,6 +3245,10 @@ static const struct snd_soc_component_driver rx_macro_component_drv = { .probe = rx_macro_component_probe, .controls = rx_macro_snd_controls, .num_controls = ARRAY_SIZE(rx_macro_snd_controls), + .dapm_widgets = rx_macro_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rx_macro_dapm_widgets), + .dapm_routes = rx_audio_map, + .num_dapm_routes = ARRAY_SIZE(rx_audio_map), }; static int rx_macro_probe(struct platform_device *pdev) -- cgit v1.2.3 From f3ce6f3c9a994d3fa5057cadfaa1d883e0d938fa Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:32 +0000 Subject: ASoC: codecs: lpass-rx-macro: add iir widgets This patch adds iir widgets and mixers on this codec Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210211122735.5691-5-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 264 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 2cf6eb9238a7..c9c21d22c2c4 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -525,6 +525,38 @@ enum { INTERP_MIX_PATH, }; +/* Codec supports 2 IIR filters */ +enum { + IIR0 = 0, + IIR1, + IIR_MAX, +}; + +/* Each IIR has 5 Filter Stages */ +enum { + BAND1 = 0, + BAND2, + BAND3, + BAND4, + BAND5, + BAND_MAX, +}; + +#define RX_MACRO_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX) + +#define RX_MACRO_IIR_FILTER_CTL(xname, iidx, bidx) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = rx_macro_iir_filter_info, \ + .get = rx_macro_get_iir_band_audio_mixer, \ + .put = rx_macro_put_iir_band_audio_mixer, \ + .private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \ + .iir_idx = iidx, \ + .band_idx = bidx, \ + .bytes_ext = {.max = RX_MACRO_IIR_FILTER_SIZE, }, \ + } \ +} + struct interp_sample_rate { int sample_rate; int rate_val; @@ -581,6 +613,12 @@ struct rx_macro { }; #define to_rx_macro(_hw) container_of(_hw, struct rx_macro, hw) +struct wcd_iir_filter_ctl { + unsigned int iir_idx; + unsigned int band_idx; + struct soc_bytes_ext bytes_ext; +}; + static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); static const char * const rx_int_mix_mux_text[] = { @@ -2596,6 +2634,166 @@ static int rx_macro_enable_rx_path_clk(struct snd_soc_dapm_widget *w, return 0; } +static int rx_macro_set_iir_gain(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: /* fall through */ + case SND_SOC_DAPM_PRE_PMD: + if (strnstr(w->name, "IIR0", sizeof("IIR0"))) { + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL)); + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL)); + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL)); + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL)); + } else { + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL)); + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL)); + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL)); + snd_soc_component_write(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, + snd_soc_component_read(component, + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL)); + } + break; + } + return 0; +} + +static uint32_t get_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, int coeff_idx) +{ + u32 value; + int reg, b2_reg; + + /* Address does not automatically update if reading */ + reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx; + b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx; + + snd_soc_component_write(component, reg, + ((band_idx * BAND_MAX + coeff_idx) * + sizeof(uint32_t)) & 0x7F); + + value = snd_soc_component_read(component, b2_reg); + snd_soc_component_write(component, reg, + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 1) & 0x7F); + + value |= (snd_soc_component_read(component, b2_reg) << 8); + snd_soc_component_write(component, reg, + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 2) & 0x7F); + + value |= (snd_soc_component_read(component, b2_reg) << 16); + snd_soc_component_write(component, reg, + ((band_idx * BAND_MAX + coeff_idx) + * sizeof(uint32_t) + 3) & 0x7F); + + /* Mask bits top 2 bits since they are reserved */ + value |= (snd_soc_component_read(component, b2_reg) << 24); + return value; +} + +static void set_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, uint32_t value) +{ + int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx; + + snd_soc_component_write(component, reg, (value & 0xFF)); + snd_soc_component_write(component, reg, (value >> 8) & 0xFF); + snd_soc_component_write(component, reg, (value >> 16) & 0xFF); + /* Mask top 2 bits, 7-8 are reserved */ + snd_soc_component_write(component, reg, (value >> 24) & 0x3F); +} + +static int rx_macro_put_iir_band_audio_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd_iir_filter_ctl *ctl = + (struct wcd_iir_filter_ctl *)kcontrol->private_value; + struct soc_bytes_ext *params = &ctl->bytes_ext; + int iir_idx = ctl->iir_idx; + int band_idx = ctl->band_idx; + u32 coeff[BAND_MAX]; + int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx; + + memcpy(&coeff[0], ucontrol->value.bytes.data, params->max); + + /* Mask top bit it is reserved */ + /* Updates addr automatically for each B2 write */ + snd_soc_component_write(component, reg, (band_idx * BAND_MAX * + sizeof(uint32_t)) & 0x7F); + + set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]); + set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]); + + return 0; +} + +static int rx_macro_get_iir_band_audio_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd_iir_filter_ctl *ctl = + (struct wcd_iir_filter_ctl *)kcontrol->private_value; + struct soc_bytes_ext *params = &ctl->bytes_ext; + int iir_idx = ctl->iir_idx; + int band_idx = ctl->band_idx; + u32 coeff[BAND_MAX]; + + coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0); + coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1); + coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2); + coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3); + coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4); + + memcpy(ucontrol->value.bytes.data, &coeff[0], params->max); + + return 0; +} + +static int rx_macro_iir_filter_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *ucontrol) +{ + struct wcd_iir_filter_ctl *ctl = + (struct wcd_iir_filter_ctl *)kcontrol->private_value; + struct soc_bytes_ext *params = &ctl->bytes_ext; + + ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; + ucontrol->count = params->max; + + return 0; +} + static const struct snd_kcontrol_new rx_macro_snd_controls[] = { SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, -84, 40, digital_gain), @@ -2630,6 +2828,65 @@ static const struct snd_kcontrol_new rx_macro_snd_controls[] = { SOC_SINGLE_EXT("AUX_HPF Switch", SND_SOC_NOPM, 0, 1, 0, rx_macro_aux_hpf_mode_get, rx_macro_aux_hpf_mode_put), + + SOC_SINGLE_S8_TLV("IIR0 INP0 Volume", + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR0 INP1 Volume", + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR0 INP2 Volume", + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR0 INP3 Volume", + CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP0 Volume", + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40, + digital_gain), + SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", + CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40, + digital_gain), + + SOC_SINGLE("IIR1 Band1 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL, + 0, 1, 0), + SOC_SINGLE("IIR1 Band2 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL, + 1, 1, 0), + SOC_SINGLE("IIR1 Band3 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL, + 2, 1, 0), + SOC_SINGLE("IIR1 Band4 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL, + 3, 1, 0), + SOC_SINGLE("IIR1 Band5 Switch", CDC_RX_SIDETONE_IIR0_IIR_CTL, + 4, 1, 0), + SOC_SINGLE("IIR2 Band1 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL, + 0, 1, 0), + SOC_SINGLE("IIR2 Band2 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL, + 1, 1, 0), + SOC_SINGLE("IIR2 Band3 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL, + 2, 1, 0), + SOC_SINGLE("IIR2 Band4 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL, + 3, 1, 0), + SOC_SINGLE("IIR2 Band5 Switch", CDC_RX_SIDETONE_IIR1_IIR_CTL, + 4, 1, 0), + + RX_MACRO_IIR_FILTER_CTL("IIR0 Band1", IIR0, BAND1), + RX_MACRO_IIR_FILTER_CTL("IIR0 Band2", IIR0, BAND2), + RX_MACRO_IIR_FILTER_CTL("IIR0 Band3", IIR0, BAND3), + RX_MACRO_IIR_FILTER_CTL("IIR0 Band4", IIR0, BAND4), + RX_MACRO_IIR_FILTER_CTL("IIR0 Band5", IIR0, BAND5), + + RX_MACRO_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1), + RX_MACRO_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2), + RX_MACRO_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3), + RX_MACRO_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4), + RX_MACRO_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5), + }; static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w, @@ -2725,6 +2982,13 @@ static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = { RX_MACRO_EC2_MUX, 0, &rx_mix_tx2_mux, rx_macro_enable_echo, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER_E("IIR0", CDC_RX_SIDETONE_IIR0_IIR_PATH_CTL, + 4, 0, NULL, 0, rx_macro_set_iir_gain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MIXER_E("IIR1", CDC_RX_SIDETONE_IIR1_IIR_PATH_CTL, + 4, 0, NULL, 0, rx_macro_set_iir_gain, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_MIXER("SRC0", CDC_RX_SIDETONE_SRC0_ST_SRC_PATH_CTL, 4, 0, NULL, 0), SND_SOC_DAPM_MIXER("SRC1", CDC_RX_SIDETONE_SRC1_ST_SRC_PATH_CTL, -- cgit v1.2.3 From ca955cc980afc066a380567e371480634e48eb7e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:33 +0000 Subject: ASoC: qcom: dt-bindings: add bindings for lpass tx macro codec This binding is for LPASS has internal codec TX macro which is for connecting with Soundwire TX codecs like WCD938x. Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210211122735.5691-6-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- .../bindings/sound/qcom,lpass-tx-macro.yaml | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml new file mode 100644 index 000000000000..6b5ca02ccce4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,lpass-tx-macro.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LPASS(Low Power Audio Subsystem) TX Macro audio codec DT bindings + +maintainers: + - Srinivas Kandagatla + +properties: + compatible: + const: qcom,sm8250-lpass-tx-macro + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + '#clock-cells': + const: 0 + + clocks: + maxItems: 5 + + clock-names: + items: + - const: mclk + - const: npl + - const: macro + - const: dcodec + - const: fsgen + + clock-output-names: + items: + - const: mclk + + qcom,dmic-sample-rate: + description: dmic sample rate + $ref: /schemas/types.yaml#/definitions/uint32 + +required: + - compatible + - reg + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + #include + codec@3220000 { + compatible = "qcom,sm8250-lpass-tx-macro"; + reg = <0x3220000 0x1000>; + #sound-dai-cells = <1>; + #clock-cells = <0>; + clocks = <&aoncc 0>, + <&aoncc 1>, + <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", "npl", "macro", "dcodec", "fsgen"; + clock-output-names = "mclk"; + qcom,dmic-sample-rate = <600000>; + }; -- cgit v1.2.3 From c39667ddcfc516fee084e449179d54430a558298 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:34 +0000 Subject: ASoC: codecs: lpass-tx-macro: add support for lpass tx macro Qualcomm LPASS (Low Power Audio SubSystem) has internal codec TX macro block which is used for connecting with external Soundwire TX Codecs like WCD938x. This patch adds support to the codec part of the TX Macro block Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210211122735.5691-7-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/lpass-tx-macro.c | 1177 +++++++++++++++++++++++++++++++++++++ 3 files changed, 1184 insertions(+) create mode 100644 sound/soc/codecs/lpass-tx-macro.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 5fb5a5a2c605..e4cf14e66a51 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -229,6 +229,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_WCD9335 imply SND_SOC_WCD934X imply SND_SOC_LPASS_RX_MACRO + imply SND_SOC_LPASS_TX_MACRO imply SND_SOC_WL1273 imply SND_SOC_WM0010 imply SND_SOC_WM1250_EV1 @@ -1838,4 +1839,8 @@ config SND_SOC_LPASS_RX_MACRO depends on COMMON_CLK tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)" +config SND_SOC_LPASS_TX_MACRO + depends on COMMON_CLK + tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)" + endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 004ffcbe0b98..81357dc62ea0 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -108,6 +108,7 @@ snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o snd-soc-lochnagar-sc-objs := lochnagar-sc.o snd-soc-lpass-rx-macro-objs := lpass-rx-macro.o +snd-soc-lpass-tx-macro-objs := lpass-tx-macro.o snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o snd-soc-lpass-va-macro-objs := lpass-va-macro.o snd-soc-madera-objs := madera.o @@ -627,6 +628,7 @@ obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o obj-$(CONFIG_SND_SOC_LPASS_WSA_MACRO) += snd-soc-lpass-wsa-macro.o obj-$(CONFIG_SND_SOC_LPASS_VA_MACRO) += snd-soc-lpass-va-macro.o obj-$(CONFIG_SND_SOC_LPASS_RX_MACRO) += snd-soc-lpass-rx-macro.o +obj-$(CONFIG_SND_SOC_LPASS_TX_MACRO) += snd-soc-lpass-tx-macro.o # Mux obj-$(CONFIG_SND_SOC_SIMPLE_MUX) += snd-soc-simple-mux.o diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c new file mode 100644 index 000000000000..06589dad6bc2 --- /dev/null +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -0,0 +1,1177 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (0x0000) +#define CDC_TX_MCLK_EN_MASK BIT(0) +#define CDC_TX_MCLK_ENABLE BIT(0) +#define CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004) +#define CDC_TX_FS_CNT_EN_MASK BIT(0) +#define CDC_TX_FS_CNT_ENABLE BIT(0) +#define CDC_TX_CLK_RST_CTRL_SWR_CONTROL (0x0008) +#define CDC_TX_SWR_RESET_MASK BIT(1) +#define CDC_TX_SWR_RESET_ENABLE BIT(1) +#define CDC_TX_SWR_CLK_EN_MASK BIT(0) +#define CDC_TX_SWR_CLK_ENABLE BIT(0) +#define CDC_TX_TOP_CSR_TOP_CFG0 (0x0080) +#define CDC_TX_TOP_CSR_ANC_CFG (0x0084) +#define CDC_TX_TOP_CSR_SWR_CTRL (0x0088) +#define CDC_TX_TOP_CSR_FREQ_MCLK (0x0090) +#define CDC_TX_TOP_CSR_DEBUG_BUS (0x0094) +#define CDC_TX_TOP_CSR_DEBUG_EN (0x0098) +#define CDC_TX_TOP_CSR_TX_I2S_CTL (0x00A4) +#define CDC_TX_TOP_CSR_I2S_CLK (0x00A8) +#define CDC_TX_TOP_CSR_I2S_RESET (0x00AC) +#define CDC_TX_TOP_CSR_SWR_DMICn_CTL(n) (0x00C0 + n * 0x4) +#define CDC_TX_TOP_CSR_SWR_DMIC0_CTL (0x00C0) +#define CDC_TX_SWR_DMIC_CLK_SEL_MASK GENMASK(3, 1) +#define CDC_TX_TOP_CSR_SWR_DMIC1_CTL (0x00C4) +#define CDC_TX_TOP_CSR_SWR_DMIC2_CTL (0x00C8) +#define CDC_TX_TOP_CSR_SWR_DMIC3_CTL (0x00CC) +#define CDC_TX_TOP_CSR_SWR_AMIC0_CTL (0x00D0) +#define CDC_TX_TOP_CSR_SWR_AMIC1_CTL (0x00D4) +#define CDC_TX_INP_MUX_ADC_MUXn_CFG0(n) (0x0100 + 0x8 * n) +#define CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK GENMASK(3, 0) +#define CDC_TX_INP_MUX_ADC_MUX0_CFG0 (0x0100) +#define CDC_TX_INP_MUX_ADC_MUXn_CFG1(n) (0x0104 + 0x8 * n) +#define CDC_TX_INP_MUX_ADC_MUX0_CFG1 (0x0104) +#define CDC_TX_INP_MUX_ADC_MUX1_CFG0 (0x0108) +#define CDC_TX_INP_MUX_ADC_MUX1_CFG1 (0x010C) +#define CDC_TX_INP_MUX_ADC_MUX2_CFG0 (0x0110) +#define CDC_TX_INP_MUX_ADC_MUX2_CFG1 (0x0114) +#define CDC_TX_INP_MUX_ADC_MUX3_CFG0 (0x0118) +#define CDC_TX_INP_MUX_ADC_MUX3_CFG1 (0x011C) +#define CDC_TX_INP_MUX_ADC_MUX4_CFG0 (0x0120) +#define CDC_TX_INP_MUX_ADC_MUX4_CFG1 (0x0124) +#define CDC_TX_INP_MUX_ADC_MUX5_CFG0 (0x0128) +#define CDC_TX_INP_MUX_ADC_MUX5_CFG1 (0x012C) +#define CDC_TX_INP_MUX_ADC_MUX6_CFG0 (0x0130) +#define CDC_TX_INP_MUX_ADC_MUX6_CFG1 (0x0134) +#define CDC_TX_INP_MUX_ADC_MUX7_CFG0 (0x0138) +#define CDC_TX_INP_MUX_ADC_MUX7_CFG1 (0x013C) +#define CDC_TX_ANC0_CLK_RESET_CTL (0x0200) +#define CDC_TX_ANC0_MODE_1_CTL (0x0204) +#define CDC_TX_ANC0_MODE_2_CTL (0x0208) +#define CDC_TX_ANC0_FF_SHIFT (0x020C) +#define CDC_TX_ANC0_FB_SHIFT (0x0210) +#define CDC_TX_ANC0_LPF_FF_A_CTL (0x0214) +#define CDC_TX_ANC0_LPF_FF_B_CTL (0x0218) +#define CDC_TX_ANC0_LPF_FB_CTL (0x021C) +#define CDC_TX_ANC0_SMLPF_CTL (0x0220) +#define CDC_TX_ANC0_DCFLT_SHIFT_CTL (0x0224) +#define CDC_TX_ANC0_IIR_ADAPT_CTL (0x0228) +#define CDC_TX_ANC0_IIR_COEFF_1_CTL (0x022C) +#define CDC_TX_ANC0_IIR_COEFF_2_CTL (0x0230) +#define CDC_TX_ANC0_FF_A_GAIN_CTL (0x0234) +#define CDC_TX_ANC0_FF_B_GAIN_CTL (0x0238) +#define CDC_TX_ANC0_FB_GAIN_CTL (0x023C) +#define CDC_TXn_TX_PATH_CTL(n) (0x0400 + 0x80 * n) +#define CDC_TXn_PCM_RATE_MASK GENMASK(3, 0) +#define CDC_TXn_PGA_MUTE_MASK BIT(4) +#define CDC_TXn_CLK_EN_MASK BIT(5) +#define CDC_TX0_TX_PATH_CTL (0x0400) +#define CDC_TXn_TX_PATH_CFG0(n) (0x0404 + 0x80 * n) +#define CDC_TX0_TX_PATH_CFG0 (0x0404) +#define CDC_TXn_PH_EN_MASK BIT(0) +#define CDC_TXn_ADC_MODE_MASK GENMASK(2, 1) +#define CDC_TXn_HPF_CUT_FREQ_MASK GENMASK(6, 5) +#define CDC_TXn_ADC_DMIC_SEL_MASK BIT(7) +#define CDC_TX0_TX_PATH_CFG1 (0x0408) +#define CDC_TXn_TX_VOL_CTL(n) (0x040C + 0x80 * n) +#define CDC_TX0_TX_VOL_CTL (0x040C) +#define CDC_TX0_TX_PATH_SEC0 (0x0410) +#define CDC_TX0_TX_PATH_SEC1 (0x0414) +#define CDC_TXn_TX_PATH_SEC2(n) (0x0418 + 0x80 * n) +#define CDC_TXn_HPF_F_CHANGE_MASK BIT(1) +#define CDC_TXn_HPF_ZERO_GATE_MASK BIT(0) +#define CDC_TX0_TX_PATH_SEC2 (0x0418) +#define CDC_TX0_TX_PATH_SEC3 (0x041C) +#define CDC_TX0_TX_PATH_SEC4 (0x0420) +#define CDC_TX0_TX_PATH_SEC5 (0x0424) +#define CDC_TX0_TX_PATH_SEC6 (0x0428) +#define CDC_TX0_TX_PATH_SEC7 (0x042C) +#define CDC_TX0_MBHC_CTL_EN_MASK BIT(6) +#define CDC_TX1_TX_PATH_CTL (0x0480) +#define CDC_TX1_TX_PATH_CFG0 (0x0484) +#define CDC_TX1_TX_PATH_CFG1 (0x0488) +#define CDC_TX1_TX_VOL_CTL (0x048C) +#define CDC_TX1_TX_PATH_SEC0 (0x0490) +#define CDC_TX1_TX_PATH_SEC1 (0x0494) +#define CDC_TX1_TX_PATH_SEC2 (0x0498) +#define CDC_TX1_TX_PATH_SEC3 (0x049C) +#define CDC_TX1_TX_PATH_SEC4 (0x04A0) +#define CDC_TX1_TX_PATH_SEC5 (0x04A4) +#define CDC_TX1_TX_PATH_SEC6 (0x04A8) +#define CDC_TX2_TX_PATH_CTL (0x0500) +#define CDC_TX2_TX_PATH_CFG0 (0x0504) +#define CDC_TX2_TX_PATH_CFG1 (0x0508) +#define CDC_TX2_TX_VOL_CTL (0x050C) +#define CDC_TX2_TX_PATH_SEC0 (0x0510) +#define CDC_TX2_TX_PATH_SEC1 (0x0514) +#define CDC_TX2_TX_PATH_SEC2 (0x0518) +#define CDC_TX2_TX_PATH_SEC3 (0x051C) +#define CDC_TX2_TX_PATH_SEC4 (0x0520) +#define CDC_TX2_TX_PATH_SEC5 (0x0524) +#define CDC_TX2_TX_PATH_SEC6 (0x0528) +#define CDC_TX3_TX_PATH_CTL (0x0580) +#define CDC_TX3_TX_PATH_CFG0 (0x0584) +#define CDC_TX3_TX_PATH_CFG1 (0x0588) +#define CDC_TX3_TX_VOL_CTL (0x058C) +#define CDC_TX3_TX_PATH_SEC0 (0x0590) +#define CDC_TX3_TX_PATH_SEC1 (0x0594) +#define CDC_TX3_TX_PATH_SEC2 (0x0598) +#define CDC_TX3_TX_PATH_SEC3 (0x059C) +#define CDC_TX3_TX_PATH_SEC4 (0x05A0) +#define CDC_TX3_TX_PATH_SEC5 (0x05A4) +#define CDC_TX3_TX_PATH_SEC6 (0x05A8) +#define CDC_TX4_TX_PATH_CTL (0x0600) +#define CDC_TX4_TX_PATH_CFG0 (0x0604) +#define CDC_TX4_TX_PATH_CFG1 (0x0608) +#define CDC_TX4_TX_VOL_CTL (0x060C) +#define CDC_TX4_TX_PATH_SEC0 (0x0610) +#define CDC_TX4_TX_PATH_SEC1 (0x0614) +#define CDC_TX4_TX_PATH_SEC2 (0x0618) +#define CDC_TX4_TX_PATH_SEC3 (0x061C) +#define CDC_TX4_TX_PATH_SEC4 (0x0620) +#define CDC_TX4_TX_PATH_SEC5 (0x0624) +#define CDC_TX4_TX_PATH_SEC6 (0x0628) +#define CDC_TX5_TX_PATH_CTL (0x0680) +#define CDC_TX5_TX_PATH_CFG0 (0x0684) +#define CDC_TX5_TX_PATH_CFG1 (0x0688) +#define CDC_TX5_TX_VOL_CTL (0x068C) +#define CDC_TX5_TX_PATH_SEC0 (0x0690) +#define CDC_TX5_TX_PATH_SEC1 (0x0694) +#define CDC_TX5_TX_PATH_SEC2 (0x0698) +#define CDC_TX5_TX_PATH_SEC3 (0x069C) +#define CDC_TX5_TX_PATH_SEC4 (0x06A0) +#define CDC_TX5_TX_PATH_SEC5 (0x06A4) +#define CDC_TX5_TX_PATH_SEC6 (0x06A8) +#define CDC_TX6_TX_PATH_CTL (0x0700) +#define CDC_TX6_TX_PATH_CFG0 (0x0704) +#define CDC_TX6_TX_PATH_CFG1 (0x0708) +#define CDC_TX6_TX_VOL_CTL (0x070C) +#define CDC_TX6_TX_PATH_SEC0 (0x0710) +#define CDC_TX6_TX_PATH_SEC1 (0x0714) +#define CDC_TX6_TX_PATH_SEC2 (0x0718) +#define CDC_TX6_TX_PATH_SEC3 (0x071C) +#define CDC_TX6_TX_PATH_SEC4 (0x0720) +#define CDC_TX6_TX_PATH_SEC5 (0x0724) +#define CDC_TX6_TX_PATH_SEC6 (0x0728) +#define CDC_TX7_TX_PATH_CTL (0x0780) +#define CDC_TX7_TX_PATH_CFG0 (0x0784) +#define CDC_TX7_TX_PATH_CFG1 (0x0788) +#define CDC_TX7_TX_VOL_CTL (0x078C) +#define CDC_TX7_TX_PATH_SEC0 (0x0790) +#define CDC_TX7_TX_PATH_SEC1 (0x0794) +#define CDC_TX7_TX_PATH_SEC2 (0x0798) +#define CDC_TX7_TX_PATH_SEC3 (0x079C) +#define CDC_TX7_TX_PATH_SEC4 (0x07A0) +#define CDC_TX7_TX_PATH_SEC5 (0x07A4) +#define CDC_TX7_TX_PATH_SEC6 (0x07A8) +#define TX_MAX_OFFSET (0x07A8) + +#define TX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) +#define TX_MACRO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_3LE) + +#define CF_MIN_3DB_4HZ 0x0 +#define CF_MIN_3DB_75HZ 0x1 +#define CF_MIN_3DB_150HZ 0x2 +#define TX_ADC_MAX 5 +#define TX_ADC_TO_DMIC(n) ((n - TX_ADC_MAX)/2) +#define NUM_DECIMATORS 8 +#define TX_NUM_CLKS_MAX 5 +#define TX_MACRO_DMIC_UNMUTE_DELAY_MS 40 +#define TX_MACRO_AMIC_UNMUTE_DELAY_MS 100 +#define TX_MACRO_DMIC_HPF_DELAY_MS 300 +#define TX_MACRO_AMIC_HPF_DELAY_MS 300 +#define MCLK_FREQ 9600000 + +enum { + TX_MACRO_AIF_INVALID = 0, + TX_MACRO_AIF1_CAP, + TX_MACRO_AIF2_CAP, + TX_MACRO_AIF3_CAP, + TX_MACRO_MAX_DAIS +}; + +enum { + TX_MACRO_DEC0, + TX_MACRO_DEC1, + TX_MACRO_DEC2, + TX_MACRO_DEC3, + TX_MACRO_DEC4, + TX_MACRO_DEC5, + TX_MACRO_DEC6, + TX_MACRO_DEC7, + TX_MACRO_DEC_MAX, +}; + +enum { + TX_MACRO_CLK_DIV_2, + TX_MACRO_CLK_DIV_3, + TX_MACRO_CLK_DIV_4, + TX_MACRO_CLK_DIV_6, + TX_MACRO_CLK_DIV_8, + TX_MACRO_CLK_DIV_16, +}; + +enum { + MSM_DMIC, + SWR_MIC, + ANC_FB_TUNE1 +}; + +struct tx_mute_work { + struct tx_macro *tx; + u32 decimator; + struct delayed_work dwork; +}; + +struct hpf_work { + struct tx_macro *tx; + u8 decimator; + u8 hpf_cut_off_freq; + struct delayed_work dwork; +}; + +struct tx_macro { + struct device *dev; + struct snd_soc_component *component; + struct hpf_work tx_hpf_work[NUM_DECIMATORS]; + struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS]; + unsigned long active_ch_mask[TX_MACRO_MAX_DAIS]; + unsigned long active_ch_cnt[TX_MACRO_MAX_DAIS]; + unsigned long active_decimator[TX_MACRO_MAX_DAIS]; + struct regmap *regmap; + struct clk_bulk_data clks[TX_NUM_CLKS_MAX]; + struct clk_hw hw; + bool dec_active[NUM_DECIMATORS]; + bool reset_swr; + int tx_mclk_users; + u16 dmic_clk_div; + bool bcs_enable; + int dec_mode[NUM_DECIMATORS]; + bool bcs_clk_en; +}; +#define to_tx_macro(_hw) container_of(_hw, struct tx_macro, hw) + +static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); + +static const struct reg_default tx_defaults[] = { + /* TX Macro */ + { CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x00 }, + { CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00 }, + { CDC_TX_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { CDC_TX_TOP_CSR_TOP_CFG0, 0x00}, + { CDC_TX_TOP_CSR_ANC_CFG, 0x00}, + { CDC_TX_TOP_CSR_SWR_CTRL, 0x00}, + { CDC_TX_TOP_CSR_FREQ_MCLK, 0x00}, + { CDC_TX_TOP_CSR_DEBUG_BUS, 0x00}, + { CDC_TX_TOP_CSR_DEBUG_EN, 0x00}, + { CDC_TX_TOP_CSR_TX_I2S_CTL, 0x0C}, + { CDC_TX_TOP_CSR_I2S_CLK, 0x00}, + { CDC_TX_TOP_CSR_I2S_RESET, 0x00}, + { CDC_TX_TOP_CSR_SWR_DMIC0_CTL, 0x00}, + { CDC_TX_TOP_CSR_SWR_DMIC1_CTL, 0x00}, + { CDC_TX_TOP_CSR_SWR_DMIC2_CTL, 0x00}, + { CDC_TX_TOP_CSR_SWR_DMIC3_CTL, 0x00}, + { CDC_TX_TOP_CSR_SWR_AMIC0_CTL, 0x00}, + { CDC_TX_TOP_CSR_SWR_AMIC1_CTL, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX4_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX5_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00}, + { CDC_TX_ANC0_CLK_RESET_CTL, 0x00}, + { CDC_TX_ANC0_MODE_1_CTL, 0x00}, + { CDC_TX_ANC0_MODE_2_CTL, 0x00}, + { CDC_TX_ANC0_FF_SHIFT, 0x00}, + { CDC_TX_ANC0_FB_SHIFT, 0x00}, + { CDC_TX_ANC0_LPF_FF_A_CTL, 0x00}, + { CDC_TX_ANC0_LPF_FF_B_CTL, 0x00}, + { CDC_TX_ANC0_LPF_FB_CTL, 0x00}, + { CDC_TX_ANC0_SMLPF_CTL, 0x00}, + { CDC_TX_ANC0_DCFLT_SHIFT_CTL, 0x00}, + { CDC_TX_ANC0_IIR_ADAPT_CTL, 0x00}, + { CDC_TX_ANC0_IIR_COEFF_1_CTL, 0x00}, + { CDC_TX_ANC0_IIR_COEFF_2_CTL, 0x00}, + { CDC_TX_ANC0_FF_A_GAIN_CTL, 0x00}, + { CDC_TX_ANC0_FF_B_GAIN_CTL, 0x00}, + { CDC_TX_ANC0_FB_GAIN_CTL, 0x00}, + { CDC_TX0_TX_PATH_CTL, 0x04}, + { CDC_TX0_TX_PATH_CFG0, 0x10}, + { CDC_TX0_TX_PATH_CFG1, 0x0B}, + { CDC_TX0_TX_VOL_CTL, 0x00}, + { CDC_TX0_TX_PATH_SEC0, 0x00}, + { CDC_TX0_TX_PATH_SEC1, 0x00}, + { CDC_TX0_TX_PATH_SEC2, 0x01}, + { CDC_TX0_TX_PATH_SEC3, 0x3C}, + { CDC_TX0_TX_PATH_SEC4, 0x20}, + { CDC_TX0_TX_PATH_SEC5, 0x00}, + { CDC_TX0_TX_PATH_SEC6, 0x00}, + { CDC_TX0_TX_PATH_SEC7, 0x25}, + { CDC_TX1_TX_PATH_CTL, 0x04}, + { CDC_TX1_TX_PATH_CFG0, 0x10}, + { CDC_TX1_TX_PATH_CFG1, 0x0B}, + { CDC_TX1_TX_VOL_CTL, 0x00}, + { CDC_TX1_TX_PATH_SEC0, 0x00}, + { CDC_TX1_TX_PATH_SEC1, 0x00}, + { CDC_TX1_TX_PATH_SEC2, 0x01}, + { CDC_TX1_TX_PATH_SEC3, 0x3C}, + { CDC_TX1_TX_PATH_SEC4, 0x20}, + { CDC_TX1_TX_PATH_SEC5, 0x00}, + { CDC_TX1_TX_PATH_SEC6, 0x00}, + { CDC_TX2_TX_PATH_CTL, 0x04}, + { CDC_TX2_TX_PATH_CFG0, 0x10}, + { CDC_TX2_TX_PATH_CFG1, 0x0B}, + { CDC_TX2_TX_VOL_CTL, 0x00}, + { CDC_TX2_TX_PATH_SEC0, 0x00}, + { CDC_TX2_TX_PATH_SEC1, 0x00}, + { CDC_TX2_TX_PATH_SEC2, 0x01}, + { CDC_TX2_TX_PATH_SEC3, 0x3C}, + { CDC_TX2_TX_PATH_SEC4, 0x20}, + { CDC_TX2_TX_PATH_SEC5, 0x00}, + { CDC_TX2_TX_PATH_SEC6, 0x00}, + { CDC_TX3_TX_PATH_CTL, 0x04}, + { CDC_TX3_TX_PATH_CFG0, 0x10}, + { CDC_TX3_TX_PATH_CFG1, 0x0B}, + { CDC_TX3_TX_VOL_CTL, 0x00}, + { CDC_TX3_TX_PATH_SEC0, 0x00}, + { CDC_TX3_TX_PATH_SEC1, 0x00}, + { CDC_TX3_TX_PATH_SEC2, 0x01}, + { CDC_TX3_TX_PATH_SEC3, 0x3C}, + { CDC_TX3_TX_PATH_SEC4, 0x20}, + { CDC_TX3_TX_PATH_SEC5, 0x00}, + { CDC_TX3_TX_PATH_SEC6, 0x00}, + { CDC_TX4_TX_PATH_CTL, 0x04}, + { CDC_TX4_TX_PATH_CFG0, 0x10}, + { CDC_TX4_TX_PATH_CFG1, 0x0B}, + { CDC_TX4_TX_VOL_CTL, 0x00}, + { CDC_TX4_TX_PATH_SEC0, 0x00}, + { CDC_TX4_TX_PATH_SEC1, 0x00}, + { CDC_TX4_TX_PATH_SEC2, 0x01}, + { CDC_TX4_TX_PATH_SEC3, 0x3C}, + { CDC_TX4_TX_PATH_SEC4, 0x20}, + { CDC_TX4_TX_PATH_SEC5, 0x00}, + { CDC_TX4_TX_PATH_SEC6, 0x00}, + { CDC_TX5_TX_PATH_CTL, 0x04}, + { CDC_TX5_TX_PATH_CFG0, 0x10}, + { CDC_TX5_TX_PATH_CFG1, 0x0B}, + { CDC_TX5_TX_VOL_CTL, 0x00}, + { CDC_TX5_TX_PATH_SEC0, 0x00}, + { CDC_TX5_TX_PATH_SEC1, 0x00}, + { CDC_TX5_TX_PATH_SEC2, 0x01}, + { CDC_TX5_TX_PATH_SEC3, 0x3C}, + { CDC_TX5_TX_PATH_SEC4, 0x20}, + { CDC_TX5_TX_PATH_SEC5, 0x00}, + { CDC_TX5_TX_PATH_SEC6, 0x00}, + { CDC_TX6_TX_PATH_CTL, 0x04}, + { CDC_TX6_TX_PATH_CFG0, 0x10}, + { CDC_TX6_TX_PATH_CFG1, 0x0B}, + { CDC_TX6_TX_VOL_CTL, 0x00}, + { CDC_TX6_TX_PATH_SEC0, 0x00}, + { CDC_TX6_TX_PATH_SEC1, 0x00}, + { CDC_TX6_TX_PATH_SEC2, 0x01}, + { CDC_TX6_TX_PATH_SEC3, 0x3C}, + { CDC_TX6_TX_PATH_SEC4, 0x20}, + { CDC_TX6_TX_PATH_SEC5, 0x00}, + { CDC_TX6_TX_PATH_SEC6, 0x00}, + { CDC_TX7_TX_PATH_CTL, 0x04}, + { CDC_TX7_TX_PATH_CFG0, 0x10}, + { CDC_TX7_TX_PATH_CFG1, 0x0B}, + { CDC_TX7_TX_VOL_CTL, 0x00}, + { CDC_TX7_TX_PATH_SEC0, 0x00}, + { CDC_TX7_TX_PATH_SEC1, 0x00}, + { CDC_TX7_TX_PATH_SEC2, 0x01}, + { CDC_TX7_TX_PATH_SEC3, 0x3C}, + { CDC_TX7_TX_PATH_SEC4, 0x20}, + { CDC_TX7_TX_PATH_SEC5, 0x00}, + { CDC_TX7_TX_PATH_SEC6, 0x00}, +}; + +static bool tx_is_volatile_register(struct device *dev, unsigned int reg) +{ + /* Update volatile list for tx/tx macros */ + switch (reg) { + case CDC_TX_TOP_CSR_SWR_DMIC0_CTL: + case CDC_TX_TOP_CSR_SWR_DMIC1_CTL: + case CDC_TX_TOP_CSR_SWR_DMIC2_CTL: + case CDC_TX_TOP_CSR_SWR_DMIC3_CTL: + return true; + } + return false; +} + +static bool tx_is_rw_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_TX_CLK_RST_CTRL_MCLK_CONTROL: + case CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL: + case CDC_TX_CLK_RST_CTRL_SWR_CONTROL: + case CDC_TX_TOP_CSR_TOP_CFG0: + case CDC_TX_TOP_CSR_ANC_CFG: + case CDC_TX_TOP_CSR_SWR_CTRL: + case CDC_TX_TOP_CSR_FREQ_MCLK: + case CDC_TX_TOP_CSR_DEBUG_BUS: + case CDC_TX_TOP_CSR_DEBUG_EN: + case CDC_TX_TOP_CSR_TX_I2S_CTL: + case CDC_TX_TOP_CSR_I2S_CLK: + case CDC_TX_TOP_CSR_I2S_RESET: + case CDC_TX_TOP_CSR_SWR_DMIC0_CTL: + case CDC_TX_TOP_CSR_SWR_DMIC1_CTL: + case CDC_TX_TOP_CSR_SWR_DMIC2_CTL: + case CDC_TX_TOP_CSR_SWR_DMIC3_CTL: + case CDC_TX_TOP_CSR_SWR_AMIC0_CTL: + case CDC_TX_TOP_CSR_SWR_AMIC1_CTL: + case CDC_TX_ANC0_CLK_RESET_CTL: + case CDC_TX_ANC0_MODE_1_CTL: + case CDC_TX_ANC0_MODE_2_CTL: + case CDC_TX_ANC0_FF_SHIFT: + case CDC_TX_ANC0_FB_SHIFT: + case CDC_TX_ANC0_LPF_FF_A_CTL: + case CDC_TX_ANC0_LPF_FF_B_CTL: + case CDC_TX_ANC0_LPF_FB_CTL: + case CDC_TX_ANC0_SMLPF_CTL: + case CDC_TX_ANC0_DCFLT_SHIFT_CTL: + case CDC_TX_ANC0_IIR_ADAPT_CTL: + case CDC_TX_ANC0_IIR_COEFF_1_CTL: + case CDC_TX_ANC0_IIR_COEFF_2_CTL: + case CDC_TX_ANC0_FF_A_GAIN_CTL: + case CDC_TX_ANC0_FF_B_GAIN_CTL: + case CDC_TX_ANC0_FB_GAIN_CTL: + case CDC_TX_INP_MUX_ADC_MUX0_CFG0: + case CDC_TX_INP_MUX_ADC_MUX0_CFG1: + case CDC_TX_INP_MUX_ADC_MUX1_CFG0: + case CDC_TX_INP_MUX_ADC_MUX1_CFG1: + case CDC_TX_INP_MUX_ADC_MUX2_CFG0: + case CDC_TX_INP_MUX_ADC_MUX2_CFG1: + case CDC_TX_INP_MUX_ADC_MUX3_CFG0: + case CDC_TX_INP_MUX_ADC_MUX3_CFG1: + case CDC_TX_INP_MUX_ADC_MUX4_CFG0: + case CDC_TX_INP_MUX_ADC_MUX4_CFG1: + case CDC_TX_INP_MUX_ADC_MUX5_CFG0: + case CDC_TX_INP_MUX_ADC_MUX5_CFG1: + case CDC_TX_INP_MUX_ADC_MUX6_CFG0: + case CDC_TX_INP_MUX_ADC_MUX6_CFG1: + case CDC_TX_INP_MUX_ADC_MUX7_CFG0: + case CDC_TX_INP_MUX_ADC_MUX7_CFG1: + case CDC_TX0_TX_PATH_CTL: + case CDC_TX0_TX_PATH_CFG0: + case CDC_TX0_TX_PATH_CFG1: + case CDC_TX0_TX_VOL_CTL: + case CDC_TX0_TX_PATH_SEC0: + case CDC_TX0_TX_PATH_SEC1: + case CDC_TX0_TX_PATH_SEC2: + case CDC_TX0_TX_PATH_SEC3: + case CDC_TX0_TX_PATH_SEC4: + case CDC_TX0_TX_PATH_SEC5: + case CDC_TX0_TX_PATH_SEC6: + case CDC_TX0_TX_PATH_SEC7: + case CDC_TX1_TX_PATH_CTL: + case CDC_TX1_TX_PATH_CFG0: + case CDC_TX1_TX_PATH_CFG1: + case CDC_TX1_TX_VOL_CTL: + case CDC_TX1_TX_PATH_SEC0: + case CDC_TX1_TX_PATH_SEC1: + case CDC_TX1_TX_PATH_SEC2: + case CDC_TX1_TX_PATH_SEC3: + case CDC_TX1_TX_PATH_SEC4: + case CDC_TX1_TX_PATH_SEC5: + case CDC_TX1_TX_PATH_SEC6: + case CDC_TX2_TX_PATH_CTL: + case CDC_TX2_TX_PATH_CFG0: + case CDC_TX2_TX_PATH_CFG1: + case CDC_TX2_TX_VOL_CTL: + case CDC_TX2_TX_PATH_SEC0: + case CDC_TX2_TX_PATH_SEC1: + case CDC_TX2_TX_PATH_SEC2: + case CDC_TX2_TX_PATH_SEC3: + case CDC_TX2_TX_PATH_SEC4: + case CDC_TX2_TX_PATH_SEC5: + case CDC_TX2_TX_PATH_SEC6: + case CDC_TX3_TX_PATH_CTL: + case CDC_TX3_TX_PATH_CFG0: + case CDC_TX3_TX_PATH_CFG1: + case CDC_TX3_TX_VOL_CTL: + case CDC_TX3_TX_PATH_SEC0: + case CDC_TX3_TX_PATH_SEC1: + case CDC_TX3_TX_PATH_SEC2: + case CDC_TX3_TX_PATH_SEC3: + case CDC_TX3_TX_PATH_SEC4: + case CDC_TX3_TX_PATH_SEC5: + case CDC_TX3_TX_PATH_SEC6: + case CDC_TX4_TX_PATH_CTL: + case CDC_TX4_TX_PATH_CFG0: + case CDC_TX4_TX_PATH_CFG1: + case CDC_TX4_TX_VOL_CTL: + case CDC_TX4_TX_PATH_SEC0: + case CDC_TX4_TX_PATH_SEC1: + case CDC_TX4_TX_PATH_SEC2: + case CDC_TX4_TX_PATH_SEC3: + case CDC_TX4_TX_PATH_SEC4: + case CDC_TX4_TX_PATH_SEC5: + case CDC_TX4_TX_PATH_SEC6: + case CDC_TX5_TX_PATH_CTL: + case CDC_TX5_TX_PATH_CFG0: + case CDC_TX5_TX_PATH_CFG1: + case CDC_TX5_TX_VOL_CTL: + case CDC_TX5_TX_PATH_SEC0: + case CDC_TX5_TX_PATH_SEC1: + case CDC_TX5_TX_PATH_SEC2: + case CDC_TX5_TX_PATH_SEC3: + case CDC_TX5_TX_PATH_SEC4: + case CDC_TX5_TX_PATH_SEC5: + case CDC_TX5_TX_PATH_SEC6: + case CDC_TX6_TX_PATH_CTL: + case CDC_TX6_TX_PATH_CFG0: + case CDC_TX6_TX_PATH_CFG1: + case CDC_TX6_TX_VOL_CTL: + case CDC_TX6_TX_PATH_SEC0: + case CDC_TX6_TX_PATH_SEC1: + case CDC_TX6_TX_PATH_SEC2: + case CDC_TX6_TX_PATH_SEC3: + case CDC_TX6_TX_PATH_SEC4: + case CDC_TX6_TX_PATH_SEC5: + case CDC_TX6_TX_PATH_SEC6: + case CDC_TX7_TX_PATH_CTL: + case CDC_TX7_TX_PATH_CFG0: + case CDC_TX7_TX_PATH_CFG1: + case CDC_TX7_TX_VOL_CTL: + case CDC_TX7_TX_PATH_SEC0: + case CDC_TX7_TX_PATH_SEC1: + case CDC_TX7_TX_PATH_SEC2: + case CDC_TX7_TX_PATH_SEC3: + case CDC_TX7_TX_PATH_SEC4: + case CDC_TX7_TX_PATH_SEC5: + case CDC_TX7_TX_PATH_SEC6: + return true; + } + + return false; +} + +static const struct regmap_config tx_regmap_config = { + .name = "tx_macro", + .reg_bits = 16, + .val_bits = 32, + .reg_stride = 4, + .cache_type = REGCACHE_FLAT, + .max_register = TX_MAX_OFFSET, + .reg_defaults = tx_defaults, + .num_reg_defaults = ARRAY_SIZE(tx_defaults), + .writeable_reg = tx_is_rw_register, + .volatile_reg = tx_is_volatile_register, + .readable_reg = tx_is_rw_register, +}; + +static int tx_macro_mclk_enable(struct tx_macro *tx, + bool mclk_enable) +{ + struct regmap *regmap = tx->regmap; + + if (mclk_enable) { + if (tx->tx_mclk_users == 0) { + /* 9.6MHz MCLK, set value 0x00 if other frequency */ + regmap_update_bits(regmap, CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01); + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, + CDC_TX_MCLK_EN_MASK, + CDC_TX_MCLK_ENABLE); + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_TX_FS_CNT_EN_MASK, + CDC_TX_FS_CNT_ENABLE); + regcache_mark_dirty(regmap); + regcache_sync(regmap); + } + tx->tx_mclk_users++; + } else { + if (tx->tx_mclk_users <= 0) { + dev_err(tx->dev, "clock already disabled\n"); + tx->tx_mclk_users = 0; + goto exit; + } + tx->tx_mclk_users--; + if (tx->tx_mclk_users == 0) { + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_TX_FS_CNT_EN_MASK, 0x0); + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, + CDC_TX_MCLK_EN_MASK, 0x0); + } + } +exit: + return 0; +} + +static bool is_amic_enabled(struct snd_soc_component *component, int decimator) +{ + u16 adc_mux_reg, adc_reg, adc_n; + + adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator); + + if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) { + adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator); + adc_n = snd_soc_component_read_field(component, adc_reg, + CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK); + if (adc_n < TX_ADC_MAX) + return true; + } + + return false; +} + +static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work) +{ + struct delayed_work *hpf_delayed_work; + struct hpf_work *hpf_work; + struct tx_macro *tx; + struct snd_soc_component *component; + u16 dec_cfg_reg, hpf_gate_reg; + u8 hpf_cut_off_freq; + + hpf_delayed_work = to_delayed_work(work); + hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork); + tx = hpf_work->tx; + component = tx->component; + hpf_cut_off_freq = hpf_work->hpf_cut_off_freq; + + dec_cfg_reg = CDC_TXn_TX_PATH_CFG0(hpf_work->decimator); + hpf_gate_reg = CDC_TXn_TX_PATH_SEC2(hpf_work->decimator); + + if (is_amic_enabled(component, hpf_work->decimator)) { + snd_soc_component_write_field(component, + dec_cfg_reg, + CDC_TXn_HPF_CUT_FREQ_MASK, + hpf_cut_off_freq); + snd_soc_component_update_bits(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x02); + snd_soc_component_update_bits(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x01); + } else { + snd_soc_component_write_field(component, dec_cfg_reg, + CDC_TXn_HPF_CUT_FREQ_MASK, + hpf_cut_off_freq); + snd_soc_component_write_field(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK, 0x1); + /* Minimum 1 clk cycle delay is required as per HW spec */ + usleep_range(1000, 1010); + snd_soc_component_write_field(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK, 0x0); + } +} + +static void tx_macro_mute_update_callback(struct work_struct *work) +{ + struct tx_mute_work *tx_mute_dwork; + struct snd_soc_component *component; + struct tx_macro *tx; + struct delayed_work *delayed_work; + u8 decimator; + + delayed_work = to_delayed_work(work); + tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork); + tx = tx_mute_dwork->tx; + component = tx->component; + decimator = tx_mute_dwork->decimator; + + snd_soc_component_write_field(component, CDC_TXn_TX_PATH_CTL(decimator), + CDC_TXn_PGA_MUTE_MASK, 0x0); +} + +static int tx_macro_dec_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int path = e->shift_l; + + ucontrol->value.integer.value[0] = tx->dec_mode[path]; + + return 0; +} + +static int tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int value = ucontrol->value.integer.value[0]; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int path = e->shift_l; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + tx->dec_mode[path] = value; + + return 0; +} + +static int tx_macro_get_bcs(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = tx->bcs_enable; + + return 0; +} + +static int tx_macro_set_bcs(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + int value = ucontrol->value.integer.value[0]; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + tx->bcs_enable = value; + + return 0; +} + +static int tx_macro_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + u32 decimator, sample_rate; + int tx_fs_rate; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + sample_rate = params_rate(params); + switch (sample_rate) { + case 8000: + tx_fs_rate = 0; + break; + case 16000: + tx_fs_rate = 1; + break; + case 32000: + tx_fs_rate = 3; + break; + case 48000: + tx_fs_rate = 4; + break; + case 96000: + tx_fs_rate = 5; + break; + case 192000: + tx_fs_rate = 6; + break; + case 384000: + tx_fs_rate = 7; + break; + default: + dev_err(component->dev, "%s: Invalid TX sample rate: %d\n", + __func__, params_rate(params)); + return -EINVAL; + } + + for_each_set_bit(decimator, &tx->active_ch_mask[dai->id], TX_MACRO_DEC_MAX) + snd_soc_component_update_bits(component, CDC_TXn_TX_PATH_CTL(decimator), + CDC_TXn_PCM_RATE_MASK, + tx_fs_rate); + return 0; +} + +static int tx_macro_get_channel_map(struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct snd_soc_component *component = dai->component; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + switch (dai->id) { + case TX_MACRO_AIF1_CAP: + case TX_MACRO_AIF2_CAP: + case TX_MACRO_AIF3_CAP: + *tx_slot = tx->active_ch_mask[dai->id]; + *tx_num = tx->active_ch_cnt[dai->id]; + break; + default: + break; + } + return 0; +} + +static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *component = dai->component; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + u16 decimator; + + decimator = tx->active_decimator[dai->id]; + + if (mute) + snd_soc_component_write_field(component, + CDC_TXn_TX_PATH_CTL(decimator), + CDC_TXn_PGA_MUTE_MASK, 0x1); + else + snd_soc_component_update_bits(component, + CDC_TXn_TX_PATH_CTL(decimator), + CDC_TXn_PGA_MUTE_MASK, 0x0); + + return 0; +} + +static struct snd_soc_dai_ops tx_macro_dai_ops = { + .hw_params = tx_macro_hw_params, + .get_channel_map = tx_macro_get_channel_map, + .mute_stream = tx_macro_digital_mute, +}; + +static struct snd_soc_dai_driver tx_macro_dai[] = { + { + .name = "tx_macro_tx1", + .id = TX_MACRO_AIF1_CAP, + .capture = { + .stream_name = "TX_AIF1 Capture", + .rates = TX_MACRO_RATES, + .formats = TX_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &tx_macro_dai_ops, + }, + { + .name = "tx_macro_tx2", + .id = TX_MACRO_AIF2_CAP, + .capture = { + .stream_name = "TX_AIF2 Capture", + .rates = TX_MACRO_RATES, + .formats = TX_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &tx_macro_dai_ops, + }, + { + .name = "tx_macro_tx3", + .id = TX_MACRO_AIF3_CAP, + .capture = { + .stream_name = "TX_AIF3 Capture", + .rates = TX_MACRO_RATES, + .formats = TX_MACRO_FORMATS, + .rate_max = 192000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 8, + }, + .ops = &tx_macro_dai_ops, + }, +}; + +static const char * const dec_mode_mux_text[] = { + "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF", +}; + +static const struct soc_enum dec_mode_mux_enum[] = { + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 4, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 5, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 6, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 7, ARRAY_SIZE(dec_mode_mux_text), + dec_mode_mux_text), +}; + +static const struct snd_kcontrol_new tx_macro_snd_controls[] = { + SOC_SINGLE_S8_TLV("TX_DEC0 Volume", + CDC_TX0_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC1 Volume", + CDC_TX1_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC2 Volume", + CDC_TX2_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC3 Volume", + CDC_TX3_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC4 Volume", + CDC_TX4_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC5 Volume", + CDC_TX5_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC6 Volume", + CDC_TX6_TX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC7 Volume", + CDC_TX7_TX_VOL_CTL, + -84, 40, digital_gain), + + SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum[0], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum[1], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum[2], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum[3], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum[4], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum[5], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum[6], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum[7], + tx_macro_dec_mode_get, tx_macro_dec_mode_put), + + SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0, + tx_macro_get_bcs, tx_macro_set_bcs), +}; + +static int tx_macro_component_probe(struct snd_soc_component *comp) +{ + struct tx_macro *tx = snd_soc_component_get_drvdata(comp); + int i; + + snd_soc_component_init_regmap(comp, tx->regmap); + + for (i = 0; i < NUM_DECIMATORS; i++) { + tx->tx_hpf_work[i].tx = tx; + tx->tx_hpf_work[i].decimator = i; + INIT_DELAYED_WORK(&tx->tx_hpf_work[i].dwork, + tx_macro_tx_hpf_corner_freq_callback); + } + + for (i = 0; i < NUM_DECIMATORS; i++) { + tx->tx_mute_dwork[i].tx = tx; + tx->tx_mute_dwork[i].decimator = i; + INIT_DELAYED_WORK(&tx->tx_mute_dwork[i].dwork, + tx_macro_mute_update_callback); + } + tx->component = comp; + + snd_soc_component_update_bits(comp, CDC_TX0_TX_PATH_SEC7, 0x3F, + 0x0A); + + return 0; +} + +static int swclk_gate_enable(struct clk_hw *hw) +{ + struct tx_macro *tx = to_tx_macro(hw); + struct regmap *regmap = tx->regmap; + + tx_macro_mclk_enable(tx, true); + if (tx->reset_swr) + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + CDC_TX_SWR_RESET_MASK, + CDC_TX_SWR_RESET_ENABLE); + + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + CDC_TX_SWR_CLK_EN_MASK, + CDC_TX_SWR_CLK_ENABLE); + if (tx->reset_swr) + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + CDC_TX_SWR_RESET_MASK, 0x0); + tx->reset_swr = false; + + return 0; +} + +static void swclk_gate_disable(struct clk_hw *hw) +{ + struct tx_macro *tx = to_tx_macro(hw); + struct regmap *regmap = tx->regmap; + + regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, + CDC_TX_SWR_CLK_EN_MASK, 0x0); + + tx_macro_mclk_enable(tx, false); +} + +static int swclk_gate_is_enabled(struct clk_hw *hw) +{ + struct tx_macro *tx = to_tx_macro(hw); + int ret, val; + + regmap_read(tx->regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, &val); + ret = val & BIT(0); + + return ret; +} + +static unsigned long swclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate / 2; +} + +static const struct clk_ops swclk_gate_ops = { + .prepare = swclk_gate_enable, + .unprepare = swclk_gate_disable, + .is_enabled = swclk_gate_is_enabled, + .recalc_rate = swclk_recalc_rate, + +}; + +static struct clk *tx_macro_register_mclk_output(struct tx_macro *tx) +{ + struct device *dev = tx->dev; + struct device_node *np = dev->of_node; + const char *parent_clk_name = NULL; + const char *clk_name = "lpass-tx-mclk"; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + parent_clk_name = __clk_get_name(tx->clks[2].clk); + + init.name = clk_name; + init.ops = &swclk_gate_ops; + init.flags = 0; + init.parent_names = &parent_clk_name; + init.num_parents = 1; + tx->hw.init = &init; + hw = &tx->hw; + ret = clk_hw_register(tx->dev, hw); + if (ret) + return ERR_PTR(ret); + + of_clk_add_provider(np, of_clk_src_simple_get, hw->clk); + + return NULL; +} + +static const struct snd_soc_component_driver tx_macro_component_drv = { + .name = "RX-MACRO", + .probe = tx_macro_component_probe, + .controls = tx_macro_snd_controls, + .num_controls = ARRAY_SIZE(tx_macro_snd_controls), +}; + +static int tx_macro_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tx_macro *tx; + void __iomem *base; + int ret; + + tx = devm_kzalloc(dev, sizeof(*tx), GFP_KERNEL); + if (!tx) + return -ENOMEM; + + tx->clks[0].id = "macro"; + tx->clks[1].id = "dcodec"; + tx->clks[2].id = "mclk"; + tx->clks[3].id = "npl"; + tx->clks[4].id = "fsgen"; + + ret = devm_clk_bulk_get(dev, TX_NUM_CLKS_MAX, tx->clks); + if (ret) { + dev_err(dev, "Error getting RX Clocks (%d)\n", ret); + return ret; + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + tx->regmap = devm_regmap_init_mmio(dev, base, &tx_regmap_config); + + dev_set_drvdata(dev, tx); + + tx->reset_swr = true; + tx->dev = dev; + + /* set MCLK and NPL rates */ + clk_set_rate(tx->clks[2].clk, MCLK_FREQ); + clk_set_rate(tx->clks[3].clk, MCLK_FREQ); + + ret = clk_bulk_prepare_enable(TX_NUM_CLKS_MAX, tx->clks); + if (ret) + return ret; + + tx_macro_register_mclk_output(tx); + + ret = devm_snd_soc_register_component(dev, &tx_macro_component_drv, + tx_macro_dai, + ARRAY_SIZE(tx_macro_dai)); + if (ret) + goto err; + return ret; +err: + clk_bulk_disable_unprepare(TX_NUM_CLKS_MAX, tx->clks); + + return ret; +} + +static int tx_macro_remove(struct platform_device *pdev) +{ + struct tx_macro *tx = dev_get_drvdata(&pdev->dev); + + of_clk_del_provider(pdev->dev.of_node); + + clk_bulk_disable_unprepare(TX_NUM_CLKS_MAX, tx->clks); + + return 0; +} + +static const struct of_device_id tx_macro_dt_match[] = { + { .compatible = "qcom,sm8250-lpass-tx-macro" }, + { } +}; +static struct platform_driver tx_macro_driver = { + .driver = { + .name = "tx_macro", + .of_match_table = tx_macro_dt_match, + .suppress_bind_attrs = true, + }, + .probe = tx_macro_probe, + .remove = tx_macro_remove, +}; + +module_platform_driver(tx_macro_driver); + +MODULE_DESCRIPTION("TX macro driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From d207bdea0ca9efde321ff142e9b9f2ef73f9cdf5 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 11 Feb 2021 12:27:35 +0000 Subject: ASoC: codecs: lpass-tx-macro: add dapm widgets and route This patch adds dapm widgets and routes on this codec Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210211122735.5691-8-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 685 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 685 insertions(+) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 06589dad6bc2..36d7a6442cdb 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -706,6 +706,289 @@ static void tx_macro_mute_update_callback(struct work_struct *work) CDC_TXn_PGA_MUTE_MASK, 0x0); } +static int tx_macro_mclk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + tx_macro_mclk_enable(tx, true); + break; + case SND_SOC_DAPM_POST_PMD: + tx_macro_mclk_enable(tx, false); + break; + default: + break; + } + + return 0; +} + +static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val, dmic; + u16 mic_sel_reg; + u16 dmic_clk_reg; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + val = ucontrol->value.enumerated.item[0]; + + switch (e->reg) { + case CDC_TX_INP_MUX_ADC_MUX0_CFG0: + mic_sel_reg = CDC_TX0_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX1_CFG0: + mic_sel_reg = CDC_TX1_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX2_CFG0: + mic_sel_reg = CDC_TX2_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX3_CFG0: + mic_sel_reg = CDC_TX3_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX4_CFG0: + mic_sel_reg = CDC_TX4_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX5_CFG0: + mic_sel_reg = CDC_TX5_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX6_CFG0: + mic_sel_reg = CDC_TX6_TX_PATH_CFG0; + break; + case CDC_TX_INP_MUX_ADC_MUX7_CFG0: + mic_sel_reg = CDC_TX7_TX_PATH_CFG0; + break; + } + + if (val != 0) { + if (val < 5) { + snd_soc_component_write_field(component, mic_sel_reg, + CDC_TXn_ADC_DMIC_SEL_MASK, 0); + } else { + snd_soc_component_write_field(component, mic_sel_reg, + CDC_TXn_ADC_DMIC_SEL_MASK, 1); + dmic = TX_ADC_TO_DMIC(val); + dmic_clk_reg = CDC_TX_TOP_CSR_SWR_DMICn_CTL(dmic); + snd_soc_component_write_field(component, dmic_clk_reg, + CDC_TX_SWR_DMIC_CLK_SEL_MASK, + tx->dmic_clk_div); + } + } + + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); +} + +static int tx_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; + u32 dai_id = widget->shift; + u32 dec_id = mc->shift; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + if (test_bit(dec_id, &tx->active_ch_mask[dai_id])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int tx_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); + struct snd_soc_dapm_update *update = NULL; + struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; + u32 dai_id = widget->shift; + u32 dec_id = mc->shift; + u32 enable = ucontrol->value.integer.value[0]; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + if (enable) { + set_bit(dec_id, &tx->active_ch_mask[dai_id]); + tx->active_ch_cnt[dai_id]++; + tx->active_decimator[dai_id] = dec_id; + } else { + tx->active_ch_cnt[dai_id]--; + clear_bit(dec_id, &tx->active_ch_mask[dai_id]); + tx->active_decimator[dai_id] = -1; + } + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update); + + return 0; +} + +static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + unsigned int decimator; + u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg, tx_gain_ctl_reg; + u8 hpf_cut_off_freq; + int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; + int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS; + u16 adc_mux_reg, adc_reg, adc_n, dmic; + u16 dmic_clk_reg; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + decimator = w->shift; + tx_vol_ctl_reg = CDC_TXn_TX_PATH_CTL(decimator); + hpf_gate_reg = CDC_TXn_TX_PATH_SEC2(decimator); + dec_cfg_reg = CDC_TXn_TX_PATH_CFG0(decimator); + tx_gain_ctl_reg = CDC_TXn_TX_VOL_CTL(decimator); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator); + if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) { + adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator); + adc_n = snd_soc_component_read(component, adc_reg) & + CDC_TX_MACRO_SWR_MIC_MUX_SEL_MASK; + if (adc_n >= TX_ADC_MAX) { + dmic = TX_ADC_TO_DMIC(adc_n); + dmic_clk_reg = CDC_TX_TOP_CSR_SWR_DMICn_CTL(dmic); + + snd_soc_component_write_field(component, dmic_clk_reg, + CDC_TX_SWR_DMIC_CLK_SEL_MASK, + tx->dmic_clk_div); + } + } + snd_soc_component_write_field(component, dec_cfg_reg, + CDC_TXn_ADC_MODE_MASK, + tx->dec_mode[decimator]); + /* Enable TX PGA Mute */ + snd_soc_component_write_field(component, tx_vol_ctl_reg, + CDC_TXn_PGA_MUTE_MASK, 0x1); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_write_field(component, tx_vol_ctl_reg, + CDC_TXn_CLK_EN_MASK, 0x1); + if (!is_amic_enabled(component, decimator)) { + snd_soc_component_update_bits(component, hpf_gate_reg, 0x01, 0x00); + /* Minimum 1 clk cycle delay is required as per HW spec */ + usleep_range(1000, 1010); + } + hpf_cut_off_freq = snd_soc_component_read_field(component, dec_cfg_reg, + CDC_TXn_HPF_CUT_FREQ_MASK); + + tx->tx_hpf_work[decimator].hpf_cut_off_freq = + hpf_cut_off_freq; + + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) + snd_soc_component_write_field(component, dec_cfg_reg, + CDC_TXn_HPF_CUT_FREQ_MASK, + CF_MIN_3DB_150HZ); + + if (is_amic_enabled(component, decimator)) { + hpf_delay = TX_MACRO_AMIC_HPF_DELAY_MS; + unmute_delay = TX_MACRO_AMIC_UNMUTE_DELAY_MS; + } + /* schedule work queue to Remove Mute */ + queue_delayed_work(system_freezable_wq, + &tx->tx_mute_dwork[decimator].dwork, + msecs_to_jiffies(unmute_delay)); + if (tx->tx_hpf_work[decimator].hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + queue_delayed_work(system_freezable_wq, + &tx->tx_hpf_work[decimator].dwork, + msecs_to_jiffies(hpf_delay)); + snd_soc_component_update_bits(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x02); + if (!is_amic_enabled(component, decimator)) + snd_soc_component_update_bits(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x00); + snd_soc_component_update_bits(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x01); + + /* + * 6ms delay is required as per HW spec + */ + usleep_range(6000, 6010); + } + /* apply gain after decimator is enabled */ + snd_soc_component_write(component, tx_gain_ctl_reg, + snd_soc_component_read(component, + tx_gain_ctl_reg)); + if (tx->bcs_enable) { + snd_soc_component_update_bits(component, dec_cfg_reg, + 0x01, 0x01); + tx->bcs_clk_en = true; + } + break; + case SND_SOC_DAPM_PRE_PMD: + hpf_cut_off_freq = + tx->tx_hpf_work[decimator].hpf_cut_off_freq; + snd_soc_component_write_field(component, tx_vol_ctl_reg, + CDC_TXn_PGA_MUTE_MASK, 0x1); + if (cancel_delayed_work_sync( + &tx->tx_hpf_work[decimator].dwork)) { + if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + snd_soc_component_write_field( + component, dec_cfg_reg, + CDC_TXn_HPF_CUT_FREQ_MASK, + hpf_cut_off_freq); + if (is_amic_enabled(component, decimator)) + snd_soc_component_update_bits(component, + hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x02); + else + snd_soc_component_update_bits(component, + hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x03); + + /* + * Minimum 1 clk cycle delay is required + * as per HW spec + */ + usleep_range(1000, 1010); + snd_soc_component_update_bits(component, hpf_gate_reg, + CDC_TXn_HPF_F_CHANGE_MASK | + CDC_TXn_HPF_ZERO_GATE_MASK, + 0x1); + } + } + cancel_delayed_work_sync(&tx->tx_mute_dwork[decimator].dwork); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_write_field(component, tx_vol_ctl_reg, + CDC_TXn_CLK_EN_MASK, 0x0); + snd_soc_component_write_field(component, dec_cfg_reg, + CDC_TXn_ADC_MODE_MASK, 0x0); + snd_soc_component_write_field(component, tx_vol_ctl_reg, + CDC_TXn_PGA_MUTE_MASK, 0x0); + if (tx->bcs_enable) { + snd_soc_component_write_field(component, dec_cfg_reg, + CDC_TXn_PH_EN_MASK, 0x0); + snd_soc_component_write_field(component, + CDC_TX0_TX_PATH_SEC7, + CDC_TX0_MBHC_CTL_EN_MASK, + 0x0); + tx->bcs_clk_en = false; + } + break; + } + return 0; +} + static int tx_macro_dec_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -892,6 +1175,83 @@ static struct snd_soc_dai_driver tx_macro_dai[] = { }, }; +static const char * const adc_mux_text[] = { + "MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1" +}; + +static SOC_ENUM_SINGLE_DECL(tx_dec0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG1, + 0, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_dec7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG1, + 0, adc_mux_text); + +static const struct snd_kcontrol_new tx_dec0_mux = SOC_DAPM_ENUM("tx_dec0", tx_dec0_enum); +static const struct snd_kcontrol_new tx_dec1_mux = SOC_DAPM_ENUM("tx_dec1", tx_dec1_enum); +static const struct snd_kcontrol_new tx_dec2_mux = SOC_DAPM_ENUM("tx_dec2", tx_dec2_enum); +static const struct snd_kcontrol_new tx_dec3_mux = SOC_DAPM_ENUM("tx_dec3", tx_dec3_enum); +static const struct snd_kcontrol_new tx_dec4_mux = SOC_DAPM_ENUM("tx_dec4", tx_dec4_enum); +static const struct snd_kcontrol_new tx_dec5_mux = SOC_DAPM_ENUM("tx_dec5", tx_dec5_enum); +static const struct snd_kcontrol_new tx_dec6_mux = SOC_DAPM_ENUM("tx_dec6", tx_dec6_enum); +static const struct snd_kcontrol_new tx_dec7_mux = SOC_DAPM_ENUM("tx_dec7", tx_dec7_enum); + +static const char * const smic_mux_text[] = { + "ZERO", "ADC0", "ADC1", "ADC2", "ADC3", "SWR_DMIC0", + "SWR_DMIC1", "SWR_DMIC2", "SWR_DMIC3", "SWR_DMIC4", + "SWR_DMIC5", "SWR_DMIC6", "SWR_DMIC7" +}; + +static SOC_ENUM_SINGLE_DECL(tx_smic0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(tx_smic7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG0, + 0, smic_mux_text); + +static const struct snd_kcontrol_new tx_smic0_mux = SOC_DAPM_ENUM_EXT("tx_smic0", tx_smic0_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic1_mux = SOC_DAPM_ENUM_EXT("tx_smic1", tx_smic1_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic2_mux = SOC_DAPM_ENUM_EXT("tx_smic2", tx_smic2_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic3_mux = SOC_DAPM_ENUM_EXT("tx_smic3", tx_smic3_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic4_mux = SOC_DAPM_ENUM_EXT("tx_smic4", tx_smic4_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic5_mux = SOC_DAPM_ENUM_EXT("tx_smic5", tx_smic5_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic6_mux = SOC_DAPM_ENUM_EXT("tx_smic6", tx_smic6_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic7_mux = SOC_DAPM_ENUM_EXT("tx_smic7", tx_smic7_enum, + snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); + static const char * const dec_mode_mux_text[] = { "ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF", }; @@ -915,6 +1275,327 @@ static const struct soc_enum dec_mode_mux_enum[] = { dec_mode_mux_text), }; +static const struct snd_kcontrol_new tx_aif1_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif2_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), +}; + +static const struct snd_kcontrol_new tx_aif3_cap_mixer[] = { + SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC4", SND_SOC_NOPM, TX_MACRO_DEC4, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC5", SND_SOC_NOPM, TX_MACRO_DEC5, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC6", SND_SOC_NOPM, TX_MACRO_DEC6, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), + SOC_SINGLE_EXT("DEC7", SND_SOC_NOPM, TX_MACRO_DEC7, 1, 0, + tx_macro_tx_mixer_get, tx_macro_tx_mixer_put), +}; + +static const struct snd_soc_dapm_widget tx_macro_dapm_widgets[] = { + SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0, + SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0, + SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0), + + SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0, + SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0), + + SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0, + tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)), + + SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0, + tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)), + + SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0, + tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)), + + SND_SOC_DAPM_MUX("TX SMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_smic0_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_smic1_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_smic2_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_smic3_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_smic4_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_smic5_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_smic6_mux), + SND_SOC_DAPM_MUX("TX SMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_smic7_mux), + + SND_SOC_DAPM_INPUT("TX SWR_ADC0"), + SND_SOC_DAPM_INPUT("TX SWR_ADC1"), + SND_SOC_DAPM_INPUT("TX SWR_ADC2"), + SND_SOC_DAPM_INPUT("TX SWR_ADC3"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC0"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC1"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC2"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC3"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC4"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC5"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC6"), + SND_SOC_DAPM_INPUT("TX SWR_DMIC7"), + + SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM, + TX_MACRO_DEC0, 0, + &tx_dec0_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM, + TX_MACRO_DEC1, 0, + &tx_dec1_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM, + TX_MACRO_DEC2, 0, + &tx_dec2_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM, + TX_MACRO_DEC3, 0, + &tx_dec3_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM, + TX_MACRO_DEC4, 0, + &tx_dec4_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM, + TX_MACRO_DEC5, 0, + &tx_dec5_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM, + TX_MACRO_DEC6, 0, + &tx_dec6_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM, + TX_MACRO_DEC7, 0, + &tx_dec7_mux, tx_macro_enable_dec, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0, + tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0, + NULL, 0), +}; + +static const struct snd_soc_dapm_route tx_audio_map[] = { + {"TX_AIF1 CAP", NULL, "TX_MCLK"}, + {"TX_AIF2 CAP", NULL, "TX_MCLK"}, + {"TX_AIF3 CAP", NULL, "TX_MCLK"}, + + {"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"}, + {"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"}, + {"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"}, + + {"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"}, + {"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"}, + + {"TX DEC0 MUX", NULL, "TX_MCLK"}, + {"TX DEC1 MUX", NULL, "TX_MCLK"}, + {"TX DEC2 MUX", NULL, "TX_MCLK"}, + {"TX DEC3 MUX", NULL, "TX_MCLK"}, + {"TX DEC4 MUX", NULL, "TX_MCLK"}, + {"TX DEC5 MUX", NULL, "TX_MCLK"}, + {"TX DEC6 MUX", NULL, "TX_MCLK"}, + {"TX DEC7 MUX", NULL, "TX_MCLK"}, + + {"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"}, + {"TX SMIC MUX0", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX0", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX0", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX0", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX0", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX0", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX0", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX0", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX0", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX0", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX0", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX0", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX0", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"}, + {"TX SMIC MUX1", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX1", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX1", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX1", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX1", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX1", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX1", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX1", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX1", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX1", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX1", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX1", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX1", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"}, + {"TX SMIC MUX2", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX2", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX2", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX2", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX2", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX2", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX2", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX2", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX2", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX2", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX2", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX2", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX2", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"}, + {"TX SMIC MUX3", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX3", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX3", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX3", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX3", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX3", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX3", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX3", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX3", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX3", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX3", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX3", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX3", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"}, + {"TX SMIC MUX4", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX4", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX4", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX4", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX4", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX4", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX4", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX4", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX4", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX4", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX4", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX4", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX4", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"}, + {"TX SMIC MUX5", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX5", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX5", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX5", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX5", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX5", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX5", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX5", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX5", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX5", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX5", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX5", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX5", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"}, + {"TX SMIC MUX6", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX6", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX6", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX6", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX6", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX6", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX6", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX6", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX6", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX6", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX6", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX6", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX6", "SWR_DMIC7", "TX SWR_DMIC7"}, + + {"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"}, + {"TX SMIC MUX7", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX7", "ADC0", "TX SWR_ADC0"}, + {"TX SMIC MUX7", "ADC1", "TX SWR_ADC1"}, + {"TX SMIC MUX7", "ADC2", "TX SWR_ADC2"}, + {"TX SMIC MUX7", "ADC3", "TX SWR_ADC3"}, + {"TX SMIC MUX7", "SWR_DMIC0", "TX SWR_DMIC0"}, + {"TX SMIC MUX7", "SWR_DMIC1", "TX SWR_DMIC1"}, + {"TX SMIC MUX7", "SWR_DMIC2", "TX SWR_DMIC2"}, + {"TX SMIC MUX7", "SWR_DMIC3", "TX SWR_DMIC3"}, + {"TX SMIC MUX7", "SWR_DMIC4", "TX SWR_DMIC4"}, + {"TX SMIC MUX7", "SWR_DMIC5", "TX SWR_DMIC5"}, + {"TX SMIC MUX7", "SWR_DMIC6", "TX SWR_DMIC6"}, + {"TX SMIC MUX7", "SWR_DMIC7", "TX SWR_DMIC7"}, +}; + static const struct snd_kcontrol_new tx_macro_snd_controls[] = { SOC_SINGLE_S8_TLV("TX_DEC0 Volume", CDC_TX0_TX_VOL_CTL, @@ -1088,6 +1769,10 @@ static const struct snd_soc_component_driver tx_macro_component_drv = { .probe = tx_macro_component_probe, .controls = tx_macro_snd_controls, .num_controls = ARRAY_SIZE(tx_macro_snd_controls), + .dapm_widgets = tx_macro_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tx_macro_dapm_widgets), + .dapm_routes = tx_audio_map, + .num_dapm_routes = ARRAY_SIZE(tx_audio_map), }; static int tx_macro_probe(struct platform_device *pdev) -- cgit v1.2.3 From 53129e66e4b716ea7cffa4477a96ccb48f78e7ac Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 11 Feb 2021 19:24:40 +0200 Subject: ASoC: SOF: relax ABI checks and avoid unnecessary warnings With recent SOF 1.7 pre-releases, kernel has been emitting following warnings at probe: [10006.645216] sof-audio-pci 0000:00:1f.3: warn: FW ABI is more recent than kernel [10006.652137] sof-audio-pci 0000:00:1f.3: warn: topology ABI is more recent than kernel The warnings are emitted due to increase of the patch-level in firmware mainline (to 3.17.1). But the patch level should not be considered even in the strict ABI check, so modify the kernel side logic that makes the check and only consider the major.minor components. BugLink: https://github.com/thesofproject/linux/issues/2647 Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210211172440.2371447-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc.c | 2 +- sound/soc/sof/topology.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 1bc3d6282f16..c2d07b783f60 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -798,7 +798,7 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev) return -EINVAL; } - if (v->abi_version > SOF_ABI_VERSION) { + if (SOF_ABI_VERSION_MINOR(v->abi_version) > SOF_ABI_MINOR) { if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) { dev_warn(sdev->dev, "warn: FW ABI is more recent than kernel\n"); } else { diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index d6e1f33eb1e9..10f99620eb31 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3658,7 +3658,7 @@ static int sof_manifest(struct snd_soc_component *scomp, int index, return -EINVAL; } - if (abi_version > SOF_ABI_VERSION) { + if (SOF_ABI_VERSION_MINOR(abi_version) > SOF_ABI_MINOR) { if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) { dev_warn(scomp->dev, "warn: topology ABI is more recent than kernel\n"); } else { -- cgit v1.2.3 From 6e9586361e145cd688e525880e1f84c0ccf57566 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 11 Feb 2021 17:21:06 +0000 Subject: ASoC: wm_adsp: Remove unused control callback structure This callback structure has never been used and it is not clear why it was added in the first place. Remove it to clear up the code a little. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20210211172106.16258-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 262c2db4f81c..070ca7d8c661 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -595,13 +595,6 @@ static const struct { [WM_ADSP_FW_MISC] = { .file = "misc" }, }; -struct wm_coeff_ctl_ops { - int (*xget)(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - int (*xput)(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -}; - struct wm_coeff_ctl { const char *name; const char *fw_name; @@ -609,7 +602,6 @@ struct wm_coeff_ctl { const char *subname; unsigned int subname_len; struct wm_adsp_alg_region alg_region; - struct wm_coeff_ctl_ops ops; struct wm_adsp *dsp; unsigned int enabled:1; struct list_head list; @@ -1497,8 +1489,6 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, } ctl->enabled = 1; ctl->set = 0; - ctl->ops.xget = wm_coeff_get; - ctl->ops.xput = wm_coeff_put; ctl->dsp = dsp; ctl->flags = flags; -- cgit v1.2.3 From f6c04af5dc4b80e70160acd9a7b04b185e093c71 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Feb 2021 08:50:31 +0900 Subject: ASoC: soc-pcm: add soc_pcm_hw_update_rate() To update hw, we need to follow setting order 1) set hw->rates 2) call snd_pcm_limit_hw_rates() 3) update hw->rate_min/max To avoid random settings, this patch adds new soc_pcm_hw_update_rate() and share updating code. Signed-off-by: Kuninori Morimoto Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/87sg6c90qv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 56 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8d55f39d4014..0cf212c8bd88 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -473,6 +473,26 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) soc_pcm_set_msb(substream, cpu_bits); } +static void soc_pcm_hw_init(struct snd_pcm_hardware *hw) +{ + hw->rates = UINT_MAX; + hw->rate_min = 0; + hw->rate_max = UINT_MAX; +} + +static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw, + struct snd_soc_pcm_stream *p) +{ + hw->rates = snd_pcm_rate_mask_intersect(hw->rates, p->rates); + + /* setup hw->rate_min/max via hw->rates first */ + snd_pcm_hw_limit_rates(hw); + + /* update hw->rate_min/max by snd_soc_pcm_stream */ + hw->rate_min = max(hw->rate_min, p->rate_min); + hw->rate_max = min_not_zero(hw->rate_max, p->rate_max); +} + /** * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream * @rtd: ASoC PCM runtime @@ -491,12 +511,11 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, struct snd_soc_pcm_stream *cpu_stream; unsigned int chan_min = 0, chan_max = UINT_MAX; unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX; - unsigned int rate_min = 0, rate_max = UINT_MAX; - unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX; - unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX; u64 formats = ULLONG_MAX; int i; + soc_pcm_hw_init(hw); + /* first calculate min/max only for CPUs in the DAI link */ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { @@ -513,11 +532,8 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min); cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max); - cpu_rate_min = max(cpu_rate_min, cpu_stream->rate_min); - cpu_rate_max = min_not_zero(cpu_rate_max, cpu_stream->rate_max); + soc_pcm_hw_update_rate(hw, cpu_stream); formats &= cpu_stream->formats; - cpu_rates = snd_pcm_rate_mask_intersect(cpu_stream->rates, - cpu_rates); } /* second calculate min/max only for CODECs in the DAI link */ @@ -536,10 +552,8 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, chan_min = max(chan_min, codec_stream->channels_min); chan_max = min(chan_max, codec_stream->channels_max); - rate_min = max(rate_min, codec_stream->rate_min); - rate_max = min_not_zero(rate_max, codec_stream->rate_max); + soc_pcm_hw_update_rate(hw, codec_stream); formats &= codec_stream->formats; - rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates); } /* Verify both a valid CPU DAI and a valid CODEC DAI were found */ @@ -560,14 +574,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, hw->channels_min = max(chan_min, cpu_chan_min); hw->channels_max = min(chan_max, cpu_chan_max); hw->formats = formats; - hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates); - - snd_pcm_hw_limit_rates(hw); - - hw->rate_min = max(hw->rate_min, cpu_rate_min); - hw->rate_min = max(hw->rate_min, rate_min); - hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max); - hw->rate_max = min_not_zero(hw->rate_max, rate_max); return 0; } @@ -1514,12 +1520,9 @@ unwind: static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, struct snd_soc_pcm_stream *stream) { - runtime->hw.rates = stream->rates; - - snd_pcm_limit_hw_rates(runtime); + struct snd_pcm_hardware *hw = &runtime->hw; - runtime->hw.rate_min = stream->rate_min; - runtime->hw.rate_max = min_not_zero(stream->rate_max, UINT_MAX); + soc_pcm_hw_update_rate(hw, stream); runtime->hw.channels_min = stream->channels_min; runtime->hw.channels_max = stream->channels_max; if (runtime->hw.formats) @@ -1651,12 +1654,7 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, pcm = snd_soc_dai_get_pcm_stream(dai, stream); - hw->rates = snd_pcm_rate_mask_intersect(hw->rates, pcm->rates); - - snd_pcm_limit_hw_rates(runtime); - - hw->rate_min = max(hw->rate_min, pcm->rate_min); - hw->rate_max = min_not_zero(hw->rate_max, pcm->rate_max); + soc_pcm_hw_update_rate(hw, pcm); } } } -- cgit v1.2.3 From 6cb56a4549e9e2e0f7f67b99cb1887c0e803245a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Feb 2021 08:51:49 +0900 Subject: ASoC: soc-pcm: add soc_pcm_hw_update_chan() We have soc_pcm_hw_update_rate() now. This patch creates same function for chan. Signed-off-by: Kuninori Morimoto Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/87r1lw90oo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 0cf212c8bd88..23d6709a295d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -478,6 +478,8 @@ static void soc_pcm_hw_init(struct snd_pcm_hardware *hw) hw->rates = UINT_MAX; hw->rate_min = 0; hw->rate_max = UINT_MAX; + hw->channels_min = 0; + hw->channels_max = UINT_MAX; } static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw, @@ -493,6 +495,13 @@ static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw, hw->rate_max = min_not_zero(hw->rate_max, p->rate_max); } +static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw, + struct snd_soc_pcm_stream *p) +{ + hw->channels_min = max(hw->channels_min, p->channels_min); + hw->channels_max = min(hw->channels_max, p->channels_max); +} + /** * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream * @rtd: ASoC PCM runtime @@ -509,7 +518,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *cpu_dai; struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; - unsigned int chan_min = 0, chan_max = UINT_MAX; unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX; u64 formats = ULLONG_MAX; int i; @@ -530,11 +538,12 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream); - cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min); - cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max); + soc_pcm_hw_update_chan(hw, cpu_stream); soc_pcm_hw_update_rate(hw, cpu_stream); formats &= cpu_stream->formats; } + cpu_chan_min = hw->channels_min; + cpu_chan_max = hw->channels_max; /* second calculate min/max only for CODECs in the DAI link */ for_each_rtd_codec_dais(rtd, i, codec_dai) { @@ -550,14 +559,13 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream); - chan_min = max(chan_min, codec_stream->channels_min); - chan_max = min(chan_max, codec_stream->channels_max); + soc_pcm_hw_update_chan(hw, codec_stream); soc_pcm_hw_update_rate(hw, codec_stream); formats &= codec_stream->formats; } /* Verify both a valid CPU DAI and a valid CODEC DAI were found */ - if (!chan_min || !cpu_chan_min) + if (!hw->channels_min) return -EINVAL; /* @@ -566,13 +574,11 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, * channel allocation be fixed up later */ if (rtd->num_codecs > 1) { - chan_min = cpu_chan_min; - chan_max = cpu_chan_max; + hw->channels_min = cpu_chan_min; + hw->channels_max = cpu_chan_max; } /* finally find a intersection between CODECs and CPUs */ - hw->channels_min = max(chan_min, cpu_chan_min); - hw->channels_max = min(chan_max, cpu_chan_max); hw->formats = formats; return 0; @@ -1523,8 +1529,7 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, struct snd_pcm_hardware *hw = &runtime->hw; soc_pcm_hw_update_rate(hw, stream); - runtime->hw.channels_min = stream->channels_min; - runtime->hw.channels_max = stream->channels_max; + soc_pcm_hw_update_chan(hw, stream); if (runtime->hw.formats) runtime->hw.formats &= stream->formats; else @@ -1601,10 +1606,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); - hw->channels_min = max(hw->channels_min, - cpu_stream->channels_min); - hw->channels_max = min(hw->channels_max, - cpu_stream->channels_max); + soc_pcm_hw_update_chan(hw, cpu_stream); } /* @@ -1614,10 +1616,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, if (be->num_codecs == 1) { codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream); - hw->channels_min = max(hw->channels_min, - codec_stream->channels_min); - hw->channels_max = min(hw->channels_max, - codec_stream->channels_max); + soc_pcm_hw_update_chan(hw, codec_stream); } } } -- cgit v1.2.3 From debc71f26cdbd45798c63b0dcdabdea93d2f6870 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Feb 2021 08:52:04 +0900 Subject: ASoC: soc-pcm: add soc_pcm_hw_update_format() We have soc_pcm_hw_update_xxx() now. This patch creates same function for format. Signed-off-by: Kuninori Morimoto Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/87pn1g90oa.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 23d6709a295d..b7c90da1820e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -480,6 +480,7 @@ static void soc_pcm_hw_init(struct snd_pcm_hardware *hw) hw->rate_max = UINT_MAX; hw->channels_min = 0; hw->channels_max = UINT_MAX; + hw->formats = ULLONG_MAX; } static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw, @@ -502,6 +503,12 @@ static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw, hw->channels_max = min(hw->channels_max, p->channels_max); } +static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw, + struct snd_soc_pcm_stream *p) +{ + hw->formats &= p->formats; +} + /** * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream * @rtd: ASoC PCM runtime @@ -519,7 +526,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX; - u64 formats = ULLONG_MAX; int i; soc_pcm_hw_init(hw); @@ -540,7 +546,7 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, soc_pcm_hw_update_chan(hw, cpu_stream); soc_pcm_hw_update_rate(hw, cpu_stream); - formats &= cpu_stream->formats; + soc_pcm_hw_update_format(hw, cpu_stream); } cpu_chan_min = hw->channels_min; cpu_chan_max = hw->channels_max; @@ -561,7 +567,7 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, soc_pcm_hw_update_chan(hw, codec_stream); soc_pcm_hw_update_rate(hw, codec_stream); - formats &= codec_stream->formats; + soc_pcm_hw_update_format(hw, codec_stream); } /* Verify both a valid CPU DAI and a valid CODEC DAI were found */ @@ -578,9 +584,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, hw->channels_max = cpu_chan_max; } - /* finally find a intersection between CODECs and CPUs */ - hw->formats = formats; - return 0; } EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw); @@ -1568,7 +1571,7 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, codec_stream = snd_soc_dai_get_pcm_stream(dai, stream); - hw->formats &= codec_stream->formats; + soc_pcm_hw_update_format(hw, codec_stream); } } } -- cgit v1.2.3 From 0d3070f5e6551d8a759619e85736e49a3bf40398 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 12 Feb 2021 17:10:22 +0200 Subject: ALSA: hda: Add another CometLake-H PCI ID Add one more HD Audio PCI ID for CometLake-H PCH. Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Cc: Link: https://lore.kernel.org/r/20210212151022.2568567-1-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5a50d3a46445..1233d4ee8a39 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2481,6 +2481,8 @@ static const struct pci_device_id azx_ids[] = { /* CometLake-H */ { PCI_DEVICE(0x8086, 0x06C8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + { PCI_DEVICE(0x8086, 0xf1c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* CometLake-S */ { PCI_DEVICE(0x8086, 0xa3f0), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, -- cgit v1.2.3 From 15447b64789d9ade71eb374d5ae1f37d0bbce0bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 14 Feb 2021 16:42:51 +0100 Subject: ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10 BOSS GP-10 with 0582:0185 requires the similar quirk to make the implicit feedback working like other BOSS devices. Reported-by: Keith Milner Cc: Link: https://lore.kernel.org/r/20210214154251.10750-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/implicit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index e7216d0b860d..11a85e66aa96 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -73,6 +73,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { /* No quirk for playback but with capture quirk (see below) */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0130), /* BOSS BR-80 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0171), /* BOSS RC-505 */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x0185), /* BOSS GP-10 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0189), /* BOSS GT-100v2 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d6), /* BOSS GT-1 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8), /* BOSS Katana */ @@ -86,6 +87,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { IMPLICIT_FB_FIXED_DEV(0x0582, 0x0130, 0x0d, 0x01), /* BOSS BR-80 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x0171, 0x0d, 0x01), /* BOSS RC-505 */ + IMPLICIT_FB_FIXED_DEV(0x0582, 0x0185, 0x0d, 0x01), /* BOSS GP-10 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x0189, 0x0d, 0x01), /* BOSS GT-100v2 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d6, 0x0d, 0x01), /* BOSS GT-1 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d8, 0x0d, 0x01), /* BOSS Katana */ -- cgit v1.2.3 From c3bb2b521944ffbbc8c24b849f81977a9915fb5e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 15 Feb 2021 09:25:40 +0100 Subject: ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup HP Spectre x360 14 model (PCI SSID 103c:87f7) seems requiring a unique setup for its external amp: the GPIO0 needs to be toggled on and off shortly at each device initialization via runtime PM. This patch implements that workaround as well as the model option string, so that users with other devices may try the same workaround more easily. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=210633 Cc: Link: https://lore.kernel.org/r/20210215082540.4520-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 52907506e16e..1927605f0f7e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4291,6 +4291,28 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, } } +/* HP Spectre x360 14 model needs a unique workaround for enabling the amp; + * it needs to toggle the GPIO0 once on and off at each time (bko#210633) + */ +static void alc245_fixup_hp_x360_amp(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + spec->gpio_mask |= 0x01; + spec->gpio_dir |= 0x01; + break; + case HDA_FIXUP_ACT_INIT: + /* need to toggle GPIO to enable the amp */ + alc_update_gpio_data(codec, 0x01, true); + msleep(100); + alc_update_gpio_data(codec, 0x01, false); + break; + } +} + static void alc_update_coef_led(struct hda_codec *codec, struct alc_coef_led *led, bool polarity, bool on) @@ -6277,6 +6299,7 @@ enum { ALC280_FIXUP_HP_DOCK_PINS, ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, ALC280_FIXUP_HP_9480M, + ALC245_FIXUP_HP_X360_AMP, ALC288_FIXUP_DELL_HEADSET_MODE, ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, ALC288_FIXUP_DELL_XPS_13, @@ -6982,6 +7005,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc280_fixup_hp_9480m, }, + [ALC245_FIXUP_HP_X360_AMP] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc245_fixup_hp_x360_amp, + }, [ALC288_FIXUP_DELL_HEADSET_MODE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode_dell_alc288, @@ -7996,6 +8023,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -8368,6 +8396,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"}, {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"}, {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"}, + {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"}, {} }; #define ALC225_STANDARD_PINS \ -- cgit v1.2.3 From 140f553d1298e0ddbe21983efe5789fe8b484273 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 15 Feb 2021 00:04:14 +0200 Subject: ASoC: soc-pcm: fix hwparams min/max init for dpcm When runtime is initialized with dpcm_init_runtime_hw(), some of the min/max calculations assume that defaults are set. For example calculation of channel min/max values may be done using zero-initialized data and soc_pcm_hw_update_chan() will always return max-channels of 0 in this case. This will result in failure to open the PCM at all. Fix the issue by calling soc_pcm_hw_init() before calling any soc_pcm_hw_update_*() functions. Remove the conditional code on runtime->hw.formats as this field is anyways set in soc_pcm_hw_init(). Fixes: 6cb56a4549e9 ("ASoC: soc-pcm: add soc_pcm_hw_update_chan()") Reported-by: Pierre-Louis Bossart Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210214220414.2876690-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b7c90da1820e..37094aeff440 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1531,12 +1531,10 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, { struct snd_pcm_hardware *hw = &runtime->hw; + soc_pcm_hw_init(hw); soc_pcm_hw_update_rate(hw, stream); soc_pcm_hw_update_chan(hw, stream); - if (runtime->hw.formats) - runtime->hw.formats &= stream->formats; - else - runtime->hw.formats = stream->formats; + soc_pcm_hw_update_format(hw, stream); } static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, -- cgit v1.2.3 From bdea43fc0436c9e98fdfe151c2ed8a3fc7277404 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Feb 2021 22:35:52 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R tablet The Estar Beauty HD MID 7316R tablet almost fully works with out default settings. The only problem is that it has only 1 speaker so any sounds only playing on the right channel get lost. Add a quirk for this model using the default settings + MONO_SPEAKER. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210216213555.36555-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 2dee84578b90..3008e3cbcbb8 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -531,6 +531,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_MONO_SPEAKER | BYT_RT5640_MCLK_EN), }, + { /* Estar Beauty HD MID 7316R */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Estar"), + DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"), + }, + .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -- cgit v1.2.3 From e1317cc9ca4ac20262895fddb065ffda4fc29cfb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Feb 2021 22:35:53 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet The Voyo Winpad A15 tablet uses a Bay Trail (non CR) SoC, so it is using SSP2 (AIF1) and it mostly works with the defaults. But instead of using DMIC1 it is using an analog mic on IN1, add a quirk for this. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210216213555.36555-3-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 3008e3cbcbb8..a81820943de6 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -824,6 +824,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF2 | BYT_RT5640_MCLK_EN), }, + { /* Voyo Winpad A15 */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + /* Above strings are too generic, also match on BIOS date */ + DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_MCLK_EN), + }, { /* Catch-all for generic Insyde tablets, must be last */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), -- cgit v1.2.3 From df8359c512fa770ffa6b0b0309807d9b9825a47f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Feb 2021 22:35:54 +0100 Subject: ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet Add a DMI quirk for the Jumper EZpad 7 tablet, this tablet has a jack-detect switch which reads 1/high when a jack is inserted, rather then using the standard active-low setup which most jack-detect switches use. All other settings are using the defaults. Add a DMI-quirk setting the defaults + the BYT_RT5651_JD_NOT_INV flags for this. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210216213555.36555-4-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5651.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index f289ec8563a1..148b7b1bd3e8 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -435,6 +435,19 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = { BYT_RT5651_SSP0_AIF1 | BYT_RT5651_MONO_SPEAKER), }, + { + /* Jumper EZpad 7 */ + .callback = byt_rt5651_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Jumper"), + DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"), + /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */ + DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"), + }, + .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS | + BYT_RT5651_IN2_MAP | + BYT_RT5651_JD_NOT_INV), + }, { /* KIANO SlimNote 14.2 */ .callback = byt_rt5651_quirk_cb, -- cgit v1.2.3 From c58947af08aedbdee0fce5ea6e6bf3e488ae0e2c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Feb 2021 22:35:55 +0100 Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet The Acer One S1002 tablet is using an analog mic on IN1 and has its jack-detect connected to JD2_IN4N, instead of using the default IN3 for its internal mic and JD1_IN4P for jack-detect. Note it is also using AIF2 instead of AIF1 which is somewhat unusual, this is correctly advertised in the ACPI CHAN package, so the speakers do work without the quirk. Add a quirk for the mic and jack-detect settings. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210216213555.36555-5-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index a81820943de6..782f2b4d72ad 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -406,6 +406,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { /* Acer One 10 S1002 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF2 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -- cgit v1.2.3 From 8a353d7bafddb447fae136ca68899a6ba6187be6 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 16 Feb 2021 19:22:51 +0200 Subject: ASoC: soc-pcm: fix hw param limits calculation for multi-DAI In case DPCM runtime has multiple CPU DAIs, dpcm_init_runtime_hw() is called multiple times, once for each CPU DAI. This will lead to ignoring hw limits of all but the last DAI. Fix this by moving soc_pcm_hw_init() up by one level to dpcm_init_runtime_hw(). Fixes: 140f553d1298 ("ASoC: soc-pcm: fix hwparams min/max init for dpcm") Suggested-by: Kuninori Morimoto Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210216172251.3023723-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 37094aeff440..14d85ca1e435 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1531,10 +1531,12 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, { struct snd_pcm_hardware *hw = &runtime->hw; - soc_pcm_hw_init(hw); soc_pcm_hw_update_rate(hw, stream); soc_pcm_hw_update_chan(hw, stream); - soc_pcm_hw_update_format(hw, stream); + if (runtime->hw.formats) + runtime->hw.formats &= stream->formats; + else + runtime->hw.formats = stream->formats; } static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, @@ -1662,10 +1664,13 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; int i; + soc_pcm_hw_init(hw); + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { /* * Skip CPUs which don't support the current stream -- cgit v1.2.3 From c4294d7f057d05053412ebd0d5700228d0f2588d Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 10 Feb 2021 13:13:10 +0200 Subject: ALSA: hda: intel-dsp-config: add Alder Lake support Add rules to select SOF driver for Alder Lake systems if a digital microphone or SoundWire codecs are present in the system. This is following same rules as for older Tiger Lake systems. Signed-off-by: Kai Vehmanen Reviewed-by: Xiuli Pan Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210210111310.2227417-1-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/intel-dsp-config.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 68bb977c6a37..d1eb9d34993a 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -321,6 +321,18 @@ static const struct config_entry config_table[] = { }, #endif +/* Alder Lake */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_ALDERLAKE) + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x7ad0, + }, + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x51c8, + }, +#endif + }; static const struct config_entry *snd_intel_dsp_find_config -- cgit v1.2.3