Merge remote-tracking branches 'asoc/topic/pxa', 'asoc/topic/rcar' and 'asoc/topic/rt286' into asoc-next

This commit is contained in:
Mark Brown 2015-02-09 15:10:24 +08:00
commit af70797105
19 changed files with 438 additions and 382 deletions

View file

@ -55,6 +55,7 @@ struct rsnd_ssi_platform_info {
struct rsnd_src_platform_info {
u32 convert_rate; /* sampling rate convert */
int dma_id; /* for Gen2 SCU */
int irq;
};
/*

View file

@ -34,6 +34,7 @@
#include "rt286.h"
#define RT286_VENDOR_ID 0x10ec0286
#define RT288_VENDOR_ID 0x10ec0288
struct rt286_priv {
struct regmap *regmap;
@ -1171,6 +1172,7 @@ static const struct regmap_config rt286_regmap = {
static const struct i2c_device_id rt286_i2c_id[] = {
{"rt286", 0},
{"rt288", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, rt286_i2c_id);
@ -1191,6 +1193,17 @@ static struct dmi_system_id force_combo_jack_table[] = {
{ }
};
static struct dmi_system_id dmi_dell_dino[] = {
{
.ident = "Dell Dino",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_BOARD_NAME, "0144P8")
}
},
{ }
};
static int rt286_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -1213,7 +1226,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
regmap_read(rt286->regmap,
RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret);
if (ret != RT286_VENDOR_ID) {
if (ret != RT286_VENDOR_ID && ret != RT288_VENDOR_ID) {
dev_err(&i2c->dev,
"Device with ID register %x is not rt286\n", ret);
return -ENODEV;
@ -1226,7 +1239,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt286->pdata = *pdata;
if (dmi_check_system(force_combo_jack_table))
if (dmi_check_system(force_combo_jack_table) ||
dmi_check_system(dmi_dell_dino))
rt286->pdata.cbj_en = true;
regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
@ -1265,6 +1279,17 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
if (dmi_check_system(dmi_dell_dino)) {
regmap_update_bits(rt286->regmap,
RT286_SET_GPIO_MASK, 0x40, 0x40);
regmap_update_bits(rt286->regmap,
RT286_SET_GPIO_DIRECTION, 0x40, 0x40);
regmap_update_bits(rt286->regmap,
RT286_SET_GPIO_DATA, 0x40, 0x40);
regmap_update_bits(rt286->regmap,
RT286_GPIO_CTRL, 0xc, 0x8);
}
if (rt286->i2c->irq) {
ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286);

View file

@ -117,6 +117,12 @@
VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0)
#define RT286_PROC_COEF\
VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0)
#define RT286_SET_GPIO_MASK\
VERB_CMD(AC_VERB_SET_GPIO_MASK, RT286_AUDIO_FUNCTION_GROUP, 0)
#define RT286_SET_GPIO_DIRECTION\
VERB_CMD(AC_VERB_SET_GPIO_DIRECTION, RT286_AUDIO_FUNCTION_GROUP, 0)
#define RT286_SET_GPIO_DATA\
VERB_CMD(AC_VERB_SET_GPIO_DATA, RT286_AUDIO_FUNCTION_GROUP, 0)
/* Index registers */
#define RT286_A_BIAS_CTRL1 0x01
@ -131,6 +137,7 @@
#define RT286_POWER_CTRL3 0x0f
#define RT286_MIC1_DET_CTRL 0x19
#define RT286_MISC_CTRL1 0x20
#define RT286_GPIO_CTRL 0x29
#define RT286_IRQ_CTRL 0x33
#define RT286_PLL_CTRL1 0x49
#define RT286_CBJ_CTRL1 0x4f

View file

@ -140,7 +140,7 @@ config SND_PXA910_SOC
Marvell PXA910 reference platform.
config SND_SOC_TTC_DKB
bool "SoC Audio support for TTC DKB"
tristate "SoC Audio support for TTC DKB"
depends on SND_PXA910_SOC && MACH_TTC_DKB && I2C=y
select PXA_SSP
select SND_PXA_SOC_SSP

View file

@ -259,20 +259,6 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
corgi_set_spk),
};
/*
* Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
*/
static int corgi_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;
}
/* corgi digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link corgi_dai = {
.name = "WM8731",
@ -281,7 +267,6 @@ static struct snd_soc_dai_link corgi_dai = {
.codec_dai_name = "wm8731-hifi",
.platform_name = "pxa-pcm-audio",
.codec_name = "wm8731.0-001b",
.init = corgi_wm8731_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &corgi_ops,
@ -300,6 +285,7 @@ static struct snd_soc_card corgi = {
.num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
.dapm_routes = corgi_audio_map,
.num_dapm_routes = ARRAY_SIZE(corgi_audio_map),
.fully_routed = true,
};
static int corgi_probe(struct platform_device *pdev)

View file

@ -88,24 +88,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Mic Amp", NULL, "Mic (Internal)"},
};
static int e740_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, "HPOUTL");
snd_soc_dapm_nc_pin(dapm, "HPOUTR");
snd_soc_dapm_nc_pin(dapm, "PHONE");
snd_soc_dapm_nc_pin(dapm, "LINEINL");
snd_soc_dapm_nc_pin(dapm, "LINEINR");
snd_soc_dapm_nc_pin(dapm, "CDINL");
snd_soc_dapm_nc_pin(dapm, "CDINR");
snd_soc_dapm_nc_pin(dapm, "PCBEEP");
snd_soc_dapm_nc_pin(dapm, "MIC2");
return 0;
}
static struct snd_soc_dai_link e740_dai[] = {
{
.name = "AC97",
@ -114,7 +96,6 @@ static struct snd_soc_dai_link e740_dai[] = {
.codec_dai_name = "wm9705-hifi",
.platform_name = "pxa-pcm-audio",
.codec_name = "wm9705-codec",
.init = e740_ac97_init,
},
{
.name = "AC97 Aux",
@ -136,6 +117,7 @@ static struct snd_soc_card e740 = {
.num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
};
static struct gpio e740_audio_gpios[] = {

View file

@ -70,24 +70,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"MIC1", NULL, "Mic (Internal)"},
};
static int e750_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, "LOUT");
snd_soc_dapm_nc_pin(dapm, "ROUT");
snd_soc_dapm_nc_pin(dapm, "PHONE");
snd_soc_dapm_nc_pin(dapm, "LINEINL");
snd_soc_dapm_nc_pin(dapm, "LINEINR");
snd_soc_dapm_nc_pin(dapm, "CDINL");
snd_soc_dapm_nc_pin(dapm, "CDINR");
snd_soc_dapm_nc_pin(dapm, "PCBEEP");
snd_soc_dapm_nc_pin(dapm, "MIC2");
return 0;
}
static struct snd_soc_dai_link e750_dai[] = {
{
.name = "AC97",
@ -96,7 +78,6 @@ static struct snd_soc_dai_link e750_dai[] = {
.codec_dai_name = "wm9705-hifi",
.platform_name = "pxa-pcm-audio",
.codec_name = "wm9705-codec",
.init = e750_ac97_init,
/* use ops to check startup state */
},
{
@ -119,6 +100,7 @@ static struct snd_soc_card e750 = {
.num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
};
static struct gpio e750_audio_gpios[] = {

View file

@ -127,15 +127,8 @@ static const struct snd_soc_dapm_route hx4700_audio_map[] = {
static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int err;
/* NC codec pins */
/* FIXME: is anything connected here? */
snd_soc_dapm_nc_pin(dapm, "MOUT1");
snd_soc_dapm_nc_pin(dapm, "MICEXT");
snd_soc_dapm_nc_pin(dapm, "AUX");
/* Jack detection API stuff */
err = snd_soc_jack_new(codec, "Headphone Jack",
SND_JACK_HEADPHONE, &hs_jack);
@ -184,6 +177,7 @@ static struct snd_soc_card snd_soc_card_hx4700 = {
.num_dapm_widgets = ARRAY_SIZE(hx4700_dapm_widgets),
.dapm_routes = hx4700_audio_map,
.num_dapm_routes = ARRAY_SIZE(hx4700_audio_map),
.fully_routed = true,
};
static struct gpio hx4700_audio_gpios[] = {

View file

@ -391,25 +391,6 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = {
magician_get_input, magician_set_input),
};
/*
* Logic for a uda1380 as connected on a HTC Magician
*/
static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
/* NC codec pins */
snd_soc_dapm_nc_pin(dapm, "VOUTLHP");
snd_soc_dapm_nc_pin(dapm, "VOUTRHP");
/* FIXME: is anything connected here? */
snd_soc_dapm_nc_pin(dapm, "VINL");
snd_soc_dapm_nc_pin(dapm, "VINR");
return 0;
}
/* magician digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link magician_dai[] = {
{
@ -419,7 +400,6 @@ static struct snd_soc_dai_link magician_dai[] = {
.codec_dai_name = "uda1380-hifi-playback",
.platform_name = "pxa-pcm-audio",
.codec_name = "uda1380-codec.0-0018",
.init = magician_uda1380_init,
.ops = &magician_playback_ops,
},
{
@ -446,6 +426,7 @@ static struct snd_soc_card snd_soc_card_magician = {
.num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
};
static struct platform_device *magician_snd_device;

View file

@ -68,7 +68,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Ext. Speaker", NULL, "ROUT2"},
/* mic connected to MIC1 */
{"Ext. Microphone", NULL, "MIC1"},
{"MIC1", NULL, "Ext. Microphone"},
};
static struct snd_soc_card palm27x_asoc;
@ -76,18 +76,8 @@ static struct snd_soc_card palm27x_asoc;
static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int err;
/* not connected pins */
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "MONOOUT");
snd_soc_dapm_nc_pin(dapm, "LINEINL");
snd_soc_dapm_nc_pin(dapm, "LINEINR");
snd_soc_dapm_nc_pin(dapm, "PCBEEP");
snd_soc_dapm_nc_pin(dapm, "PHONE");
snd_soc_dapm_nc_pin(dapm, "MIC2");
/* Jack detection API stuff */
err = snd_soc_jack_new(codec, "Headphone Jack",
SND_JACK_HEADPHONE, &hs_jack);
@ -133,7 +123,8 @@ static struct snd_soc_card palm27x_asoc = {
.dapm_widgets = palm27x_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(palm27x_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map)
.num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
};
static int palm27x_asoc_probe(struct platform_device *pdev)

View file

@ -256,26 +256,6 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
spitz_set_spk),
};
/*
* Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
*/
static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
/* NC codec pins */
snd_soc_dapm_nc_pin(dapm, "RINPUT1");
snd_soc_dapm_nc_pin(dapm, "LINPUT2");
snd_soc_dapm_nc_pin(dapm, "RINPUT2");
snd_soc_dapm_nc_pin(dapm, "LINPUT3");
snd_soc_dapm_nc_pin(dapm, "RINPUT3");
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "MONO1");
return 0;
}
/* spitz digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link spitz_dai = {
.name = "wm8750",
@ -284,7 +264,6 @@ static struct snd_soc_dai_link spitz_dai = {
.codec_dai_name = "wm8750-hifi",
.platform_name = "pxa-pcm-audio",
.codec_name = "wm8750.0-001b",
.init = spitz_wm8750_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &spitz_ops,
@ -303,6 +282,7 @@ static struct snd_soc_card snd_soc_spitz = {
.num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
.dapm_routes = spitz_audio_map,
.num_dapm_routes = ARRAY_SIZE(spitz_audio_map),
.fully_routed = true,
};
static int spitz_probe(struct platform_device *pdev)

View file

@ -76,10 +76,6 @@ static const struct snd_soc_dapm_route ttc_audio_map[] = {
static int ttc_pm860x_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_disable_pin(dapm, "Headset Mic 2");
snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
/* Headset jack detection */
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE

View file

@ -57,8 +57,7 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
return (0x6 + ws) << 8;
}
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai,
struct rsnd_mod *mod,
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io)
{
int id = rsnd_mod_id(mod);
@ -75,12 +74,11 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai,
return 0;
}
static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai,
struct rsnd_mod *mod,
static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
u32 timsel)
{
int is_play = rsnd_dai_is_play(rdai, io);
int is_play = rsnd_io_is_play(io);
int id = rsnd_mod_id(mod);
int shift = (id % 2) ? 16 : 0;
u32 mask, ws;
@ -122,7 +120,6 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai,
}
int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io,
unsigned int src_rate,
unsigned int dst_rate)
@ -178,7 +175,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
return -EIO;
}
ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val);
ret = rsnd_adg_set_src_timsel_gen2(mod, io, val);
if (ret < 0) {
dev_err(dev, "timsel error\n");
return ret;
@ -190,12 +187,11 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
}
int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io)
{
u32 val = rsnd_adg_ssi_ws_timing_gen2(io);
return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val);
return rsnd_adg_set_src_timsel_gen2(mod, io, val);
}
int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,

View file

@ -149,16 +149,16 @@ char *rsnd_mod_dma_name(struct rsnd_mod *mod)
return mod->ops->dma_name(mod);
}
void rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
void rsnd_mod_init(struct rsnd_mod *mod,
struct rsnd_mod_ops *ops,
struct clk *clk,
enum rsnd_mod_type type,
int id)
{
mod->priv = priv;
mod->id = id;
mod->ops = ops;
mod->type = type;
mod->clk = clk;
}
/*
@ -412,7 +412,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
/*
* rsnd_dai functions
*/
#define __rsnd_mod_call(mod, func, rdai...) \
#define __rsnd_mod_call(mod, func, param...) \
({ \
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \
struct device *dev = rsnd_priv_to_dev(priv); \
@ -422,18 +422,18 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
if ((mod->status & mask) == call) { \
dev_dbg(dev, "%s[%d] %s\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \
ret = (mod)->ops->func(mod, rdai); \
ret = (mod)->ops->func(mod, param); \
mod->status = (mod->status & ~mask) | (~call & mask); \
} \
ret; \
})
#define rsnd_mod_call(mod, func, rdai...) \
#define rsnd_mod_call(mod, func, param...) \
(!(mod) ? -ENODEV : \
!((mod)->ops->func) ? 0 : \
__rsnd_mod_call(mod, func, rdai))
__rsnd_mod_call(mod, func, param))
#define rsnd_dai_call(fn, io, rdai...) \
#define rsnd_dai_call(fn, io, param...) \
({ \
struct rsnd_mod *mod; \
int ret = 0, i; \
@ -441,7 +441,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
mod = (io)->mod[i]; \
if (!mod) \
continue; \
ret = rsnd_mod_call(mod, fn, rdai); \
ret = rsnd_mod_call(mod, fn, param); \
if (ret < 0) \
break; \
} \
@ -477,17 +477,7 @@ static void rsnd_dai_disconnect(struct rsnd_mod *mod,
io->mod[mod->type] = NULL;
}
int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai)
{
int id = rdai - priv->rdai;
if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
return -EINVAL;
return id;
}
struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id)
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
{
if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
return NULL;
@ -499,12 +489,7 @@ static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
{
struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
return rsnd_dai_get(priv, dai->id);
}
int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io)
{
return &rdai->playback == io;
return rsnd_rdai_get(priv, dai->id);
}
/*
@ -598,20 +583,20 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
if (ret < 0)
goto dai_trigger_end;
ret = rsnd_dai_call(init, io, rdai);
ret = rsnd_dai_call(init, io, priv);
if (ret < 0)
goto dai_trigger_end;
ret = rsnd_dai_call(start, io, rdai);
ret = rsnd_dai_call(start, io, priv);
if (ret < 0)
goto dai_trigger_end;
break;
case SNDRV_PCM_TRIGGER_STOP:
ret = rsnd_dai_call(stop, io, rdai);
ret = rsnd_dai_call(stop, io, priv);
if (ret < 0)
goto dai_trigger_end;
ret = rsnd_dai_call(quit, io, rdai);
ret = rsnd_dai_call(quit, io, priv);
if (ret < 0)
goto dai_trigger_end;
@ -873,15 +858,15 @@ static int rsnd_dai_probe(struct platform_device *pdev,
priv->rdai = rdai;
for (i = 0; i < dai_nr; i++) {
rdai[i].info = &info->dai_info[i];
pmod = rdai[i].info->playback.ssi;
cmod = rdai[i].info->capture.ssi;
pmod = info->dai_info[i].playback.ssi;
cmod = info->dai_info[i].capture.ssi;
/*
* init rsnd_dai
*/
snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i);
rdai[i].priv = priv;
/*
* init snd_soc_dai_driver
@ -895,6 +880,7 @@ static int rsnd_dai_probe(struct platform_device *pdev,
drv[i].playback.channels_max = 2;
rdai[i].playback.info = &info->dai_info[i].playback;
rdai[i].playback.rdai = rdai + i;
rsnd_path_init(priv, &rdai[i], &rdai[i].playback);
}
if (cmod) {
@ -904,6 +890,7 @@ static int rsnd_dai_probe(struct platform_device *pdev,
drv[i].capture.channels_max = 2;
rdai[i].capture.info = &info->dai_info[i].capture;
rdai[i].capture.rdai = rdai + i;
rsnd_path_init(priv, &rdai[i], &rdai[i].capture);
}
@ -1037,7 +1024,6 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
}
static int __rsnd_kctrl_new(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
struct rsnd_kctrl_cfg *cfg,
@ -1060,16 +1046,24 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
return -ENOMEM;
ret = snd_ctl_add(card, kctrl);
if (ret < 0)
if (ret < 0) {
snd_ctl_free_one(kctrl);
return ret;
}
cfg->update = update;
cfg->card = card;
cfg->kctrl = kctrl;
return 0;
}
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg)
{
snd_ctl_remove(cfg->card, cfg->kctrl);
}
int rsnd_kctrl_new_m(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_mod *mod),
@ -1079,11 +1073,10 @@ int rsnd_kctrl_new_m(struct rsnd_mod *mod,
_cfg->cfg.max = max;
_cfg->cfg.size = RSND_DVC_CHANNELS;
_cfg->cfg.val = _cfg->val;
return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update);
return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update);
}
int rsnd_kctrl_new_s(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_mod *mod),
@ -1093,11 +1086,10 @@ int rsnd_kctrl_new_s(struct rsnd_mod *mod,
_cfg->cfg.max = max;
_cfg->cfg.size = 1;
_cfg->cfg.val = &_cfg->val;
return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update);
return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update);
}
int rsnd_kctrl_new_e(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
struct rsnd_kctrl_cfg_s *_cfg,
@ -1109,7 +1101,7 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod,
_cfg->cfg.size = 1;
_cfg->cfg.val = &_cfg->val;
_cfg->cfg.texts = texts;
return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update);
return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update);
}
/*
@ -1125,11 +1117,11 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
int ret;
ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd);
ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd);
if (ret)
return ret;
ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd);
ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd);
if (ret)
return ret;
@ -1140,15 +1132,9 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
}
static void rsnd_pcm_free(struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static struct snd_soc_platform_driver rsnd_soc_platform = {
.ops = &rsnd_pcm_ops,
.pcm_new = rsnd_pcm_new,
.pcm_free = rsnd_pcm_free,
};
static const struct snd_soc_component_driver rsnd_soc_component = {
@ -1156,13 +1142,11 @@ static const struct snd_soc_component_driver rsnd_soc_component = {
};
static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
struct rsnd_dai *rdai,
int is_play)
struct rsnd_dai_stream *io)
{
struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture;
int ret;
ret = rsnd_dai_call(probe, io, rdai);
ret = rsnd_dai_call(probe, io, priv);
if (ret == -EAGAIN) {
/*
* Fallback to PIO mode
@ -1175,7 +1159,7 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
* rsnd_dma_init()
* rsnd_ssi_fallback()
*/
rsnd_dai_call(remove, io, rdai);
rsnd_dai_call(remove, io, priv);
/*
* remove SRC/DVC from DAI,
@ -1186,13 +1170,13 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
/*
* fallback
*/
rsnd_dai_call(fallback, io, rdai);
rsnd_dai_call(fallback, io, priv);
/*
* retry to "probe".
* DAI has SSI which is PIO mode only now.
*/
ret = rsnd_dai_call(probe, io, rdai);
ret = rsnd_dai_call(probe, io, priv);
}
return ret;
@ -1259,11 +1243,11 @@ static int rsnd_probe(struct platform_device *pdev)
}
for_each_rsnd_dai(rdai, priv, i) {
ret = rsnd_rdai_continuance_probe(priv, rdai, 1);
ret = rsnd_rdai_continuance_probe(priv, &rdai->playback);
if (ret)
goto exit_snd_probe;
ret = rsnd_rdai_continuance_probe(priv, rdai, 0);
ret = rsnd_rdai_continuance_probe(priv, &rdai->capture);
if (ret)
goto exit_snd_probe;
}
@ -1295,8 +1279,8 @@ exit_snd_soc:
snd_soc_unregister_platform(dev);
exit_snd_probe:
for_each_rsnd_dai(rdai, priv, i) {
rsnd_dai_call(remove, &rdai->playback, rdai);
rsnd_dai_call(remove, &rdai->capture, rdai);
rsnd_dai_call(remove, &rdai->playback, priv);
rsnd_dai_call(remove, &rdai->capture, priv);
}
return ret;
@ -1311,10 +1295,13 @@ static int rsnd_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
for_each_rsnd_dai(rdai, priv, i) {
ret |= rsnd_dai_call(remove, &rdai->playback, rdai);
ret |= rsnd_dai_call(remove, &rdai->capture, rdai);
ret |= rsnd_dai_call(remove, &rdai->playback, priv);
ret |= rsnd_dai_call(remove, &rdai->capture, priv);
}
snd_soc_unregister_component(&pdev->dev);
snd_soc_unregister_platform(&pdev->dev);
return ret;
}

View file

@ -17,7 +17,6 @@
struct rsnd_dvc {
struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
struct clk *clk;
struct rsnd_kctrl_cfg_m volume;
struct rsnd_kctrl_cfg_m mute;
struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */
@ -118,9 +117,8 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
}
static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
dev_dbg(dev, "%s[%d] (Gen2) is probed\n",
@ -129,12 +127,24 @@ static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
return 0;
}
static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
struct rsnd_dai *rdai)
static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
rsnd_kctrl_remove(dvc->volume);
rsnd_kctrl_remove(dvc->mute);
rsnd_kctrl_remove(dvc->ren);
rsnd_kctrl_remove(dvc->rup);
rsnd_kctrl_remove(dvc->rdown);
return 0;
}
static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
struct rsnd_priv *priv)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod);
struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod);
struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
struct device *dev = rsnd_priv_to_dev(priv);
int dvc_id = rsnd_mod_id(dvc_mod);
@ -153,7 +163,7 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
return -EINVAL;
}
clk_prepare_enable(dvc->clk);
rsnd_mod_hw_start(dvc_mod);
/*
* fixme
@ -173,23 +183,21 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
rsnd_mod_write(dvc_mod, DVC_DVUIR, 0);
rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io);
rsnd_adg_set_cmd_timsel_gen2(dvc_mod, io);
return 0;
}
static int rsnd_dvc_quit(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
clk_disable_unprepare(dvc->clk);
rsnd_mod_hw_stop(mod);
return 0;
}
static int rsnd_dvc_start(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
rsnd_mod_write(mod, CMD_CTRL, 0x10);
@ -197,7 +205,7 @@ static int rsnd_dvc_start(struct rsnd_mod *mod,
}
static int rsnd_dvc_stop(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
rsnd_mod_write(mod, CMD_CTRL, 0);
@ -205,16 +213,16 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
}
static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
int is_play = rsnd_io_is_play(io);
int ret;
/* Volume */
ret = rsnd_kctrl_new_m(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
ret = rsnd_kctrl_new_m(mod, rtd,
is_play ?
"DVC Out Playback Volume" : "DVC In Capture Volume",
rsnd_dvc_volume_update,
&dvc->volume, 0x00800000 - 1);
@ -222,8 +230,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
return ret;
/* Mute */
ret = rsnd_kctrl_new_m(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
ret = rsnd_kctrl_new_m(mod, rtd,
is_play ?
"DVC Out Mute Switch" : "DVC In Mute Switch",
rsnd_dvc_volume_update,
&dvc->mute, 1);
@ -231,16 +239,16 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
return ret;
/* Ramp */
ret = rsnd_kctrl_new_s(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
ret = rsnd_kctrl_new_s(mod, rtd,
is_play ?
"DVC Out Ramp Switch" : "DVC In Ramp Switch",
rsnd_dvc_volume_update,
&dvc->ren, 1);
if (ret < 0)
return ret;
ret = rsnd_kctrl_new_e(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
ret = rsnd_kctrl_new_e(mod, rtd,
is_play ?
"DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
&dvc->rup,
rsnd_dvc_volume_update,
@ -248,8 +256,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
if (ret < 0)
return ret;
ret = rsnd_kctrl_new_e(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
ret = rsnd_kctrl_new_e(mod, rtd,
is_play ?
"DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
&dvc->rdown,
rsnd_dvc_volume_update,
@ -264,6 +272,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_dvc_ops = {
.name = DVC_NAME,
.probe = rsnd_dvc_probe_gen2,
.remove = rsnd_dvc_remove_gen2,
.init = rsnd_dvc_init,
.quit = rsnd_dvc_quit,
.start = rsnd_dvc_start,
@ -356,9 +365,9 @@ int rsnd_dvc_probe(struct platform_device *pdev,
return PTR_ERR(clk);
dvc->info = &info->dvc_info[i];
dvc->clk = clk;
rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i);
rsnd_mod_init(&dvc->mod, &rsnd_dvc_ops,
clk, RSND_MOD_DVC, i);
dev_dbg(dev, "CMD%d probed\n", i);
}

View file

@ -309,8 +309,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20),
RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1c4),
RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
@ -403,6 +408,16 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40),
/*
* ADD US
*
* SRC_STATUS
* SRC_INT_EN
* SCU_SYS_STATUS0
* SCU_SYS_STATUS1
* SCU_SYS_INT_EN0
* SCU_SYS_INT_EN1
*/
};
struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00),

View file

@ -44,6 +44,8 @@ enum rsnd_reg {
RSND_REG_SRC_IFSCR,
RSND_REG_SRC_IFSVR,
RSND_REG_SRC_SRCCR,
RSND_REG_SCU_SYS_STATUS0,
RSND_REG_SCU_SYS_INT_EN0,
RSND_REG_CMD_ROUTE_SLCT,
RSND_REG_DVC_SWRSR,
RSND_REG_DVC_DVUIR,
@ -94,6 +96,9 @@ enum rsnd_reg {
RSND_REG_SHARE23,
RSND_REG_SHARE24,
RSND_REG_SHARE25,
RSND_REG_SHARE26,
RSND_REG_SHARE27,
RSND_REG_SHARE28,
RSND_REG_MAX,
};
@ -135,6 +140,9 @@ enum rsnd_reg {
#define RSND_REG_DVC_VRCTR RSND_REG_SHARE23
#define RSND_REG_DVC_VRPDR RSND_REG_SHARE24
#define RSND_REG_DVC_VRDBR RSND_REG_SHARE25
#define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26
#define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27
#define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28
struct rsnd_of_data;
struct rsnd_priv;
@ -182,9 +190,9 @@ void rsnd_dma_quit(struct rsnd_priv *priv,
* R-Car sound mod
*/
enum rsnd_mod_type {
RSND_MOD_SRC = 0,
RSND_MOD_DVC = 0,
RSND_MOD_SRC,
RSND_MOD_SSI,
RSND_MOD_DVC,
RSND_MOD_MAX,
};
@ -192,32 +200,31 @@ struct rsnd_mod_ops {
char *name;
char* (*dma_name)(struct rsnd_mod *mod);
int (*probe)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
int (*remove)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
int (*init)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
int (*quit)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
int (*start)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
int (*stop)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
int (*pcm_new)(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd);
int (*fallback)(struct rsnd_mod *mod,
struct rsnd_dai *rdai);
struct rsnd_priv *priv);
};
struct rsnd_dai_stream;
struct rsnd_mod {
int id;
enum rsnd_mod_type type;
struct rsnd_priv *priv;
struct rsnd_mod_ops *ops;
struct rsnd_dma dma;
struct rsnd_dai_stream *io;
struct clk *clk;
u32 status;
};
/*
@ -248,15 +255,17 @@ struct rsnd_mod {
#define __rsnd_mod_call_pcm_new 0
#define __rsnd_mod_call_fallback 0
#define rsnd_mod_to_priv(mod) ((mod)->priv)
#define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod)))
#define rsnd_mod_to_dma(mod) (&(mod)->dma)
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
#define rsnd_mod_to_io(mod) ((mod)->io)
#define rsnd_mod_id(mod) ((mod)->id)
#define rsnd_mod_hw_start(mod) clk_prepare_enable((mod)->clk)
#define rsnd_mod_hw_stop(mod) clk_disable_unprepare((mod)->clk)
void rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
void rsnd_mod_init(struct rsnd_mod *mod,
struct rsnd_mod_ops *ops,
struct clk *clk,
enum rsnd_mod_type type,
int id);
char *rsnd_mod_name(struct rsnd_mod *mod);
@ -270,6 +279,7 @@ struct rsnd_dai_stream {
struct snd_pcm_substream *substream;
struct rsnd_mod *mod[RSND_MOD_MAX];
struct rsnd_dai_path_info *info; /* rcar_snd.h */
struct rsnd_dai *rdai;
int byte_pos;
int period_pos;
int byte_per_period;
@ -278,12 +288,18 @@ struct rsnd_dai_stream {
#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI])
#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC])
#define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC])
#define rsnd_io_to_rdai(io) ((io)->rdai)
#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
#define rsnd_io_to_runtime(io) ((io)->substream ? \
(io)->substream->runtime : NULL)
struct rsnd_dai {
char name[RSND_DAI_NAME_SIZE];
struct rsnd_dai_platform_info *info; /* rcar_snd.h */
struct rsnd_dai_stream playback;
struct rsnd_dai_stream capture;
struct rsnd_priv *priv;
unsigned int clk_master:1;
unsigned int bit_clk_inv:1;
@ -293,22 +309,18 @@ struct rsnd_dai {
};
#define rsnd_rdai_nr(priv) ((priv)->rdai_nr)
#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
#define rsnd_rdai_to_priv(rdai) ((rdai)->priv)
#define for_each_rsnd_dai(rdai, priv, i) \
for (i = 0; \
(i < rsnd_rdai_nr(priv)) && \
((rdai) = rsnd_dai_get(priv, i)); \
((rdai) = rsnd_rdai_get(priv, i)); \
i++)
struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id);
int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai);
#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
#define rsnd_io_to_runtime(io) ((io)->substream ? \
(io)->substream->runtime : NULL)
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
#define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master)
/*
* R-Car Gen1/Gen2
@ -339,15 +351,12 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
unsigned int src_rate,
unsigned int dst_rate);
int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io,
unsigned int src_rate,
unsigned int dst_rate);
int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io);
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai,
struct rsnd_mod *mod,
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io);
/*
@ -427,6 +436,8 @@ struct rsnd_kctrl_cfg {
u32 *val;
const char * const *texts;
void (*update)(struct rsnd_mod *mod);
struct snd_card *card;
struct snd_kcontrol *kctrl;
};
#define RSND_DVC_CHANNELS 2
@ -440,22 +451,22 @@ struct rsnd_kctrl_cfg_s {
u32 val;
};
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg);
#define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg))
int rsnd_kctrl_new_m(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_m *_cfg,
u32 max);
int rsnd_kctrl_new_s(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_s *_cfg,
u32 max);
int rsnd_kctrl_new_e(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
struct rsnd_kctrl_cfg_s *_cfg,
@ -474,14 +485,10 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
struct rsnd_dai_stream *io,
struct snd_pcm_runtime *runtime);
int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai,
int use_busif);
int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai);
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai);
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai);
int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod);
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod);
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
#define rsnd_src_nr(priv) ((priv)->src_nr)

View file

@ -12,10 +12,17 @@
#define SRC_NAME "src"
/* SRCx_STATUS */
#define OUF_SRCO ((1 << 12) | (1 << 13))
#define OUF_SRCI ((1 << 9) | (1 << 8))
/* SCU_SYSTEM_STATUS0/1 */
#define OUF_SRC(id) ((1 << (id + 16)) | (1 << id))
struct rsnd_src {
struct rsnd_src_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
struct clk *clk;
int err;
};
#define RSND_SRC_NAME_SIZE 16
@ -107,10 +114,10 @@ struct rsnd_src {
* Gen1/Gen2 common functions
*/
int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai,
int use_busif)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
int ssi_id = rsnd_mod_id(ssi_mod);
@ -140,7 +147,7 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
if (shift >= 0)
rsnd_mod_bset(ssi_mod, SSI_MODE1,
0x3 << shift,
rsnd_dai_is_clk_master(rdai) ?
rsnd_rdai_is_clk_master(rdai) ?
0x2 << shift : 0x1 << shift);
}
@ -174,8 +181,7 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
return 0;
}
int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai)
int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod)
{
/*
* DMA settings for SSIU
@ -185,8 +191,7 @@ int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
return 0;
}
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai)
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
@ -202,8 +207,7 @@ int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod,
return 0;
}
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod,
struct rsnd_dai *rdai)
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
@ -240,8 +244,7 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
return rate;
}
static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
static int rsnd_src_set_convert_rate(struct rsnd_mod *mod)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
@ -273,12 +276,13 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
return 0;
}
static int rsnd_src_init(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
static int rsnd_src_init(struct rsnd_mod *mod)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
clk_prepare_enable(src->clk);
rsnd_mod_hw_start(mod);
src->err = 0;
/*
* Initialize the operation of the SRC internal circuits
@ -290,11 +294,16 @@ static int rsnd_src_init(struct rsnd_mod *mod,
}
static int rsnd_src_quit(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
struct device *dev = rsnd_priv_to_dev(priv);
clk_disable_unprepare(src->clk);
rsnd_mod_hw_stop(mod);
if (src->err)
dev_warn(dev, "%s[%d] under/over flow err = %d\n",
rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);
return 0;
}
@ -319,8 +328,7 @@ static int rsnd_src_stop(struct rsnd_mod *mod)
/*
* Gen1 functions
*/
static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
static int rsnd_src_set_route_gen1(struct rsnd_mod *mod)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct src_route_config {
@ -348,7 +356,7 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
/*
* SRC_ROUTE_SELECT
*/
val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2;
val = rsnd_io_is_play(io) ? 0x1 : 0x2;
val = val << routes[id].shift;
mask = routes[id].mask << routes[id].shift;
@ -357,8 +365,7 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
return 0;
}
static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
@ -416,13 +423,12 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod,
return 0;
}
static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
int ret;
ret = rsnd_src_set_convert_rate(mod, rdai);
ret = rsnd_src_set_convert_rate(mod);
if (ret < 0)
return ret;
@ -443,9 +449,8 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod,
}
static int rsnd_src_probe_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
dev_dbg(dev, "%s[%d] (Gen1) is probed\n",
@ -455,23 +460,23 @@ static int rsnd_src_probe_gen1(struct rsnd_mod *mod,
}
static int rsnd_src_init_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
int ret;
ret = rsnd_src_init(mod, rdai);
ret = rsnd_src_init(mod);
if (ret < 0)
return ret;
ret = rsnd_src_set_route_gen1(mod, rdai);
ret = rsnd_src_set_route_gen1(mod);
if (ret < 0)
return ret;
ret = rsnd_src_set_convert_rate_gen1(mod, rdai);
ret = rsnd_src_set_convert_rate_gen1(mod);
if (ret < 0)
return ret;
ret = rsnd_src_set_convert_timing_gen1(mod, rdai);
ret = rsnd_src_set_convert_timing_gen1(mod);
if (ret < 0)
return ret;
@ -479,7 +484,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod,
}
static int rsnd_src_start_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
int id = rsnd_mod_id(mod);
@ -489,7 +494,7 @@ static int rsnd_src_start_gen1(struct rsnd_mod *mod,
}
static int rsnd_src_stop_gen1(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
int id = rsnd_mod_id(mod);
@ -510,8 +515,111 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
/*
* Gen2 functions
*/
static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
#define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1)
#define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0)
static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 sys_int_val, int_val, sys_int_mask;
int irq = src->info->irq;
int id = rsnd_mod_id(mod);
sys_int_val =
sys_int_mask = OUF_SRC(id);
int_val = 0x3300;
/*
* IRQ is not supported on non-DT
* see
* rsnd_src_probe_gen2()
*/
if ((irq <= 0) || !enable) {
sys_int_val = 0;
int_val = 0;
}
rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
}
static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod)
{
u32 val = OUF_SRC(rsnd_mod_id(mod));
rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val);
rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val);
}
static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
{
u32 val = OUF_SRC(rsnd_mod_id(mod));
bool ret = false;
if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val) ||
(rsnd_mod_read(mod, SCU_SYS_STATUS1) & val)) {
struct rsnd_src *src = rsnd_mod_to_src(mod);
src->err++;
ret = true;
}
/* clear error static */
rsnd_src_error_clear_gen2(mod);
return ret;
}
static int _rsnd_src_start_gen2(struct rsnd_mod *mod)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11;
rsnd_mod_write(mod, SRC_CTRL, val);
rsnd_src_error_clear_gen2(mod);
rsnd_src_start(mod);
rsnd_src_irq_enable_gen2(mod);
return 0;
}
static int _rsnd_src_stop_gen2(struct rsnd_mod *mod)
{
rsnd_src_irq_disable_gen2(mod);
rsnd_mod_write(mod, SRC_CTRL, 0);
rsnd_src_error_record_gen2(mod);
return rsnd_src_stop(mod);
}
static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
{
struct rsnd_mod *mod = data;
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
if (!io)
return IRQ_NONE;
if (rsnd_src_error_record_gen2(mod)) {
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
_rsnd_src_stop_gen2(mod);
_rsnd_src_start_gen2(mod);
dev_dbg(dev, "%s[%d] restart\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
return IRQ_HANDLED;
}
static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
@ -535,7 +643,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
return -EINVAL;
}
ret = rsnd_src_set_convert_rate(mod, rdai);
ret = rsnd_src_set_convert_rate(mod);
if (ret < 0)
return ret;
@ -563,8 +671,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
return 0;
}
static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
@ -573,59 +680,78 @@ static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod,
int ret;
if (convert_rate)
ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io,
ret = rsnd_adg_set_convert_clk_gen2(mod, io,
runtime->rate,
convert_rate);
else
ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io);
ret = rsnd_adg_set_convert_timing_gen2(mod, io);
return ret;
}
static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_src *src = rsnd_mod_to_src(mod);
struct device *dev = rsnd_priv_to_dev(priv);
int irq = src->info->irq;
int ret;
if (irq > 0) {
/*
* IRQ is not supported on non-DT
* see
* rsnd_src_irq_enable_gen2()
*/
ret = devm_request_irq(dev, irq,
rsnd_src_interrupt_gen2,
IRQF_SHARED,
dev_name(dev), mod);
if (ret)
goto rsnd_src_probe_gen2_fail;
}
ret = rsnd_dma_init(priv,
rsnd_mod_to_dma(mod),
rsnd_info_is_playback(priv, src),
src->info->dma_id);
if (ret < 0)
dev_err(dev, "%s[%d] (Gen2) failed\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
else
dev_dbg(dev, "%s[%d] (Gen2) is probed\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
if (ret)
goto rsnd_src_probe_gen2_fail;
dev_dbg(dev, "%s[%d] (Gen2) is probed\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
return ret;
rsnd_src_probe_gen2_fail:
dev_err(dev, "%s[%d] (Gen2) failed\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
return ret;
}
static int rsnd_src_remove_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
rsnd_dma_quit(priv, rsnd_mod_to_dma(mod));
return 0;
}
static int rsnd_src_init_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
int ret;
ret = rsnd_src_init(mod, rdai);
ret = rsnd_src_init(mod);
if (ret < 0)
return ret;
ret = rsnd_src_set_convert_rate_gen2(mod, rdai);
ret = rsnd_src_set_convert_rate_gen2(mod);
if (ret < 0)
return ret;
ret = rsnd_src_set_convert_timing_gen2(mod, rdai);
ret = rsnd_src_set_convert_timing_gen2(mod);
if (ret < 0)
return ret;
@ -633,29 +759,23 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod,
}
static int rsnd_src_start_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11;
rsnd_dma_start(rsnd_mod_to_dma(mod));
rsnd_dma_start(rsnd_mod_to_dma(&src->mod));
rsnd_mod_write(mod, SRC_CTRL, val);
return rsnd_src_start(mod);
return _rsnd_src_start_gen2(mod);
}
static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
int ret;
rsnd_mod_write(mod, SRC_CTRL, 0);
ret = _rsnd_src_stop_gen2(mod);
rsnd_dma_stop(rsnd_mod_to_dma(&src->mod));
rsnd_dma_stop(rsnd_mod_to_dma(mod));
return rsnd_src_stop(mod);
return ret;
}
static struct rsnd_mod_ops rsnd_src_gen2_ops = {
@ -681,10 +801,11 @@ static void rsnd_of_parse_src(struct platform_device *pdev,
struct rsnd_priv *priv)
{
struct device_node *src_node;
struct device_node *np;
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct rsnd_src_platform_info *src_info;
struct device *dev = &pdev->dev;
int nr;
int nr, i;
if (!of_data)
return;
@ -708,6 +829,13 @@ static void rsnd_of_parse_src(struct platform_device *pdev,
info->src_info = src_info;
info->src_info_nr = nr;
i = 0;
for_each_child_of_node(src_node, np) {
src_info[i].irq = irq_of_parse_and_map(np, 0);
i++;
}
rsnd_of_parse_src_end:
of_node_put(src_node);
}
@ -761,9 +889,8 @@ int rsnd_src_probe(struct platform_device *pdev,
return PTR_ERR(clk);
src->info = &info->src_info[i];
src->clk = clk;
rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i);
rsnd_mod_init(&src->mod, ops, clk, RSND_MOD_SRC, i);
dev_dbg(dev, "SRC%d probed\n", i);
}

View file

@ -60,17 +60,14 @@
#define SSI_NAME "ssi"
struct rsnd_ssi {
struct clk *clk;
struct rsnd_ssi_platform_info *info; /* rcar_snd.h */
struct rsnd_ssi *parent;
struct rsnd_mod mod;
struct rsnd_dai *rdai;
u32 cr_own;
u32 cr_clk;
int err;
unsigned int usrcnt;
unsigned int rate;
};
#define for_each_rsnd_ssi(pos, priv, i) \
@ -128,7 +125,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv);
int i, j, ret;
@ -157,7 +154,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate);
if (0 == ret) {
ssi->rate = rate;
ssi->cr_clk = FORCE | SWL_32 |
SCKD | SWSD | CKDV(j);
@ -176,26 +172,25 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi)
{
ssi->rate = 0;
ssi->cr_clk = 0;
rsnd_adg_ssi_clk_stop(&ssi->mod);
}
static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct device *dev = rsnd_priv_to_dev(priv);
u32 cr_mode;
u32 cr;
if (0 == ssi->usrcnt) {
clk_prepare_enable(ssi->clk);
rsnd_mod_hw_start(&ssi->mod);
if (rsnd_dai_is_clk_master(rdai)) {
if (rsnd_rdai_is_clk_master(rdai)) {
if (rsnd_ssi_clk_from_parent(ssi))
rsnd_ssi_hw_start(ssi->parent, rdai, io);
rsnd_ssi_hw_start(ssi->parent, io);
else
rsnd_ssi_master_clk_start(ssi, io);
}
@ -214,7 +209,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
rsnd_mod_write(&ssi->mod, SSICR, cr);
/* enable WS continue */
if (rsnd_dai_is_clk_master(rdai))
if (rsnd_rdai_is_clk_master(rdai))
rsnd_mod_write(&ssi->mod, SSIWSR, CONT);
/* clear error status */
@ -226,10 +221,11 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod));
}
static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
struct rsnd_dai *rdai)
static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
struct rsnd_dai_stream *io = rsnd_mod_to_io(&ssi->mod);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct device *dev = rsnd_priv_to_dev(priv);
u32 cr;
@ -256,14 +252,14 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */
rsnd_ssi_status_check(&ssi->mod, IIRQ);
if (rsnd_dai_is_clk_master(rdai)) {
if (rsnd_rdai_is_clk_master(rdai)) {
if (rsnd_ssi_clk_from_parent(ssi))
rsnd_ssi_hw_stop(ssi->parent, rdai);
rsnd_ssi_hw_stop(ssi->parent);
else
rsnd_ssi_master_clk_stop(ssi);
}
clk_disable_unprepare(ssi->clk);
rsnd_mod_hw_stop(&ssi->mod);
}
dev_dbg(dev, "%s[%d] hw stopped\n",
@ -274,10 +270,11 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
* SSI mod common functions
*/
static int rsnd_ssi_init(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
u32 cr;
@ -311,13 +308,12 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
cr |= SDTA;
if (rdai->sys_delay)
cr |= DEL;
if (rsnd_dai_is_play(rdai, io))
if (rsnd_io_is_play(io))
cr |= TRMD;
/*
* set ssi parameter
*/
ssi->rdai = rdai;
ssi->cr_own = cr;
ssi->err = -1; /* ignore 1st error */
@ -325,16 +321,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
}
static int rsnd_ssi_quit(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
if (ssi->err > 0)
dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err);
dev_warn(dev, "%s[%d] under/over flow err = %d\n",
rsnd_mod_name(mod), rsnd_mod_id(mod), ssi->err);
ssi->rdai = NULL;
ssi->cr_own = 0;
ssi->err = 0;
@ -353,32 +348,32 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
}
static int rsnd_ssi_start(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod));
rsnd_src_ssiu_start(mod, rsnd_ssi_use_busif(mod));
rsnd_ssi_hw_start(ssi, rdai, io);
rsnd_ssi_hw_start(ssi, io);
rsnd_src_ssi_irq_enable(mod, rdai);
rsnd_src_ssi_irq_enable(mod);
return 0;
}
static int rsnd_ssi_stop(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
rsnd_src_ssi_irq_disable(mod, rdai);
rsnd_src_ssi_irq_disable(mod);
rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR));
rsnd_ssi_hw_stop(ssi, rdai);
rsnd_ssi_hw_stop(ssi);
rsnd_src_ssiu_stop(mod, rdai);
rsnd_src_ssiu_stop(mod);
return 0;
}
@ -386,16 +381,17 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
{
struct rsnd_ssi *ssi = data;
struct rsnd_dai *rdai = ssi->rdai;
struct rsnd_mod *mod = &ssi->mod;
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
int is_dma = rsnd_ssi_is_dma_mode(mod);
u32 status = rsnd_mod_read(mod, SSISR);
if (!io)
return IRQ_NONE;
/* PIO only */
if (status & DIRQ) {
if (!is_dma && (status & DIRQ)) {
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
u32 *buf = (u32 *)(runtime->dma_area +
rsnd_dai_pointer_offset(io, 0));
@ -405,7 +401,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
* directly as 32bit data
* see rsnd_ssi_init()
*/
if (rsnd_dai_is_play(rdai, io))
if (rsnd_io_is_play(io))
rsnd_mod_write(mod, SSITDR, *buf);
else
*buf = rsnd_mod_read(mod, SSIRDR);
@ -415,14 +411,13 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
/* PIO / DMA */
if (status & (UIRQ | OIRQ)) {
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
/*
* restart SSI
*/
rsnd_ssi_stop(mod, rdai);
rsnd_ssi_start(mod, rdai);
rsnd_ssi_stop(mod, priv);
rsnd_ssi_start(mod, priv);
dev_dbg(dev, "%s[%d] restart\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
@ -437,9 +432,8 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
* SSI PIO
*/
static int rsnd_ssi_pio_probe(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
int ret;
@ -468,9 +462,8 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
};
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
int dma_id = ssi->info->dma_id;
@ -503,14 +496,13 @@ rsnd_ssi_dma_probe_fail:
}
static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
int irq = ssi->info->irq;
rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
rsnd_dma_quit(priv, rsnd_mod_to_dma(mod));
/* PIO will request IRQ again */
devm_free_irq(dev, irq, ssi);
@ -519,9 +511,8 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
}
static int rsnd_ssi_fallback(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
/*
@ -540,25 +531,25 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod,
}
static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
rsnd_ssi_start(mod, rdai);
rsnd_dma_start(dma);
rsnd_ssi_start(mod, priv);
return 0;
}
static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
struct rsnd_dai *rdai)
struct rsnd_priv *priv)
{
struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
rsnd_dma_stop(dma);
rsnd_ssi_stop(mod, priv);
rsnd_ssi_stop(mod, rdai);
rsnd_dma_stop(dma);
return 0;
}
@ -734,7 +725,6 @@ int rsnd_ssi_probe(struct platform_device *pdev,
return PTR_ERR(clk);
ssi->info = pinfo;
ssi->clk = clk;
ops = &rsnd_ssi_non_ops;
if (pinfo->dma_id > 0)
@ -742,7 +732,7 @@ int rsnd_ssi_probe(struct platform_device *pdev,
else if (rsnd_ssi_pio_available(ssi))
ops = &rsnd_ssi_pio_ops;
rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i);
rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i);
rsnd_ssi_parent_clk_setup(priv, ssi);
}