Merge remote-tracking branches 'asoc/topic/adsp', 'asoc/topic/ak4624', 'asoc/topic/atmel' and 'asoc/topic/au1x' into asoc-next
This commit is contained in:
commit
3b15d43bdf
|
@ -652,7 +652,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
|
||||
| SSC_BF(RCMR_STTDLY, 1)
|
||||
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
|
||||
| SSC_BF(RCMR_CKI, SSC_CKI_FALLING)
|
||||
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
||||
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
|
||||
|
||||
|
@ -692,7 +692,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
rcmr = SSC_BF(RCMR_PERIOD, 0)
|
||||
| SSC_BF(RCMR_STTDLY, START_DELAY)
|
||||
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
|
||||
| SSC_BF(RCMR_CKI, SSC_CKI_FALLING)
|
||||
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
||||
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
||||
| SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ?
|
||||
SSC_CKS_PIN : SSC_CKS_CLOCK);
|
||||
|
|
|
@ -206,8 +206,8 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
stype = substream->stream;
|
||||
pcd = to_dmadata(substream);
|
||||
|
||||
DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
|
||||
"runtime->min_align %d\n",
|
||||
DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %zu "
|
||||
"runtime->min_align %lu\n",
|
||||
(unsigned long)runtime->dma_area,
|
||||
(unsigned long)runtime->dma_addr, runtime->dma_bytes,
|
||||
runtime->min_align);
|
||||
|
|
|
@ -608,9 +608,7 @@ static struct clk *ak4642_of_parse_mcko(struct device *dev)
|
|||
|
||||
of_property_read_string(np, "clock-output-names", &clk_name);
|
||||
|
||||
clk = clk_register_fixed_rate(dev, clk_name, parent_clk_name,
|
||||
(parent_clk_name) ? 0 : CLK_IS_ROOT,
|
||||
rate);
|
||||
clk = clk_register_fixed_rate(dev, clk_name, parent_clk_name, 0, rate);
|
||||
if (!IS_ERR(clk))
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
|
||||
|
|
|
@ -221,6 +221,8 @@ int arizona_init_spk(struct snd_soc_codec *codec)
|
|||
|
||||
switch (arizona->type) {
|
||||
case WM8997:
|
||||
case CS47L24:
|
||||
case WM1831:
|
||||
break;
|
||||
default:
|
||||
ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1);
|
||||
|
@ -1134,7 +1136,6 @@ int arizona_anc_ev(struct snd_soc_dapm_widget *w,
|
|||
int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
unsigned int mask = 0x3 << w->shift;
|
||||
unsigned int val;
|
||||
|
||||
switch (event) {
|
||||
|
@ -1148,7 +1149,7 @@ int arizona_anc_ev(struct snd_soc_dapm_widget *w,
|
|||
return 0;
|
||||
}
|
||||
|
||||
snd_soc_update_bits(codec, ARIZONA_CLOCK_CONTROL, mask, val);
|
||||
snd_soc_write(codec, ARIZONA_CLOCK_CONTROL, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2047,7 +2048,21 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
|||
init_ratio, Fref, refdiv);
|
||||
|
||||
while (div <= ARIZONA_FLL_MAX_REFDIV) {
|
||||
for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
|
||||
/* start from init_ratio because this may already give a
|
||||
* fractional N.K
|
||||
*/
|
||||
for (ratio = init_ratio; ratio > 0; ratio--) {
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
arizona_fll_dbg(fll,
|
||||
"pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
|
||||
Fref, refdiv, div, ratio);
|
||||
return ratio;
|
||||
}
|
||||
}
|
||||
|
||||
for (ratio = init_ratio + 1; ratio <= ARIZONA_FLL_MAX_FRATIO;
|
||||
ratio++) {
|
||||
if ((ARIZONA_FLL_VCO_CORNER / 2) /
|
||||
(fll->vco_mult * ratio) < Fref) {
|
||||
|
@ -2073,17 +2088,6 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
|
|||
}
|
||||
}
|
||||
|
||||
for (ratio = init_ratio - 1; ratio > 0; ratio--) {
|
||||
if (target % (ratio * Fref)) {
|
||||
cfg->refdiv = refdiv;
|
||||
cfg->fratio = ratio - 1;
|
||||
arizona_fll_dbg(fll,
|
||||
"pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
|
||||
Fref, refdiv, div, ratio);
|
||||
return ratio;
|
||||
}
|
||||
}
|
||||
|
||||
div *= 2;
|
||||
Fref /= 2;
|
||||
refdiv++;
|
||||
|
|
|
@ -807,6 +807,9 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = {
|
|||
{ "IN2L PGA", NULL, "IN2L" },
|
||||
{ "IN2R PGA", NULL, "IN2R" },
|
||||
|
||||
{ "Audio Trace DSP", NULL, "DSP2" },
|
||||
{ "Audio Trace DSP", NULL, "SYSCLK" },
|
||||
|
||||
ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
|
||||
ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
|
||||
|
||||
|
@ -1016,6 +1019,27 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
|
|||
.formats = CS47L24_FORMATS,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "cs47l24-cpu-trace",
|
||||
.capture = {
|
||||
.stream_name = "Audio Trace CPU",
|
||||
.channels_min = 1,
|
||||
.channels_max = 6,
|
||||
.rates = CS47L24_RATES,
|
||||
.formats = CS47L24_FORMATS,
|
||||
},
|
||||
.compress_new = snd_soc_new_compress,
|
||||
},
|
||||
{
|
||||
.name = "cs47l24-dsp-trace",
|
||||
.capture = {
|
||||
.stream_name = "Audio Trace DSP",
|
||||
.channels_min = 1,
|
||||
.channels_max = 6,
|
||||
.rates = CS47L24_RATES,
|
||||
.formats = CS47L24_FORMATS,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int cs47l24_open(struct snd_compr_stream *stream)
|
||||
|
@ -1027,6 +1051,8 @@ static int cs47l24_open(struct snd_compr_stream *stream)
|
|||
|
||||
if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-voicectrl") == 0) {
|
||||
n_adsp = 2;
|
||||
} else if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-trace") == 0) {
|
||||
n_adsp = 1;
|
||||
} else {
|
||||
dev_err(arizona->dev,
|
||||
"No suitable compressed stream for DAI '%s'\n",
|
||||
|
@ -1041,10 +1067,16 @@ static irqreturn_t cs47l24_adsp2_irq(int irq, void *data)
|
|||
{
|
||||
struct cs47l24_priv *priv = data;
|
||||
struct arizona *arizona = priv->core.arizona;
|
||||
int ret;
|
||||
int serviced = 0;
|
||||
int i, ret;
|
||||
|
||||
ret = wm_adsp_compr_handle_irq(&priv->core.adsp[2]);
|
||||
if (ret == -ENODEV) {
|
||||
for (i = 1; i <= 2; ++i) {
|
||||
ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]);
|
||||
if (ret != -ENODEV)
|
||||
serviced++;
|
||||
}
|
||||
|
||||
if (!serviced) {
|
||||
dev_err(arizona->dev, "Spurious compressed data IRQ\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
@ -1160,6 +1192,7 @@ static struct snd_compr_ops cs47l24_compr_ops = {
|
|||
static struct snd_soc_platform_driver cs47l24_compr_platform = {
|
||||
.compr_ops = &cs47l24_compr_ops,
|
||||
};
|
||||
|
||||
static int cs47l24_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
|
||||
|
@ -1228,9 +1261,9 @@ static int cs47l24_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
|
||||
cs47l24_dai, ARRAY_SIZE(cs47l24_dai));
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
|
@ -1241,10 +1274,15 @@ static int cs47l24_probe(struct platform_device *pdev)
|
|||
|
||||
static int cs47l24_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cs47l24_priv *cs47l24 = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
wm_adsp2_remove(&cs47l24->core.adsp[1]);
|
||||
wm_adsp2_remove(&cs47l24->core.adsp[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2098,10 +2098,14 @@ static int wm5102_probe(struct platform_device *pdev)
|
|||
|
||||
static int wm5102_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm5102_priv *wm5102 = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
wm_adsp2_remove(&wm5102->core.adsp[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2437,10 +2437,16 @@ static int wm5110_probe(struct platform_device *pdev)
|
|||
|
||||
static int wm5110_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm5110_priv *wm5110 = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
for (i = 0; i < WM5110_NUM_ADSP; i++)
|
||||
wm_adsp2_remove(&wm5110->core.adsp[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,6 +160,8 @@
|
|||
#define ADSP2_RAM_RDY_SHIFT 0
|
||||
#define ADSP2_RAM_RDY_WIDTH 1
|
||||
|
||||
#define ADSP_MAX_STD_CTRL_SIZE 512
|
||||
|
||||
struct wm_adsp_buf {
|
||||
struct list_head list;
|
||||
void *buf;
|
||||
|
@ -271,8 +273,11 @@ struct wm_adsp_buffer {
|
|||
__be32 words_written[2]; /* total words written (64 bit) */
|
||||
};
|
||||
|
||||
struct wm_adsp_compr;
|
||||
|
||||
struct wm_adsp_compr_buf {
|
||||
struct wm_adsp *dsp;
|
||||
struct wm_adsp_compr *compr;
|
||||
|
||||
struct wm_adsp_buffer_region *regions;
|
||||
u32 host_buf_ptr;
|
||||
|
@ -435,6 +440,7 @@ struct wm_coeff_ctl {
|
|||
size_t len;
|
||||
unsigned int set:1;
|
||||
struct snd_kcontrol *kcontrol;
|
||||
struct soc_bytes_ext bytes_ext;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
|
@ -711,10 +717,17 @@ static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
|
|||
be16_to_cpu(scratch[3]));
|
||||
}
|
||||
|
||||
static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
|
||||
{
|
||||
return container_of(ext, struct wm_coeff_ctl, bytes_ext);
|
||||
}
|
||||
|
||||
static int wm_coeff_info(struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value;
|
||||
struct soc_bytes_ext *bytes_ext =
|
||||
(struct soc_bytes_ext *)kctl->private_value;
|
||||
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
|
||||
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
||||
uinfo->count = ctl->len;
|
||||
|
@ -763,7 +776,9 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
|
|||
static int wm_coeff_put(struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value;
|
||||
struct soc_bytes_ext *bytes_ext =
|
||||
(struct soc_bytes_ext *)kctl->private_value;
|
||||
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
|
||||
char *p = ucontrol->value.bytes.data;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -780,6 +795,29 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
|
||||
const unsigned int __user *bytes, unsigned int size)
|
||||
{
|
||||
struct soc_bytes_ext *bytes_ext =
|
||||
(struct soc_bytes_ext *)kctl->private_value;
|
||||
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&ctl->dsp->pwr_lock);
|
||||
|
||||
if (copy_from_user(ctl->cache, bytes, size)) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
ctl->set = 1;
|
||||
if (ctl->enabled)
|
||||
ret = wm_coeff_write_control(ctl, ctl->cache, size);
|
||||
}
|
||||
|
||||
mutex_unlock(&ctl->dsp->pwr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
|
@ -822,7 +860,9 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
|
|||
static int wm_coeff_get(struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value;
|
||||
struct soc_bytes_ext *bytes_ext =
|
||||
(struct soc_bytes_ext *)kctl->private_value;
|
||||
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
|
||||
char *p = ucontrol->value.bytes.data;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -845,12 +885,72 @@ static int wm_coeff_get(struct snd_kcontrol *kctl,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
|
||||
unsigned int __user *bytes, unsigned int size)
|
||||
{
|
||||
struct soc_bytes_ext *bytes_ext =
|
||||
(struct soc_bytes_ext *)kctl->private_value;
|
||||
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&ctl->dsp->pwr_lock);
|
||||
|
||||
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
|
||||
if (ctl->enabled)
|
||||
ret = wm_coeff_read_control(ctl, ctl->cache, size);
|
||||
else
|
||||
ret = -EPERM;
|
||||
} else {
|
||||
if (!ctl->flags && ctl->enabled)
|
||||
ret = wm_coeff_read_control(ctl, ctl->cache, size);
|
||||
}
|
||||
|
||||
if (!ret && copy_to_user(bytes, ctl->cache, size))
|
||||
ret = -EFAULT;
|
||||
|
||||
mutex_unlock(&ctl->dsp->pwr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct wmfw_ctl_work {
|
||||
struct wm_adsp *dsp;
|
||||
struct wm_coeff_ctl *ctl;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
|
||||
{
|
||||
unsigned int out, rd, wr, vol;
|
||||
|
||||
if (len > ADSP_MAX_STD_CTRL_SIZE) {
|
||||
rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
|
||||
wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
|
||||
vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
|
||||
|
||||
out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
|
||||
} else {
|
||||
rd = SNDRV_CTL_ELEM_ACCESS_READ;
|
||||
wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
|
||||
|
||||
out = 0;
|
||||
}
|
||||
|
||||
if (in) {
|
||||
if (in & WMFW_CTL_FLAG_READABLE)
|
||||
out |= rd;
|
||||
if (in & WMFW_CTL_FLAG_WRITEABLE)
|
||||
out |= wr;
|
||||
if (in & WMFW_CTL_FLAG_VOLATILE)
|
||||
out |= vol;
|
||||
} else {
|
||||
out |= rd | wr | vol;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
|
||||
{
|
||||
struct snd_kcontrol_new *kcontrol;
|
||||
|
@ -868,19 +968,15 @@ static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
|
|||
kcontrol->info = wm_coeff_info;
|
||||
kcontrol->get = wm_coeff_get;
|
||||
kcontrol->put = wm_coeff_put;
|
||||
kcontrol->private_value = (unsigned long)ctl;
|
||||
kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
|
||||
kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
|
||||
|
||||
if (ctl->flags) {
|
||||
if (ctl->flags & WMFW_CTL_FLAG_WRITEABLE)
|
||||
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
if (ctl->flags & WMFW_CTL_FLAG_READABLE)
|
||||
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ;
|
||||
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
|
||||
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
|
||||
} else {
|
||||
kcontrol->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
|
||||
}
|
||||
ctl->bytes_ext.max = ctl->len;
|
||||
ctl->bytes_ext.get = wm_coeff_tlv_get;
|
||||
ctl->bytes_ext.put = wm_coeff_tlv_put;
|
||||
|
||||
kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len);
|
||||
|
||||
ret = snd_soc_add_card_controls(dsp->card, kcontrol, 1);
|
||||
if (ret < 0)
|
||||
|
@ -944,6 +1040,13 @@ static void wm_adsp_ctl_work(struct work_struct *work)
|
|||
kfree(ctl_work);
|
||||
}
|
||||
|
||||
static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl)
|
||||
{
|
||||
kfree(ctl->cache);
|
||||
kfree(ctl->name);
|
||||
kfree(ctl);
|
||||
}
|
||||
|
||||
static int wm_adsp_create_control(struct wm_adsp *dsp,
|
||||
const struct wm_adsp_alg_region *alg_region,
|
||||
unsigned int offset, unsigned int len,
|
||||
|
@ -1032,11 +1135,6 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
|
|||
|
||||
ctl->flags = flags;
|
||||
ctl->offset = offset;
|
||||
if (len > 512) {
|
||||
adsp_warn(dsp, "Truncating control %s from %d\n",
|
||||
ctl->name, len);
|
||||
len = 512;
|
||||
}
|
||||
ctl->len = len;
|
||||
ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
|
||||
if (!ctl->cache) {
|
||||
|
@ -1564,6 +1662,19 @@ static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp,
|
|||
return alg_region;
|
||||
}
|
||||
|
||||
static void wm_adsp_free_alg_regions(struct wm_adsp *dsp)
|
||||
{
|
||||
struct wm_adsp_alg_region *alg_region;
|
||||
|
||||
while (!list_empty(&dsp->alg_regions)) {
|
||||
alg_region = list_first_entry(&dsp->alg_regions,
|
||||
struct wm_adsp_alg_region,
|
||||
list);
|
||||
list_del(&alg_region->list);
|
||||
kfree(alg_region);
|
||||
}
|
||||
}
|
||||
|
||||
static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
|
||||
{
|
||||
struct wmfw_adsp1_id_hdr adsp1_id;
|
||||
|
@ -1994,7 +2105,6 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
|||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
|
||||
struct wm_adsp *dsp = &dsps[w->shift];
|
||||
struct wm_adsp_alg_region *alg_region;
|
||||
struct wm_coeff_ctl *ctl;
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
@ -2074,13 +2184,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
|||
list_for_each_entry(ctl, &dsp->ctl_list, list)
|
||||
ctl->enabled = 0;
|
||||
|
||||
while (!list_empty(&dsp->alg_regions)) {
|
||||
alg_region = list_first_entry(&dsp->alg_regions,
|
||||
struct wm_adsp_alg_region,
|
||||
list);
|
||||
list_del(&alg_region->list);
|
||||
kfree(alg_region);
|
||||
}
|
||||
|
||||
wm_adsp_free_alg_regions(dsp);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2222,7 +2327,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
|
||||
struct wm_adsp *dsp = &dsps[w->shift];
|
||||
struct wm_adsp_alg_region *alg_region;
|
||||
struct wm_coeff_ctl *ctl;
|
||||
int ret;
|
||||
|
||||
|
@ -2240,9 +2344,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
if (wm_adsp_fw[dsp->fw].num_caps != 0)
|
||||
ret = wm_adsp_buffer_init(dsp);
|
||||
|
||||
mutex_unlock(&dsp->pwr_lock);
|
||||
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
|
@ -2269,13 +2377,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|||
list_for_each_entry(ctl, &dsp->ctl_list, list)
|
||||
ctl->enabled = 0;
|
||||
|
||||
while (!list_empty(&dsp->alg_regions)) {
|
||||
alg_region = list_first_entry(&dsp->alg_regions,
|
||||
struct wm_adsp_alg_region,
|
||||
list);
|
||||
list_del(&alg_region->list);
|
||||
kfree(alg_region);
|
||||
}
|
||||
wm_adsp_free_alg_regions(dsp);
|
||||
|
||||
if (wm_adsp_fw[dsp->fw].num_caps != 0)
|
||||
wm_adsp_buffer_free(dsp);
|
||||
|
@ -2340,6 +2442,54 @@ int wm_adsp2_init(struct wm_adsp *dsp)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp2_init);
|
||||
|
||||
void wm_adsp2_remove(struct wm_adsp *dsp)
|
||||
{
|
||||
struct wm_coeff_ctl *ctl;
|
||||
|
||||
while (!list_empty(&dsp->ctl_list)) {
|
||||
ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl,
|
||||
list);
|
||||
list_del(&ctl->list);
|
||||
wm_adsp_free_ctl_blk(ctl);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp2_remove);
|
||||
|
||||
static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
|
||||
{
|
||||
return compr->buf != NULL;
|
||||
}
|
||||
|
||||
static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
|
||||
{
|
||||
/*
|
||||
* Note this will be more complex once each DSP can support multiple
|
||||
* streams
|
||||
*/
|
||||
if (!compr->dsp->buffer)
|
||||
return -EINVAL;
|
||||
|
||||
compr->buf = compr->dsp->buffer;
|
||||
compr->buf->compr = compr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
|
||||
{
|
||||
if (!compr)
|
||||
return;
|
||||
|
||||
/* Wake the poll so it can see buffer is no longer attached */
|
||||
if (compr->stream)
|
||||
snd_compr_fragment_elapsed(compr->stream);
|
||||
|
||||
if (wm_adsp_compr_attached(compr)) {
|
||||
compr->buf->compr = NULL;
|
||||
compr->buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
|
||||
{
|
||||
struct wm_adsp_compr *compr;
|
||||
|
@ -2393,6 +2543,7 @@ int wm_adsp_compr_free(struct snd_compr_stream *stream)
|
|||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
wm_adsp_compr_detach(compr);
|
||||
dsp->compr = NULL;
|
||||
|
||||
kfree(compr->raw_buf);
|
||||
|
@ -2689,6 +2840,8 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp)
|
|||
static int wm_adsp_buffer_free(struct wm_adsp *dsp)
|
||||
{
|
||||
if (dsp->buffer) {
|
||||
wm_adsp_compr_detach(dsp->buffer->compr);
|
||||
|
||||
kfree(dsp->buffer->regions);
|
||||
kfree(dsp->buffer);
|
||||
|
||||
|
@ -2698,25 +2851,6 @@ static int wm_adsp_buffer_free(struct wm_adsp *dsp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
|
||||
{
|
||||
return compr->buf != NULL;
|
||||
}
|
||||
|
||||
static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
|
||||
{
|
||||
/*
|
||||
* Note this will be more complex once each DSP can support multiple
|
||||
* streams
|
||||
*/
|
||||
if (!compr->dsp->buffer)
|
||||
return -EINVAL;
|
||||
|
||||
compr->buf = compr->dsp->buffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
|
||||
{
|
||||
struct wm_adsp_compr *compr = stream->runtime->private_data;
|
||||
|
@ -2805,21 +2939,41 @@ static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
|
|||
avail += wm_adsp_buffer_size(buf);
|
||||
|
||||
adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
|
||||
buf->read_index, write_index, avail);
|
||||
buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
|
||||
|
||||
buf->avail = avail;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
|
||||
if (ret < 0) {
|
||||
adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (buf->error != 0) {
|
||||
adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
|
||||
{
|
||||
struct wm_adsp_compr_buf *buf = dsp->buffer;
|
||||
struct wm_adsp_compr *compr = dsp->compr;
|
||||
struct wm_adsp_compr_buf *buf;
|
||||
struct wm_adsp_compr *compr;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
buf = dsp->buffer;
|
||||
compr = dsp->compr;
|
||||
|
||||
if (!buf) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
|
@ -2827,16 +2981,9 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
|
|||
|
||||
adsp_dbg(dsp, "Handling buffer IRQ\n");
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp, "Failed to check buffer error: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
if (buf->error != 0) {
|
||||
adsp_err(dsp, "Buffer error occurred: %d\n", buf->error);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ret = wm_adsp_buffer_get_error(buf);
|
||||
if (ret < 0)
|
||||
goto out_notify; /* Wake poll to report error */
|
||||
|
||||
ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
|
||||
&buf->irq_count);
|
||||
|
@ -2851,6 +2998,7 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
|
|||
goto out;
|
||||
}
|
||||
|
||||
out_notify:
|
||||
if (compr && compr->stream)
|
||||
snd_compr_fragment_elapsed(compr->stream);
|
||||
|
||||
|
@ -2879,14 +3027,16 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
|
|||
struct snd_compr_tstamp *tstamp)
|
||||
{
|
||||
struct wm_adsp_compr *compr = stream->runtime->private_data;
|
||||
struct wm_adsp_compr_buf *buf = compr->buf;
|
||||
struct wm_adsp *dsp = compr->dsp;
|
||||
struct wm_adsp_compr_buf *buf;
|
||||
int ret = 0;
|
||||
|
||||
adsp_dbg(dsp, "Pointer request\n");
|
||||
|
||||
mutex_lock(&dsp->pwr_lock);
|
||||
|
||||
buf = compr->buf;
|
||||
|
||||
if (!compr->buf) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
|
@ -2909,6 +3059,10 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
|
|||
* DSP to inform us once a whole fragment is available.
|
||||
*/
|
||||
if (buf->avail < wm_adsp_compr_frag_words(compr)) {
|
||||
ret = wm_adsp_buffer_get_error(buf);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wm_adsp_buffer_reenable_irq(buf);
|
||||
if (ret < 0) {
|
||||
adsp_err(dsp,
|
||||
|
|
|
@ -92,6 +92,7 @@ extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
|
|||
|
||||
int wm_adsp1_init(struct wm_adsp *dsp);
|
||||
int wm_adsp2_init(struct wm_adsp *dsp);
|
||||
void wm_adsp2_remove(struct wm_adsp *dsp);
|
||||
int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec);
|
||||
int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec);
|
||||
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
||||
|
|
Loading…
Reference in New Issue