mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
ASoC: Updates for v4.19
A fairly big update, including quite a bit of core activity this time
around (which is good to see) along with a fairly large set of new
drivers.
- A new snd_pcm_stop_xrun() helper which is now used in several
drivers.
- Support for providing name prefixes to generic component nodes.
- Quite a few fixes for DPCM as it gains a bit wider use and more
robust testing.
- Generalization of the DIO2125 support to a simple amplifier driver.
- Accessory detection support for the audio graph card.
- DT support for PXA AC'97 devices.
- Quirks for a number of new x86 systems.
- Support for AM Logic Meson, Everest ES7154, Intel systems with
RT5682, Qualcomm QDSP6 and WCD9335, Realtek RT5682 and TI TAS5707.
-----BEGIN PGP SIGNATURE-----
iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAltxVZsTHGJyb29uaWVA
a2VybmVsLm9yZwAKCRAk1otyXVSH0CtwB/0U+IUWLlojWD6RDfueycvc9TiZW0t4
gBT3OD8f4oif0MuMy6oE2ag8JPNU8n5MnO14U366GDaEyZPj79W7f50Q8Nnyht/n
py6fQfyo7Ec2hFJstDI42KvDymTbAer6hnAUJarr/FdZHdGeOfYV+s7aHp5aEQAS
KACnX8qWo87VePouNBorqWXWueAJTb6zpWy7YQ1KGb/pJIAeue2Y9pLRGXQos1BS
E1AP+ge2BMnz7BeiCgw/39hN6X545nJ1fcZKuIu8Gqy9ahqEDHgmBWPAehtGnfVj
D8JPplTaBFtAsJwi18b7ApWtcytpizPPN/l3NTA4fTRJQe9kxfDmnE7b
=fvKX
-----END PGP SIGNATURE-----
Merge tag 'asoc-v4.19' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.19
A fairly big update, including quite a bit of core activity this time
around (which is good to see) along with a fairly large set of new
drivers.
- A new snd_pcm_stop_xrun() helper which is now used in several
drivers.
- Support for providing name prefixes to generic component nodes.
- Quite a few fixes for DPCM as it gains a bit wider use and more
robust testing.
- Generalization of the DIO2125 support to a simple amplifier driver.
- Accessory detection support for the audio graph card.
- DT support for PXA AC'97 devices.
- Quirks for a number of new x86 systems.
- Support for AM Logic Meson, Everest ES7154, Intel systems with
RT5682, Qualcomm QDSP6 and WCD9335, Realtek RT5682 and TI TAS5707.
This commit is contained in:
commit
f5b6c1fcb4
984 changed files with 21040 additions and 6606 deletions
|
|
@ -17,14 +17,9 @@ config SND_ARMAACI
|
|||
select SND_PCM
|
||||
select SND_AC97_CODEC
|
||||
|
||||
config SND_PXA2XX_PCM
|
||||
tristate
|
||||
select SND_PCM
|
||||
|
||||
config SND_PXA2XX_AC97
|
||||
tristate "AC97 driver for the Intel PXA2xx chip"
|
||||
depends on ARCH_PXA
|
||||
select SND_PXA2XX_PCM
|
||||
select SND_AC97_CODEC
|
||||
select SND_PXA2XX_LIB
|
||||
select SND_PXA2XX_LIB_AC97
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@
|
|||
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
|
||||
snd-aaci-objs := aaci.o
|
||||
|
||||
obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
|
||||
snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
|
||||
|
||||
obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o
|
||||
snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o
|
||||
snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <sound/pxa2xx-lib.h>
|
||||
|
||||
|
|
@ -337,6 +338,17 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
|
|||
dev_err(&dev->dev, "Invalid reset GPIO %d\n",
|
||||
pdata->reset_gpio);
|
||||
}
|
||||
} else if (!pdata && dev->dev.of_node) {
|
||||
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
pdata->reset_gpio = of_get_named_gpio(dev->dev.of_node,
|
||||
"reset-gpios", 0);
|
||||
if (pdata->reset_gpio == -ENOENT)
|
||||
pdata->reset_gpio = -1;
|
||||
else if (pdata->reset_gpio < 0)
|
||||
return pdata->reset_gpio;
|
||||
reset_gpio = pdata->reset_gpio;
|
||||
} else {
|
||||
if (cpu_is_pxa27x())
|
||||
reset_gpio = 113;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma/pxa-dma.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
@ -27,8 +27,6 @@
|
|||
#include <mach/regs-ac97.h>
|
||||
#include <mach/audio.h>
|
||||
|
||||
#include "pxa2xx-pcm.h"
|
||||
|
||||
static void pxa2xx_ac97_legacy_reset(struct snd_ac97 *ac97)
|
||||
{
|
||||
if (!pxa2xx_ac97_try_cold_reset())
|
||||
|
|
@ -63,61 +61,46 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
|
|||
.reset = pxa2xx_ac97_legacy_reset,
|
||||
};
|
||||
|
||||
static struct pxad_param pxa2xx_ac97_pcm_out_req = {
|
||||
.prio = PXAD_PRIO_LOWEST,
|
||||
.drcmr = 12,
|
||||
};
|
||||
|
||||
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = {
|
||||
.addr = __PREG(PCDR),
|
||||
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||
.maxburst = 32,
|
||||
.filter_data = &pxa2xx_ac97_pcm_out_req,
|
||||
};
|
||||
|
||||
static struct pxad_param pxa2xx_ac97_pcm_in_req = {
|
||||
.prio = PXAD_PRIO_LOWEST,
|
||||
.drcmr = 11,
|
||||
};
|
||||
|
||||
static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = {
|
||||
.addr = __PREG(PCDR),
|
||||
.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
|
||||
.maxburst = 32,
|
||||
.filter_data = &pxa2xx_ac97_pcm_in_req,
|
||||
};
|
||||
|
||||
static struct snd_pcm *pxa2xx_ac97_pcm;
|
||||
static struct snd_ac97 *pxa2xx_ac97_ac97;
|
||||
|
||||
static int pxa2xx_ac97_pcm_startup(struct snd_pcm_substream *substream)
|
||||
static int pxa2xx_ac97_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
pxa2xx_audio_ops_t *platform_ops;
|
||||
int r;
|
||||
int ret, i;
|
||||
|
||||
ret = pxa2xx_pcm_open(substream);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
runtime->hw.channels_min = 2;
|
||||
runtime->hw.channels_max = 2;
|
||||
|
||||
r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
|
||||
runtime->hw.rates = pxa2xx_ac97_ac97->rates[r];
|
||||
i = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
|
||||
runtime->hw.rates = pxa2xx_ac97_ac97->rates[i];
|
||||
snd_pcm_limit_hw_rates(runtime);
|
||||
|
||||
platform_ops = substream->pcm->card->dev->platform_data;
|
||||
if (platform_ops && platform_ops->startup)
|
||||
return platform_ops->startup(substream, platform_ops->priv);
|
||||
else
|
||||
return 0;
|
||||
platform_ops = substream->pcm->card->dev->platform_data;
|
||||
if (platform_ops && platform_ops->startup) {
|
||||
ret = platform_ops->startup(substream, platform_ops->priv);
|
||||
if (ret < 0)
|
||||
pxa2xx_pcm_close(substream);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pxa2xx_ac97_pcm_shutdown(struct snd_pcm_substream *substream)
|
||||
static int pxa2xx_ac97_pcm_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
pxa2xx_audio_ops_t *platform_ops;
|
||||
|
||||
platform_ops = substream->pcm->card->dev->platform_data;
|
||||
platform_ops = substream->pcm->card->dev->platform_data;
|
||||
if (platform_ops && platform_ops->shutdown)
|
||||
platform_ops->shutdown(substream, platform_ops->priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
|
|
@ -125,17 +108,15 @@ static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
|
||||
int ret;
|
||||
|
||||
ret = pxa2xx_pcm_prepare(substream);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate);
|
||||
}
|
||||
|
||||
static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = {
|
||||
.playback_params = &pxa2xx_ac97_pcm_out,
|
||||
.capture_params = &pxa2xx_ac97_pcm_in,
|
||||
.startup = pxa2xx_ac97_pcm_startup,
|
||||
.shutdown = pxa2xx_ac97_pcm_shutdown,
|
||||
.prepare = pxa2xx_ac97_pcm_prepare,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int pxa2xx_ac97_do_suspend(struct snd_card *card)
|
||||
|
|
@ -193,6 +174,53 @@ static int pxa2xx_ac97_resume(struct device *dev)
|
|||
static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume);
|
||||
#endif
|
||||
|
||||
static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
|
||||
.open = pxa2xx_ac97_pcm_open,
|
||||
.close = pxa2xx_ac97_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = pxa2xx_pcm_hw_params,
|
||||
.hw_free = pxa2xx_pcm_hw_free,
|
||||
.prepare = pxa2xx_ac97_pcm_prepare,
|
||||
.trigger = pxa2xx_pcm_trigger,
|
||||
.pointer = pxa2xx_pcm_pointer,
|
||||
.mmap = pxa2xx_pcm_mmap,
|
||||
};
|
||||
|
||||
|
||||
static int pxa2xx_ac97_pcm_new(struct snd_card *card)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
int stream, ret;
|
||||
|
||||
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, 1, 1, &pcm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pcm->private_free = pxa2xx_pcm_free_dma_buffers;
|
||||
|
||||
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
stream = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
|
||||
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
stream = SNDRV_PCM_STREAM_CAPTURE;
|
||||
snd_pcm_set_ops(pcm, stream, &pxa2xx_ac97_pcm_ops);
|
||||
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pxa2xx_ac97_pcm = pcm;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pxa2xx_ac97_probe(struct platform_device *dev)
|
||||
{
|
||||
struct snd_card *card;
|
||||
|
|
@ -214,7 +242,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
|
|||
|
||||
strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
|
||||
|
||||
ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);
|
||||
ret = pxa2xx_ac97_pcm_new(card);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@
|
|||
#include <sound/pxa2xx-lib.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
#include "pxa2xx-pcm.h"
|
||||
|
||||
static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
|
|
@ -25,8 +23,8 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
|
|||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_RESUME,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE,
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE,
|
||||
.period_bytes_min = 32,
|
||||
.period_bytes_max = 8192 - 32,
|
||||
.periods_min = 1,
|
||||
|
|
@ -35,8 +33,8 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
|
|||
.fifo_size = 32,
|
||||
};
|
||||
|
||||
int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
|
|
@ -64,14 +62,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__pxa2xx_pcm_hw_params);
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
|
||||
|
||||
int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
snd_pcm_set_runtime_buffer(substream, NULL);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__pxa2xx_pcm_hw_free);
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_hw_free);
|
||||
|
||||
int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
|
|
@ -86,13 +84,13 @@ pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
|
|||
}
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_pointer);
|
||||
|
||||
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_prepare);
|
||||
|
||||
int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
|
@ -125,17 +123,17 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return snd_dmaengine_pcm_open_request_chan(substream,
|
||||
pxad_filter_fn,
|
||||
dma_params->filter_data);
|
||||
return snd_dmaengine_pcm_open(
|
||||
substream, dma_request_slave_channel(rtd->cpu_dai->dev,
|
||||
dma_params->chan_name));
|
||||
}
|
||||
EXPORT_SYMBOL(__pxa2xx_pcm_open);
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_open);
|
||||
|
||||
int __pxa2xx_pcm_close(struct snd_pcm_substream *substream)
|
||||
int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_dmaengine_pcm_close_release_chan(substream);
|
||||
}
|
||||
EXPORT_SYMBOL(__pxa2xx_pcm_close);
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_close);
|
||||
|
||||
int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma)
|
||||
|
|
@ -181,6 +179,47 @@ void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
|
|||
}
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
|
||||
|
||||
int pxa2xx_soc_pcm_new(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) {
|
||||
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
|
||||
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
|
||||
|
||||
const struct snd_pcm_ops pxa2xx_pcm_ops = {
|
||||
.open = pxa2xx_pcm_open,
|
||||
.close = pxa2xx_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = pxa2xx_pcm_hw_params,
|
||||
.hw_free = pxa2xx_pcm_hw_free,
|
||||
.prepare = pxa2xx_pcm_prepare,
|
||||
.trigger = pxa2xx_pcm_trigger,
|
||||
.pointer = pxa2xx_pcm_pointer,
|
||||
.mmap = pxa2xx_pcm_mmap,
|
||||
};
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_ops);
|
||||
|
||||
MODULE_AUTHOR("Nicolas Pitre");
|
||||
MODULE_DESCRIPTION("Intel PXA2xx sound library");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Nov 30, 2004
|
||||
* Copyright: (C) 2004 MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pxa2xx-lib.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
|
||||
#include "pxa2xx-pcm.h"
|
||||
|
||||
static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct pxa2xx_pcm_client *client = substream->private_data;
|
||||
|
||||
__pxa2xx_pcm_prepare(substream);
|
||||
|
||||
return client->prepare(substream);
|
||||
}
|
||||
|
||||
static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct pxa2xx_pcm_client *client = substream->private_data;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct pxa2xx_runtime_data *rtd;
|
||||
int ret;
|
||||
|
||||
ret = __pxa2xx_pcm_open(substream);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
rtd = runtime->private_data;
|
||||
|
||||
rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
client->playback_params : client->capture_params;
|
||||
|
||||
ret = client->startup(substream);
|
||||
if (!ret)
|
||||
goto err2;
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
__pxa2xx_pcm_close(substream);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct pxa2xx_pcm_client *client = substream->private_data;
|
||||
|
||||
client->shutdown(substream);
|
||||
|
||||
return __pxa2xx_pcm_close(substream);
|
||||
}
|
||||
|
||||
static const struct snd_pcm_ops pxa2xx_pcm_ops = {
|
||||
.open = pxa2xx_pcm_open,
|
||||
.close = pxa2xx_pcm_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = __pxa2xx_pcm_hw_params,
|
||||
.hw_free = __pxa2xx_pcm_hw_free,
|
||||
.prepare = pxa2xx_pcm_prepare,
|
||||
.trigger = pxa2xx_pcm_trigger,
|
||||
.pointer = pxa2xx_pcm_pointer,
|
||||
.mmap = pxa2xx_pcm_mmap,
|
||||
};
|
||||
|
||||
int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
|
||||
struct snd_pcm **rpcm)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
int play = client->playback_params ? 1 : 0;
|
||||
int capt = client->capture_params ? 1 : 0;
|
||||
int ret;
|
||||
|
||||
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pcm->private_data = client;
|
||||
pcm->private_free = pxa2xx_pcm_free_dma_buffers;
|
||||
|
||||
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (play) {
|
||||
int stream = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
|
||||
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
if (capt) {
|
||||
int stream = SNDRV_PCM_STREAM_CAPTURE;
|
||||
snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
|
||||
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rpcm)
|
||||
*rpcm = pcm;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pxa2xx_pcm_new);
|
||||
|
||||
MODULE_AUTHOR("Nicolas Pitre");
|
||||
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Nov 30, 2004
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
struct pxa2xx_runtime_data {
|
||||
int dma_ch;
|
||||
struct snd_dmaengine_dai_dma_data *params;
|
||||
};
|
||||
|
||||
struct pxa2xx_pcm_client {
|
||||
struct snd_dmaengine_dai_dma_data *playback_params;
|
||||
struct snd_dmaengine_dai_dma_data *capture_params;
|
||||
int (*startup)(struct snd_pcm_substream *);
|
||||
void (*shutdown)(struct snd_pcm_substream *);
|
||||
int (*prepare)(struct snd_pcm_substream *);
|
||||
};
|
||||
|
||||
extern int pxa2xx_pcm_new(struct snd_card *, struct pxa2xx_pcm_client *, struct snd_pcm **);
|
||||
|
||||
|
|
@ -57,6 +57,7 @@ source "sound/soc/kirkwood/Kconfig"
|
|||
source "sound/soc/img/Kconfig"
|
||||
source "sound/soc/intel/Kconfig"
|
||||
source "sound/soc/mediatek/Kconfig"
|
||||
source "sound/soc/meson/Kconfig"
|
||||
source "sound/soc/mxs/Kconfig"
|
||||
source "sound/soc/pxa/Kconfig"
|
||||
source "sound/soc/qcom/Kconfig"
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ obj-$(CONFIG_SND_SOC) += jz4740/
|
|||
obj-$(CONFIG_SND_SOC) += img/
|
||||
obj-$(CONFIG_SND_SOC) += intel/
|
||||
obj-$(CONFIG_SND_SOC) += mediatek/
|
||||
obj-$(CONFIG_SND_SOC) += meson/
|
||||
obj-$(CONFIG_SND_SOC) += mxs/
|
||||
obj-$(CONFIG_SND_SOC) += nuc900/
|
||||
obj-$(CONFIG_SND_SOC) += omap/
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
|
|||
select SND_SOC_DA7219
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_ADAU7002
|
||||
select REGULATOR
|
||||
depends on SND_SOC_AMD_ACP && I2C
|
||||
help
|
||||
This option enables machine driver for DA7219 and MAX9835.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/acpi.h>
|
||||
|
|
@ -148,7 +150,8 @@ static int cz_da7219_startup(struct snd_pcm_substream *substream)
|
|||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_rates);
|
||||
|
||||
machine->i2s_instance = I2S_BT_INSTANCE;
|
||||
machine->i2s_instance = I2S_SP_INSTANCE;
|
||||
machine->capture_channel = CAP_CHANNEL1;
|
||||
return da7219_clk_enable(substream);
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +166,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
|
|||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->i2s_instance = I2S_SP_INSTANCE;
|
||||
machine->i2s_instance = I2S_BT_INSTANCE;
|
||||
return da7219_clk_enable(substream);
|
||||
}
|
||||
|
||||
|
|
@ -172,13 +175,24 @@ static void cz_max_shutdown(struct snd_pcm_substream *substream)
|
|||
da7219_clk_disable();
|
||||
}
|
||||
|
||||
static int cz_dmic_startup(struct snd_pcm_substream *substream)
|
||||
static int cz_dmic0_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->i2s_instance = I2S_BT_INSTANCE;
|
||||
return da7219_clk_enable(substream);
|
||||
}
|
||||
|
||||
static int cz_dmic1_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
machine->i2s_instance = I2S_SP_INSTANCE;
|
||||
machine->capture_channel = CAP_CHANNEL0;
|
||||
return da7219_clk_enable(substream);
|
||||
}
|
||||
|
||||
|
|
@ -197,23 +211,39 @@ static const struct snd_soc_ops cz_max_play_ops = {
|
|||
.shutdown = cz_max_shutdown,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops cz_dmic_cap_ops = {
|
||||
.startup = cz_dmic_startup,
|
||||
static const struct snd_soc_ops cz_dmic0_cap_ops = {
|
||||
.startup = cz_dmic0_startup,
|
||||
.shutdown = cz_dmic_shutdown,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops cz_dmic1_cap_ops = {
|
||||
.startup = cz_dmic1_startup,
|
||||
.shutdown = cz_dmic_shutdown,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link cz_dai_7219_98357[] = {
|
||||
{
|
||||
.name = "amd-da7219-play-cap",
|
||||
.stream_name = "Playback and Capture",
|
||||
.name = "amd-da7219-play",
|
||||
.stream_name = "Playback",
|
||||
.platform_name = "acp_audio_dma.0.auto",
|
||||
.cpu_dai_name = "designware-i2s.3.auto",
|
||||
.cpu_dai_name = "designware-i2s.1.auto",
|
||||
.codec_dai_name = "da7219-hifi",
|
||||
.codec_name = "i2c-DLGS7219:00",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.init = cz_da7219_init,
|
||||
.dpcm_playback = 1,
|
||||
.ops = &cz_da7219_cap_ops,
|
||||
},
|
||||
{
|
||||
.name = "amd-da7219-cap",
|
||||
.stream_name = "Capture",
|
||||
.platform_name = "acp_audio_dma.0.auto",
|
||||
.cpu_dai_name = "designware-i2s.2.auto",
|
||||
.codec_dai_name = "da7219-hifi",
|
||||
.codec_name = "i2c-DLGS7219:00",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &cz_da7219_cap_ops,
|
||||
},
|
||||
|
|
@ -221,7 +251,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
|
|||
.name = "amd-max98357-play",
|
||||
.stream_name = "HiFi Playback",
|
||||
.platform_name = "acp_audio_dma.0.auto",
|
||||
.cpu_dai_name = "designware-i2s.1.auto",
|
||||
.cpu_dai_name = "designware-i2s.3.auto",
|
||||
.codec_dai_name = "HiFi",
|
||||
.codec_name = "MX98357A:00",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
|
|
@ -230,8 +260,22 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
|
|||
.ops = &cz_max_play_ops,
|
||||
},
|
||||
{
|
||||
.name = "dmic",
|
||||
.stream_name = "DMIC Capture",
|
||||
/* C panel DMIC */
|
||||
.name = "dmic0",
|
||||
.stream_name = "DMIC0 Capture",
|
||||
.platform_name = "acp_audio_dma.0.auto",
|
||||
.cpu_dai_name = "designware-i2s.3.auto",
|
||||
.codec_dai_name = "adau7002-hifi",
|
||||
.codec_name = "ADAU7002:00",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &cz_dmic0_cap_ops,
|
||||
},
|
||||
{
|
||||
/* A/B panel DMIC */
|
||||
.name = "dmic1",
|
||||
.stream_name = "DMIC1 Capture",
|
||||
.platform_name = "acp_audio_dma.0.auto",
|
||||
.cpu_dai_name = "designware-i2s.2.auto",
|
||||
.codec_dai_name = "adau7002-hifi",
|
||||
|
|
@ -239,7 +283,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
|
|||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &cz_dmic_cap_ops,
|
||||
.ops = &cz_dmic1_cap_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -278,11 +322,52 @@ static struct snd_soc_card cz_card = {
|
|||
.num_controls = ARRAY_SIZE(cz_mc_controls),
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply acp_da7219_supplies[] = {
|
||||
REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
|
||||
REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
|
||||
REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
|
||||
REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
|
||||
};
|
||||
|
||||
static struct regulator_init_data acp_da7219_data = {
|
||||
.constraints = {
|
||||
.always_on = 1,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
|
||||
.consumer_supplies = acp_da7219_supplies,
|
||||
};
|
||||
|
||||
static struct regulator_config acp_da7219_cfg = {
|
||||
.init_data = &acp_da7219_data,
|
||||
};
|
||||
|
||||
static struct regulator_ops acp_da7219_ops = {
|
||||
};
|
||||
|
||||
static struct regulator_desc acp_da7219_desc = {
|
||||
.name = "reg-fixed-1.8V",
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.ops = &acp_da7219_ops,
|
||||
.fixed_uV = 1800000, /* 1.8V */
|
||||
.n_voltages = 1,
|
||||
};
|
||||
|
||||
static int cz_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_card *card;
|
||||
struct acp_platform_info *machine;
|
||||
struct regulator_dev *rdev;
|
||||
|
||||
acp_da7219_cfg.dev = &pdev->dev;
|
||||
rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc,
|
||||
&acp_da7219_cfg);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "Failed to register regulator: %d\n",
|
||||
(int)PTR_ERR(rdev));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info),
|
||||
GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -224,13 +224,11 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
|
|||
switch (asic_type) {
|
||||
case CHIP_STONEY:
|
||||
dmadscr[i].xfer_val |=
|
||||
BIT(22) |
|
||||
(ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) |
|
||||
(size / 2);
|
||||
break;
|
||||
default:
|
||||
dmadscr[i].xfer_val |=
|
||||
BIT(22) |
|
||||
(ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) |
|
||||
(size / 2);
|
||||
}
|
||||
|
|
@ -322,22 +320,87 @@ static void config_acp_dma(void __iomem *acp_mmio,
|
|||
struct audio_substream_data *rtd,
|
||||
u32 asic_type)
|
||||
{
|
||||
u16 ch_acp_sysmem, ch_acp_i2s;
|
||||
|
||||
acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
|
||||
rtd->pte_offset);
|
||||
|
||||
if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
ch_acp_sysmem = rtd->ch1;
|
||||
ch_acp_i2s = rtd->ch2;
|
||||
} else {
|
||||
ch_acp_i2s = rtd->ch1;
|
||||
ch_acp_sysmem = rtd->ch2;
|
||||
}
|
||||
/* Configure System memory <-> ACP SRAM DMA descriptors */
|
||||
set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
|
||||
rtd->direction, rtd->pte_offset,
|
||||
rtd->ch1, rtd->sram_bank,
|
||||
ch_acp_sysmem, rtd->sram_bank,
|
||||
rtd->dma_dscr_idx_1, asic_type);
|
||||
/* Configure ACP SRAM <-> I2S DMA descriptors */
|
||||
set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
|
||||
rtd->direction, rtd->sram_bank,
|
||||
rtd->destination, rtd->ch2,
|
||||
rtd->destination, ch_acp_i2s,
|
||||
rtd->dma_dscr_idx_2, asic_type);
|
||||
}
|
||||
|
||||
static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
|
||||
u16 cap_channel)
|
||||
{
|
||||
u32 val, ch_reg, imr_reg, res_reg;
|
||||
|
||||
switch (cap_channel) {
|
||||
case CAP_CHANNEL1:
|
||||
ch_reg = mmACP_I2SMICSP_RER1;
|
||||
res_reg = mmACP_I2SMICSP_RCR1;
|
||||
imr_reg = mmACP_I2SMICSP_IMR1;
|
||||
break;
|
||||
case CAP_CHANNEL0:
|
||||
default:
|
||||
ch_reg = mmACP_I2SMICSP_RER0;
|
||||
res_reg = mmACP_I2SMICSP_RCR0;
|
||||
imr_reg = mmACP_I2SMICSP_IMR0;
|
||||
break;
|
||||
}
|
||||
val = acp_reg_read(acp_mmio,
|
||||
mmACP_I2S_16BIT_RESOLUTION_EN);
|
||||
if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) {
|
||||
acp_reg_write(0x0, acp_mmio, ch_reg);
|
||||
/* Set 16bit resolution on capture */
|
||||
acp_reg_write(0x2, acp_mmio, res_reg);
|
||||
}
|
||||
val = acp_reg_read(acp_mmio, imr_reg);
|
||||
val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
|
||||
val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
|
||||
acp_reg_write(val, acp_mmio, imr_reg);
|
||||
acp_reg_write(0x1, acp_mmio, ch_reg);
|
||||
}
|
||||
|
||||
static void acp_dma_cap_channel_disable(void __iomem *acp_mmio,
|
||||
u16 cap_channel)
|
||||
{
|
||||
u32 val, ch_reg, imr_reg;
|
||||
|
||||
switch (cap_channel) {
|
||||
case CAP_CHANNEL1:
|
||||
imr_reg = mmACP_I2SMICSP_IMR1;
|
||||
ch_reg = mmACP_I2SMICSP_RER1;
|
||||
break;
|
||||
case CAP_CHANNEL0:
|
||||
default:
|
||||
imr_reg = mmACP_I2SMICSP_IMR0;
|
||||
ch_reg = mmACP_I2SMICSP_RER0;
|
||||
break;
|
||||
}
|
||||
val = acp_reg_read(acp_mmio, imr_reg);
|
||||
val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
|
||||
val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
|
||||
acp_reg_write(val, acp_mmio, imr_reg);
|
||||
acp_reg_write(0x0, acp_mmio, ch_reg);
|
||||
}
|
||||
|
||||
/* Start a given DMA channel transfer */
|
||||
static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
|
||||
static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
|
||||
{
|
||||
u32 dma_ctrl;
|
||||
|
||||
|
|
@ -356,10 +419,8 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
|
|||
|
||||
switch (ch_num) {
|
||||
case ACP_TO_I2S_DMA_CH_NUM:
|
||||
case ACP_TO_SYSRAM_CH_NUM:
|
||||
case I2S_TO_ACP_DMA_CH_NUM:
|
||||
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
|
||||
case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
|
||||
case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
|
||||
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
|
||||
break;
|
||||
|
|
@ -368,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
|
|||
break;
|
||||
}
|
||||
|
||||
/* circular for both DMA channel */
|
||||
dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
|
||||
/* enable for ACP to SRAM DMA channel */
|
||||
if (is_circular == true)
|
||||
dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
|
||||
else
|
||||
dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
|
||||
|
||||
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
|
||||
}
|
||||
|
|
@ -613,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio)
|
|||
/* ACP DMA irq handler routine for playback, capture usecases */
|
||||
static irqreturn_t dma_irq_handler(int irq, void *arg)
|
||||
{
|
||||
u16 dscr_idx;
|
||||
u32 intr_flag, ext_intr_status;
|
||||
struct audio_drv_data *irq_data;
|
||||
void __iomem *acp_mmio;
|
||||
|
|
@ -644,32 +709,39 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
|
|||
|
||||
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
|
||||
valid_irq = true;
|
||||
if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) ==
|
||||
CAPTURE_START_DMA_DESCR_CH15)
|
||||
dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
|
||||
else
|
||||
dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
|
||||
config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
|
||||
1, 0);
|
||||
acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
|
||||
|
||||
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
|
||||
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
|
||||
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
|
||||
}
|
||||
|
||||
if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
|
||||
valid_irq = true;
|
||||
acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
|
||||
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
|
||||
}
|
||||
|
||||
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
|
||||
valid_irq = true;
|
||||
if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) ==
|
||||
CAPTURE_START_DMA_DESCR_CH11)
|
||||
dscr_idx = CAPTURE_END_DMA_DESCR_CH10;
|
||||
else
|
||||
dscr_idx = CAPTURE_START_DMA_DESCR_CH10;
|
||||
config_acp_dma_channel(acp_mmio,
|
||||
ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
|
||||
dscr_idx, 1, 0);
|
||||
acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
|
||||
false);
|
||||
|
||||
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
|
||||
acp_reg_write((intr_flag &
|
||||
BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
|
||||
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
|
||||
}
|
||||
|
||||
if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
|
||||
valid_irq = true;
|
||||
acp_reg_write((intr_flag &
|
||||
BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
|
||||
acp_mmio, mmACP_EXTERNAL_INTR_STAT);
|
||||
}
|
||||
|
||||
if (valid_irq)
|
||||
return IRQ_HANDLED;
|
||||
else
|
||||
|
|
@ -773,7 +845,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
|
|||
if (WARN_ON(!rtd))
|
||||
return -EINVAL;
|
||||
|
||||
rtd->i2s_instance = pinfo->i2s_instance;
|
||||
if (pinfo) {
|
||||
rtd->i2s_instance = pinfo->i2s_instance;
|
||||
rtd->capture_channel = pinfo->capture_channel;
|
||||
}
|
||||
if (adata->asic_type == CHIP_STONEY) {
|
||||
val = acp_reg_read(adata->acp_mmio,
|
||||
mmACP_I2S_16BIT_RESOLUTION_EN);
|
||||
|
|
@ -841,8 +916,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
|
|||
switch (rtd->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET;
|
||||
rtd->ch1 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
|
||||
rtd->ch2 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
|
||||
rtd->ch1 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM;
|
||||
rtd->ch2 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM;
|
||||
rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS;
|
||||
rtd->destination = FROM_BLUETOOTH;
|
||||
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
|
||||
|
|
@ -851,13 +926,14 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
|
|||
mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
|
||||
rtd->byte_cnt_low_reg_offset =
|
||||
mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
|
||||
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
|
||||
adata->capture_i2sbt_stream = substream;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET;
|
||||
rtd->ch1 = ACP_TO_SYSRAM_CH_NUM;
|
||||
rtd->ch2 = I2S_TO_ACP_DMA_CH_NUM;
|
||||
rtd->ch1 = I2S_TO_ACP_DMA_CH_NUM;
|
||||
rtd->ch2 = ACP_TO_SYSRAM_CH_NUM;
|
||||
switch (adata->asic_type) {
|
||||
case CHIP_STONEY:
|
||||
rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET;
|
||||
|
|
@ -874,6 +950,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
|
|||
mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
|
||||
rtd->byte_cnt_low_reg_offset =
|
||||
mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
|
||||
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
|
||||
adata->capture_i2ssp_stream = substream;
|
||||
}
|
||||
}
|
||||
|
|
@ -927,6 +1004,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
|
|||
u32 buffersize;
|
||||
u32 pos = 0;
|
||||
u64 bytescount = 0;
|
||||
u16 dscr;
|
||||
u32 period_bytes, delay;
|
||||
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct audio_substream_data *rtd = runtime->private_data;
|
||||
|
|
@ -934,12 +1013,25 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
|
|||
if (!rtd)
|
||||
return -EINVAL;
|
||||
|
||||
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
|
||||
bytescount = acp_get_byte_count(rtd);
|
||||
|
||||
if (bytescount > rtd->bytescount)
|
||||
bytescount -= rtd->bytescount;
|
||||
pos = do_div(bytescount, buffersize);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
period_bytes = frames_to_bytes(runtime, runtime->period_size);
|
||||
dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
|
||||
if (dscr == rtd->dma_dscr_idx_1)
|
||||
pos = period_bytes;
|
||||
else
|
||||
pos = 0;
|
||||
bytescount = acp_get_byte_count(rtd);
|
||||
if (bytescount > rtd->bytescount)
|
||||
bytescount -= rtd->bytescount;
|
||||
delay = do_div(bytescount, period_bytes);
|
||||
runtime->delay = bytes_to_frames(runtime, delay);
|
||||
} else {
|
||||
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
|
||||
bytescount = acp_get_byte_count(rtd);
|
||||
if (bytescount > rtd->bytescount)
|
||||
bytescount -= rtd->bytescount;
|
||||
pos = do_div(bytescount, buffersize);
|
||||
}
|
||||
return bytes_to_frames(runtime, pos);
|
||||
}
|
||||
|
||||
|
|
@ -953,16 +1045,24 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream)
|
|||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct audio_substream_data *rtd = runtime->private_data;
|
||||
u16 ch_acp_sysmem, ch_acp_i2s;
|
||||
|
||||
if (!rtd)
|
||||
return -EINVAL;
|
||||
|
||||
if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
ch_acp_sysmem = rtd->ch1;
|
||||
ch_acp_i2s = rtd->ch2;
|
||||
} else {
|
||||
ch_acp_i2s = rtd->ch1;
|
||||
ch_acp_sysmem = rtd->ch2;
|
||||
}
|
||||
config_acp_dma_channel(rtd->acp_mmio,
|
||||
rtd->ch1,
|
||||
ch_acp_sysmem,
|
||||
rtd->dma_dscr_idx_1,
|
||||
NUM_DSCRS_PER_CHANNEL, 0);
|
||||
config_acp_dma_channel(rtd->acp_mmio,
|
||||
rtd->ch2,
|
||||
ch_acp_i2s,
|
||||
rtd->dma_dscr_idx_2,
|
||||
NUM_DSCRS_PER_CHANNEL, 0);
|
||||
return 0;
|
||||
|
|
@ -971,7 +1071,6 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream)
|
|||
static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
int ret;
|
||||
u64 bytescount = 0;
|
||||
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct audio_substream_data *rtd = runtime->private_data;
|
||||
|
|
@ -982,37 +1081,32 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
bytescount = acp_get_byte_count(rtd);
|
||||
if (rtd->bytescount == 0)
|
||||
rtd->bytescount = bytescount;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch1);
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch2);
|
||||
rtd->bytescount = acp_get_byte_count(rtd);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
if (rtd->capture_channel == CAP_CHANNEL0) {
|
||||
acp_dma_cap_channel_disable(rtd->acp_mmio,
|
||||
CAP_CHANNEL1);
|
||||
acp_dma_cap_channel_enable(rtd->acp_mmio,
|
||||
CAP_CHANNEL0);
|
||||
}
|
||||
if (rtd->capture_channel == CAP_CHANNEL1) {
|
||||
acp_dma_cap_channel_disable(rtd->acp_mmio,
|
||||
CAP_CHANNEL0);
|
||||
acp_dma_cap_channel_enable(rtd->acp_mmio,
|
||||
CAP_CHANNEL1);
|
||||
}
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
|
||||
} else {
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch2);
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch1);
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
|
||||
acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
/* For playback, non circular dma should be stopped first
|
||||
* i.e Sysram to acp dma transfer channel(rtd->ch1) should be
|
||||
* stopped before stopping cirular dma which is acp sram to i2s
|
||||
* fifo dma transfer channel(rtd->ch2). Where as in Capture
|
||||
* scenario, i2s fifo to acp sram dma channel(rtd->ch2) stopped
|
||||
* first before stopping acp sram to sysram which is circular
|
||||
* dma(rtd->ch1).
|
||||
*/
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
acp_dma_stop(rtd->acp_mmio, rtd->ch1);
|
||||
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch2);
|
||||
} else {
|
||||
acp_dma_stop(rtd->acp_mmio, rtd->ch2);
|
||||
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
|
||||
}
|
||||
rtd->bytescount = 0;
|
||||
acp_dma_stop(rtd->acp_mmio, rtd->ch2);
|
||||
ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@
|
|||
|
||||
#define I2S_SP_INSTANCE 0x01
|
||||
#define I2S_BT_INSTANCE 0x02
|
||||
#define CAP_CHANNEL0 0x00
|
||||
#define CAP_CHANNEL1 0x01
|
||||
|
||||
#define ACP_TILE_ON_MASK 0x03
|
||||
#define ACP_TILE_OFF_MASK 0x02
|
||||
|
|
@ -72,16 +74,16 @@
|
|||
#define ACP_TO_I2S_DMA_CH_NUM 13
|
||||
|
||||
/* Capture DMA channels */
|
||||
#define ACP_TO_SYSRAM_CH_NUM 14
|
||||
#define I2S_TO_ACP_DMA_CH_NUM 15
|
||||
#define I2S_TO_ACP_DMA_CH_NUM 14
|
||||
#define ACP_TO_SYSRAM_CH_NUM 15
|
||||
|
||||
/* Playback DMA Channels for I2S BT instance */
|
||||
#define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM 8
|
||||
#define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9
|
||||
|
||||
/* Capture DMA Channels for I2S BT Instance */
|
||||
#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 10
|
||||
#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 11
|
||||
#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10
|
||||
#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11
|
||||
|
||||
#define NUM_DSCRS_PER_CHANNEL 2
|
||||
|
||||
|
|
@ -125,6 +127,7 @@ struct audio_substream_data {
|
|||
unsigned int order;
|
||||
u16 num_of_pages;
|
||||
u16 i2s_instance;
|
||||
u16 capture_channel;
|
||||
u16 direction;
|
||||
u16 ch1;
|
||||
u16 ch2;
|
||||
|
|
@ -135,6 +138,7 @@ struct audio_substream_data {
|
|||
u32 sram_bank;
|
||||
u32 byte_cnt_high_reg_offset;
|
||||
u32 byte_cnt_low_reg_offset;
|
||||
u32 dma_curr_dscr;
|
||||
uint64_t size;
|
||||
u64 bytescount;
|
||||
void __iomem *acp_mmio;
|
||||
|
|
@ -155,6 +159,7 @@ struct audio_drv_data {
|
|||
*/
|
||||
struct acp_platform_info {
|
||||
u16 i2s_instance;
|
||||
u16 capture_channel;
|
||||
};
|
||||
|
||||
union acp_dma_count {
|
||||
|
|
|
|||
|
|
@ -206,7 +206,6 @@ struct atmel_i2s_dev {
|
|||
struct regmap *regmap;
|
||||
struct clk *pclk;
|
||||
struct clk *gclk;
|
||||
struct clk *aclk;
|
||||
struct snd_dmaengine_dai_dma_data playback;
|
||||
struct snd_dmaengine_dai_dma_data capture;
|
||||
unsigned int fmt;
|
||||
|
|
@ -303,7 +302,7 @@ static int atmel_i2s_get_gck_param(struct atmel_i2s_dev *dev, int fs)
|
|||
{
|
||||
int i, best;
|
||||
|
||||
if (!dev->gclk || !dev->aclk) {
|
||||
if (!dev->gclk) {
|
||||
dev_err(dev->dev, "cannot generate the I2S Master Clock\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -421,7 +420,7 @@ static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
|
|||
bool enabled)
|
||||
{
|
||||
unsigned int mr, mr_mask;
|
||||
unsigned long aclk_rate;
|
||||
unsigned long gclk_rate;
|
||||
int ret;
|
||||
|
||||
mr = 0;
|
||||
|
|
@ -445,35 +444,18 @@ static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
|
|||
/* Disable/unprepare the PMC generated clock. */
|
||||
clk_disable_unprepare(dev->gclk);
|
||||
|
||||
/* Disable/unprepare the PLL audio clock. */
|
||||
clk_disable_unprepare(dev->aclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev->gck_param)
|
||||
return -EINVAL;
|
||||
|
||||
aclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
|
||||
gclk_rate = dev->gck_param->mck * (dev->gck_param->imckdiv + 1);
|
||||
|
||||
/* Fist change the PLL audio clock frequency ... */
|
||||
ret = clk_set_rate(dev->aclk, aclk_rate);
|
||||
ret = clk_set_rate(dev->gclk, gclk_rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* ... then set the PMC generated clock rate to the very same frequency
|
||||
* to set the gclk parent to aclk.
|
||||
*/
|
||||
ret = clk_set_rate(dev->gclk, aclk_rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Prepare and enable the PLL audio clock first ... */
|
||||
ret = clk_prepare_enable(dev->aclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* ... then prepare and enable the PMC generated clock. */
|
||||
ret = clk_prepare_enable(dev->gclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -668,28 +650,14 @@ static int atmel_i2s_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Get audio clocks to generate the I2S Master Clock (I2S_MCK) */
|
||||
dev->aclk = devm_clk_get(&pdev->dev, "aclk");
|
||||
/* Get audio clock to generate the I2S Master Clock (I2S_MCK) */
|
||||
dev->gclk = devm_clk_get(&pdev->dev, "gclk");
|
||||
if (IS_ERR(dev->aclk) && IS_ERR(dev->gclk)) {
|
||||
if (PTR_ERR(dev->aclk) == -EPROBE_DEFER ||
|
||||
PTR_ERR(dev->gclk) == -EPROBE_DEFER)
|
||||
if (IS_ERR(dev->gclk)) {
|
||||
if (PTR_ERR(dev->gclk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
/* Master Mode not supported */
|
||||
dev->aclk = NULL;
|
||||
dev->gclk = NULL;
|
||||
} else if (IS_ERR(dev->gclk)) {
|
||||
err = PTR_ERR(dev->gclk);
|
||||
dev_err(&pdev->dev,
|
||||
"failed to get the PMC generated clock: %d\n", err);
|
||||
return err;
|
||||
} else if (IS_ERR(dev->aclk)) {
|
||||
err = PTR_ERR(dev->aclk);
|
||||
dev_err(&pdev->dev,
|
||||
"failed to get the PLL audio clock: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev->dev = &pdev->dev;
|
||||
dev->regmap = regmap;
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
|
|
|||
|
|
@ -74,12 +74,12 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_DA7219 if I2C
|
||||
select SND_SOC_DA732X if I2C
|
||||
select SND_SOC_DA9055 if I2C
|
||||
select SND_SOC_DIO2125
|
||||
select SND_SOC_DMIC if GPIOLIB
|
||||
select SND_SOC_ES8316 if I2C
|
||||
select SND_SOC_ES8328_SPI if SPI_MASTER
|
||||
select SND_SOC_ES8328_I2C if I2C
|
||||
select SND_SOC_ES7134
|
||||
select SND_SOC_ES7241
|
||||
select SND_SOC_GTM601
|
||||
select SND_SOC_HDAC_HDMI
|
||||
select SND_SOC_ICS43432
|
||||
|
|
@ -141,8 +141,10 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_RT5668 if I2C
|
||||
select SND_SOC_RT5670 if I2C
|
||||
select SND_SOC_RT5677 if I2C && SPI_MASTER
|
||||
select SND_SOC_RT5682 if I2C
|
||||
select SND_SOC_SGTL5000 if I2C
|
||||
select SND_SOC_SI476X if MFD_SI476X_CORE
|
||||
select SND_SOC_SIMPLE_AMPLIFIER
|
||||
select SND_SOC_SIRF_AUDIO_CODEC
|
||||
select SND_SOC_SPDIF
|
||||
select SND_SOC_SSM2305
|
||||
|
|
@ -572,10 +574,6 @@ config SND_SOC_DA732X
|
|||
config SND_SOC_DA9055
|
||||
tristate
|
||||
|
||||
config SND_SOC_DIO2125
|
||||
tristate "Dioo DIO2125 Amplifier"
|
||||
select GPIOLIB
|
||||
|
||||
config SND_SOC_DMIC
|
||||
tristate
|
||||
|
||||
|
|
@ -588,6 +586,9 @@ config SND_SOC_HDMI_CODEC
|
|||
config SND_SOC_ES7134
|
||||
tristate "Everest Semi ES7134 CODEC"
|
||||
|
||||
config SND_SOC_ES7241
|
||||
tristate "Everest Semi ES7241 CODEC"
|
||||
|
||||
config SND_SOC_ES8316
|
||||
tristate "Everest Semi ES8316 CODEC"
|
||||
depends on I2C
|
||||
|
|
@ -778,6 +779,7 @@ config SND_SOC_RL6231
|
|||
default y if SND_SOC_RT5668=y
|
||||
default y if SND_SOC_RT5670=y
|
||||
default y if SND_SOC_RT5677=y
|
||||
default y if SND_SOC_RT5682=y
|
||||
default y if SND_SOC_RT1305=y
|
||||
default m if SND_SOC_RT5514=m
|
||||
default m if SND_SOC_RT5616=m
|
||||
|
|
@ -791,6 +793,7 @@ config SND_SOC_RL6231
|
|||
default m if SND_SOC_RT5668=m
|
||||
default m if SND_SOC_RT5670=m
|
||||
default m if SND_SOC_RT5677=m
|
||||
default m if SND_SOC_RT5682=m
|
||||
default m if SND_SOC_RT1305=m
|
||||
|
||||
config SND_SOC_RL6347A
|
||||
|
|
@ -871,6 +874,9 @@ config SND_SOC_RT5677_SPI
|
|||
tristate
|
||||
default SND_SOC_RT5677 && SPI
|
||||
|
||||
config SND_SOC_RT5682
|
||||
tristate
|
||||
|
||||
#Freescale sgtl5000 codec
|
||||
config SND_SOC_SGTL5000
|
||||
tristate "Freescale SGTL5000 CODEC"
|
||||
|
|
@ -891,6 +897,10 @@ config SND_SOC_SIGMADSP_REGMAP
|
|||
tristate
|
||||
select SND_SOC_SIGMADSP
|
||||
|
||||
config SND_SOC_SIMPLE_AMPLIFIER
|
||||
tristate "Simple Audio Amplifier"
|
||||
select GPIOLIB
|
||||
|
||||
config SND_SOC_SIRF_AUDIO_CODEC
|
||||
tristate "SiRF SoC internal audio codec"
|
||||
select REGMAP_MMIO
|
||||
|
|
@ -953,8 +963,11 @@ config SND_SOC_TAS5086
|
|||
depends on I2C
|
||||
|
||||
config SND_SOC_TAS571X
|
||||
tristate "Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 power amplifiers"
|
||||
tristate "Texas Instruments TAS571x power amplifiers"
|
||||
depends on I2C
|
||||
help
|
||||
Enable support for Texas Instruments TAS5707, TAS5711, TAS5717,
|
||||
TAS5719 and TAS5721 power amplifiers
|
||||
|
||||
config SND_SOC_TAS5720
|
||||
tristate "Texas Instruments TAS5720 Mono Audio amplifier"
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ snd-soc-da732x-objs := da732x.o
|
|||
snd-soc-da9055-objs := da9055.o
|
||||
snd-soc-dmic-objs := dmic.o
|
||||
snd-soc-es7134-objs := es7134.o
|
||||
snd-soc-es7241-objs := es7241.o
|
||||
snd-soc-es8316-objs := es8316.o
|
||||
snd-soc-es8328-objs := es8328.o
|
||||
snd-soc-es8328-i2c-objs := es8328-i2c.o
|
||||
|
|
@ -146,6 +147,7 @@ snd-soc-rt5668-objs := rt5668.o
|
|||
snd-soc-rt5670-objs := rt5670.o
|
||||
snd-soc-rt5677-objs := rt5677.o
|
||||
snd-soc-rt5677-spi-objs := rt5677-spi.o
|
||||
snd-soc-rt5682-objs := rt5682.o
|
||||
snd-soc-sgtl5000-objs := sgtl5000.o
|
||||
snd-soc-alc5623-objs := alc5623.o
|
||||
snd-soc-alc5632-objs := alc5632.o
|
||||
|
|
@ -249,9 +251,9 @@ snd-soc-wm9713-objs := wm9713.o
|
|||
snd-soc-wm-hubs-objs := wm_hubs.o
|
||||
snd-soc-zx-aud96p22-objs := zx_aud96p22.o
|
||||
# Amp
|
||||
snd-soc-dio2125-objs := dio2125.o
|
||||
snd-soc-max9877-objs := max9877.o
|
||||
snd-soc-max98504-objs := max98504.o
|
||||
snd-soc-simple-amplifier-objs := simple-amplifier.o
|
||||
snd-soc-tpa6130a2-objs := tpa6130a2.o
|
||||
snd-soc-tas2552-objs := tas2552.o
|
||||
|
||||
|
|
@ -329,6 +331,7 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
|
|||
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
|
||||
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
|
||||
obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o
|
||||
obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o
|
||||
obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o
|
||||
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
|
||||
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
|
||||
|
|
@ -405,6 +408,7 @@ obj-$(CONFIG_SND_SOC_RT5668) += snd-soc-rt5668.o
|
|||
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
|
||||
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
|
||||
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
|
||||
obj-$(CONFIG_SND_SOC_RT5682) += snd-soc-rt5682.o
|
||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
||||
obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
|
||||
|
|
@ -507,7 +511,7 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
|
|||
obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o
|
||||
|
||||
# Amp
|
||||
obj-$(CONFIG_SND_SOC_DIO2125) += snd-soc-dio2125.o
|
||||
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
|
||||
obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o
|
||||
obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o
|
||||
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
|
||||
|
|
|
|||
|
|
@ -299,6 +299,7 @@ static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = {
|
|||
|
||||
{ "DSP", NULL, "Left Decimator" },
|
||||
{ "DSP", NULL, "Right Decimator" },
|
||||
{ "DSP", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = {
|
||||
|
|
|
|||
|
|
@ -648,6 +648,7 @@ static int adav80x_set_pll(struct snd_soc_component *component, int pll_id,
|
|||
pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ static int __maybe_unused ak4458_runtime_resume(struct device *dev)
|
|||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
struct snd_soc_component_driver soc_codec_dev_ak4458 = {
|
||||
static const struct snd_soc_component_driver soc_codec_dev_ak4458 = {
|
||||
.probe = ak4458_probe,
|
||||
.remove = ak4458_remove,
|
||||
.controls = ak4458_snd_controls,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
/*
|
||||
* ak4554.c
|
||||
*
|
||||
* Copyright (C) 2013 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// ak4554.c
|
||||
//
|
||||
// Copyright (C) 2013 Renesas Solutions Corp.
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <sound/soc.h>
|
||||
|
|
@ -97,6 +92,6 @@ static struct platform_driver ak4554_driver = {
|
|||
};
|
||||
module_platform_driver(ak4554_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("SoC AK4554 driver");
|
||||
MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
|
||||
|
|
|
|||
|
|
@ -1,18 +1,14 @@
|
|||
/*
|
||||
* ak4613.c -- Asahi Kasei ALSA Soc Audio driver
|
||||
*
|
||||
* Copyright (C) 2015 Renesas Electronics Corporation
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* Based on ak4642.c by Kuninori Morimoto
|
||||
* Based on wm8731.c by Richard Purdie
|
||||
* Based on ak4535.c by Richard Purdie
|
||||
* Based on wm8753.c by Liam Girdwood
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// ak4613.c -- Asahi Kasei ALSA Soc Audio driver
|
||||
//
|
||||
// Copyright (C) 2015 Renesas Electronics Corporation
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
//
|
||||
// Based on ak4642.c by Kuninori Morimoto
|
||||
// Based on wm8731.c by Richard Purdie
|
||||
// Based on ak4535.c by Richard Purdie
|
||||
// Based on wm8753.c by Liam Girdwood
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
/*
|
||||
* ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver
|
||||
*
|
||||
* Copyright (C) 2009 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <morimoto.kuninori@renesas.com>
|
||||
*
|
||||
* Based on wm8731.c by Richard Purdie
|
||||
* Based on ak4535.c by Richard Purdie
|
||||
* Based on wm8753.c by Liam Girdwood
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver
|
||||
//
|
||||
// Copyright (C) 2009 Renesas Solutions Corp.
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
//
|
||||
// Based on wm8731.c by Richard Purdie
|
||||
// Based on ak4535.c by Richard Purdie
|
||||
// Based on wm8753.c by Liam Girdwood
|
||||
|
||||
/* ** CAUTION **
|
||||
*
|
||||
|
|
@ -709,4 +705,4 @@ module_i2c_driver(ak4642_i2c_driver);
|
|||
|
||||
MODULE_DESCRIPTION("Soc AK4642 driver");
|
||||
MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
|||
|
|
@ -322,13 +322,13 @@ static int __maybe_unused ak5558_runtime_resume(struct device *dev)
|
|||
return regcache_sync(ak5558->regmap);
|
||||
}
|
||||
|
||||
const struct dev_pm_ops ak5558_pm = {
|
||||
static const struct dev_pm_ops ak5558_pm = {
|
||||
SET_RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
struct snd_soc_component_driver soc_codec_dev_ak5558 = {
|
||||
static const struct snd_soc_component_driver soc_codec_dev_ak5558 = {
|
||||
.probe = ak5558_probe,
|
||||
.remove = ak5558_remove,
|
||||
.controls = ak5558_snd_controls,
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg)
|
|||
{
|
||||
/* Unreadable registers are considered volatile */
|
||||
if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
return reg == CS4270_CHIPID;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,6 +235,9 @@ ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE),
|
|||
|
||||
ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
|
||||
|
||||
WM_ADSP_FW_CONTROL("DSP2", 1),
|
||||
WM_ADSP_FW_CONTROL("DSP3", 2),
|
||||
};
|
||||
|
||||
ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
|
||||
|
|
@ -1283,6 +1286,12 @@ static int cs47l24_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1);
|
||||
if (ret != 0)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to set compressed IRQ as a wake source: %d\n",
|
||||
ret);
|
||||
|
||||
arizona_init_common(arizona);
|
||||
|
||||
ret = arizona_init_vol_limit(arizona);
|
||||
|
|
@ -1306,6 +1315,7 @@ static int cs47l24_probe(struct platform_device *pdev)
|
|||
err_spk_irqs:
|
||||
arizona_free_spk_irqs(arizona);
|
||||
err_dsp_irq:
|
||||
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1323,6 +1333,7 @@ static int cs47l24_remove(struct platform_device *pdev)
|
|||
|
||||
arizona_free_spk_irqs(arizona);
|
||||
|
||||
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -362,8 +362,27 @@ static int cx20442_component_probe(struct snd_soc_component *component)
|
|||
return -ENOMEM;
|
||||
|
||||
cx20442->por = regulator_get(component->dev, "POR");
|
||||
if (IS_ERR(cx20442->por))
|
||||
dev_warn(component->dev, "failed to get the regulator");
|
||||
if (IS_ERR(cx20442->por)) {
|
||||
int err = PTR_ERR(cx20442->por);
|
||||
|
||||
dev_warn(component->dev, "failed to get POR supply (%d)", err);
|
||||
/*
|
||||
* When running on a non-dt platform and requested regulator
|
||||
* is not available, regulator_get() never returns
|
||||
* -EPROBE_DEFER as it is not able to justify if the regulator
|
||||
* may still appear later. On the other hand, the board can
|
||||
* still set full constraints flag at late_initcall in order
|
||||
* to instruct regulator_get() to return a dummy one if
|
||||
* sufficient. Hence, if we get -ENODEV here, let's convert
|
||||
* it to -EPROBE_DEFER and wait for the board to decide or
|
||||
* let Deferred Probe infrastructure handle this error.
|
||||
*/
|
||||
if (err == -ENODEV)
|
||||
err = -EPROBE_DEFER;
|
||||
kfree(cx20442);
|
||||
return err;
|
||||
}
|
||||
|
||||
cx20442->tty = NULL;
|
||||
|
||||
snd_soc_component_set_drvdata(component, cx20442);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,14 @@
|
|||
/*
|
||||
* DA7210 ALSA Soc codec driver
|
||||
*
|
||||
* Copyright (c) 2009 Dialog Semiconductor
|
||||
* Written by David Chen <Dajun.chen@diasemi.com>
|
||||
*
|
||||
* Copyright (C) 2009 Renesas Solutions Corp.
|
||||
* Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com>
|
||||
*
|
||||
* Tested on SuperH Ecovec24 board with S16/S24 LE in 48KHz using I2S
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// DA7210 ALSA Soc codec driver
|
||||
//
|
||||
// Copyright (c) 2009 Dialog Semiconductor
|
||||
// Written by David Chen <[email protected]>
|
||||
//
|
||||
// Copyright (C) 2009 Renesas Solutions Corp.
|
||||
// Cleanups by Kuninori Morimoto <[email protected]>
|
||||
//
|
||||
// Tested on SuperH Ecovec24 board with S16/S24 LE in 48KHz using I2S
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
|
|||
|
|
@ -1140,9 +1140,9 @@ static bool da7213_volatile_register(struct device *dev, unsigned int reg)
|
|||
case DA7213_ALC_OFFSET_AUTO_M_R:
|
||||
case DA7213_ALC_OFFSET_AUTO_U_R:
|
||||
case DA7213_ALC_CIC_OP_LVL_DATA:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work)
|
|||
container_of(work, struct da7219_aad_priv, btn_det_work);
|
||||
struct snd_soc_component *component = da7219_aad->component;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
|
||||
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
|
||||
u8 statusa, micbias_ctrl;
|
||||
bool micbias_up = false;
|
||||
int retries = 0;
|
||||
|
|
@ -86,6 +87,8 @@ static void da7219_aad_btn_det_work(struct work_struct *work)
|
|||
if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES)
|
||||
dev_warn(component->dev, "Mic bias status check timed out");
|
||||
|
||||
da7219->micbias_on_event = true;
|
||||
|
||||
/*
|
||||
* Mic bias pulse required to enable mic, must be done before enabling
|
||||
* button detection to prevent erroneous button readings.
|
||||
|
|
@ -439,6 +442,8 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
|
|||
snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
|
||||
DA7219_BUTTON_CONFIG_MASK, 0);
|
||||
|
||||
da7219->micbias_on_event = false;
|
||||
|
||||
/* Disable mic bias */
|
||||
snd_soc_dapm_disable_pin(dapm, "Mic Bias");
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
|
|
|||
|
|
@ -768,6 +768,30 @@ static const struct snd_kcontrol_new da7219_st_out_filtr_mix_controls[] = {
|
|||
* DAPM Events
|
||||
*/
|
||||
|
||||
static int da7219_mic_pga_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 da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
if (da7219->micbias_on_event) {
|
||||
/*
|
||||
* Delay only for first capture after bias enabled to
|
||||
* avoid possible DC offset related noise.
|
||||
*/
|
||||
da7219->micbias_on_event = false;
|
||||
msleep(da7219->mic_pga_delay);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da7219_dai_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
|
|
@ -937,12 +961,12 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_INPUT("MIC"),
|
||||
|
||||
/* Input PGAs */
|
||||
SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL,
|
||||
DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT,
|
||||
NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL,
|
||||
DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
|
||||
NULL, 0),
|
||||
SND_SOC_DAPM_PGA_E("Mic PGA", DA7219_MIC_1_CTRL,
|
||||
DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT,
|
||||
NULL, 0, da7219_mic_pga_event, SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_PGA_E("Mixin PGA", DA7219_MIXIN_L_CTRL,
|
||||
DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
|
||||
NULL, 0, da7219_settling_event, SND_SOC_DAPM_POST_PMU),
|
||||
|
||||
/* Input Filters */
|
||||
SND_SOC_DAPM_ADC("ADC", NULL, DA7219_ADC_L_CTRL, DA7219_ADC_L_EN_SHIFT,
|
||||
|
|
@ -1847,6 +1871,14 @@ static void da7219_handle_pdata(struct snd_soc_component *component)
|
|||
|
||||
snd_soc_component_write(component, DA7219_MICBIAS_CTRL, micbias_lvl);
|
||||
|
||||
/*
|
||||
* Calculate delay required to compensate for DC offset in
|
||||
* Mic PGA, based on Mic Bias voltage.
|
||||
*/
|
||||
da7219->mic_pga_delay = DA7219_MIC_PGA_BASE_DELAY +
|
||||
(pdata->micbias_lvl *
|
||||
DA7219_MIC_PGA_OFFSET_DELAY);
|
||||
|
||||
/* Mic */
|
||||
switch (pdata->mic_amp_in_sel) {
|
||||
case DA7219_MIC_AMP_IN_SEL_DIFF:
|
||||
|
|
@ -2143,9 +2175,9 @@ static bool da7219_volatile_register(struct device *dev, unsigned int reg)
|
|||
case DA7219_ACCDET_IRQ_EVENT_B:
|
||||
case DA7219_ACCDET_CONFIG_8:
|
||||
case DA7219_SYSTEM_STATUS:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -781,8 +781,10 @@
|
|||
#define DA7219_SYS_STAT_CHECK_DELAY 50
|
||||
|
||||
/* Power up/down Delays */
|
||||
#define DA7219_SETTLING_DELAY 40
|
||||
#define DA7219_MIN_GAIN_DELAY 30
|
||||
#define DA7219_SETTLING_DELAY 40
|
||||
#define DA7219_MIN_GAIN_DELAY 30
|
||||
#define DA7219_MIC_PGA_BASE_DELAY 100
|
||||
#define DA7219_MIC_PGA_OFFSET_DELAY 40
|
||||
|
||||
enum da7219_clk_src {
|
||||
DA7219_CLKSRC_MCLK = 0,
|
||||
|
|
@ -828,6 +830,8 @@ struct da7219_priv {
|
|||
|
||||
bool master;
|
||||
bool alc_en;
|
||||
bool micbias_on_event;
|
||||
unsigned int mic_pga_delay;
|
||||
u8 gain_ramp_ctrl;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1041,9 +1041,9 @@ static bool da9055_volatile_register(struct device *dev,
|
|||
case DA9055_HP_R_GAIN_STATUS:
|
||||
case DA9055_LINE_GAIN_STATUS:
|
||||
case DA9055_ALC_CIC_OP_LVL_DATA:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
* in the file called COPYING.
|
||||
*/
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/module.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
|
|
@ -24,6 +25,82 @@
|
|||
* The everest 7134 is a very simple DA converter with no register
|
||||
*/
|
||||
|
||||
struct es7134_clock_mode {
|
||||
unsigned int rate_min;
|
||||
unsigned int rate_max;
|
||||
unsigned int *mclk_fs;
|
||||
unsigned int mclk_fs_num;
|
||||
};
|
||||
|
||||
struct es7134_chip {
|
||||
struct snd_soc_dai_driver *dai_drv;
|
||||
const struct es7134_clock_mode *modes;
|
||||
unsigned int mode_num;
|
||||
const struct snd_soc_dapm_widget *extra_widgets;
|
||||
unsigned int extra_widget_num;
|
||||
const struct snd_soc_dapm_route *extra_routes;
|
||||
unsigned int extra_route_num;
|
||||
};
|
||||
|
||||
struct es7134_data {
|
||||
unsigned int mclk;
|
||||
const struct es7134_chip *chip;
|
||||
};
|
||||
|
||||
static int es7134_check_mclk(struct snd_soc_dai *dai,
|
||||
struct es7134_data *priv,
|
||||
unsigned int rate)
|
||||
{
|
||||
unsigned int mfs = priv->mclk / rate;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < priv->chip->mode_num; i++) {
|
||||
const struct es7134_clock_mode *mode = &priv->chip->modes[i];
|
||||
|
||||
if (rate < mode->rate_min || rate > mode->rate_max)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < mode->mclk_fs_num; j++) {
|
||||
if (mode->mclk_fs[j] == mfs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_err(dai->dev, "unsupported mclk_fs %u for rate %u\n",
|
||||
mfs, rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* should not happen */
|
||||
dev_err(dai->dev, "unsupported rate: %u\n", rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int es7134_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct es7134_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
/* mclk has not been provided, assume it is OK */
|
||||
if (!priv->mclk)
|
||||
return 0;
|
||||
|
||||
return es7134_check_mclk(dai, priv, params_rate(params));
|
||||
}
|
||||
|
||||
static int es7134_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct es7134_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
if (dir == SND_SOC_CLOCK_IN && clk_id == 0) {
|
||||
priv->mclk = freq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int es7134_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
{
|
||||
fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK |
|
||||
|
|
@ -38,8 +115,38 @@ static int es7134_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int es7134_component_probe(struct snd_soc_component *c)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(c);
|
||||
struct es7134_data *priv = snd_soc_component_get_drvdata(c);
|
||||
const struct es7134_chip *chip = priv->chip;
|
||||
int ret;
|
||||
|
||||
if (chip->extra_widget_num) {
|
||||
ret = snd_soc_dapm_new_controls(dapm, chip->extra_widgets,
|
||||
chip->extra_widget_num);
|
||||
if (ret) {
|
||||
dev_err(c->dev, "failed to add extra widgets\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (chip->extra_route_num) {
|
||||
ret = snd_soc_dapm_add_routes(dapm, chip->extra_routes,
|
||||
chip->extra_route_num);
|
||||
if (ret) {
|
||||
dev_err(c->dev, "failed to add extra routes\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops es7134_dai_ops = {
|
||||
.set_fmt = es7134_set_fmt,
|
||||
.hw_params = es7134_hw_params,
|
||||
.set_sysclk = es7134_set_sysclk,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver es7134_dai = {
|
||||
|
|
@ -48,7 +155,11 @@ static struct snd_soc_dai_driver es7134_dai = {
|
|||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.rates = (SNDRV_PCM_RATE_8000_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000 |
|
||||
SNDRV_PCM_RATE_176400 |
|
||||
SNDRV_PCM_RATE_192000),
|
||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S18_3LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
|
|
@ -58,18 +169,56 @@ static struct snd_soc_dai_driver es7134_dai = {
|
|||
.ops = &es7134_dai_ops,
|
||||
};
|
||||
|
||||
static const struct es7134_clock_mode es7134_modes[] = {
|
||||
{
|
||||
/* Single speed mode */
|
||||
.rate_min = 8000,
|
||||
.rate_max = 50000,
|
||||
.mclk_fs = (unsigned int[]) { 256, 384, 512, 768, 1024 },
|
||||
.mclk_fs_num = 5,
|
||||
}, {
|
||||
/* Double speed mode */
|
||||
.rate_min = 84000,
|
||||
.rate_max = 100000,
|
||||
.mclk_fs = (unsigned int[]) { 128, 192, 256, 384, 512 },
|
||||
.mclk_fs_num = 5,
|
||||
}, {
|
||||
/* Quad speed mode */
|
||||
.rate_min = 167000,
|
||||
.rate_max = 192000,
|
||||
.mclk_fs = (unsigned int[]) { 128, 192, 256 },
|
||||
.mclk_fs_num = 3,
|
||||
},
|
||||
};
|
||||
|
||||
/* Digital I/O are also supplied by VDD on the es7134 */
|
||||
static const struct snd_soc_dapm_route es7134_extra_routes[] = {
|
||||
{ "Playback", NULL, "VDD", }
|
||||
};
|
||||
|
||||
static const struct es7134_chip es7134_chip = {
|
||||
.dai_drv = &es7134_dai,
|
||||
.modes = es7134_modes,
|
||||
.mode_num = ARRAY_SIZE(es7134_modes),
|
||||
.extra_routes = es7134_extra_routes,
|
||||
.extra_route_num = ARRAY_SIZE(es7134_extra_routes),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget es7134_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_OUTPUT("AOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("AOUTR"),
|
||||
SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("VDD", 0, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route es7134_dapm_routes[] = {
|
||||
{ "AOUTL", NULL, "DAC" },
|
||||
{ "AOUTR", NULL, "DAC" },
|
||||
{ "DAC", NULL, "VDD" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver es7134_component_driver = {
|
||||
.probe = es7134_component_probe,
|
||||
.dapm_widgets = es7134_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(es7134_dapm_widgets),
|
||||
.dapm_routes = es7134_dapm_routes,
|
||||
|
|
@ -80,17 +229,87 @@ static const struct snd_soc_component_driver es7134_component_driver = {
|
|||
.non_legacy_dai_naming = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver es7154_dai = {
|
||||
.name = "es7154-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = (SNDRV_PCM_RATE_8000_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000),
|
||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S18_3LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE),
|
||||
},
|
||||
.ops = &es7134_dai_ops,
|
||||
};
|
||||
|
||||
static const struct es7134_clock_mode es7154_modes[] = {
|
||||
{
|
||||
/* Single speed mode */
|
||||
.rate_min = 8000,
|
||||
.rate_max = 50000,
|
||||
.mclk_fs = (unsigned int[]) { 32, 64, 128, 192, 256,
|
||||
384, 512, 768, 1024 },
|
||||
.mclk_fs_num = 9,
|
||||
}, {
|
||||
/* Double speed mode */
|
||||
.rate_min = 84000,
|
||||
.rate_max = 100000,
|
||||
.mclk_fs = (unsigned int[]) { 128, 192, 256, 384, 512,
|
||||
768, 1024},
|
||||
.mclk_fs_num = 7,
|
||||
}
|
||||
};
|
||||
|
||||
/* Es7154 has a separate supply for digital I/O */
|
||||
static const struct snd_soc_dapm_widget es7154_extra_widgets[] = {
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("PVDD", 0, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route es7154_extra_routes[] = {
|
||||
{ "Playback", NULL, "PVDD", }
|
||||
};
|
||||
|
||||
static const struct es7134_chip es7154_chip = {
|
||||
.dai_drv = &es7154_dai,
|
||||
.modes = es7154_modes,
|
||||
.mode_num = ARRAY_SIZE(es7154_modes),
|
||||
.extra_routes = es7154_extra_routes,
|
||||
.extra_route_num = ARRAY_SIZE(es7154_extra_routes),
|
||||
.extra_widgets = es7154_extra_widgets,
|
||||
.extra_widget_num = ARRAY_SIZE(es7154_extra_widgets),
|
||||
};
|
||||
|
||||
static int es7134_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct es7134_data *priv;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->chip = of_device_get_match_data(dev);
|
||||
if (!priv->chip) {
|
||||
dev_err(dev, "failed to match device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return devm_snd_soc_register_component(&pdev->dev,
|
||||
&es7134_component_driver,
|
||||
&es7134_dai, 1);
|
||||
priv->chip->dai_drv, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id es7134_ids[] = {
|
||||
{ .compatible = "everest,es7134", },
|
||||
{ .compatible = "everest,es7144", },
|
||||
{ .compatible = "everest,es7134", .data = &es7134_chip },
|
||||
{ .compatible = "everest,es7144", .data = &es7134_chip },
|
||||
{ .compatible = "everest,es7154", .data = &es7154_chip },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, es7134_ids);
|
||||
|
|
|
|||
322
sound/soc/codecs/es7241.c
Normal file
322
sound/soc/codecs/es7241.c
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
//
|
||||
// Copyright (c) 2018 BayLibre, SAS.
|
||||
// Author: Jerome Brunet <[email protected]>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/module.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
struct es7241_clock_mode {
|
||||
unsigned int rate_min;
|
||||
unsigned int rate_max;
|
||||
unsigned int *slv_mfs;
|
||||
unsigned int slv_mfs_num;
|
||||
unsigned int mst_mfs;
|
||||
unsigned int mst_m0:1;
|
||||
unsigned int mst_m1:1;
|
||||
};
|
||||
|
||||
struct es7241_chip {
|
||||
const struct es7241_clock_mode *modes;
|
||||
unsigned int mode_num;
|
||||
};
|
||||
|
||||
struct es7241_data {
|
||||
struct gpio_desc *reset;
|
||||
struct gpio_desc *m0;
|
||||
struct gpio_desc *m1;
|
||||
unsigned int fmt;
|
||||
unsigned int mclk;
|
||||
bool is_slave;
|
||||
const struct es7241_chip *chip;
|
||||
};
|
||||
|
||||
static void es7241_set_mode(struct es7241_data *priv, int m0, int m1)
|
||||
{
|
||||
/* put the device in reset */
|
||||
gpiod_set_value_cansleep(priv->reset, 0);
|
||||
|
||||
/* set the mode */
|
||||
gpiod_set_value_cansleep(priv->m0, m0);
|
||||
gpiod_set_value_cansleep(priv->m1, m1);
|
||||
|
||||
/* take the device out of reset - datasheet does not specify a delay */
|
||||
gpiod_set_value_cansleep(priv->reset, 1);
|
||||
}
|
||||
|
||||
static int es7241_set_slave_mode(struct es7241_data *priv,
|
||||
const struct es7241_clock_mode *mode,
|
||||
unsigned int mfs)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (!mfs)
|
||||
goto out_ok;
|
||||
|
||||
for (j = 0; j < mode->slv_mfs_num; j++) {
|
||||
if (mode->slv_mfs[j] == mfs)
|
||||
goto out_ok;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
||||
out_ok:
|
||||
es7241_set_mode(priv, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int es7241_set_master_mode(struct es7241_data *priv,
|
||||
const struct es7241_clock_mode *mode,
|
||||
unsigned int mfs)
|
||||
{
|
||||
/*
|
||||
* We can't really set clock ratio, if the mclk/lrclk is different
|
||||
* from what we provide, then error out
|
||||
*/
|
||||
if (mfs && mfs != mode->mst_mfs)
|
||||
return -EINVAL;
|
||||
|
||||
es7241_set_mode(priv, mode->mst_m0, mode->mst_m1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int es7241_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int rate = params_rate(params);
|
||||
unsigned int mfs = priv->mclk / rate;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->chip->mode_num; i++) {
|
||||
const struct es7241_clock_mode *mode = &priv->chip->modes[i];
|
||||
|
||||
if (rate < mode->rate_min || rate >= mode->rate_max)
|
||||
continue;
|
||||
|
||||
if (priv->is_slave)
|
||||
return es7241_set_slave_mode(priv, mode, mfs);
|
||||
else
|
||||
return es7241_set_master_mode(priv, mode, mfs);
|
||||
}
|
||||
|
||||
/* should not happen */
|
||||
dev_err(dai->dev, "unsupported rate: %u\n", rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int es7241_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
if (dir == SND_SOC_CLOCK_IN && clk_id == 0) {
|
||||
priv->mclk = freq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int es7241_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
|
||||
dev_err(dai->dev, "Unsupported dai clock inversion\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != priv->fmt) {
|
||||
dev_err(dai->dev, "Invalid dai format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
priv->is_slave = true;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
priv->is_slave = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(dai->dev, "Unsupported clock configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops es7241_dai_ops = {
|
||||
.set_fmt = es7241_set_fmt,
|
||||
.hw_params = es7241_hw_params,
|
||||
.set_sysclk = es7241_set_sysclk,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver es7241_dai = {
|
||||
.name = "es7241-hifi",
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE),
|
||||
},
|
||||
.ops = &es7241_dai_ops,
|
||||
};
|
||||
|
||||
static const struct es7241_clock_mode es7241_modes[] = {
|
||||
{
|
||||
/* Single speed mode */
|
||||
.rate_min = 8000,
|
||||
.rate_max = 50000,
|
||||
.slv_mfs = (unsigned int[]) { 256, 384, 512, 768, 1024 },
|
||||
.slv_mfs_num = 5,
|
||||
.mst_mfs = 256,
|
||||
.mst_m0 = 0,
|
||||
.mst_m1 = 0,
|
||||
}, {
|
||||
/* Double speed mode */
|
||||
.rate_min = 50000,
|
||||
.rate_max = 100000,
|
||||
.slv_mfs = (unsigned int[]) { 128, 192 },
|
||||
.slv_mfs_num = 2,
|
||||
.mst_mfs = 128,
|
||||
.mst_m0 = 1,
|
||||
.mst_m1 = 0,
|
||||
}, {
|
||||
/* Quad speed mode */
|
||||
.rate_min = 100000,
|
||||
.rate_max = 200000,
|
||||
.slv_mfs = (unsigned int[]) { 64 },
|
||||
.slv_mfs_num = 1,
|
||||
.mst_mfs = 64,
|
||||
.mst_m0 = 0,
|
||||
.mst_m1 = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct es7241_chip es7241_chip = {
|
||||
.modes = es7241_modes,
|
||||
.mode_num = ARRAY_SIZE(es7241_modes),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget es7241_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("AINL"),
|
||||
SND_SOC_DAPM_INPUT("AINR"),
|
||||
SND_SOC_DAPM_DAC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("VDDP", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("VDDD", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("VDDA", 0, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route es7241_dapm_routes[] = {
|
||||
{ "ADC", NULL, "AINL", },
|
||||
{ "ADC", NULL, "AINR", },
|
||||
{ "ADC", NULL, "VDDA", },
|
||||
{ "Capture", NULL, "VDDP", },
|
||||
{ "Capture", NULL, "VDDD", },
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver es7241_component_driver = {
|
||||
.dapm_widgets = es7241_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(es7241_dapm_widgets),
|
||||
.dapm_routes = es7241_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(es7241_dapm_routes),
|
||||
.idle_bias_on = 1,
|
||||
.endianness = 1,
|
||||
.non_legacy_dai_naming = 1,
|
||||
};
|
||||
|
||||
static void es7241_parse_fmt(struct device *dev, struct es7241_data *priv)
|
||||
{
|
||||
bool is_leftj;
|
||||
|
||||
/*
|
||||
* The format is given by a pull resistor on the SDOUT pin:
|
||||
* pull-up for i2s, pull-down for left justified.
|
||||
*/
|
||||
is_leftj = of_property_read_bool(dev->of_node,
|
||||
"everest,sdout-pull-down");
|
||||
if (is_leftj)
|
||||
priv->fmt = SND_SOC_DAIFMT_LEFT_J;
|
||||
else
|
||||
priv->fmt = SND_SOC_DAIFMT_I2S;
|
||||
}
|
||||
|
||||
static int es7241_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct es7241_data *priv;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->chip = of_device_get_match_data(dev);
|
||||
if (!priv->chip) {
|
||||
dev_err(dev, "failed to match device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
es7241_parse_fmt(dev, priv);
|
||||
|
||||
priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->reset)) {
|
||||
err = PTR_ERR(priv->reset);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get 'reset' gpio: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
priv->m0 = devm_gpiod_get_optional(dev, "m0", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->m0)) {
|
||||
err = PTR_ERR(priv->m0);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get 'm0' gpio: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
priv->m1 = devm_gpiod_get_optional(dev, "m1", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->m1)) {
|
||||
err = PTR_ERR(priv->m1);
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get 'm1' gpio: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return devm_snd_soc_register_component(&pdev->dev,
|
||||
&es7241_component_driver,
|
||||
&es7241_dai, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id es7241_ids[] = {
|
||||
{ .compatible = "everest,es7241", .data = &es7241_chip },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, es7241_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver es7241_driver = {
|
||||
.driver = {
|
||||
.name = "es7241",
|
||||
.of_match_table = of_match_ptr(es7241_ids),
|
||||
},
|
||||
.probe = es7241_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(es7241_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ES7241 audio codec driver");
|
||||
MODULE_AUTHOR("Jerome Brunet <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -2093,6 +2093,75 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/*
|
||||
* Power management sequences
|
||||
* ==========================
|
||||
*
|
||||
* The following explains the PM handling of HDAC HDMI with its parent
|
||||
* device SKL and display power usage
|
||||
*
|
||||
* Probe
|
||||
* -----
|
||||
* In SKL probe,
|
||||
* 1. skl_probe_work() powers up the display (refcount++ -> 1)
|
||||
* 2. enumerates the codecs on the link
|
||||
* 3. powers down the display (refcount-- -> 0)
|
||||
*
|
||||
* In HDAC HDMI probe,
|
||||
* 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1)
|
||||
* 2. probe the codec
|
||||
* 3. put the HDAC HDMI device to runtime suspend
|
||||
* 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
|
||||
*
|
||||
* Once children are runtime suspended, SKL device also goes to runtime
|
||||
* suspend
|
||||
*
|
||||
* HDMI Playback
|
||||
* -------------
|
||||
* Open HDMI device,
|
||||
* 1. skl_runtime_resume() invoked
|
||||
* 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
|
||||
*
|
||||
* Close HDMI device,
|
||||
* 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
|
||||
* 2. skl_runtime_suspend() invoked
|
||||
*
|
||||
* S0/S3 Cycle with playback in progress
|
||||
* -------------------------------------
|
||||
* When the device is opened for playback, the device is runtime active
|
||||
* already and the display refcount is 1 as explained above.
|
||||
*
|
||||
* Entering to S3,
|
||||
* 1. hdmi_codec_prepare() invoke the runtime resume of codec which just
|
||||
* increments the PM runtime usage count of the codec since the device
|
||||
* is in use already
|
||||
* 2. skl_suspend() powers down the display (refcount-- -> 0)
|
||||
*
|
||||
* Wakeup from S3,
|
||||
* 1. skl_resume() powers up the display (refcount++ -> 1)
|
||||
* 2. hdmi_codec_complete() invokes the runtime suspend of codec which just
|
||||
* decrements the PM runtime usage count of the codec since the device
|
||||
* is in use already
|
||||
*
|
||||
* Once playback is stopped, the display refcount is set to 0 as explained
|
||||
* above in the HDMI playback sequence. The PM handlings are designed in
|
||||
* such way that to balance the refcount of display power when the codec
|
||||
* device put to S3 while playback is going on.
|
||||
*
|
||||
* S0/S3 Cycle without playback in progress
|
||||
* ----------------------------------------
|
||||
* Entering to S3,
|
||||
* 1. hdmi_codec_prepare() invoke the runtime resume of codec
|
||||
* 2. skl_runtime_resume() invoked
|
||||
* 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
|
||||
* 4. skl_suspend() powers down the display (refcount-- -> 0)
|
||||
*
|
||||
* Wakeup from S3,
|
||||
* 1. skl_resume() powers up the display (refcount++ -> 1)
|
||||
* 2. hdmi_codec_complete() invokes the runtime suspend of codec
|
||||
* 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
|
||||
* 4. skl_runtime_suspend() invoked
|
||||
*/
|
||||
static int hdac_hdmi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct hdac_device *hdev = dev_to_hdac_dev(dev);
|
||||
|
|
|
|||
|
|
@ -291,10 +291,6 @@ static const struct snd_soc_dapm_widget hdmi_widgets[] = {
|
|||
SND_SOC_DAPM_OUTPUT("TX"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route hdmi_routes[] = {
|
||||
{ "TX", NULL, "Playback" },
|
||||
};
|
||||
|
||||
enum {
|
||||
DAI_ID_I2S = 0,
|
||||
DAI_ID_SPDIF,
|
||||
|
|
@ -689,9 +685,23 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
|||
return snd_ctl_add(rtd->card->snd_card, kctl);
|
||||
}
|
||||
|
||||
static int hdmi_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
struct snd_soc_dapm_route route = {
|
||||
.sink = "TX",
|
||||
.source = dai->driver->playback.stream_name,
|
||||
};
|
||||
|
||||
dapm = snd_soc_component_get_dapm(dai->component);
|
||||
|
||||
return snd_soc_dapm_add_routes(dapm, &route, 1);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_driver hdmi_i2s_dai = {
|
||||
.name = "i2s-hifi",
|
||||
.id = DAI_ID_I2S,
|
||||
.probe = hdmi_dai_probe,
|
||||
.playback = {
|
||||
.stream_name = "I2S Playback",
|
||||
.channels_min = 2,
|
||||
|
|
@ -707,6 +717,7 @@ static const struct snd_soc_dai_driver hdmi_i2s_dai = {
|
|||
static const struct snd_soc_dai_driver hdmi_spdif_dai = {
|
||||
.name = "spdif-hifi",
|
||||
.id = DAI_ID_SPDIF,
|
||||
.probe = hdmi_dai_probe,
|
||||
.playback = {
|
||||
.stream_name = "SPDIF Playback",
|
||||
.channels_min = 2,
|
||||
|
|
@ -733,8 +744,6 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
|
|||
static const struct snd_soc_component_driver hdmi_driver = {
|
||||
.dapm_widgets = hdmi_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
|
||||
.dapm_routes = hdmi_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(hdmi_routes),
|
||||
.of_xlate_dai_id = hdmi_of_xlate_dai_id,
|
||||
.idle_bias_on = 1,
|
||||
.use_pmdown_time = 1,
|
||||
|
|
|
|||
|
|
@ -488,6 +488,7 @@ static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv,
|
|||
static bool max98373_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case MAX98373_R2000_SW_RESET:
|
||||
case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3:
|
||||
case MAX98373_R2010_IRQ_CTRL:
|
||||
case MAX98373_R2014_THERM_WARN_THRESH
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ static bool max9850_volatile_register(struct device *dev, unsigned int reg)
|
|||
switch (reg) {
|
||||
case MAX9850_STATUSA:
|
||||
case MAX9850_STATUSB:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -362,11 +362,8 @@ static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
|
|||
|
||||
static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr)
|
||||
{
|
||||
int osrate;
|
||||
|
||||
if (osr >= ARRAY_SIZE(osr_adc_sel))
|
||||
return -EINVAL;
|
||||
osrate = osr_adc_sel[osr].osr;
|
||||
|
||||
if (rate * osr > CLK_ADC_MAX) {
|
||||
dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n");
|
||||
|
|
|
|||
|
|
@ -1274,7 +1274,7 @@ static int nau8824_calc_fll_param(unsigned int fll_in,
|
|||
fvco_max = 0;
|
||||
fvco_sel = ARRAY_SIZE(mclk_src_scaling);
|
||||
for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) {
|
||||
fvco = 256 * fs * 2 * mclk_src_scaling[i].param;
|
||||
fvco = 256ULL * fs * 2 * mclk_src_scaling[i].param;
|
||||
if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX &&
|
||||
fvco_max < fvco) {
|
||||
fvco_max = fvco;
|
||||
|
|
|
|||
|
|
@ -2016,7 +2016,7 @@ static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs,
|
|||
fvco_max = 0;
|
||||
fvco_sel = ARRAY_SIZE(mclk_src_scaling);
|
||||
for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) {
|
||||
fvco = 256 * fs * 2 * mclk_src_scaling[i].param;
|
||||
fvco = 256ULL * fs * 2 * mclk_src_scaling[i].param;
|
||||
if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX &&
|
||||
fvco_max < fvco) {
|
||||
fvco_max = fvco;
|
||||
|
|
|
|||
|
|
@ -262,8 +262,7 @@ int pcm1789_common_exit(struct device *dev)
|
|||
{
|
||||
struct pcm1789_private *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (&priv->work)
|
||||
flush_work(&priv->work);
|
||||
flush_work(&priv->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ static int pcm186x_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_component *component = dai->component;
|
||||
struct pcm186x_priv *priv = snd_soc_component_get_drvdata(component);
|
||||
unsigned int rate = params_rate(params);
|
||||
unsigned int format = params_format(params);
|
||||
snd_pcm_format_t format = params_format(params);
|
||||
unsigned int width = params_width(params);
|
||||
unsigned int channels = params_channels(params);
|
||||
unsigned int div_lrck;
|
||||
|
|
|
|||
|
|
@ -1066,7 +1066,7 @@ static void rt1305_calibrate(struct rt1305_priv *rt1305)
|
|||
pr_debug("Left_rhl = 0x%x rh=0x%x rl=0x%x\n", rhl, rh, rl);
|
||||
pr_info("Left channel %d.%dohm\n", (r0ohm/10), (r0ohm%10));
|
||||
|
||||
r0l = 562949953421312;
|
||||
r0l = 562949953421312ULL;
|
||||
if (rhl != 0)
|
||||
do_div(r0l, rhl);
|
||||
pr_debug("Left_r0 = 0x%llx\n", r0l);
|
||||
|
|
@ -1083,7 +1083,7 @@ static void rt1305_calibrate(struct rt1305_priv *rt1305)
|
|||
pr_debug("Right_rhl = 0x%x rh=0x%x rl=0x%x\n", rhl, rh, rl);
|
||||
pr_info("Right channel %d.%dohm\n", (r0ohm/10), (r0ohm%10));
|
||||
|
||||
r0r = 562949953421312;
|
||||
r0r = 562949953421312ULL;
|
||||
if (rhl != 0)
|
||||
do_div(r0r, rhl);
|
||||
pr_debug("Right_r0 = 0x%llx\n", r0r);
|
||||
|
|
@ -1150,17 +1150,11 @@ static int rt1305_i2c_probe(struct i2c_client *i2c,
|
|||
rt1305_reset(rt1305->regmap);
|
||||
rt1305_calibrate(rt1305);
|
||||
|
||||
return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt1305,
|
||||
return devm_snd_soc_register_component(&i2c->dev,
|
||||
&soc_component_dev_rt1305,
|
||||
rt1305_dai, ARRAY_SIZE(rt1305_dai));
|
||||
}
|
||||
|
||||
static int rt1305_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
snd_soc_unregister_component(&i2c->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rt1305_i2c_shutdown(struct i2c_client *client)
|
||||
{
|
||||
struct rt1305_priv *rt1305 = i2c_get_clientdata(client);
|
||||
|
|
@ -1180,7 +1174,6 @@ static struct i2c_driver rt1305_i2c_driver = {
|
|||
#endif
|
||||
},
|
||||
.probe = rt1305_i2c_probe,
|
||||
.remove = rt1305_i2c_remove,
|
||||
.shutdown = rt1305_i2c_shutdown,
|
||||
.id_table = rt1305_i2c_id,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ static const struct reg_sequence rt5514_patch[] = {
|
|||
{RT5514_ANA_CTRL_LDO10, 0x00028604},
|
||||
{RT5514_ANA_CTRL_ADCFED, 0x00000800},
|
||||
{RT5514_ASRC_IN_CTRL1, 0x00000003},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000362},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000362},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000352},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000352},
|
||||
};
|
||||
|
||||
static const struct reg_default rt5514_reg[] = {
|
||||
|
|
@ -92,10 +92,10 @@ static const struct reg_default rt5514_reg[] = {
|
|||
{RT5514_ASRC_IN_CTRL1, 0x00000003},
|
||||
{RT5514_DOWNFILTER0_CTRL1, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER0_CTRL2, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000362},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000352},
|
||||
{RT5514_DOWNFILTER1_CTRL1, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER1_CTRL2, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000362},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000352},
|
||||
{RT5514_ANA_CTRL_LDO10, 0x00028604},
|
||||
{RT5514_ANA_CTRL_LDO18_16, 0x02000345},
|
||||
{RT5514_ANA_CTRL_ADC12, 0x0000a2a8},
|
||||
|
|
|
|||
|
|
@ -105,9 +105,9 @@ static bool rt5631_volatile_register(struct device *dev, unsigned int reg)
|
|||
case RT5631_INDEX_ADD:
|
||||
case RT5631_INDEX_DATA:
|
||||
case RT5631_EQ_CTRL:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,9 +164,9 @@ static bool rt5631_readable_register(struct device *dev, unsigned int reg)
|
|||
case RT5631_VENDOR_ID:
|
||||
case RT5631_VENDOR_ID1:
|
||||
case RT5631_VENDOR_ID2:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,10 +229,10 @@ static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
|
|||
static const struct snd_kcontrol_new rt5631_snd_controls[] = {
|
||||
/* MIC */
|
||||
SOC_ENUM("MIC1 Mode Control", rt5631_mic1_mode_enum),
|
||||
SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2,
|
||||
SOC_SINGLE_TLV("MIC1 Boost Volume", RT5631_MIC_CTRL_2,
|
||||
RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv),
|
||||
SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum),
|
||||
SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2,
|
||||
SOC_SINGLE_TLV("MIC2 Boost Volume", RT5631_MIC_CTRL_2,
|
||||
RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv),
|
||||
/* MONO IN */
|
||||
SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum),
|
||||
|
|
|
|||
|
|
@ -1665,6 +1665,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id)
|
|||
break;
|
||||
case RT5640_IF_113:
|
||||
ret |= RT5640_U_IF1;
|
||||
/* fall through */
|
||||
case RT5640_IF_312:
|
||||
case RT5640_IF_213:
|
||||
ret |= RT5640_U_IF2;
|
||||
|
|
@ -1680,6 +1681,7 @@ static int get_sdp_info(struct snd_soc_component *component, int dai_id)
|
|||
break;
|
||||
case RT5640_IF_223:
|
||||
ret |= RT5640_U_IF1;
|
||||
/* fall through */
|
||||
case RT5640_IF_123:
|
||||
case RT5640_IF_321:
|
||||
ret |= RT5640_U_IF2;
|
||||
|
|
|
|||
|
|
@ -331,11 +331,13 @@ static const struct snd_kcontrol_new rt5651_snd_controls[] = {
|
|||
SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5651_DAC2_DIG_VOL,
|
||||
RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
|
||||
175, 0, dac_vol_tlv),
|
||||
/* IN1/IN2 Control */
|
||||
/* IN1/IN2/IN3 Control */
|
||||
SOC_SINGLE_TLV("IN1 Boost", RT5651_IN1_IN2,
|
||||
RT5651_BST_SFT1, 8, 0, bst_tlv),
|
||||
SOC_SINGLE_TLV("IN2 Boost", RT5651_IN1_IN2,
|
||||
RT5651_BST_SFT2, 8, 0, bst_tlv),
|
||||
SOC_SINGLE_TLV("IN3 Boost", RT5651_IN3,
|
||||
RT5651_BST_SFT1, 8, 0, bst_tlv),
|
||||
/* INL/INR Volume Control */
|
||||
SOC_DOUBLE_TLV("IN Capture Volume", RT5651_INL1_INR1_VOL,
|
||||
RT5651_INL_VOL_SFT, RT5651_INR_VOL_SFT,
|
||||
|
|
@ -1581,6 +1583,24 @@ static void rt5651_disable_micbias1_for_ovcd(struct snd_soc_component *component
|
|||
snd_soc_dapm_mutex_unlock(dapm);
|
||||
}
|
||||
|
||||
static void rt5651_enable_micbias1_ovcd_irq(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
snd_soc_component_update_bits(component, RT5651_IRQ_CTRL2,
|
||||
RT5651_IRQ_MB1_OC_MASK, RT5651_IRQ_MB1_OC_NOR);
|
||||
rt5651->ovcd_irq_enabled = true;
|
||||
}
|
||||
|
||||
static void rt5651_disable_micbias1_ovcd_irq(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
snd_soc_component_update_bits(component, RT5651_IRQ_CTRL2,
|
||||
RT5651_IRQ_MB1_OC_MASK, RT5651_IRQ_MB1_OC_BP);
|
||||
rt5651->ovcd_irq_enabled = false;
|
||||
}
|
||||
|
||||
static void rt5651_clear_micbias1_ovcd(struct snd_soc_component *component)
|
||||
{
|
||||
snd_soc_component_update_bits(component, RT5651_IRQ_CTRL2,
|
||||
|
|
@ -1622,10 +1642,80 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component)
|
|||
return val == 0;
|
||||
}
|
||||
|
||||
/* Jack detect timings */
|
||||
/* Jack detect and button-press timings */
|
||||
#define JACK_SETTLE_TIME 100 /* milli seconds */
|
||||
#define JACK_DETECT_COUNT 5
|
||||
#define JACK_DETECT_MAXCOUNT 20 /* Aprox. 2 seconds worth of tries */
|
||||
#define JACK_UNPLUG_TIME 80 /* milli seconds */
|
||||
#define BP_POLL_TIME 10 /* milli seconds */
|
||||
#define BP_POLL_MAXCOUNT 200 /* assume something is wrong after this */
|
||||
#define BP_THRESHOLD 3
|
||||
|
||||
static void rt5651_start_button_press_work(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
rt5651->poll_count = 0;
|
||||
rt5651->press_count = 0;
|
||||
rt5651->release_count = 0;
|
||||
rt5651->pressed = false;
|
||||
rt5651->press_reported = false;
|
||||
rt5651_clear_micbias1_ovcd(component);
|
||||
schedule_delayed_work(&rt5651->bp_work, msecs_to_jiffies(BP_POLL_TIME));
|
||||
}
|
||||
|
||||
static void rt5651_button_press_work(struct work_struct *work)
|
||||
{
|
||||
struct rt5651_priv *rt5651 =
|
||||
container_of(work, struct rt5651_priv, bp_work.work);
|
||||
struct snd_soc_component *component = rt5651->component;
|
||||
|
||||
/* Check the jack was not removed underneath us */
|
||||
if (!rt5651_jack_inserted(component))
|
||||
return;
|
||||
|
||||
if (rt5651_micbias1_ovcd(component)) {
|
||||
rt5651->release_count = 0;
|
||||
rt5651->press_count++;
|
||||
/* Remember till after JACK_UNPLUG_TIME wait */
|
||||
if (rt5651->press_count >= BP_THRESHOLD)
|
||||
rt5651->pressed = true;
|
||||
rt5651_clear_micbias1_ovcd(component);
|
||||
} else {
|
||||
rt5651->press_count = 0;
|
||||
rt5651->release_count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* The pins get temporarily shorted on jack unplug, so we poll for
|
||||
* at least JACK_UNPLUG_TIME milli-seconds before reporting a press.
|
||||
*/
|
||||
rt5651->poll_count++;
|
||||
if (rt5651->poll_count < (JACK_UNPLUG_TIME / BP_POLL_TIME)) {
|
||||
schedule_delayed_work(&rt5651->bp_work,
|
||||
msecs_to_jiffies(BP_POLL_TIME));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rt5651->pressed && !rt5651->press_reported) {
|
||||
dev_dbg(component->dev, "headset button press\n");
|
||||
snd_soc_jack_report(rt5651->hp_jack, SND_JACK_BTN_0,
|
||||
SND_JACK_BTN_0);
|
||||
rt5651->press_reported = true;
|
||||
}
|
||||
|
||||
if (rt5651->release_count >= BP_THRESHOLD) {
|
||||
if (rt5651->press_reported) {
|
||||
dev_dbg(component->dev, "headset button release\n");
|
||||
snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0);
|
||||
}
|
||||
/* Re-enable OVCD IRQ to detect next press */
|
||||
rt5651_enable_micbias1_ovcd_irq(component);
|
||||
return; /* Stop polling */
|
||||
}
|
||||
|
||||
schedule_delayed_work(&rt5651->bp_work, msecs_to_jiffies(BP_POLL_TIME));
|
||||
}
|
||||
|
||||
static int rt5651_detect_headset(struct snd_soc_component *component)
|
||||
{
|
||||
|
|
@ -1676,15 +1766,58 @@ static void rt5651_jack_detect_work(struct work_struct *work)
|
|||
{
|
||||
struct rt5651_priv *rt5651 =
|
||||
container_of(work, struct rt5651_priv, jack_detect_work);
|
||||
struct snd_soc_component *component = rt5651->component;
|
||||
int report = 0;
|
||||
|
||||
if (rt5651_jack_inserted(rt5651->component)) {
|
||||
rt5651_enable_micbias1_for_ovcd(rt5651->component);
|
||||
report = rt5651_detect_headset(rt5651->component);
|
||||
rt5651_disable_micbias1_for_ovcd(rt5651->component);
|
||||
}
|
||||
if (!rt5651_jack_inserted(component)) {
|
||||
/* Jack removed, or spurious IRQ? */
|
||||
if (rt5651->hp_jack->status & SND_JACK_HEADPHONE) {
|
||||
if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) {
|
||||
cancel_delayed_work_sync(&rt5651->bp_work);
|
||||
rt5651_disable_micbias1_ovcd_irq(component);
|
||||
rt5651_disable_micbias1_for_ovcd(component);
|
||||
}
|
||||
snd_soc_jack_report(rt5651->hp_jack, 0,
|
||||
SND_JACK_HEADSET | SND_JACK_BTN_0);
|
||||
dev_dbg(component->dev, "jack unplugged\n");
|
||||
}
|
||||
} else if (!(rt5651->hp_jack->status & SND_JACK_HEADPHONE)) {
|
||||
/* Jack inserted */
|
||||
WARN_ON(rt5651->ovcd_irq_enabled);
|
||||
rt5651_enable_micbias1_for_ovcd(component);
|
||||
report = rt5651_detect_headset(component);
|
||||
if (report == SND_JACK_HEADSET) {
|
||||
/* Enable ovcd IRQ for button press detect. */
|
||||
rt5651_enable_micbias1_ovcd_irq(component);
|
||||
} else {
|
||||
/* No more need for overcurrent detect. */
|
||||
rt5651_disable_micbias1_for_ovcd(component);
|
||||
}
|
||||
dev_dbg(component->dev, "detect report %#02x\n", report);
|
||||
snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
|
||||
} else if (rt5651->ovcd_irq_enabled && rt5651_micbias1_ovcd(component)) {
|
||||
dev_dbg(component->dev, "OVCD IRQ\n");
|
||||
|
||||
snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
|
||||
/*
|
||||
* The ovcd IRQ keeps firing while the button is pressed, so
|
||||
* we disable it and start polling the button until released.
|
||||
*
|
||||
* The disable will make the IRQ pin 0 again and since we get
|
||||
* IRQs on both edges (so as to detect both jack plugin and
|
||||
* unplug) this means we will immediately get another IRQ.
|
||||
* The ovcd_irq_enabled check above makes the 2ND IRQ a NOP.
|
||||
*/
|
||||
rt5651_disable_micbias1_ovcd_irq(component);
|
||||
rt5651_start_button_press_work(component);
|
||||
|
||||
/*
|
||||
* If the jack-detect IRQ flag goes high (unplug) after our
|
||||
* above rt5651_jack_inserted() check and before we have
|
||||
* disabled the OVCD IRQ, the IRQ pin will stay high and as
|
||||
* we react to edges, we miss the unplug event -> recheck.
|
||||
*/
|
||||
queue_work(system_long_wq, &rt5651->jack_detect_work);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t rt5651_irq(int irq, void *data)
|
||||
|
|
@ -1696,14 +1829,18 @@ static irqreturn_t rt5651_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rt5651_set_jack(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *hp_jack, void *data)
|
||||
static void rt5651_cancel_work(void *data)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = data;
|
||||
|
||||
cancel_work_sync(&rt5651->jack_detect_work);
|
||||
cancel_delayed_work_sync(&rt5651->bp_work);
|
||||
}
|
||||
|
||||
static void rt5651_enable_jack_detect(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *hp_jack)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
if (!rt5651->irq)
|
||||
return -EINVAL;
|
||||
|
||||
/* IRQ output on GPIO1 */
|
||||
snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1,
|
||||
|
|
@ -1730,10 +1867,10 @@ static int rt5651_set_jack(struct snd_soc_component *component,
|
|||
RT5651_JD2_IRQ_EN, RT5651_JD2_IRQ_EN);
|
||||
break;
|
||||
case RT5651_JD_NULL:
|
||||
return 0;
|
||||
return;
|
||||
default:
|
||||
dev_err(component->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable jack detect power */
|
||||
|
|
@ -1767,19 +1904,39 @@ static int rt5651_set_jack(struct snd_soc_component *component,
|
|||
RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN);
|
||||
|
||||
rt5651->hp_jack = hp_jack;
|
||||
|
||||
ret = devm_request_threaded_irq(component->dev, rt5651->irq, NULL,
|
||||
rt5651_irq,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT, "rt5651", rt5651);
|
||||
if (ret) {
|
||||
dev_err(component->dev, "Failed to reguest IRQ: %d\n", ret);
|
||||
return ret;
|
||||
if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) {
|
||||
rt5651_enable_micbias1_for_ovcd(component);
|
||||
rt5651_enable_micbias1_ovcd_irq(component);
|
||||
}
|
||||
|
||||
enable_irq(rt5651->irq);
|
||||
/* sync initial jack state */
|
||||
queue_work(system_power_efficient_wq, &rt5651->jack_detect_work);
|
||||
}
|
||||
|
||||
static void rt5651_disable_jack_detect(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
disable_irq(rt5651->irq);
|
||||
rt5651_cancel_work(rt5651);
|
||||
|
||||
if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) {
|
||||
rt5651_disable_micbias1_ovcd_irq(component);
|
||||
rt5651_disable_micbias1_for_ovcd(component);
|
||||
snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0);
|
||||
}
|
||||
|
||||
rt5651->hp_jack = NULL;
|
||||
}
|
||||
|
||||
static int rt5651_set_jack(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *jack, void *data)
|
||||
{
|
||||
if (jack)
|
||||
rt5651_enable_jack_detect(component, jack);
|
||||
else
|
||||
rt5651_disable_jack_detect(component);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2034,8 +2191,26 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
|
|||
rt5651->irq = i2c->irq;
|
||||
rt5651->hp_mute = 1;
|
||||
|
||||
INIT_DELAYED_WORK(&rt5651->bp_work, rt5651_button_press_work);
|
||||
INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
|
||||
|
||||
/* Make sure work is stopped on probe-error / remove */
|
||||
ret = devm_add_action_or_reset(&i2c->dev, rt5651_cancel_work, rt5651);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_request_irq(&i2c->dev, rt5651->irq, rt5651_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
|
||||
| IRQF_ONESHOT, "rt5651", rt5651);
|
||||
if (ret == 0) {
|
||||
/* Gets re-enabled by rt5651_set_jack() */
|
||||
disable_irq(rt5651->irq);
|
||||
} else {
|
||||
dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n",
|
||||
rt5651->irq, ret);
|
||||
rt5651->irq = -ENXIO;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&i2c->dev,
|
||||
&soc_component_dev_rt5651,
|
||||
rt5651_dai, ARRAY_SIZE(rt5651_dai));
|
||||
|
|
@ -2043,15 +2218,6 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int rt5651_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
|
||||
|
||||
cancel_work_sync(&rt5651->jack_detect_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver rt5651_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rt5651",
|
||||
|
|
@ -2059,7 +2225,6 @@ static struct i2c_driver rt5651_i2c_driver = {
|
|||
.of_match_table = of_match_ptr(rt5651_of_match),
|
||||
},
|
||||
.probe = rt5651_i2c_probe,
|
||||
.remove = rt5651_i2c_remove,
|
||||
.id_table = rt5651_i2c_id,
|
||||
};
|
||||
module_i2c_driver(rt5651_i2c_driver);
|
||||
|
|
|
|||
|
|
@ -2071,8 +2071,16 @@ struct rt5651_pll_code {
|
|||
struct rt5651_priv {
|
||||
struct snd_soc_component *component;
|
||||
struct regmap *regmap;
|
||||
/* Jack and button detect data */
|
||||
struct snd_soc_jack *hp_jack;
|
||||
struct work_struct jack_detect_work;
|
||||
struct delayed_work bp_work;
|
||||
bool ovcd_irq_enabled;
|
||||
bool pressed;
|
||||
bool press_reported;
|
||||
int press_count;
|
||||
int release_count;
|
||||
int poll_count;
|
||||
unsigned int jd_src;
|
||||
unsigned int ovcd_th;
|
||||
unsigned int ovcd_sf;
|
||||
|
|
|
|||
|
|
@ -4417,6 +4417,7 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
|||
break;
|
||||
case 25:
|
||||
slot_width_25 = 0x8080;
|
||||
/* fall through */
|
||||
case 24:
|
||||
val |= (2 << 8);
|
||||
break;
|
||||
|
|
@ -5007,7 +5008,7 @@ static const struct regmap_config rt5677_regmap = {
|
|||
};
|
||||
|
||||
static const struct of_device_id rt5677_of_match[] = {
|
||||
{ .compatible = "realtek,rt5677", RT5677 },
|
||||
{ .compatible = "realtek,rt5677", .data = (const void *)RT5677 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rt5677_of_match);
|
||||
|
|
|
|||
2681
sound/soc/codecs/rt5682.c
Normal file
2681
sound/soc/codecs/rt5682.c
Normal file
File diff suppressed because it is too large
Load diff
1324
sound/soc/codecs/rt5682.h
Normal file
1324
sound/soc/codecs/rt5682.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -21,9 +21,9 @@
|
|||
#include <linux/module.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#define DRV_NAME "dio2125"
|
||||
#define DRV_NAME "simple-amplifier"
|
||||
|
||||
struct dio2125 {
|
||||
struct simple_amp {
|
||||
struct gpio_desc *gpiod_enable;
|
||||
};
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ static int drv_event(struct snd_soc_dapm_widget *w,
|
|||
struct snd_kcontrol *control, int event)
|
||||
{
|
||||
struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
|
||||
struct dio2125 *priv = snd_soc_component_get_drvdata(c);
|
||||
struct simple_amp *priv = snd_soc_component_get_drvdata(c);
|
||||
int val;
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -51,7 +51,7 @@ static int drv_event(struct snd_soc_dapm_widget *w,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget dio2125_dapm_widgets[] = {
|
||||
static const struct snd_soc_dapm_widget simple_amp_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_INPUT("INL"),
|
||||
SND_SOC_DAPM_INPUT("INR"),
|
||||
SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, drv_event,
|
||||
|
|
@ -60,24 +60,24 @@ static const struct snd_soc_dapm_widget dio2125_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_OUTPUT("OUTR"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route dio2125_dapm_routes[] = {
|
||||
static const struct snd_soc_dapm_route simple_amp_dapm_routes[] = {
|
||||
{ "DRV", NULL, "INL" },
|
||||
{ "DRV", NULL, "INR" },
|
||||
{ "OUTL", NULL, "DRV" },
|
||||
{ "OUTR", NULL, "DRV" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver dio2125_component_driver = {
|
||||
.dapm_widgets = dio2125_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(dio2125_dapm_widgets),
|
||||
.dapm_routes = dio2125_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(dio2125_dapm_routes),
|
||||
static const struct snd_soc_component_driver simple_amp_component_driver = {
|
||||
.dapm_widgets = simple_amp_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets),
|
||||
.dapm_routes = simple_amp_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes),
|
||||
};
|
||||
|
||||
static int dio2125_probe(struct platform_device *pdev)
|
||||
static int simple_amp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dio2125 *priv;
|
||||
struct simple_amp *priv;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
|
@ -93,28 +93,30 @@ static int dio2125_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
return devm_snd_soc_register_component(dev, &dio2125_component_driver,
|
||||
return devm_snd_soc_register_component(dev,
|
||||
&simple_amp_component_driver,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id dio2125_ids[] = {
|
||||
static const struct of_device_id simple_amp_ids[] = {
|
||||
{ .compatible = "dioo,dio2125", },
|
||||
{ .compatible = "simple-audio-amplifier", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dio2125_ids);
|
||||
MODULE_DEVICE_TABLE(of, simple_amp_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver dio2125_driver = {
|
||||
static struct platform_driver simple_amp_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = of_match_ptr(dio2125_ids),
|
||||
.of_match_table = of_match_ptr(simple_amp_ids),
|
||||
},
|
||||
.probe = dio2125_probe,
|
||||
.probe = simple_amp_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(dio2125_driver);
|
||||
module_platform_driver(simple_amp_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC DIO2125 output driver");
|
||||
MODULE_DESCRIPTION("ASoC Simple Audio Amplifier driver");
|
||||
MODULE_AUTHOR("Jerome Brunet <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -7,6 +7,9 @@
|
|||
* TAS5721 support:
|
||||
* Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com>
|
||||
*
|
||||
* TAS5707 support:
|
||||
* Copyright (C) 2018 Jerome Brunet, Baylibre SAS <jbrunet@baylibre.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
|
|
@ -444,6 +447,111 @@ static const struct tas571x_chip tas5711_chip = {
|
|||
.vol_reg_size = 1,
|
||||
};
|
||||
|
||||
static const struct regmap_range tas5707_volatile_regs_range[] = {
|
||||
regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG),
|
||||
regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG),
|
||||
regmap_reg_range(TAS5707_CH1_BQ0_REG, TAS5707_CH2_BQ6_REG),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table tas5707_volatile_regs = {
|
||||
.yes_ranges = tas5707_volatile_regs_range,
|
||||
.n_yes_ranges = ARRAY_SIZE(tas5707_volatile_regs_range),
|
||||
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(tas5707_volume_tlv, -7900, 50, 1);
|
||||
|
||||
static const char * const tas5707_volume_slew_step_txt[] = {
|
||||
"256", "512", "1024", "2048",
|
||||
};
|
||||
|
||||
static const unsigned int tas5707_volume_slew_step_values[] = {
|
||||
3, 0, 1, 2,
|
||||
};
|
||||
|
||||
static SOC_VALUE_ENUM_SINGLE_DECL(tas5707_volume_slew_step_enum,
|
||||
TAS571X_VOL_CFG_REG, 0, 0x3,
|
||||
tas5707_volume_slew_step_txt,
|
||||
tas5707_volume_slew_step_values);
|
||||
|
||||
static const struct snd_kcontrol_new tas5707_controls[] = {
|
||||
SOC_SINGLE_TLV("Master Volume",
|
||||
TAS571X_MVOL_REG,
|
||||
0, 0xff, 1, tas5707_volume_tlv),
|
||||
SOC_DOUBLE_R_TLV("Speaker Volume",
|
||||
TAS571X_CH1_VOL_REG,
|
||||
TAS571X_CH2_VOL_REG,
|
||||
0, 0xff, 1, tas5707_volume_tlv),
|
||||
SOC_DOUBLE("Speaker Switch",
|
||||
TAS571X_SOFT_MUTE_REG,
|
||||
TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
|
||||
1, 1),
|
||||
|
||||
SOC_ENUM("Slew Rate Steps", tas5707_volume_slew_step_enum),
|
||||
|
||||
BIQUAD_COEFS("CH1 - Biquad 0", TAS5707_CH1_BQ0_REG),
|
||||
BIQUAD_COEFS("CH1 - Biquad 1", TAS5707_CH1_BQ1_REG),
|
||||
BIQUAD_COEFS("CH1 - Biquad 2", TAS5707_CH1_BQ2_REG),
|
||||
BIQUAD_COEFS("CH1 - Biquad 3", TAS5707_CH1_BQ3_REG),
|
||||
BIQUAD_COEFS("CH1 - Biquad 4", TAS5707_CH1_BQ4_REG),
|
||||
BIQUAD_COEFS("CH1 - Biquad 5", TAS5707_CH1_BQ5_REG),
|
||||
BIQUAD_COEFS("CH1 - Biquad 6", TAS5707_CH1_BQ6_REG),
|
||||
|
||||
BIQUAD_COEFS("CH2 - Biquad 0", TAS5707_CH2_BQ0_REG),
|
||||
BIQUAD_COEFS("CH2 - Biquad 1", TAS5707_CH2_BQ1_REG),
|
||||
BIQUAD_COEFS("CH2 - Biquad 2", TAS5707_CH2_BQ2_REG),
|
||||
BIQUAD_COEFS("CH2 - Biquad 3", TAS5707_CH2_BQ3_REG),
|
||||
BIQUAD_COEFS("CH2 - Biquad 4", TAS5707_CH2_BQ4_REG),
|
||||
BIQUAD_COEFS("CH2 - Biquad 5", TAS5707_CH2_BQ5_REG),
|
||||
BIQUAD_COEFS("CH2 - Biquad 6", TAS5707_CH2_BQ6_REG),
|
||||
};
|
||||
|
||||
static const struct reg_default tas5707_reg_defaults[] = {
|
||||
{TAS571X_CLK_CTRL_REG, 0x6c},
|
||||
{TAS571X_DEV_ID_REG, 0x70},
|
||||
{TAS571X_ERR_STATUS_REG, 0x00},
|
||||
{TAS571X_SYS_CTRL_1_REG, 0xa0},
|
||||
{TAS571X_SDI_REG, 0x05},
|
||||
{TAS571X_SYS_CTRL_2_REG, 0x40},
|
||||
{TAS571X_SOFT_MUTE_REG, 0x00},
|
||||
{TAS571X_MVOL_REG, 0xff},
|
||||
{TAS571X_CH1_VOL_REG, 0x30},
|
||||
{TAS571X_CH2_VOL_REG, 0x30},
|
||||
{TAS571X_VOL_CFG_REG, 0x91},
|
||||
{TAS571X_MODULATION_LIMIT_REG, 0x02},
|
||||
{TAS571X_IC_DELAY_CH1_REG, 0xac},
|
||||
{TAS571X_IC_DELAY_CH2_REG, 0x54},
|
||||
{TAS571X_IC_DELAY_CH3_REG, 0xac},
|
||||
{TAS571X_IC_DELAY_CH4_REG, 0x54},
|
||||
{TAS571X_START_STOP_PERIOD_REG, 0x0f},
|
||||
{TAS571X_OSC_TRIM_REG, 0x82},
|
||||
{TAS571X_BKND_ERR_REG, 0x02},
|
||||
{TAS571X_INPUT_MUX_REG, 0x17772},
|
||||
{TAS571X_PWM_MUX_REG, 0x1021345},
|
||||
};
|
||||
|
||||
static const struct regmap_config tas5707_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 32,
|
||||
.max_register = 0xff,
|
||||
.reg_read = tas571x_reg_read,
|
||||
.reg_write = tas571x_reg_write,
|
||||
.reg_defaults = tas5707_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(tas5707_reg_defaults),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.wr_table = &tas571x_write_regs,
|
||||
.volatile_table = &tas5707_volatile_regs,
|
||||
};
|
||||
|
||||
static const struct tas571x_chip tas5707_chip = {
|
||||
.supply_names = tas5711_supply_names,
|
||||
.num_supply_names = ARRAY_SIZE(tas5711_supply_names),
|
||||
.controls = tas5707_controls,
|
||||
.num_controls = ARRAY_SIZE(tas5707_controls),
|
||||
.regmap_config = &tas5707_regmap_config,
|
||||
.vol_reg_size = 1,
|
||||
};
|
||||
|
||||
static const char *const tas5717_supply_names[] = {
|
||||
"AVDD",
|
||||
"DVDD",
|
||||
|
|
@ -775,6 +883,7 @@ static int tas571x_i2c_remove(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct of_device_id tas571x_of_match[] = {
|
||||
{ .compatible = "ti,tas5707", .data = &tas5707_chip, },
|
||||
{ .compatible = "ti,tas5711", .data = &tas5711_chip, },
|
||||
{ .compatible = "ti,tas5717", .data = &tas5717_chip, },
|
||||
{ .compatible = "ti,tas5719", .data = &tas5717_chip, },
|
||||
|
|
@ -784,6 +893,7 @@ static const struct of_device_id tas571x_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, tas571x_of_match);
|
||||
|
||||
static const struct i2c_device_id tas571x_i2c_id[] = {
|
||||
{ "tas5707", (kernel_ulong_t) &tas5707_chip },
|
||||
{ "tas5711", (kernel_ulong_t) &tas5711_chip },
|
||||
{ "tas5717", (kernel_ulong_t) &tas5717_chip },
|
||||
{ "tas5719", (kernel_ulong_t) &tas5717_chip },
|
||||
|
|
|
|||
|
|
@ -53,6 +53,22 @@
|
|||
#define TAS571X_PWM_MUX_REG 0x25
|
||||
|
||||
/* 20-byte biquad registers */
|
||||
#define TAS5707_CH1_BQ0_REG 0x29
|
||||
#define TAS5707_CH1_BQ1_REG 0x2a
|
||||
#define TAS5707_CH1_BQ2_REG 0x2b
|
||||
#define TAS5707_CH1_BQ3_REG 0x2c
|
||||
#define TAS5707_CH1_BQ4_REG 0x2d
|
||||
#define TAS5707_CH1_BQ5_REG 0x2e
|
||||
#define TAS5707_CH1_BQ6_REG 0x2f
|
||||
|
||||
#define TAS5707_CH2_BQ0_REG 0x30
|
||||
#define TAS5707_CH2_BQ1_REG 0x31
|
||||
#define TAS5707_CH2_BQ2_REG 0x32
|
||||
#define TAS5707_CH2_BQ3_REG 0x33
|
||||
#define TAS5707_CH2_BQ4_REG 0x34
|
||||
#define TAS5707_CH2_BQ5_REG 0x35
|
||||
#define TAS5707_CH2_BQ6_REG 0x36
|
||||
|
||||
#define TAS5717_CH1_BQ0_REG 0x26
|
||||
#define TAS5717_CH1_BQ1_REG 0x27
|
||||
#define TAS5717_CH1_BQ2_REG 0x28
|
||||
|
|
|
|||
|
|
@ -142,9 +142,9 @@ struct tda7419_vol_control {
|
|||
static inline bool tda7419_vol_is_stereo(struct tda7419_vol_control *tvc)
|
||||
{
|
||||
if (tvc->reg == tvc->rreg)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int tda7419_vol_info(struct snd_kcontrol *kcontrol,
|
||||
|
|
|
|||
|
|
@ -625,25 +625,34 @@ static int bytes_info_ext(struct snd_kcontrol *kcontrol,
|
|||
|
||||
static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
|
||||
/* Volumes */
|
||||
SOC_DOUBLE_R_TLV("Headphone Playback Volume", R_HPVOLL, R_HPVOLR,
|
||||
SOC_DOUBLE_R_TLV("Headphone Volume", R_HPVOLL, R_HPVOLR,
|
||||
FB_HPVOLL, 0x7F, 0, hpvol_scale),
|
||||
SOC_DOUBLE_R_TLV("Speaker Playback Volume", R_SPKVOLL, R_SPKVOLR,
|
||||
SOC_DOUBLE_R_TLV("Speaker Volume", R_SPKVOLL, R_SPKVOLR,
|
||||
FB_SPKVOLL, 0x7F, 0, spkvol_scale),
|
||||
SOC_DOUBLE_R_TLV("Master Playback Volume", R_DACVOLL, R_DACVOLR,
|
||||
SOC_DOUBLE_R_TLV("Master Volume", R_DACVOLL, R_DACVOLR,
|
||||
FB_DACVOLL, 0xFF, 0, dacvol_scale),
|
||||
SOC_DOUBLE_R_TLV("PCM Capture Volume", R_ADCVOLL, R_ADCVOLR,
|
||||
SOC_DOUBLE_R_TLV("PCM Volume", R_ADCVOLL, R_ADCVOLR,
|
||||
FB_ADCVOLL, 0xFF, 0, adcvol_scale),
|
||||
SOC_DOUBLE_R_TLV("Master Capture Volume", R_INVOLL, R_INVOLR,
|
||||
SOC_DOUBLE_R_TLV("Input Volume", R_INVOLL, R_INVOLR,
|
||||
FB_INVOLL, 0x3F, 0, invol_scale),
|
||||
|
||||
/* INSEL */
|
||||
SOC_DOUBLE_R_TLV("Mic Boost Capture Volume", R_INSELL, R_INSELR,
|
||||
SOC_DOUBLE_R_TLV("Mic Boost Volume", R_INSELL, R_INSELR,
|
||||
FB_INSELL_MICBSTL, FV_INSELL_MICBSTL_30DB,
|
||||
0, mic_boost_scale),
|
||||
|
||||
/* Input Channel Map */
|
||||
SOC_ENUM("Input Channel Map", ch_map_select_enum),
|
||||
|
||||
/* Mic Bias */
|
||||
SOC_SINGLE("Mic Bias Boost Switch", 0x71, 0x07, 1, 0),
|
||||
|
||||
/* Headphone Auto Switching */
|
||||
SOC_SINGLE("Headphone Auto Switching Switch",
|
||||
R_CTL, FB_CTL_HPSWEN, 1, 0),
|
||||
SOC_SINGLE("Headphone Detect Polarity Toggle Switch",
|
||||
R_CTL, FB_CTL_HPSWPOL, 1, 0),
|
||||
|
||||
/* Coefficient Ram */
|
||||
COEFF_RAM_CTL("Cascade1L BiQuad1", BIQUAD_SIZE, 0x00),
|
||||
COEFF_RAM_CTL("Cascade1L BiQuad2", BIQUAD_SIZE, 0x05),
|
||||
|
|
@ -733,9 +742,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
|
|||
R_CLECTL, FB_CLECTL_LIMIT_EN, 1, 0),
|
||||
SOC_SINGLE("Comp Switch",
|
||||
R_CLECTL, FB_CLECTL_COMP_EN, 1, 0),
|
||||
SOC_SINGLE_TLV("CLE Make-Up Gain Playback Volume",
|
||||
SOC_SINGLE_TLV("CLE Make-Up Gain Volume",
|
||||
R_MUGAIN, FB_MUGAIN_CLEMUG, 0x1f, 0, mugain_scale),
|
||||
SOC_SINGLE_TLV("Comp Thresh Playback Volume",
|
||||
SOC_SINGLE_TLV("Comp Thresh Volume",
|
||||
R_COMPTH, FB_COMPTH, 0xff, 0, compth_scale),
|
||||
SOC_ENUM("Comp Ratio", compressor_ratio_enum),
|
||||
SND_SOC_BYTES("Comp Atk Time", R_CATKTCL, 2),
|
||||
|
|
@ -766,9 +775,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
|
|||
|
||||
SOC_SINGLE("MBC1 Phase Invert Switch",
|
||||
R_DACMBCMUG1, FB_DACMBCMUG1_PHASE, 1, 0),
|
||||
SOC_SINGLE_TLV("DAC MBC1 Make-Up Gain Playback Volume",
|
||||
SOC_SINGLE_TLV("DAC MBC1 Make-Up Gain Volume",
|
||||
R_DACMBCMUG1, FB_DACMBCMUG1_MUGAIN, 0x1f, 0, mugain_scale),
|
||||
SOC_SINGLE_TLV("DAC MBC1 Comp Thresh Playback Volume",
|
||||
SOC_SINGLE_TLV("DAC MBC1 Comp Thresh Volume",
|
||||
R_DACMBCTHR1, FB_DACMBCTHR1_THRESH, 0xff, 0, compth_scale),
|
||||
SOC_ENUM("DAC MBC1 Comp Ratio",
|
||||
dac_mbc1_compressor_ratio_enum),
|
||||
|
|
@ -778,9 +787,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
|
|||
|
||||
SOC_SINGLE("MBC2 Phase Invert Switch",
|
||||
R_DACMBCMUG2, FB_DACMBCMUG2_PHASE, 1, 0),
|
||||
SOC_SINGLE_TLV("DAC MBC2 Make-Up Gain Playback Volume",
|
||||
SOC_SINGLE_TLV("DAC MBC2 Make-Up Gain Volume",
|
||||
R_DACMBCMUG2, FB_DACMBCMUG2_MUGAIN, 0x1f, 0, mugain_scale),
|
||||
SOC_SINGLE_TLV("DAC MBC2 Comp Thresh Playback Volume",
|
||||
SOC_SINGLE_TLV("DAC MBC2 Comp Thresh Volume",
|
||||
R_DACMBCTHR2, FB_DACMBCTHR2_THRESH, 0xff, 0, compth_scale),
|
||||
SOC_ENUM("DAC MBC2 Comp Ratio",
|
||||
dac_mbc2_compressor_ratio_enum),
|
||||
|
|
@ -790,9 +799,9 @@ static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
|
|||
|
||||
SOC_SINGLE("MBC3 Phase Invert Switch",
|
||||
R_DACMBCMUG3, FB_DACMBCMUG3_PHASE, 1, 0),
|
||||
SOC_SINGLE_TLV("DAC MBC3 Make-Up Gain Playback Volume",
|
||||
SOC_SINGLE_TLV("DAC MBC3 Make-Up Gain Volume",
|
||||
R_DACMBCMUG3, FB_DACMBCMUG3_MUGAIN, 0x1f, 0, mugain_scale),
|
||||
SOC_SINGLE_TLV("DAC MBC3 Comp Thresh Playback Volume",
|
||||
SOC_SINGLE_TLV("DAC MBC3 Comp Thresh Volume",
|
||||
R_DACMBCTHR3, FB_DACMBCTHR3_THRESH, 0xff, 0, compth_scale),
|
||||
SOC_ENUM("DAC MBC3 Comp Ratio",
|
||||
dac_mbc3_compressor_ratio_enum),
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ enum {
|
|||
#define R_DACSR 0x19
|
||||
#define R_PWRM1 0x1A
|
||||
#define R_PWRM2 0x1B
|
||||
#define R_CTL 0x1C
|
||||
#define R_CONFIG0 0x1F
|
||||
#define R_CONFIG1 0x20
|
||||
#define R_DMICCTL 0x24
|
||||
|
|
@ -1110,6 +1111,13 @@ enum {
|
|||
#define RV_PWRM2_VREF_DISABLE \
|
||||
RV(FV_PWRM2_VREF_DISABLE, FB_PWRM2_VREF)
|
||||
|
||||
/******************************
|
||||
* R_CTL (0x1C) *
|
||||
******************************/
|
||||
|
||||
/* Fiel Offsets */
|
||||
#define FB_CTL_HPSWEN 7
|
||||
#define FB_CTL_HPSWPOL 6
|
||||
|
||||
/******************************
|
||||
* R_CONFIG0 (0x1F) *
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ static bool twl6040_can_write_to_chip(struct snd_soc_component *component,
|
|||
case TWL6040_REG_HFRCTL:
|
||||
return priv->dl2_unmuted;
|
||||
default:
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1180,6 +1180,9 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
|
|||
SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
|
||||
WM2200_SPK1R_MUTE_SHIFT, 1, 1),
|
||||
SOC_ENUM("RxANC Src", wm2200_rxanc_input_sel),
|
||||
|
||||
WM_ADSP_FW_CONTROL("DSP1", 0),
|
||||
WM_ADSP_FW_CONTROL("DSP2", 1),
|
||||
};
|
||||
|
||||
WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
|
||||
|
|
@ -1553,15 +1556,10 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
|
|||
static int wm2200_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
wm2200->component = component;
|
||||
|
||||
ret = snd_soc_add_component_controls(component, wm_adsp_fw_controls, 2);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ bool wm5100_volatile_register(struct device *dev, unsigned int reg)
|
|||
case WM5100_OUTPUT_STATUS_2:
|
||||
case WM5100_INPUT_ENABLES_STATUS:
|
||||
case WM5100_MIC_DETECT_3:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
if ((reg >= WM5100_DSP1_PM_0 && reg <= WM5100_DSP1_PM_1535) ||
|
||||
(reg >= WM5100_DSP1_ZM_0 && reg <= WM5100_DSP1_ZM_2047) ||
|
||||
|
|
@ -41,9 +41,9 @@ bool wm5100_volatile_register(struct device *dev, unsigned int reg)
|
|||
(reg >= WM5100_DSP3_PM_0 && reg <= WM5100_DSP3_PM_1535) ||
|
||||
(reg >= WM5100_DSP3_ZM_0 && reg <= WM5100_DSP3_ZM_2047) ||
|
||||
(reg >= WM5100_DSP3_DM_0 && reg <= WM5100_DSP3_DM_511))
|
||||
return 1;
|
||||
return true;
|
||||
else
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -798,7 +798,7 @@ bool wm5100_readable_register(struct device *dev, unsigned int reg)
|
|||
case WM5100_DSP3_CONTROL_28:
|
||||
case WM5100_DSP3_CONTROL_29:
|
||||
case WM5100_DSP3_CONTROL_30:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
if ((reg >= WM5100_DSP1_PM_0 && reg <= WM5100_DSP1_PM_1535) ||
|
||||
(reg >= WM5100_DSP1_ZM_0 && reg <= WM5100_DSP1_ZM_2047) ||
|
||||
|
|
@ -809,9 +809,9 @@ bool wm5100_readable_register(struct device *dev, unsigned int reg)
|
|||
(reg >= WM5100_DSP3_PM_0 && reg <= WM5100_DSP3_PM_1535) ||
|
||||
(reg >= WM5100_DSP3_ZM_0 && reg <= WM5100_DSP3_ZM_2047) ||
|
||||
(reg >= WM5100_DSP3_DM_0 && reg <= WM5100_DSP3_DM_511))
|
||||
return 1;
|
||||
return true;
|
||||
else
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -985,6 +985,8 @@ ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE),
|
|||
ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE),
|
||||
|
||||
WM_ADSP_FW_CONTROL("DSP1", 0),
|
||||
};
|
||||
|
||||
ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
|
||||
|
|
@ -2094,6 +2096,12 @@ static int wm5102_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1);
|
||||
if (ret != 0)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to set compressed IRQ as a wake source: %d\n",
|
||||
ret);
|
||||
|
||||
arizona_init_common(arizona);
|
||||
|
||||
ret = arizona_init_vol_limit(arizona);
|
||||
|
|
@ -2117,6 +2125,7 @@ static int wm5102_probe(struct platform_device *pdev)
|
|||
err_spk_irqs:
|
||||
arizona_free_spk_irqs(arizona);
|
||||
err_dsp_irq:
|
||||
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
|
||||
|
||||
return ret;
|
||||
|
|
@ -2133,6 +2142,7 @@ static int wm5102_remove(struct platform_device *pdev)
|
|||
|
||||
arizona_free_spk_irqs(arizona);
|
||||
|
||||
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -927,6 +927,11 @@ ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE),
|
|||
ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE),
|
||||
|
||||
WM_ADSP_FW_CONTROL("DSP1", 0),
|
||||
WM_ADSP_FW_CONTROL("DSP2", 1),
|
||||
WM_ADSP_FW_CONTROL("DSP3", 2),
|
||||
WM_ADSP_FW_CONTROL("DSP4", 3),
|
||||
};
|
||||
|
||||
ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
|
||||
|
|
@ -2455,6 +2460,12 @@ static int wm5110_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1);
|
||||
if (ret != 0)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to set compressed IRQ as a wake source: %d\n",
|
||||
ret);
|
||||
|
||||
arizona_init_common(arizona);
|
||||
|
||||
ret = arizona_init_vol_limit(arizona);
|
||||
|
|
@ -2478,6 +2489,7 @@ static int wm5110_probe(struct platform_device *pdev)
|
|||
err_spk_irqs:
|
||||
arizona_free_spk_irqs(arizona);
|
||||
err_dsp_irq:
|
||||
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
|
||||
|
||||
return ret;
|
||||
|
|
@ -2496,6 +2508,7 @@ static int wm5110_remove(struct platform_device *pdev)
|
|||
|
||||
arizona_free_spk_irqs(arizona);
|
||||
|
||||
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
|
||||
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -251,10 +251,10 @@ static bool wm8903_volatile_register(struct device *dev, unsigned int reg)
|
|||
case WM8903_DC_SERVO_READBACK_2:
|
||||
case WM8903_DC_SERVO_READBACK_3:
|
||||
case WM8903_DC_SERVO_READBACK_4:
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1455,6 +1455,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif1 |= 0x3 | WM8904_AIF_LRCLK_INV;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif1 |= 0x3;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -686,6 +686,7 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif |= WM8955_LRP;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif |= 0x3;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -839,6 +839,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
|
|||
iface |= 0x000c;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
dev_err(component->dev, "unsupported width %d\n",
|
||||
params_width(params));
|
||||
|
|
|
|||
|
|
@ -653,6 +653,7 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif |= WM8961_LRP;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif |= 3;
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
|
|
|
|||
|
|
@ -2649,6 +2649,7 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif0 |= WM8962_LRCLK_INV | 3;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif0 |= 3;
|
||||
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ static inline int get_coeff(int mclk, int rate)
|
|||
/* The set of rates we can generate from the above for each SYSCLK */
|
||||
|
||||
static const unsigned int rates_12288[] = {
|
||||
8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
|
||||
8000, 12000, 16000, 24000, 32000, 48000, 96000,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hw_constraint_list constraints_12288 = {
|
||||
|
|
@ -540,7 +540,7 @@ static const struct snd_pcm_hw_constraint_list constraints_112896 = {
|
|||
};
|
||||
|
||||
static const unsigned int rates_12[] = {
|
||||
8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
|
||||
8000, 11025, 12000, 16000, 22050, 24000, 32000, 41100, 48000,
|
||||
48000, 88235, 96000,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ static bool wm8990_volatile_register(struct device *dev, unsigned int reg)
|
|||
{
|
||||
switch (reg) {
|
||||
case WM8990_RESET:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2432,6 +2432,7 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
|
|||
snd_soc_component_update_bits(component, WM8994_POWER_MANAGEMENT_2,
|
||||
WM8994_OPCLK_ENA, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -1465,6 +1465,7 @@ static int wm8995_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif |= WM8995_AIF1_LRCLK_INV;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif |= (0x3 << WM8995_AIF1_FMT_SHIFT);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1498,9 +1498,9 @@ static bool wm8996_readable_register(struct device *dev, unsigned int reg)
|
|||
case WM8996_RIGHT_PDM_SPEAKER:
|
||||
case WM8996_PDM_SPEAKER_MUTE_SEQUENCE:
|
||||
case WM8996_PDM_SPEAKER_VOLUME:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1522,9 +1522,9 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
|
|||
case WM8996_MIC_DETECT_3:
|
||||
case WM8996_HEADPHONE_DETECT_1:
|
||||
case WM8996_HEADPHONE_DETECT_2:
|
||||
return 1;
|
||||
return true;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1858,6 +1858,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
|
|||
case 24576000:
|
||||
ratediv = WM8996_SYSCLK_DIV;
|
||||
wm8996->sysclk /= 2;
|
||||
/* fall through */
|
||||
case 11289600:
|
||||
case 12288000:
|
||||
snd_soc_component_update_bits(component, WM8996_AIF_RATE,
|
||||
|
|
|
|||
|
|
@ -933,6 +933,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
|
|||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
aif2 |= WM9081_AIF_LRCLK_INV;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
aif2 |= 0x3;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
|
@ -35,15 +36,15 @@
|
|||
#include "wm_adsp.h"
|
||||
|
||||
#define adsp_crit(_dsp, fmt, ...) \
|
||||
dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
|
||||
dev_crit(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
|
||||
#define adsp_err(_dsp, fmt, ...) \
|
||||
dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
|
||||
dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
|
||||
#define adsp_warn(_dsp, fmt, ...) \
|
||||
dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
|
||||
dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
|
||||
#define adsp_info(_dsp, fmt, ...) \
|
||||
dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
|
||||
dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
|
||||
#define adsp_dbg(_dsp, fmt, ...) \
|
||||
dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
|
||||
dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
|
||||
|
||||
#define ADSP1_CONTROL_1 0x00
|
||||
#define ADSP1_CONTROL_2 0x02
|
||||
|
|
@ -418,7 +419,7 @@ static const struct wm_adsp_fw_caps ctrl_caps[] = {
|
|||
{
|
||||
.id = SND_AUDIOCODEC_BESPOKE,
|
||||
.desc = {
|
||||
.max_ch = 1,
|
||||
.max_ch = 8,
|
||||
.sample_rates = { 16000 },
|
||||
.num_sample_rates = 1,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
|
|
@ -608,7 +609,6 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
|
|||
struct snd_soc_component *component)
|
||||
{
|
||||
struct dentry *root = NULL;
|
||||
char *root_name;
|
||||
int i;
|
||||
|
||||
if (!component->debugfs_root) {
|
||||
|
|
@ -616,13 +616,7 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
|
|||
goto err;
|
||||
}
|
||||
|
||||
root_name = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!root_name)
|
||||
goto err;
|
||||
|
||||
snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num);
|
||||
root = debugfs_create_dir(root_name, component->debugfs_root);
|
||||
kfree(root_name);
|
||||
root = debugfs_create_dir(dsp->name, component->debugfs_root);
|
||||
|
||||
if (!root)
|
||||
goto err;
|
||||
|
|
@ -684,8 +678,8 @@ static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
|
|
@ -695,9 +689,10 @@ static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_fw_get);
|
||||
|
||||
static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
|
|
@ -721,8 +716,9 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_fw_put);
|
||||
|
||||
static const struct soc_enum wm_adsp_fw_enum[] = {
|
||||
const struct soc_enum wm_adsp_fw_enum[] = {
|
||||
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||
SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||
SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||
|
|
@ -731,24 +727,7 @@ static const struct soc_enum wm_adsp_fw_enum[] = {
|
|||
SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||
SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
|
||||
};
|
||||
|
||||
const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
|
||||
SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
SOC_ENUM_EXT("DSP5 Firmware", wm_adsp_fw_enum[4],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
SOC_ENUM_EXT("DSP6 Firmware", wm_adsp_fw_enum[5],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
SOC_ENUM_EXT("DSP7 Firmware", wm_adsp_fw_enum[6],
|
||||
wm_adsp_fw_get, wm_adsp_fw_put),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_fw_enum);
|
||||
|
||||
static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
|
||||
int type)
|
||||
|
|
@ -1330,12 +1309,12 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
|
|||
switch (dsp->fw_ver) {
|
||||
case 0:
|
||||
case 1:
|
||||
snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x",
|
||||
dsp->num, region_name, alg_region->alg);
|
||||
snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x",
|
||||
dsp->name, region_name, alg_region->alg);
|
||||
break;
|
||||
default:
|
||||
ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
|
||||
"DSP%d%c %.12s %x", dsp->num, *region_name,
|
||||
"%s%c %.12s %x", dsp->name, *region_name,
|
||||
wm_adsp_fw_text[dsp->fw], alg_region->alg);
|
||||
|
||||
/* Truncate the subname from the start if it is too long */
|
||||
|
|
@ -1343,6 +1322,9 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
|
|||
int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
|
||||
int skip = 0;
|
||||
|
||||
if (dsp->component->name_prefix)
|
||||
avail -= strlen(dsp->component->name_prefix) + 1;
|
||||
|
||||
if (subname_len > avail)
|
||||
skip = subname_len - avail;
|
||||
|
||||
|
|
@ -1604,6 +1586,15 @@ static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
|
|||
if (ret)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case WMFW_CTL_TYPE_HOST_BUFFER:
|
||||
ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
|
||||
WMFW_CTL_FLAG_SYS |
|
||||
WMFW_CTL_FLAG_VOLATILE |
|
||||
WMFW_CTL_FLAG_READABLE,
|
||||
0);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
adsp_err(dsp, "Unknown control type: %d\n",
|
||||
coeff_blk.ctl_type);
|
||||
|
|
@ -1651,7 +1642,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
|
|||
if (file == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
|
||||
snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name,
|
||||
wm_adsp_fw[dsp->fw].file);
|
||||
file[PAGE_SIZE - 1] = '\0';
|
||||
|
||||
|
|
@ -1871,9 +1862,11 @@ static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp,
|
|||
}
|
||||
|
||||
static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
|
||||
const struct wm_adsp_region *mem,
|
||||
unsigned int pos, unsigned int len)
|
||||
{
|
||||
void *alg;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
__be32 val;
|
||||
|
||||
|
|
@ -1888,7 +1881,9 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
|
|||
}
|
||||
|
||||
/* Read the terminator first to validate the length */
|
||||
ret = regmap_raw_read(dsp->regmap, pos + len, &val, sizeof(val));
|
||||
reg = wm_adsp_region_to_reg(mem, pos + len);
|
||||
|
||||
ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
|
||||
if (ret != 0) {
|
||||
adsp_err(dsp, "Failed to read algorithm list end: %d\n",
|
||||
ret);
|
||||
|
|
@ -1897,13 +1892,18 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
|
|||
|
||||
if (be32_to_cpu(val) != 0xbedead)
|
||||
adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n",
|
||||
pos + len, be32_to_cpu(val));
|
||||
reg, be32_to_cpu(val));
|
||||
|
||||
alg = kcalloc(len, 2, GFP_KERNEL | GFP_DMA);
|
||||
/* Convert length from DSP words to bytes */
|
||||
len *= sizeof(u32);
|
||||
|
||||
alg = kzalloc(len, GFP_KERNEL | GFP_DMA);
|
||||
if (!alg)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2);
|
||||
reg = wm_adsp_region_to_reg(mem, pos);
|
||||
|
||||
ret = regmap_raw_read(dsp->regmap, reg, alg, len);
|
||||
if (ret != 0) {
|
||||
adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
|
||||
kfree(alg);
|
||||
|
|
@ -2002,10 +2002,11 @@ static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
|
|||
if (IS_ERR(alg_region))
|
||||
return PTR_ERR(alg_region);
|
||||
|
||||
pos = sizeof(adsp1_id) / 2;
|
||||
len = (sizeof(*adsp1_alg) * n_algs) / 2;
|
||||
/* Calculate offset and length in DSP words */
|
||||
pos = sizeof(adsp1_id) / sizeof(u32);
|
||||
len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32);
|
||||
|
||||
adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len);
|
||||
adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
|
||||
if (IS_ERR(adsp1_alg))
|
||||
return PTR_ERR(adsp1_alg);
|
||||
|
||||
|
|
@ -2113,10 +2114,11 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
|
|||
if (IS_ERR(alg_region))
|
||||
return PTR_ERR(alg_region);
|
||||
|
||||
pos = sizeof(adsp2_id) / 2;
|
||||
len = (sizeof(*adsp2_alg) * n_algs) / 2;
|
||||
/* Calculate offset and length in DSP words */
|
||||
pos = sizeof(adsp2_id) / sizeof(u32);
|
||||
len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32);
|
||||
|
||||
adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len);
|
||||
adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
|
||||
if (IS_ERR(adsp2_alg))
|
||||
return PTR_ERR(adsp2_alg);
|
||||
|
||||
|
|
@ -2218,7 +2220,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
|
|||
if (file == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
|
||||
snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name,
|
||||
wm_adsp_fw[dsp->fw].file);
|
||||
file[PAGE_SIZE - 1] = '\0';
|
||||
|
||||
|
|
@ -2390,8 +2392,38 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wm_adsp_create_name(struct wm_adsp *dsp)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!dsp->name) {
|
||||
dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d",
|
||||
dsp->num);
|
||||
if (!dsp->name)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!dsp->fwf_name) {
|
||||
p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
dsp->fwf_name = p;
|
||||
for (; *p != 0; ++p)
|
||||
*p = tolower(*p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wm_adsp1_init(struct wm_adsp *dsp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wm_adsp_create_name(dsp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
INIT_LIST_HEAD(&dsp->alg_regions);
|
||||
|
||||
mutex_init(&dsp->pwr_lock);
|
||||
|
|
@ -2642,7 +2674,10 @@ int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
|
||||
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct wm_adsp *dsp = &dsps[mc->shift - 1];
|
||||
|
||||
ucontrol->value.integer.value[0] = dsp->preloaded;
|
||||
|
||||
|
|
@ -2654,13 +2689,14 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
|
||||
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct wm_adsp *dsp = &dsps[mc->shift - 1];
|
||||
char preload[32];
|
||||
|
||||
snprintf(preload, ARRAY_SIZE(preload), "DSP%u Preload", mc->shift);
|
||||
snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name);
|
||||
|
||||
dsp->preloaded = ucontrol->value.integer.value[0];
|
||||
|
||||
|
|
@ -2671,6 +2707,8 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
|
|||
|
||||
snd_soc_dapm_sync(dapm);
|
||||
|
||||
flush_work(&dsp->boot_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
|
||||
|
|
@ -2853,17 +2891,14 @@ int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *comp
|
|||
{
|
||||
char preload[32];
|
||||
|
||||
snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", dsp->num);
|
||||
|
||||
snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name);
|
||||
snd_soc_component_disable_pin(component, preload);
|
||||
|
||||
wm_adsp2_init_debugfs(dsp, component);
|
||||
|
||||
dsp->component = component;
|
||||
|
||||
return snd_soc_add_component_controls(component,
|
||||
&wm_adsp_fw_controls[dsp->num - 1],
|
||||
1);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
|
||||
|
||||
|
|
@ -2879,6 +2914,10 @@ int wm_adsp2_init(struct wm_adsp *dsp)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = wm_adsp_create_name(dsp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (dsp->rev) {
|
||||
case 0:
|
||||
/*
|
||||
|
|
@ -3186,7 +3225,7 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
|
|||
buf->host_buf_ptr + field_offset, data);
|
||||
}
|
||||
|
||||
static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
|
||||
static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
struct wm_adsp_alg_region *alg_region;
|
||||
struct wm_adsp *dsp = buf->dsp;
|
||||
|
|
@ -3225,6 +3264,61 @@ static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct wm_coeff_ctl *
|
||||
wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
struct wm_adsp *dsp = buf->dsp;
|
||||
struct wm_coeff_ctl *ctl;
|
||||
|
||||
list_for_each_entry(ctl, &dsp->ctl_list, list) {
|
||||
if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
|
||||
continue;
|
||||
|
||||
if (!ctl->enabled)
|
||||
continue;
|
||||
|
||||
return ctl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
struct wm_adsp *dsp = buf->dsp;
|
||||
struct wm_coeff_ctl *ctl;
|
||||
unsigned int reg;
|
||||
u32 val;
|
||||
int i, ret;
|
||||
|
||||
ctl = wm_adsp_find_host_buffer_ctrl(buf);
|
||||
if (!ctl)
|
||||
return wm_adsp_legacy_host_buf_addr(buf);
|
||||
|
||||
ret = wm_coeff_base_reg(ctl, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (val)
|
||||
break;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
if (!val)
|
||||
return -EIO;
|
||||
|
||||
buf->host_buf_ptr = be32_to_cpu(val);
|
||||
adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ struct wm_adsp_compr_buf;
|
|||
|
||||
struct wm_adsp {
|
||||
const char *part;
|
||||
const char *name;
|
||||
const char *fwf_name;
|
||||
int rev;
|
||||
int num;
|
||||
int type;
|
||||
|
|
@ -121,7 +123,11 @@ struct wm_adsp {
|
|||
.reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
|
||||
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
|
||||
|
||||
extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
|
||||
#define WM_ADSP_FW_CONTROL(dspname, num) \
|
||||
SOC_ENUM_EXT(dspname " Firmware", wm_adsp_fw_enum[num], \
|
||||
wm_adsp_fw_get, wm_adsp_fw_put)
|
||||
|
||||
extern const struct soc_enum wm_adsp_fw_enum[];
|
||||
|
||||
int wm_adsp1_init(struct wm_adsp *dsp);
|
||||
int wm_adsp2_init(struct wm_adsp *dsp);
|
||||
|
|
@ -144,6 +150,10 @@ int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream);
|
||||
int wm_adsp_compr_free(struct snd_compr_stream *stream);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
/* 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 */
|
||||
|
||||
struct wmfw_header {
|
||||
char magic[4];
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
|
|||
* rate is lowered.
|
||||
*/
|
||||
inv_fs = true;
|
||||
/* fall through */
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
dev->mode = MOD_DSP_A;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -320,12 +320,8 @@ static irqreturn_t davinci_mcasp_tx_irq_handler(int irq, void *data)
|
|||
handled_mask |= XUNDRN;
|
||||
|
||||
substream = mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
if (substream) {
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (snd_pcm_running(substream))
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
if (substream)
|
||||
snd_pcm_stop_xrun(substream);
|
||||
}
|
||||
|
||||
if (!handled_mask)
|
||||
|
|
@ -355,12 +351,8 @@ static irqreturn_t davinci_mcasp_rx_irq_handler(int irq, void *data)
|
|||
handled_mask |= ROVRN;
|
||||
|
||||
substream = mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
if (substream) {
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (snd_pcm_running(substream))
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
if (substream)
|
||||
snd_pcm_stop_xrun(substream);
|
||||
}
|
||||
|
||||
if (!handled_mask)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
/*
|
||||
* Freescale Generic ASoC Sound Card driver with ASRC
|
||||
*
|
||||
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale Generic ASoC Sound Card driver with ASRC
|
||||
//
|
||||
// Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
//
|
||||
// Author: Nicolin Chen <[email protected]>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
@ -199,7 +195,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
|
||||
mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
snd_mask_none(mask);
|
||||
snd_mask_set(mask, (__force int)priv->asrc_format);
|
||||
snd_mask_set_format(mask, priv->asrc_format);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
/*
|
||||
* Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
|
||||
*
|
||||
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
|
||||
//
|
||||
// Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
//
|
||||
// Author: Nicolin Chen <[email protected]>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* fsl_asrc.h - Freescale ASRC ALSA SoC header file
|
||||
*
|
||||
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_ASRC_H
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
/*
|
||||
* Freescale ASRC ALSA SoC Platform (DMA) driver
|
||||
*
|
||||
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Nicolin Chen <nicoleotsuka@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale ASRC ALSA SoC Platform (DMA) driver
|
||||
//
|
||||
// Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
//
|
||||
// Author: Nicolin Chen <[email protected]>
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
|||
break;
|
||||
case ESAI_HCKT_EXTAL:
|
||||
ecr |= ESAI_ECR_ETI;
|
||||
/* fall through */
|
||||
case ESAI_HCKR_EXTAL:
|
||||
ecr |= ESAI_ECR_ERI;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1118,7 +1118,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
|
|||
|
||||
for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) {
|
||||
for (txclk_df = 1; txclk_df <= 128; txclk_df++) {
|
||||
rate_ideal = rate[index] * txclk_df * 64;
|
||||
rate_ideal = rate[index] * txclk_df * 64ULL;
|
||||
if (round)
|
||||
rate_actual = clk_round_rate(clk, rate_ideal);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
/**
|
||||
* Freescale ALSA SoC Machine driver utility
|
||||
*
|
||||
* Author: Timur Tabi <timur@freescale.com>
|
||||
*
|
||||
* Copyright 2010 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale ALSA SoC Machine driver utility
|
||||
//
|
||||
// Author: Timur Tabi <[email protected]>
|
||||
//
|
||||
// Copyright 2010 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
/**
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Freescale ALSA SoC Machine driver utility
|
||||
*
|
||||
* Author: Timur Tabi <timur@freescale.com>
|
||||
*
|
||||
* Copyright 2010 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef _FSL_UTILS_H
|
||||
|
|
|
|||
|
|
@ -1,14 +1,7 @@
|
|||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright 2012 Linaro Ltd.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Copyright 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright 2012 Linaro Ltd.
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
/*
|
||||
* ASoC audio graph sound card support
|
||||
*
|
||||
* Copyright (C) 2016 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* based on ${LINUX}/sound/soc/generic/simple-card.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// ASoC audio graph sound card support
|
||||
//
|
||||
// Copyright (C) 2016 Renesas Solutions Corp.
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
//
|
||||
// based on ${LINUX}/sound/soc/generic/simple-card.c
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
|
@ -21,7 +18,6 @@
|
|||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/simple_card_utils.h>
|
||||
|
||||
struct graph_card_data {
|
||||
|
|
@ -32,6 +28,8 @@ struct graph_card_data {
|
|||
unsigned int mclk_fs;
|
||||
} *dai_props;
|
||||
unsigned int mclk_fs;
|
||||
struct asoc_simple_jack hp_jack;
|
||||
struct asoc_simple_jack mic_jack;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct gpio_desc *pa_gpio;
|
||||
};
|
||||
|
|
@ -278,6 +276,22 @@ static int asoc_graph_get_dais_count(struct device *dev)
|
|||
return count;
|
||||
}
|
||||
|
||||
static int asoc_graph_soc_card_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct graph_card_data *priv = snd_soc_card_get_drvdata(card);
|
||||
int ret;
|
||||
|
||||
ret = asoc_simple_card_init_hp(card, &priv->hp_jack, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = asoc_simple_card_init_mic(card, &priv->mic_jack, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asoc_graph_card_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct graph_card_data *priv;
|
||||
|
|
@ -319,6 +333,7 @@ static int asoc_graph_card_probe(struct platform_device *pdev)
|
|||
card->num_links = num;
|
||||
card->dapm_widgets = asoc_graph_card_dapm_widgets;
|
||||
card->num_dapm_widgets = ARRAY_SIZE(asoc_graph_card_dapm_widgets);
|
||||
card->probe = asoc_graph_soc_card_probe;
|
||||
|
||||
ret = asoc_graph_card_parse_of(priv);
|
||||
if (ret < 0) {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
/*
|
||||
* ASoC audio graph SCU sound card support
|
||||
*
|
||||
* Copyright (C) 2017 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* based on
|
||||
* ${LINUX}/sound/soc/generic/simple-scu-card.c
|
||||
* ${LINUX}/sound/soc/generic/audio-graph-card.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// ASoC audio graph SCU sound card support
|
||||
//
|
||||
// Copyright (C) 2017 Renesas Solutions Corp.
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
//
|
||||
// based on
|
||||
// ${LINUX}/sound/soc/generic/simple-scu-card.c
|
||||
// ${LINUX}/sound/soc/generic/audio-graph-card.c
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
/*
|
||||
* simple-card-utils.c
|
||||
*
|
||||
* Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// simple-card-utils.c
|
||||
//
|
||||
// Copyright (c) 2016 Kuninori Morimoto <[email protected]>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/simple_card_utils.h>
|
||||
|
||||
void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data,
|
||||
|
|
@ -419,6 +420,61 @@ int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets);
|
||||
|
||||
int asoc_simple_card_init_jack(struct snd_soc_card *card,
|
||||
struct asoc_simple_jack *sjack,
|
||||
int is_hp, char *prefix)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
enum of_gpio_flags flags;
|
||||
char prop[128];
|
||||
char *pin_name;
|
||||
char *gpio_name;
|
||||
int mask;
|
||||
int det;
|
||||
|
||||
if (!prefix)
|
||||
prefix = "";
|
||||
|
||||
sjack->gpio.gpio = -ENOENT;
|
||||
|
||||
if (is_hp) {
|
||||
snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
|
||||
pin_name = "Headphones";
|
||||
gpio_name = "Headphone detection";
|
||||
mask = SND_JACK_HEADPHONE;
|
||||
} else {
|
||||
snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
|
||||
pin_name = "Mic Jack";
|
||||
gpio_name = "Mic detection";
|
||||
mask = SND_JACK_MICROPHONE;
|
||||
}
|
||||
|
||||
det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
|
||||
if (det == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (gpio_is_valid(det)) {
|
||||
sjack->pin.pin = pin_name;
|
||||
sjack->pin.mask = mask;
|
||||
|
||||
sjack->gpio.name = gpio_name;
|
||||
sjack->gpio.report = mask;
|
||||
sjack->gpio.gpio = det;
|
||||
sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
|
||||
sjack->gpio.debounce_time = 150;
|
||||
|
||||
snd_soc_card_jack_new(card, pin_name, mask,
|
||||
&sjack->jack,
|
||||
&sjack->pin, 1);
|
||||
|
||||
snd_soc_jack_add_gpios(&sjack->jack, 1,
|
||||
&sjack->gpio);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(asoc_simple_card_init_jack);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
|
||||
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
|
||||
|
|
|
|||
|
|
@ -1,32 +1,20 @@
|
|||
/*
|
||||
* ASoC simple sound card support
|
||||
*
|
||||
* Copyright (C) 2012 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// ASoC simple sound card support
|
||||
//
|
||||
// Copyright (C) 2012 Renesas Solutions Corp.
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/simple_card.h>
|
||||
#include <sound/soc-dai.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
struct asoc_simple_jack {
|
||||
struct snd_soc_jack jack;
|
||||
struct snd_soc_jack_pin pin;
|
||||
struct snd_soc_jack_gpio gpio;
|
||||
};
|
||||
|
||||
struct simple_card_data {
|
||||
struct snd_soc_card snd_card;
|
||||
struct simple_dai_props {
|
||||
|
|
@ -49,61 +37,6 @@ struct simple_card_data {
|
|||
#define CELL "#sound-dai-cells"
|
||||
#define PREFIX "simple-audio-card,"
|
||||
|
||||
#define asoc_simple_card_init_hp(card, sjack, prefix)\
|
||||
asoc_simple_card_init_jack(card, sjack, 1, prefix)
|
||||
#define asoc_simple_card_init_mic(card, sjack, prefix)\
|
||||
asoc_simple_card_init_jack(card, sjack, 0, prefix)
|
||||
static int asoc_simple_card_init_jack(struct snd_soc_card *card,
|
||||
struct asoc_simple_jack *sjack,
|
||||
int is_hp, char *prefix)
|
||||
{
|
||||
struct device *dev = card->dev;
|
||||
enum of_gpio_flags flags;
|
||||
char prop[128];
|
||||
char *pin_name;
|
||||
char *gpio_name;
|
||||
int mask;
|
||||
int det;
|
||||
|
||||
sjack->gpio.gpio = -ENOENT;
|
||||
|
||||
if (is_hp) {
|
||||
snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
|
||||
pin_name = "Headphones";
|
||||
gpio_name = "Headphone detection";
|
||||
mask = SND_JACK_HEADPHONE;
|
||||
} else {
|
||||
snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
|
||||
pin_name = "Mic Jack";
|
||||
gpio_name = "Mic detection";
|
||||
mask = SND_JACK_MICROPHONE;
|
||||
}
|
||||
|
||||
det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
|
||||
if (det == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (gpio_is_valid(det)) {
|
||||
sjack->pin.pin = pin_name;
|
||||
sjack->pin.mask = mask;
|
||||
|
||||
sjack->gpio.name = gpio_name;
|
||||
sjack->gpio.report = mask;
|
||||
sjack->gpio.gpio = det;
|
||||
sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
|
||||
sjack->gpio.debounce_time = 150;
|
||||
|
||||
snd_soc_card_jack_new(card, pin_name, mask,
|
||||
&sjack->jack,
|
||||
&sjack->pin, 1);
|
||||
|
||||
snd_soc_jack_add_gpios(&sjack->jack, 1,
|
||||
&sjack->gpio);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
|
|
@ -213,14 +146,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = asoc_simple_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -414,6 +339,22 @@ card_parse_end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int asoc_simple_soc_card_probe(struct snd_soc_card *card)
|
||||
{
|
||||
struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
|
||||
int ret;
|
||||
|
||||
ret = asoc_simple_card_init_hp(card, &priv->hp_jack, PREFIX);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = asoc_simple_card_init_mic(card, &priv->mic_jack, PREFIX);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asoc_simple_card_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct simple_card_data *priv;
|
||||
|
|
@ -449,6 +390,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
|
|||
card->dev = dev;
|
||||
card->dai_link = priv->dai_link;
|
||||
card->num_links = num;
|
||||
card->probe = asoc_simple_soc_card_probe;
|
||||
|
||||
if (np && of_device_is_available(np)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
/*
|
||||
* ASoC simple SCU sound card support
|
||||
*
|
||||
* Copyright (C) 2015 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* based on ${LINUX}/sound/soc/generic/simple-card.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// ASoC simple SCU sound card support
|
||||
//
|
||||
// Copyright (C) 2015 Renesas Solutions Corp.
|
||||
// Kuninori Morimoto <[email protected]>
|
||||
//
|
||||
// based on ${LINUX}/sound/soc/generic/simple-card.c
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
|||
|
|
@ -266,17 +266,15 @@ static int sst_cdev_ack(struct device *dev, unsigned int str_id,
|
|||
stream->cumm_bytes += bytes;
|
||||
dev_dbg(dev, "bytes copied %d inc by %ld\n", stream->cumm_bytes, bytes);
|
||||
|
||||
memcpy_fromio(&fw_tstamp,
|
||||
((void *)(ctx->mailbox + ctx->tstamp)
|
||||
+(str_id * sizeof(fw_tstamp))),
|
||||
sizeof(fw_tstamp));
|
||||
addr = ((void __iomem *)(ctx->mailbox + ctx->tstamp)) +
|
||||
(str_id * sizeof(fw_tstamp));
|
||||
|
||||
memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
|
||||
|
||||
fw_tstamp.bytes_copied = stream->cumm_bytes;
|
||||
dev_dbg(dev, "bytes sent to fw %llu inc by %ld\n",
|
||||
fw_tstamp.bytes_copied, bytes);
|
||||
|
||||
addr = ((void *)(ctx->mailbox + ctx->tstamp)) +
|
||||
(str_id * sizeof(fw_tstamp));
|
||||
offset = offsetof(struct snd_sst_tstamp, bytes_copied);
|
||||
sst_shim_write(addr, offset, fw_tstamp.bytes_copied);
|
||||
return 0;
|
||||
|
|
@ -360,11 +358,12 @@ static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
|
|||
struct snd_sst_tstamp fw_tstamp = {0,};
|
||||
struct stream_info *stream;
|
||||
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
|
||||
void __iomem *addr;
|
||||
|
||||
memcpy_fromio(&fw_tstamp,
|
||||
((void *)(ctx->mailbox + ctx->tstamp)
|
||||
+(str_id * sizeof(fw_tstamp))),
|
||||
sizeof(fw_tstamp));
|
||||
addr = (void __iomem *)(ctx->mailbox + ctx->tstamp) +
|
||||
(str_id * sizeof(fw_tstamp));
|
||||
|
||||
memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
|
||||
|
||||
stream = get_stream_info(ctx, str_id);
|
||||
if (!stream)
|
||||
|
|
@ -530,6 +529,7 @@ static int sst_read_timestamp(struct device *dev, struct pcm_stream_info *info)
|
|||
struct snd_sst_tstamp fw_tstamp;
|
||||
unsigned int str_id;
|
||||
struct intel_sst_drv *ctx = dev_get_drvdata(dev);
|
||||
void __iomem *addr;
|
||||
|
||||
str_id = info->str_id;
|
||||
stream = get_stream_info(ctx, str_id);
|
||||
|
|
@ -540,10 +540,11 @@ static int sst_read_timestamp(struct device *dev, struct pcm_stream_info *info)
|
|||
return -EINVAL;
|
||||
substream = stream->pcm_substream;
|
||||
|
||||
memcpy_fromio(&fw_tstamp,
|
||||
((void *)(ctx->mailbox + ctx->tstamp)
|
||||
+ (str_id * sizeof(fw_tstamp))),
|
||||
sizeof(fw_tstamp));
|
||||
addr = (void __iomem *)(ctx->mailbox + ctx->tstamp) +
|
||||
(str_id * sizeof(fw_tstamp));
|
||||
|
||||
memcpy_fromio(&fw_tstamp, addr, sizeof(fw_tstamp));
|
||||
|
||||
return sst_calc_tstamp(ctx, info, substream, &fw_tstamp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,15 +44,15 @@ void memcpy32_toio(void __iomem *dst, const void *src, int count)
|
|||
/* __iowrite32_copy uses 32-bit count values so divide by 4 for
|
||||
* right count in words
|
||||
*/
|
||||
__iowrite32_copy(dst, src, count/4);
|
||||
__iowrite32_copy(dst, src, count / 4);
|
||||
}
|
||||
|
||||
void memcpy32_fromio(void *dst, const void __iomem *src, int count)
|
||||
{
|
||||
/* __iowrite32_copy uses 32-bit count values so divide by 4 for
|
||||
/* __ioread32_copy uses 32-bit count values so divide by 4 for
|
||||
* right count in words
|
||||
*/
|
||||
__iowrite32_copy(dst, src, count/4);
|
||||
__ioread32_copy(dst, src, count / 4);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -281,6 +281,20 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH
|
|||
Say Y if you have such a device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
|
||||
tristate "GLK with RT5682 and MAX98357A in I2S Mode"
|
||||
depends on MFD_INTEL_LPSS && I2C && ACPI
|
||||
select SND_SOC_RT5682
|
||||
select SND_SOC_MAX98357A
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_HDAC_HDMI
|
||||
select SND_HDA_DSP_LOADER
|
||||
help
|
||||
This adds support for ASoC machine driver for Geminilake platforms
|
||||
with RT5682 + MAX98357A I2S audio codec.
|
||||
Say Y if you have such a device.
|
||||
If unsure select "N".
|
||||
|
||||
endif ## SND_SOC_INTEL_SKYLAKE
|
||||
|
||||
endif ## SND_SOC_INTEL_MACH
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o
|
|||
snd-soc-sst-broadwell-objs := broadwell.o
|
||||
snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o
|
||||
snd-soc-sst-bxt-rt298-objs := bxt_rt298.o
|
||||
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o
|
||||
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
|
||||
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
|
||||
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
|
||||
|
|
@ -27,6 +28,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
|
|||
obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_max98357a.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH) += snd-soc-sst-glk-rt5682_max98357a.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.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
|
||||
|
|
|
|||
|
|
@ -154,9 +154,7 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
channels->min = channels->max = 2;
|
||||
|
||||
/* set SSP0 to 16 bit */
|
||||
snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT -
|
||||
SNDRV_PCM_HW_PARAM_FIRST_MASK],
|
||||
SNDRV_PCM_FORMAT_S16_LE);
|
||||
params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
|
||||
/* set SSP to 24 bit */
|
||||
snd_mask_none(fmt);
|
||||
snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
|
||||
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -324,8 +324,22 @@ static const struct snd_pcm_hw_constraint_list constraints_16000 = {
|
|||
.list = rates_16000,
|
||||
};
|
||||
|
||||
static const unsigned int ch_mono[] = {
|
||||
1,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hw_constraint_list constraints_refcap = {
|
||||
.count = ARRAY_SIZE(ch_mono),
|
||||
.list = ch_mono,
|
||||
};
|
||||
|
||||
static int broxton_refcap_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
substream->runtime->hw.channels_max = 1;
|
||||
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_refcap);
|
||||
|
||||
return snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
&constraints_16000);
|
||||
|
|
@ -586,7 +600,7 @@ static int broxton_audio_probe(struct platform_device *pdev)
|
|||
static struct platform_driver broxton_audio = {
|
||||
.probe = broxton_audio_probe,
|
||||
.driver = {
|
||||
.name = "bxt_da7219_max98357a_i2s",
|
||||
.name = "bxt_da7219_max98357a",
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
|
@ -599,4 +613,4 @@ MODULE_AUTHOR("Rohit Ainapure <[email protected]>");
|
|||
MODULE_AUTHOR("Harsha Priya <[email protected]>");
|
||||
MODULE_AUTHOR("Conrad Cooke <[email protected]>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:bxt_da7219_max98357a_i2s");
|
||||
MODULE_ALIAS("platform:bxt_da7219_max98357a");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue