Commit a178831a authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/max98095', 'asoc/topic/omap',...

Merge remote-tracking branches 'asoc/topic/max98095', 'asoc/topic/omap', 'asoc/topic/pxa', 'asoc/topic/qcom' and 'asoc/topic/rcar' into asoc-next
...@@ -4,12 +4,21 @@ This node models the Qualcomm Technologies Low-Power Audio SubSystem (LPASS). ...@@ -4,12 +4,21 @@ This node models the Qualcomm Technologies Low-Power Audio SubSystem (LPASS).
Required properties: Required properties:
- compatible : "qcom,lpass-cpu" - compatible : "qcom,lpass-cpu" or "qcom,apq8016-lpass-cpu"
- clocks : Must contain an entry for each entry in clock-names. - clocks : Must contain an entry for each entry in clock-names.
- clock-names : A list which must include the following entries: - clock-names : A list which must include the following entries:
* "ahbix-clk" * "ahbix-clk"
* "mi2s-osr-clk" * "mi2s-osr-clk"
* "mi2s-bit-clk" * "mi2s-bit-clk"
: required clocks for "qcom,lpass-cpu-apq8016"
* "ahbix-clk"
* "mi2s-bit-clk0"
* "mi2s-bit-clk1"
* "mi2s-bit-clk2"
* "mi2s-bit-clk3"
* "pcnoc-mport-clk"
* "pcnoc-sway-clk"
- interrupts : Must contain an entry for each entry in - interrupts : Must contain an entry for each entry in
interrupt-names. interrupt-names.
- interrupt-names : A list which must include the following entries: - interrupt-names : A list which must include the following entries:
...@@ -22,6 +31,8 @@ Required properties: ...@@ -22,6 +31,8 @@ Required properties:
- reg-names : A list which must include the following entries: - reg-names : A list which must include the following entries:
* "lpass-lpaif" * "lpass-lpaif"
Optional properties: Optional properties:
- qcom,adsp : Phandle for the audio DSP node - qcom,adsp : Phandle for the audio DSP node
......
...@@ -48,7 +48,7 @@ DAI subnode properties: ...@@ -48,7 +48,7 @@ DAI subnode properties:
Example: Example:
rcar_sound: rcar_sound@ec500000 { rcar_sound: sound@ec500000 {
#sound-dai-cells = <1>; #sound-dai-cells = <1>;
compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2"; compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2";
reg = <0 0xec500000 0 0x1000>, /* SCU */ reg = <0 0xec500000 0 0x1000>, /* SCU */
......
...@@ -465,6 +465,7 @@ static dma_cookie_t rcar_dmac_tx_submit(struct dma_async_tx_descriptor *tx) ...@@ -465,6 +465,7 @@ static dma_cookie_t rcar_dmac_tx_submit(struct dma_async_tx_descriptor *tx)
static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp) static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
{ {
struct rcar_dmac_desc_page *page; struct rcar_dmac_desc_page *page;
unsigned long flags;
LIST_HEAD(list); LIST_HEAD(list);
unsigned int i; unsigned int i;
...@@ -482,10 +483,10 @@ static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp) ...@@ -482,10 +483,10 @@ static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
list_add_tail(&desc->node, &list); list_add_tail(&desc->node, &list);
} }
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
list_splice_tail(&list, &chan->desc.free); list_splice_tail(&list, &chan->desc.free);
list_add_tail(&page->node, &chan->desc.pages); list_add_tail(&page->node, &chan->desc.pages);
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
return 0; return 0;
} }
...@@ -516,6 +517,7 @@ static void rcar_dmac_desc_put(struct rcar_dmac_chan *chan, ...@@ -516,6 +517,7 @@ static void rcar_dmac_desc_put(struct rcar_dmac_chan *chan,
static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan) static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
{ {
struct rcar_dmac_desc *desc, *_desc; struct rcar_dmac_desc *desc, *_desc;
unsigned long flags;
LIST_HEAD(list); LIST_HEAD(list);
/* /*
...@@ -524,9 +526,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan) ...@@ -524,9 +526,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
* list_for_each_entry_safe, isn't safe if we release the channel lock * list_for_each_entry_safe, isn't safe if we release the channel lock
* around the rcar_dmac_desc_put() call. * around the rcar_dmac_desc_put() call.
*/ */
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
list_splice_init(&chan->desc.wait, &list); list_splice_init(&chan->desc.wait, &list);
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
list_for_each_entry_safe(desc, _desc, &list, node) { list_for_each_entry_safe(desc, _desc, &list, node) {
if (async_tx_test_ack(&desc->async_tx)) { if (async_tx_test_ack(&desc->async_tx)) {
...@@ -539,9 +541,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan) ...@@ -539,9 +541,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
return; return;
/* Put the remaining descriptors back in the wait list. */ /* Put the remaining descriptors back in the wait list. */
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
list_splice(&list, &chan->desc.wait); list_splice(&list, &chan->desc.wait);
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
} }
/* /*
...@@ -556,12 +558,13 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan) ...@@ -556,12 +558,13 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan) static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
{ {
struct rcar_dmac_desc *desc; struct rcar_dmac_desc *desc;
unsigned long flags;
int ret; int ret;
/* Recycle acked descriptors before attempting allocation. */ /* Recycle acked descriptors before attempting allocation. */
rcar_dmac_desc_recycle_acked(chan); rcar_dmac_desc_recycle_acked(chan);
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
while (list_empty(&chan->desc.free)) { while (list_empty(&chan->desc.free)) {
/* /*
...@@ -570,17 +573,17 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan) ...@@ -570,17 +573,17 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
* allocated descriptors. If the allocation fails return an * allocated descriptors. If the allocation fails return an
* error. * error.
*/ */
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
ret = rcar_dmac_desc_alloc(chan, GFP_NOWAIT); ret = rcar_dmac_desc_alloc(chan, GFP_NOWAIT);
if (ret < 0) if (ret < 0)
return NULL; return NULL;
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
} }
desc = list_first_entry(&chan->desc.free, struct rcar_dmac_desc, node); desc = list_first_entry(&chan->desc.free, struct rcar_dmac_desc, node);
list_del(&desc->node); list_del(&desc->node);
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
return desc; return desc;
} }
...@@ -593,6 +596,7 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan) ...@@ -593,6 +596,7 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp) static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
{ {
struct rcar_dmac_desc_page *page; struct rcar_dmac_desc_page *page;
unsigned long flags;
LIST_HEAD(list); LIST_HEAD(list);
unsigned int i; unsigned int i;
...@@ -606,10 +610,10 @@ static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp) ...@@ -606,10 +610,10 @@ static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
list_add_tail(&chunk->node, &list); list_add_tail(&chunk->node, &list);
} }
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
list_splice_tail(&list, &chan->desc.chunks_free); list_splice_tail(&list, &chan->desc.chunks_free);
list_add_tail(&page->node, &chan->desc.pages); list_add_tail(&page->node, &chan->desc.pages);
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
return 0; return 0;
} }
...@@ -627,9 +631,10 @@ static struct rcar_dmac_xfer_chunk * ...@@ -627,9 +631,10 @@ static struct rcar_dmac_xfer_chunk *
rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan) rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan)
{ {
struct rcar_dmac_xfer_chunk *chunk; struct rcar_dmac_xfer_chunk *chunk;
unsigned long flags;
int ret; int ret;
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
while (list_empty(&chan->desc.chunks_free)) { while (list_empty(&chan->desc.chunks_free)) {
/* /*
...@@ -638,18 +643,18 @@ rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan) ...@@ -638,18 +643,18 @@ rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan)
* allocated descriptors. If the allocation fails return an * allocated descriptors. If the allocation fails return an
* error. * error.
*/ */
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
ret = rcar_dmac_xfer_chunk_alloc(chan, GFP_NOWAIT); ret = rcar_dmac_xfer_chunk_alloc(chan, GFP_NOWAIT);
if (ret < 0) if (ret < 0)
return NULL; return NULL;
spin_lock_irq(&chan->lock); spin_lock_irqsave(&chan->lock, flags);
} }
chunk = list_first_entry(&chan->desc.chunks_free, chunk = list_first_entry(&chan->desc.chunks_free,
struct rcar_dmac_xfer_chunk, node); struct rcar_dmac_xfer_chunk, node);
list_del(&chunk->node); list_del(&chunk->node);
spin_unlock_irq(&chan->lock); spin_unlock_irqrestore(&chan->lock, flags);
return chunk; return chunk;
} }
......
#ifndef __DT_APQ8016_LPASS_H
#define __DT_APQ8016_LPASS_H
#define MI2S_PRIMARY 0
#define MI2S_SECONDARY 1
#define MI2S_TERTIARY 2
#define MI2S_QUATERNARY 3
#endif /* __DT_APQ8016_LPASS_H */
...@@ -2301,8 +2301,8 @@ static int max98095_probe(struct snd_soc_codec *codec) ...@@ -2301,8 +2301,8 @@ static int max98095_probe(struct snd_soc_codec *codec)
/* register an audio interrupt */ /* register an audio interrupt */
ret = request_threaded_irq(client->irq, NULL, ret = request_threaded_irq(client->irq, NULL,
max98095_report_jack, max98095_report_jack,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
"max98095", codec); IRQF_ONESHOT, "max98095", codec);
if (ret) { if (ret) {
dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
goto err_access; goto err_access;
......
...@@ -100,12 +100,13 @@ config SND_OMAP_SOC_OMAP_TWL4030 ...@@ -100,12 +100,13 @@ config SND_OMAP_SOC_OMAP_TWL4030
config SND_OMAP_SOC_OMAP_ABE_TWL6040 config SND_OMAP_SOC_OMAP_ABE_TWL6040
tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST) depends on TWL6040_CORE && SND_OMAP_SOC
depends on ARCH_OMAP4 || (SOC_OMAP5 && MFD_PALMAS) || COMPILE_TEST
select SND_OMAP_SOC_DMIC select SND_OMAP_SOC_DMIC
select SND_OMAP_SOC_MCPDM select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040 select SND_SOC_TWL6040
select SND_SOC_DMIC select SND_SOC_DMIC
select COMMON_CLK_PALMAS if MFD_PALMAS select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS)
help help
Say Y if you want to add support for SoC audio on OMAP boards using Say Y if you want to add support for SoC audio on OMAP boards using
ABE and twl6040 codec. This driver currently supports: ABE and twl6040 codec. This driver currently supports:
......
...@@ -159,9 +159,8 @@ static inline void twl4030_disconnect_pin(struct snd_soc_dapm_context *dapm, ...@@ -159,9 +159,8 @@ static inline void twl4030_disconnect_pin(struct snd_soc_dapm_context *dapm,
static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &card->dapm;
struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev); struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev);
struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card);
int ret = 0; int ret = 0;
......
...@@ -45,29 +45,6 @@ static const struct snd_soc_dapm_route brownstone_audio_map[] = { ...@@ -45,29 +45,6 @@ static const struct snd_soc_dapm_route brownstone_audio_map[] = {
{"MICBIAS1", NULL, "Main Mic"}, {"MICBIAS1", NULL, "Main Mic"},
}; };
static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
/* set endpoints to not connected */
snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
snd_soc_dapm_nc_pin(dapm, "HPOUT2N");
snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
snd_soc_dapm_nc_pin(dapm, "IN1LN");
snd_soc_dapm_nc_pin(dapm, "IN1LP");
snd_soc_dapm_nc_pin(dapm, "IN1RP");
snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
snd_soc_dapm_nc_pin(dapm, "IN2RN");
snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
snd_soc_dapm_nc_pin(dapm, "IN2LN");
return 0;
}
static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -115,7 +92,6 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = { ...@@ -115,7 +92,6 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAIFMT_CBS_CFS,
.ops = &brownstone_ops, .ops = &brownstone_ops,
.init = brownstone_wm8994_init,
}, },
}; };
...@@ -132,6 +108,7 @@ static struct snd_soc_card brownstone = { ...@@ -132,6 +108,7 @@ static struct snd_soc_card brownstone = {
.num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets),
.dapm_routes = brownstone_audio_map, .dapm_routes = brownstone_audio_map,
.num_dapm_routes = ARRAY_SIZE(brownstone_audio_map), .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map),
.fully_routed = true,
}; };
static int brownstone_probe(struct platform_device *pdev) static int brownstone_probe(struct platform_device *pdev)
......
...@@ -192,6 +192,7 @@ static int poodle_amp_event(struct snd_soc_dapm_widget *w, ...@@ -192,6 +192,7 @@ static int poodle_amp_event(struct snd_soc_dapm_widget *w,
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event), SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
SND_SOC_DAPM_MIC("Microphone", NULL),
}; };
/* Corgi machine connections to the codec pins */ /* Corgi machine connections to the codec pins */
...@@ -204,6 +205,8 @@ static const struct snd_soc_dapm_route poodle_audio_map[] = { ...@@ -204,6 +205,8 @@ static const struct snd_soc_dapm_route poodle_audio_map[] = {
/* speaker connected to LOUT, ROUT */ /* speaker connected to LOUT, ROUT */
{"Ext Spk", NULL, "ROUT"}, {"Ext Spk", NULL, "ROUT"},
{"Ext Spk", NULL, "LOUT"}, {"Ext Spk", NULL, "LOUT"},
{"MICIN", NULL, "Microphone"},
}; };
static const char *jack_function[] = {"Off", "Headphone"}; static const char *jack_function[] = {"Off", "Headphone"};
...@@ -220,20 +223,6 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { ...@@ -220,20 +223,6 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = {
poodle_set_spk), poodle_set_spk),
}; };
/*
* Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
*/
static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
return 0;
}
/* poodle digital audio interface glue - connects codec <--> CPU */ /* poodle digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link poodle_dai = { static struct snd_soc_dai_link poodle_dai = {
.name = "WM8731", .name = "WM8731",
...@@ -242,7 +231,6 @@ static struct snd_soc_dai_link poodle_dai = { ...@@ -242,7 +231,6 @@ static struct snd_soc_dai_link poodle_dai = {
.codec_dai_name = "wm8731-hifi", .codec_dai_name = "wm8731-hifi",
.platform_name = "pxa-pcm-audio", .platform_name = "pxa-pcm-audio",
.codec_name = "wm8731.0-001b", .codec_name = "wm8731.0-001b",
.init = poodle_wm8731_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAIFMT_CBS_CFS,
.ops = &poodle_ops, .ops = &poodle_ops,
...@@ -261,6 +249,7 @@ static struct snd_soc_card poodle = { ...@@ -261,6 +249,7 @@ static struct snd_soc_card poodle = {
.num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
.dapm_routes = poodle_audio_map, .dapm_routes = poodle_audio_map,
.num_dapm_routes = ARRAY_SIZE(poodle_audio_map), .num_dapm_routes = ARRAY_SIZE(poodle_audio_map),
.fully_routed = true,
}; };
static int poodle_probe(struct platform_device *pdev) static int poodle_probe(struct platform_device *pdev)
......
...@@ -185,17 +185,6 @@ static const struct snd_kcontrol_new tosa_controls[] = { ...@@ -185,17 +185,6 @@ static const struct snd_kcontrol_new tosa_controls[] = {
tosa_set_spk), tosa_set_spk),
}; };
static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "MONOOUT");
return 0;
}
static struct snd_soc_dai_link tosa_dai[] = { static struct snd_soc_dai_link tosa_dai[] = {
{ {
.name = "AC97", .name = "AC97",
...@@ -204,7 +193,6 @@ static struct snd_soc_dai_link tosa_dai[] = { ...@@ -204,7 +193,6 @@ static struct snd_soc_dai_link tosa_dai[] = {
.codec_dai_name = "wm9712-hifi", .codec_dai_name = "wm9712-hifi",
.platform_name = "pxa-pcm-audio", .platform_name = "pxa-pcm-audio",
.codec_name = "wm9712-codec", .codec_name = "wm9712-codec",
.init = tosa_ac97_init,
.ops = &tosa_ops, .ops = &tosa_ops,
}, },
{ {
...@@ -230,6 +218,7 @@ static struct snd_soc_card tosa = { ...@@ -230,6 +218,7 @@ static struct snd_soc_card tosa = {
.num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets),
.dapm_routes = audio_map, .dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map), .num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
}; };
static int tosa_probe(struct platform_device *pdev) static int tosa_probe(struct platform_device *pdev)
......
...@@ -132,16 +132,8 @@ static const struct snd_soc_dapm_route z2_audio_map[] = { ...@@ -132,16 +132,8 @@ static const struct snd_soc_dapm_route z2_audio_map[] = {
*/ */
static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret; int ret;
/* NC codec pins */
snd_soc_dapm_disable_pin(dapm, "LINPUT3");
snd_soc_dapm_disable_pin(dapm, "RINPUT3");
snd_soc_dapm_disable_pin(dapm, "OUT3");
snd_soc_dapm_disable_pin(dapm, "MONO1");
/* Jack detection API stuff */ /* Jack detection API stuff */
ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET, ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET,
&hs_jack, hs_jack_pins, &hs_jack, hs_jack_pins,
...@@ -189,6 +181,7 @@ static struct snd_soc_card snd_soc_z2 = { ...@@ -189,6 +181,7 @@ static struct snd_soc_card snd_soc_z2 = {
.num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
.dapm_routes = z2_audio_map, .dapm_routes = z2_audio_map,
.num_dapm_routes = ARRAY_SIZE(z2_audio_map), .num_dapm_routes = ARRAY_SIZE(z2_audio_map),
.fully_routed = true,
}; };
static struct platform_device *z2_snd_device; static struct platform_device *z2_snd_device;
......
...@@ -6,19 +6,28 @@ config SND_SOC_QCOM ...@@ -6,19 +6,28 @@ config SND_SOC_QCOM
config SND_SOC_LPASS_CPU config SND_SOC_LPASS_CPU
tristate tristate
depends on SND_SOC_QCOM
select REGMAP_MMIO select REGMAP_MMIO
config SND_SOC_LPASS_PLATFORM config SND_SOC_LPASS_PLATFORM
tristate tristate
depends on SND_SOC_QCOM
select REGMAP_MMIO select REGMAP_MMIO
config SND_SOC_STORM config SND_SOC_LPASS_IPQ806X
tristate "ASoC I2S support for Storm boards" tristate
depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST depends on SND_SOC_QCOM
select SND_SOC_LPASS_CPU
select SND_SOC_LPASS_PLATFORM
config SND_SOC_LPASS_APQ8016
tristate
depends on SND_SOC_QCOM
select SND_SOC_LPASS_CPU select SND_SOC_LPASS_CPU
select SND_SOC_LPASS_PLATFORM select SND_SOC_LPASS_PLATFORM
config SND_SOC_STORM
tristate "ASoC I2S support for Storm boards"
depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST)
select SND_SOC_LPASS_IPQ806X
select SND_SOC_MAX98357A select SND_SOC_MAX98357A
help help
Say Y or M if you want add support for SoC audio on the Say Y or M if you want add support for SoC audio on the
......
# Platform # Platform
snd-soc-lpass-cpu-objs := lpass-cpu.o snd-soc-lpass-cpu-objs := lpass-cpu.o
snd-soc-lpass-platform-objs := lpass-platform.o snd-soc-lpass-platform-objs := lpass-platform.o
snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o
snd-soc-lpass-apq8016-objs := lpass-apq8016.o
obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o
obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o
obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o
# Machine # Machine
snd-soc-storm-objs := storm.o snd-soc-storm-objs := storm.o
......
/*
* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* lpass-apq8016.c -- ALSA SoC CPU DAI driver for APQ8016 LPASS
*
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <dt-bindings/sound/apq8016-lpass.h>
#include "lpass-lpaif-reg.h"
#include "lpass.h"
static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = {
[MI2S_PRIMARY] = {
.id = MI2S_PRIMARY,
.name = "Primary MI2S",
.playback = {
.stream_name = "Primary Playback",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 8,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
},
[MI2S_SECONDARY] = {
.id = MI2S_SECONDARY,
.name = "Secondary MI2S",
.playback = {
.stream_name = "Secondary Playback",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 8,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
},
[MI2S_TERTIARY] = {
.id = MI2S_TERTIARY,
.name = "Tertiary MI2S",
.capture = {
.stream_name = "Tertiary Capture",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 8,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
},
[MI2S_QUATERNARY] = {
.id = MI2S_QUATERNARY,
.name = "Quatenary MI2S",
.playback = {
.stream_name = "Quatenary Playback",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 8,
},
.capture = {
.stream_name = "Quatenary Capture",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 8,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
},
};
static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata)
{
struct lpass_variant *v = drvdata->variant;
int chan = find_first_zero_bit(&drvdata->rdma_ch_bit_map,
v->rdma_channels);
if (chan >= v->rdma_channels)
return -EBUSY;
set_bit(chan, &drvdata->rdma_ch_bit_map);
return chan;
}
static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
{
clear_bit(chan, &drvdata->rdma_ch_bit_map);
return 0;
}
static int apq8016_lpass_init(struct platform_device *pdev)
{
struct lpass_data *drvdata = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
int ret;
drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk");
if (IS_ERR(drvdata->pcnoc_mport_clk)) {
dev_err(&pdev->dev, "%s() error getting pcnoc-mport-clk: %ld\n",
__func__, PTR_ERR(drvdata->pcnoc_mport_clk));
return PTR_ERR(drvdata->pcnoc_mport_clk);
}
ret = clk_prepare_enable(drvdata->pcnoc_mport_clk);
if (ret) {
dev_err(&pdev->dev, "%s() Error enabling pcnoc-mport-clk: %d\n",
__func__, ret);
return ret;
}
drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk");
if (IS_ERR(drvdata->pcnoc_sway_clk)) {
dev_err(&pdev->dev, "%s() error getting pcnoc-sway-clk: %ld\n",
__func__, PTR_ERR(drvdata->pcnoc_sway_clk));
return PTR_ERR(drvdata->pcnoc_sway_clk);
}
ret = clk_prepare_enable(drvdata->pcnoc_sway_clk);
if (ret) {
dev_err(&pdev->dev, "%s() Error enabling pcnoc_sway_clk: %d\n",
__func__, ret);
return ret;
}
return 0;
}
static int apq8016_lpass_exit(struct platform_device *pdev)
{
struct lpass_data *drvdata = platform_get_drvdata(pdev);
clk_disable_unprepare(drvdata->pcnoc_mport_clk);
clk_disable_unprepare(drvdata->pcnoc_sway_clk);
return 0;
}
static struct lpass_variant apq8016_data = {
.i2sctrl_reg_base = 0x1000,
.i2sctrl_reg_stride = 0x1000,
.i2s_ports = 4,
.irq_reg_base = 0x6000,
.irq_reg_stride = 0x1000,
.irq_ports = 3,
.rdma_reg_base = 0x8400,
.rdma_reg_stride = 0x1000,
.rdma_channels = 2,
.rdmactl_audif_start = 1,
.dai_driver = apq8016_lpass_cpu_dai_driver,
.num_dai = ARRAY_SIZE(apq8016_lpass_cpu_dai_driver),
.init = apq8016_lpass_init,
.exit = apq8016_lpass_exit,
.alloc_dma_channel = apq8016_lpass_alloc_dma_channel,
.free_dma_channel = apq8016_lpass_free_dma_channel,
};
static const struct of_device_id apq8016_lpass_cpu_device_id[] = {
{ .compatible = "qcom,lpass-cpu-apq8016", .data = &apq8016_data },
{}
};
MODULE_DEVICE_TABLE(of, apq8016_lpass_cpu_device_id);
static struct platform_driver apq8016_lpass_cpu_platform_driver = {
.driver = {
.name = "apq8016-lpass-cpu",
.of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id),
},
.probe = asoc_qcom_lpass_cpu_platform_probe,
.remove = asoc_qcom_lpass_cpu_platform_remove,
};
module_platform_driver(apq8016_lpass_cpu_platform_driver);
MODULE_DESCRIPTION("APQ8016 LPASS CPU Driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
/*
* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* lpass-ipq806x.c -- ALSA SoC CPU DAI driver for QTi LPASS
* Splited out the IPQ8064 soc specific from lpass-cpu.c
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include "lpass-lpaif-reg.h"
#include "lpass.h"
enum lpaif_i2s_ports {
IPQ806X_LPAIF_I2S_PORT_CODEC_SPK,
IPQ806X_LPAIF_I2S_PORT_CODEC_MIC,
IPQ806X_LPAIF_I2S_PORT_SEC_SPK,
IPQ806X_LPAIF_I2S_PORT_SEC_MIC,
IPQ806X_LPAIF_I2S_PORT_MI2S,
};
enum lpaif_dma_channels {
IPQ806X_LPAIF_RDMA_CHAN_MI2S,
IPQ806X_LPAIF_RDMA_CHAN_PCM0,
IPQ806X_LPAIF_RDMA_CHAN_PCM1,
};
static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = {
.id = IPQ806X_LPAIF_I2S_PORT_MI2S,
.playback = {
.stream_name = "lpass-cpu-playback",
.formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 8,
},
.probe = &asoc_qcom_lpass_cpu_dai_probe,
.ops = &asoc_qcom_lpass_cpu_dai_ops,
};
static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata)
{
return IPQ806X_LPAIF_RDMA_CHAN_MI2S;
}
static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
{
return 0;
}
struct lpass_variant ipq806x_data = {
.i2sctrl_reg_base = 0x0010,
.i2sctrl_reg_stride = 0x04,
.i2s_ports = 5,
.irq_reg_base = 0x3000,
.irq_reg_stride = 0x1000,
.irq_ports = 3,
.rdma_reg_base = 0x6000,
.rdma_reg_stride = 0x1000,
.rdma_channels = 4,
.dai_driver = &ipq806x_lpass_cpu_dai_driver,
.num_dai = 1,
.alloc_dma_channel = ipq806x_lpass_alloc_dma_channel,
.free_dma_channel = ipq806x_lpass_free_dma_channel,
};
static const struct of_device_id ipq806x_lpass_cpu_device_id[] = {
{ .compatible = "qcom,lpass-cpu", .data = &ipq806x_data },
{}
};
MODULE_DEVICE_TABLE(of, ipq806x_lpass_cpu_device_id);
static struct platform_driver ipq806x_lpass_cpu_platform_driver = {
.driver = {
.name = "lpass-cpu",
.of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id),
},
.probe = asoc_qcom_lpass_cpu_platform_probe,
.remove = asoc_qcom_lpass_cpu_platform_remove,
};
module_platform_driver(ipq806x_lpass_cpu_platform_driver);
MODULE_DESCRIPTION("QTi LPASS CPU Driver");
MODULE_LICENSE("GPL v2");
...@@ -9,37 +9,17 @@ ...@@ -9,37 +9,17 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*
* lpass-lpaif-ipq806x.h -- Definitions for the QTi LPAIF in the ipq806x LPASS
*/ */
#ifndef __LPASS_LPAIF_H__ #ifndef __LPASS_LPAIF_REG_H__
#define __LPASS_LPAIF_H__ #define __LPASS_LPAIF_REG_H__
#define LPAIF_BANK_OFFSET 0x1000
/* LPAIF I2S */ /* LPAIF I2S */
#define LPAIF_I2SCTL_REG_BASE 0x0010 #define LPAIF_I2SCTL_REG_ADDR(v, addr, port) \
#define LPAIF_I2SCTL_REG_STRIDE 0x4 (v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port))
#define LPAIF_I2SCTL_REG_ADDR(addr, port) \
(LPAIF_I2SCTL_REG_BASE + (addr) + (LPAIF_I2SCTL_REG_STRIDE * (port)))
enum lpaif_i2s_ports {
LPAIF_I2S_PORT_MIN = 0,
LPAIF_I2S_PORT_CODEC_SPK = 0,
LPAIF_I2S_PORT_CODEC_MIC = 1,
LPAIF_I2S_PORT_SEC_SPK = 2,
LPAIF_I2S_PORT_SEC_MIC = 3,
LPAIF_I2S_PORT_MI2S = 4,
LPAIF_I2S_PORT_MAX = 4,
LPAIF_I2S_PORT_NUM = 5,
};
#define LPAIF_I2SCTL_REG(port) LPAIF_I2SCTL_REG_ADDR(0x0, (port))
#define LPAIF_I2SCTL_REG(v, port) LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port))
#define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 #define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000
#define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 #define LPAIF_I2SCTL_LOOPBACK_SHIFT 15
#define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) #define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
...@@ -79,55 +59,36 @@ enum lpaif_i2s_ports { ...@@ -79,55 +59,36 @@ enum lpaif_i2s_ports {
#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) #define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
/* LPAIF IRQ */ /* LPAIF IRQ */
#define LPAIF_IRQ_REG_ADDR(v, addr, port) \
(v->irq_reg_base + (addr) + v->irq_reg_stride * (port))
#define LPAIF_IRQ_REG_BASE 0x3000 #define LPAIF_IRQ_PORT_HOST 0
#define LPAIF_IRQ_REG_STRIDE 0x1000
#define LPAIF_IRQ_REG_ADDR(addr, port) \
(LPAIF_IRQ_REG_BASE + (addr) + (LPAIF_IRQ_REG_STRIDE * (port)))
enum lpaif_irq_ports {
LPAIF_IRQ_PORT_MIN = 0,
LPAIF_IRQ_PORT_HOST = 0, #define LPAIF_IRQEN_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x0, (port))
LPAIF_IRQ_PORT_ADSP = 1, #define LPAIF_IRQSTAT_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x4, (port))
#define LPAIF_IRQCLEAR_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0xC, (port))
LPAIF_IRQ_PORT_MAX = 2,
LPAIF_IRQ_PORT_NUM = 3,
};
#define LPAIF_IRQEN_REG(port) LPAIF_IRQ_REG_ADDR(0x0, (port))
#define LPAIF_IRQSTAT_REG(port) LPAIF_IRQ_REG_ADDR(0x4, (port))
#define LPAIF_IRQCLEAR_REG(port) LPAIF_IRQ_REG_ADDR(0xC, (port))
#define LPAIF_IRQ_BITSTRIDE 3 #define LPAIF_IRQ_BITSTRIDE 3
#define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan))) #define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan)))
#define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan))) #define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan)))
#define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan))) #define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan)))
#define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan))) #define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan)))
/* LPAIF DMA */ /* LPAIF DMA */
#define LPAIF_RDMA_REG_BASE 0x6000 #define LPAIF_RDMA_REG_ADDR(v, addr, chan) \
#define LPAIF_RDMA_REG_STRIDE 0x1000 (v->rdma_reg_base + (addr) + v->rdma_reg_stride * (chan))
#define LPAIF_RDMA_REG_ADDR(addr, chan) \
(LPAIF_RDMA_REG_BASE + (addr) + (LPAIF_RDMA_REG_STRIDE * (chan)))
enum lpaif_dma_channels {
LPAIF_RDMA_CHAN_MIN = 0,
LPAIF_RDMA_CHAN_MI2S = 0,
LPAIF_RDMA_CHAN_PCM0 = 1,
LPAIF_RDMA_CHAN_PCM1 = 2,
LPAIF_RDMA_CHAN_MAX = 4, #define LPAIF_RDMACTL_AUDINTF(id) (id << LPAIF_RDMACTL_AUDINTF_SHIFT)
LPAIF_RDMA_CHAN_NUM = 5,
};
#define LPAIF_RDMACTL_REG(chan) LPAIF_RDMA_REG_ADDR(0x00, (chan)) #define LPAIF_RDMACTL_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x00, (chan))
#define LPAIF_RDMABASE_REG(chan) LPAIF_RDMA_REG_ADDR(0x04, (chan)) #define LPAIF_RDMABASE_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x04, (chan))
#define LPAIF_RDMABUFF_REG(chan) LPAIF_RDMA_REG_ADDR(0x08, (chan)) #define LPAIF_RDMABUFF_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x08, (chan))
#define LPAIF_RDMACURR_REG(chan) LPAIF_RDMA_REG_ADDR(0x0C, (chan)) #define LPAIF_RDMACURR_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x0C, (chan))
#define LPAIF_RDMAPER_REG(chan) LPAIF_RDMA_REG_ADDR(0x10, (chan)) #define LPAIF_RDMAPER_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x10, (chan))
#define LPAIF_RDMAPERCNT_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x14, (chan))
#define LPAIF_RDMACTL_BURSTEN_MASK 0x800 #define LPAIF_RDMACTL_BURSTEN_MASK 0x800
#define LPAIF_RDMACTL_BURSTEN_SHIFT 11 #define LPAIF_RDMACTL_BURSTEN_SHIFT 11
...@@ -145,13 +106,6 @@ enum lpaif_dma_channels { ...@@ -145,13 +106,6 @@ enum lpaif_dma_channels {
#define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0 #define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0
#define LPAIF_RDMACTL_AUDINTF_SHIFT 4 #define LPAIF_RDMACTL_AUDINTF_SHIFT 4
#define LPAIF_RDMACTL_AUDINTF_NONE (0 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_AUDINTF_CODEC (1 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_AUDINTF_PCM (2 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_AUDINTF_SEC_I2S (3 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_AUDINTF_MI2S (4 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_AUDINTF_HDMI (5 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_AUDINTF_SEC_PCM (7 << LPAIF_RDMACTL_AUDINTF_SHIFT)
#define LPAIF_RDMACTL_FIFOWM_MASK 0x00E #define LPAIF_RDMACTL_FIFOWM_MASK 0x00E
#define LPAIF_RDMACTL_FIFOWM_SHIFT 1 #define LPAIF_RDMACTL_FIFOWM_SHIFT 1
...@@ -169,4 +123,4 @@ enum lpaif_dma_channels { ...@@ -169,4 +123,4 @@ enum lpaif_dma_channels {
#define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT) #define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT)
#define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT) #define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT)
#endif /* __LPASS_LPAIF_H__ */ #endif /* __LPASS_LPAIF_REG_H__ */
This diff is collapsed.
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000
#define LPASS_MAX_MI2S_PORTS (8)
#define LPASS_MAX_DMA_CHANNELS (8)
/* Both the CPU DAI and platform drivers will access this data */ /* Both the CPU DAI and platform drivers will access this data */
struct lpass_data { struct lpass_data {
...@@ -30,10 +32,10 @@ struct lpass_data { ...@@ -30,10 +32,10 @@ struct lpass_data {
struct clk *ahbix_clk; struct clk *ahbix_clk;
/* MI2S system clock */ /* MI2S system clock */
struct clk *mi2s_osr_clk; struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS];
/* MI2S bit clock (derived from system clock by a divider */ /* MI2S bit clock (derived from system clock by a divider */
struct clk *mi2s_bit_clk; struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS];
/* low-power audio interface (LPAIF) registers */ /* low-power audio interface (LPAIF) registers */
void __iomem *lpaif; void __iomem *lpaif;
...@@ -43,9 +45,54 @@ struct lpass_data { ...@@ -43,9 +45,54 @@ struct lpass_data {
/* interrupts from the low-power audio interface (LPAIF) */ /* interrupts from the low-power audio interface (LPAIF) */
int lpaif_irq; int lpaif_irq;
/* SOC specific variations in the LPASS IP integration */
struct lpass_variant *variant;
/* bit map to keep track of static channel allocations */
unsigned long rdma_ch_bit_map;
/* used it for handling interrupt per dma channel */
struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS];
/* 8016 specific */
struct clk *pcnoc_mport_clk;
struct clk *pcnoc_sway_clk;
};
/* Vairant data per each SOC */
struct lpass_variant {
u32 i2sctrl_reg_base;
u32 i2sctrl_reg_stride;
u32 i2s_ports;
u32 irq_reg_base;
u32 irq_reg_stride;
u32 irq_ports;
u32 rdma_reg_base;
u32 rdma_reg_stride;
u32 rdma_channels;
/**
* on SOCs like APQ8016 the channel control bits start
* at different offset to ipq806x
**/
u32 rdmactl_audif_start;
/* SOC specific intialization like clocks */
int (*init)(struct platform_device *pdev);
int (*exit)(struct platform_device *pdev);
int (*alloc_dma_channel)(struct lpass_data *data);
int (*free_dma_channel)(struct lpass_data *data, int ch);
/* SOC specific dais */
struct snd_soc_dai_driver *dai_driver;
int num_dai;
}; };
/* register the platform driver from the CPU DAI driver */ /* register the platform driver from the CPU DAI driver */
int asoc_qcom_lpass_platform_register(struct platform_device *); int asoc_qcom_lpass_platform_register(struct platform_device *);
int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev);
int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev);
int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai);
extern struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops;
#endif /* __LPASS_H__ */ #endif /* __LPASS_H__ */
...@@ -170,6 +170,14 @@ void rsnd_mod_quit(struct rsnd_mod *mod) ...@@ -170,6 +170,14 @@ void rsnd_mod_quit(struct rsnd_mod *mod)
clk_unprepare(mod->clk); clk_unprepare(mod->clk);
} }
int rsnd_mod_is_working(struct rsnd_mod *mod)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
/* see rsnd_dai_stream_init/quit() */
return !!io->substream;
}
/* /*
* settting function * settting function
*/ */
...@@ -272,9 +280,10 @@ struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) ...@@ -272,9 +280,10 @@ struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
return priv->rdai + id; return priv->rdai + id;
} }
#define rsnd_dai_to_priv(dai) snd_soc_dai_get_drvdata(dai)
static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
{ {
struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
return rsnd_rdai_get(priv, dai->id); return rsnd_rdai_get(priv, dai->id);
} }
...@@ -314,7 +323,7 @@ void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) ...@@ -314,7 +323,7 @@ void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
} }
} }
static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, static void rsnd_dai_stream_init(struct rsnd_dai_stream *io,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
...@@ -326,8 +335,11 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, ...@@ -326,8 +335,11 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io,
runtime->channels * runtime->channels *
samples_to_bytes(runtime, 1); samples_to_bytes(runtime, 1);
io->next_period_byte = io->byte_per_period; io->next_period_byte = io->byte_per_period;
}
return 0; static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io)
{
io->substream = NULL;
} }
static static
...@@ -351,20 +363,18 @@ struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai, ...@@ -351,20 +363,18 @@ struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io)); int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io));
int ret; int ret;
unsigned long flags; unsigned long flags;
rsnd_lock(priv, flags); spin_lock_irqsave(&priv->lock, flags);
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
ret = rsnd_dai_stream_init(io, substream); rsnd_dai_stream_init(io, substream);
if (ret < 0)
goto dai_trigger_end;
ret = rsnd_platform_call(priv, dai, start, ssi_id); ret = rsnd_platform_call(priv, dai, start, ssi_id);
if (ret < 0) if (ret < 0)
...@@ -390,13 +400,15 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -390,13 +400,15 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
ret = rsnd_platform_call(priv, dai, stop, ssi_id); ret = rsnd_platform_call(priv, dai, stop, ssi_id);
if (ret < 0) if (ret < 0)
goto dai_trigger_end; goto dai_trigger_end;
rsnd_dai_stream_quit(io);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
} }
dai_trigger_end: dai_trigger_end:
rsnd_unlock(priv, flags); spin_unlock_irqrestore(&priv->lock, flags);
return ret; return ret;
} }
...@@ -833,12 +845,14 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, ...@@ -833,12 +845,14 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
struct rsnd_kctrl_cfg *cfg, struct rsnd_kctrl_cfg *cfg,
void (*update)(struct rsnd_mod *mod)) void (*update)(struct rsnd_mod *mod))
{ {
struct snd_soc_card *soc_card = rtd->card;
struct snd_card *card = rtd->card->snd_card; struct snd_card *card = rtd->card->snd_card;
struct snd_kcontrol *kctrl; struct snd_kcontrol *kctrl;
struct snd_kcontrol_new knew = { struct snd_kcontrol_new knew = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = name, .name = name,
.info = rsnd_kctrl_info, .info = rsnd_kctrl_info,
.index = rtd - soc_card->rtd,
.get = rsnd_kctrl_get, .get = rsnd_kctrl_get,
.put = rsnd_kctrl_put, .put = rsnd_kctrl_put,
.private_value = (unsigned long)cfg, .private_value = (unsigned long)cfg,
......
...@@ -303,6 +303,7 @@ int rsnd_mod_init(struct rsnd_mod *mod, ...@@ -303,6 +303,7 @@ int rsnd_mod_init(struct rsnd_mod *mod,
int id); int id);
void rsnd_mod_quit(struct rsnd_mod *mod); void rsnd_mod_quit(struct rsnd_mod *mod);
char *rsnd_mod_name(struct rsnd_mod *mod); char *rsnd_mod_name(struct rsnd_mod *mod);
int rsnd_mod_is_working(struct rsnd_mod *mod);
struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod); struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod);
/* /*
...@@ -449,8 +450,6 @@ struct rsnd_priv { ...@@ -449,8 +450,6 @@ struct rsnd_priv {
#define rsnd_priv_to_pdev(priv) ((priv)->pdev) #define rsnd_priv_to_pdev(priv) ((priv)->pdev)
#define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev)) #define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev))
#define rsnd_priv_to_info(priv) ((priv)->info) #define rsnd_priv_to_info(priv) ((priv)->info)
#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
/* /*
* rsnd_kctrl * rsnd_kctrl
......
...@@ -232,6 +232,7 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, ...@@ -232,6 +232,7 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv,
if (args_count) { if (args_count) {
*args_count = args.args_count; *args_count = args.args_count;
dai_link->dynamic = 1; dai_link->dynamic = 1;
dai_link->dpcm_merged_format = 1;
} else { } else {
dai_link->no_pcm = 1; dai_link->no_pcm = 1;
priv->codec_conf.of_node = (*p_node); priv->codec_conf.of_node = (*p_node);
......
...@@ -673,10 +673,13 @@ static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) ...@@ -673,10 +673,13 @@ static int _rsnd_src_stop_gen2(struct rsnd_mod *mod)
static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
{ {
struct rsnd_mod *mod = data; struct rsnd_mod *mod = data;
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
spin_lock(&priv->lock);
if (!io) /* ignore all cases if not working */
return IRQ_NONE; if (!rsnd_mod_is_working(mod))
goto rsnd_src_interrupt_gen2_out;
if (rsnd_src_error_record_gen2(mod)) { if (rsnd_src_error_record_gen2(mod)) {
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
...@@ -692,6 +695,8 @@ static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) ...@@ -692,6 +695,8 @@ static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
else else
dev_warn(dev, "no more SRC restart\n"); dev_warn(dev, "no more SRC restart\n");
} }
rsnd_src_interrupt_gen2_out:
spin_unlock(&priv->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -66,6 +66,7 @@ struct rsnd_ssi { ...@@ -66,6 +66,7 @@ struct rsnd_ssi {
u32 cr_own; u32 cr_own;
u32 cr_clk; u32 cr_clk;
int chan;
int err; int err;
unsigned int usrcnt; unsigned int usrcnt;
}; };
...@@ -80,7 +81,7 @@ struct rsnd_ssi { ...@@ -80,7 +81,7 @@ struct rsnd_ssi {
#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
#define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma))
#define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0)
#define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) #define rsnd_ssi_parent(ssi) ((ssi)->parent)
#define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_mode_flags(p) ((p)->info->flags)
#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
#define rsnd_ssi_of_node(priv) \ #define rsnd_ssi_of_node(priv) \
...@@ -189,8 +190,10 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, ...@@ -189,8 +190,10 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
rsnd_mod_hw_start(&ssi->mod); rsnd_mod_hw_start(&ssi->mod);
if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_rdai_is_clk_master(rdai)) {
if (rsnd_ssi_clk_from_parent(ssi)) struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
rsnd_ssi_hw_start(ssi->parent, io);
if (ssi_parent)
rsnd_ssi_hw_start(ssi_parent, io);
else else
rsnd_ssi_master_clk_start(ssi, io); rsnd_ssi_master_clk_start(ssi, io);
} }
...@@ -229,8 +232,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) ...@@ -229,8 +232,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi)
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
u32 cr; u32 cr;
if (0 == ssi->usrcnt) /* stop might be called without start */ if (0 == ssi->usrcnt) {
dev_err(dev, "%s called without starting\n", __func__);
return; return;
}
ssi->usrcnt--; ssi->usrcnt--;
...@@ -253,13 +258,17 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) ...@@ -253,13 +258,17 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi)
rsnd_ssi_status_check(&ssi->mod, IIRQ); rsnd_ssi_status_check(&ssi->mod, IIRQ);
if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_rdai_is_clk_master(rdai)) {
if (rsnd_ssi_clk_from_parent(ssi)) struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
rsnd_ssi_hw_stop(ssi->parent);
if (ssi_parent)
rsnd_ssi_hw_stop(ssi_parent);
else else
rsnd_ssi_master_clk_stop(ssi); rsnd_ssi_master_clk_stop(ssi);
} }
rsnd_mod_hw_stop(&ssi->mod); rsnd_mod_hw_stop(&ssi->mod);
ssi->chan = 0;
} }
dev_dbg(dev, "%s[%d] hw stopped\n", dev_dbg(dev, "%s[%d] hw stopped\n",
...@@ -336,6 +345,35 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, ...@@ -336,6 +345,35 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
return 0; return 0;
} }
static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
int chan = params_channels(params);
/*
* Already working.
* It will happen if SSI has parent/child connection.
*/
if (ssi->usrcnt) {
/*
* it is error if child <-> parent SSI uses
* different channels.
*/
if (ssi->chan != chan)
return -EIO;
}
/* It will be removed on rsnd_ssi_hw_stop */
ssi->chan = chan;
if (ssi_parent)
return rsnd_ssi_hw_params(&ssi_parent->mod, substream, params);
return 0;
}
static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
{ {
/* under/over flow error */ /* under/over flow error */
...@@ -385,10 +423,15 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) ...@@ -385,10 +423,15 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
int is_dma = rsnd_ssi_is_dma_mode(mod); int is_dma = rsnd_ssi_is_dma_mode(mod);
u32 status = rsnd_mod_read(mod, SSISR); u32 status;
spin_lock(&priv->lock);
if (!io) /* ignore all cases if not working */
return IRQ_NONE; if (!rsnd_mod_is_working(mod))
goto rsnd_ssi_interrupt_out;
status = rsnd_mod_read(mod, SSISR);
/* PIO only */ /* PIO only */
if (!is_dma && (status & DIRQ)) { if (!is_dma && (status & DIRQ)) {
...@@ -428,6 +471,9 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) ...@@ -428,6 +471,9 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
rsnd_ssi_record_error(ssi, status); rsnd_ssi_record_error(ssi, status);
rsnd_ssi_interrupt_out:
spin_unlock(&priv->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -456,6 +502,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { ...@@ -456,6 +502,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.quit = rsnd_ssi_quit, .quit = rsnd_ssi_quit,
.start = rsnd_ssi_start, .start = rsnd_ssi_start,
.stop = rsnd_ssi_stop, .stop = rsnd_ssi_stop,
.hw_params = rsnd_ssi_hw_params,
}; };
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
...@@ -565,6 +612,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { ...@@ -565,6 +612,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
.start = rsnd_ssi_dma_start, .start = rsnd_ssi_dma_start,
.stop = rsnd_ssi_dma_stop, .stop = rsnd_ssi_dma_stop,
.fallback = rsnd_ssi_fallback, .fallback = rsnd_ssi_fallback,
.hw_params = rsnd_ssi_hw_params,
}; };
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
...@@ -598,7 +646,7 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) ...@@ -598,7 +646,7 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
} }
static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) static void rsnd_ssi_parent_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi)
{ {
if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) if (!rsnd_ssi_is_pin_sharing(&ssi->mod))
return; return;
...@@ -732,7 +780,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, ...@@ -732,7 +780,7 @@ int rsnd_ssi_probe(struct platform_device *pdev,
if (ret) if (ret)
return ret; return ret;
rsnd_ssi_parent_clk_setup(priv, ssi); rsnd_ssi_parent_setup(priv, ssi);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment