Commit 94e26c07 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next

parents 460f623a a5702e1c
......@@ -199,10 +199,10 @@ Ex)
sound {
compatible = "simple-scu-audio-card";
...
simple-audio-card,cpu@0 {
simple-audio-card,cpu-0 {
sound-dai = <&rcar_sound 0>;
};
simple-audio-card,cpu@1 {
simple-audio-card,cpu-1 {
sound-dai = <&rcar_sound 1>;
};
simple-audio-card,codec {
......@@ -441,79 +441,79 @@ rcar_sound: sound@ec500000 {
"clk_a", "clk_b", "clk_c", "clk_i";
rcar_sound,dvc {
dvc0: dvc@0 {
dvc0: dvc-0 {
dmas = <&audma0 0xbc>;
dma-names = "tx";
};
dvc1: dvc@1 {
dvc1: dvc-1 {
dmas = <&audma0 0xbe>;
dma-names = "tx";
};
};
rcar_sound,mix {
mix0: mix@0 { };
mix1: mix@1 { };
mix0: mix-0 { };
mix1: mix-1 { };
};
rcar_sound,ctu {
ctu00: ctu@0 { };
ctu01: ctu@1 { };
ctu02: ctu@2 { };
ctu03: ctu@3 { };
ctu10: ctu@4 { };
ctu11: ctu@5 { };
ctu12: ctu@6 { };
ctu13: ctu@7 { };
ctu00: ctu-0 { };
ctu01: ctu-1 { };
ctu02: ctu-2 { };
ctu03: ctu-3 { };
ctu10: ctu-4 { };
ctu11: ctu-5 { };
ctu12: ctu-6 { };
ctu13: ctu-7 { };
};
rcar_sound,src {
src0: src@0 {
src0: src-0 {
interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x85>, <&audma1 0x9a>;
dma-names = "rx", "tx";
};
src1: src@1 {
src1: src-1 {
interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x87>, <&audma1 0x9c>;
dma-names = "rx", "tx";
};
src2: src@2 {
src2: src-2 {
interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x89>, <&audma1 0x9e>;
dma-names = "rx", "tx";
};
src3: src@3 {
src3: src-3 {
interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x8b>, <&audma1 0xa0>;
dma-names = "rx", "tx";
};
src4: src@4 {
src4: src-4 {
interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x8d>, <&audma1 0xb0>;
dma-names = "rx", "tx";
};
src5: src@5 {
src5: src-5 {
interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x8f>, <&audma1 0xb2>;
dma-names = "rx", "tx";
};
src6: src@6 {
src6: src-6 {
interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x91>, <&audma1 0xb4>;
dma-names = "rx", "tx";
};
src7: src@7 {
src7: src-7 {
interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x93>, <&audma1 0xb6>;
dma-names = "rx", "tx";
};
src8: src@8 {
src8: src-8 {
interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x95>, <&audma1 0xb8>;
dma-names = "rx", "tx";
};
src9: src@9 {
src9: src-9 {
interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x97>, <&audma1 0xba>;
dma-names = "rx", "tx";
......@@ -521,52 +521,52 @@ rcar_sound: sound@ec500000 {
};
rcar_sound,ssi {
ssi0: ssi@0 {
ssi0: ssi-0 {
interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi1: ssi@1 {
ssi1: ssi-1 {
interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi2: ssi@2 {
ssi2: ssi-2 {
interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi3: ssi@3 {
ssi3: ssi-3 {
interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi4: ssi@4 {
ssi4: ssi-4 {
interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi5: ssi@5 {
ssi5: ssi-5 {
interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi6: ssi@6 {
ssi6: ssi-6 {
interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi7: ssi@7 {
ssi7: ssi-7 {
interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi8: ssi@8 {
ssi8: ssi-8 {
interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>;
dma-names = "rx", "tx", "rxu", "txu";
};
ssi9: ssi@9 {
ssi9: ssi-9 {
interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>;
dma-names = "rx", "tx", "rxu", "txu";
......
......@@ -89,7 +89,7 @@ struct camelot_pcm {
#define DMABRG_PREALLOC_BUFFER 32 * 1024
#define DMABRG_PREALLOC_BUFFER_MAX 32 * 1024
static struct snd_pcm_hardware camelot_pcm_hardware = {
static const struct snd_pcm_hardware camelot_pcm_hardware = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
......@@ -294,7 +294,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)
return bytes_to_frames(runtime, pos);
}
static struct snd_pcm_ops camelot_pcm_ops = {
static const struct snd_pcm_ops camelot_pcm_ops = {
.open = camelot_pcm_open,
.close = camelot_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
......@@ -320,7 +320,7 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static struct snd_soc_platform_driver sh7760_soc_platform = {
static const struct snd_soc_platform_driver sh7760_soc_platform = {
.ops = &camelot_pcm_ops,
.pcm_new = camelot_pcm_new,
};
......
......@@ -1710,7 +1710,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = {
* pcm ops
*/
static struct snd_pcm_hardware fsi_pcm_hardware = {
static const struct snd_pcm_hardware fsi_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID,
......@@ -1755,7 +1755,7 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
return fsi_sample2frame(fsi, io->buff_sample_pos);
}
static struct snd_pcm_ops fsi_pcm_ops = {
static const struct snd_pcm_ops fsi_pcm_ops = {
.open = fsi_pcm_open,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = fsi_hw_params,
......@@ -1818,7 +1818,7 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
},
};
static struct snd_soc_platform_driver fsi_soc_platform = {
static const struct snd_soc_platform_driver fsi_soc_platform = {
.ops = &fsi_pcm_ops,
.pcm_new = fsi_pcm_new,
};
......
......@@ -98,7 +98,7 @@ static int migor_hw_free(struct snd_pcm_substream *substream)
return 0;
}
static struct snd_soc_ops migor_dai_ops = {
static const struct snd_soc_ops migor_dai_ops = {
.hw_params = migor_hw_params,
.hw_free = migor_hw_free,
};
......
......@@ -586,10 +586,8 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
int ret;
adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
if (!adg) {
dev_err(dev, "ADG allocate failed\n");
if (!adg)
return -ENOMEM;
}
ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
NULL, NULL, 0, 0);
......
......@@ -843,12 +843,28 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
ir, &ic);
}
static void rsnd_soc_hw_constraint(struct snd_pcm_runtime *runtime,
struct snd_soc_dai *dai)
static const struct snd_pcm_hardware rsnd_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID,
.buffer_bytes_max = 64 * 1024,
.period_bytes_min = 32,
.period_bytes_max = 8192,
.periods_min = 1,
.periods_max = 32,
.fifo_size = 256,
};
static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint;
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int max_channels = rsnd_rdai_channels_get(rdai);
int ret;
int i;
/*
......@@ -865,34 +881,26 @@ static void rsnd_soc_hw_constraint(struct snd_pcm_runtime *runtime,
constraint->count = i + 1;
}
snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS, constraint);
snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
/*
* Sampling Rate / Channel Limitation
* It depends on Clock Master Mode
*/
if (!rsnd_rdai_is_clk_master(rdai))
return;
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
rsnd_soc_hw_rule_rate, dai,
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
rsnd_soc_hw_rule_channels, dai,
SNDRV_PCM_HW_PARAM_RATE, -1);
}
static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
int ret;
/* rsnd_io_to_runtime() is not yet enabled here */
rsnd_soc_hw_constraint(substream->runtime, dai);
if (rsnd_rdai_is_clk_master(rdai)) {
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
rsnd_soc_hw_rule_rate, dai,
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
rsnd_soc_hw_rule_channels, dai,
SNDRV_PCM_HW_PARAM_RATE, -1);
}
/*
* call rsnd_dai_call without spinlock
......@@ -1104,31 +1112,6 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
/*
* pcm ops
*/
static struct snd_pcm_hardware rsnd_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID,
.buffer_bytes_max = 64 * 1024,
.period_bytes_min = 32,
.period_bytes_max = 8192,
.periods_min = 1,
.periods_max = 32,
.fifo_size = 256,
};
static int rsnd_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret = 0;
snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
return ret;
}
static int rsnd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
......@@ -1157,8 +1140,7 @@ static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream)
return pointer;
}
static struct snd_pcm_ops rsnd_pcm_ops = {
.open = rsnd_pcm_open,
static const struct snd_pcm_ops rsnd_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.hw_params = rsnd_hw_params,
.hw_free = snd_pcm_lib_free_pages,
......@@ -1168,11 +1150,10 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
/*
* snd_kcontrol
*/
#define kcontrol_to_cfg(kctrl) ((struct rsnd_kctrl_cfg *)kctrl->private_value)
static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_info *uinfo)
{
struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl);
struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
if (cfg->texts) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
......@@ -1198,7 +1179,7 @@ static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
static int rsnd_kctrl_get(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *uc)
{
struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl);
struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
int i;
for (i = 0; i < cfg->size; i++)
......@@ -1213,8 +1194,7 @@ static int rsnd_kctrl_get(struct snd_kcontrol *kctrl,
static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *uc)
{
struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl);
struct rsnd_kctrl_cfg *cfg = snd_kcontrol_chip(kctrl);
int i, change = 0;
if (!cfg->accept(cfg->io))
......@@ -1231,7 +1211,7 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
}
if (change && cfg->update)
cfg->update(cfg->io, mod);
cfg->update(cfg->io, cfg->mod);
return change;
}
......@@ -1283,14 +1263,13 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
.index = rtd->num,
.get = rsnd_kctrl_get,
.put = rsnd_kctrl_put,
.private_value = (unsigned long)cfg,
};
int ret;
if (size > RSND_MAX_CHANNELS)
return -EINVAL;
kctrl = snd_ctl_new1(&knew, mod);
kctrl = snd_ctl_new1(&knew, cfg);
if (!kctrl)
return -ENOMEM;
......@@ -1306,6 +1285,7 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
cfg->card = card;
cfg->kctrl = kctrl;
cfg->io = io;
cfg->mod = mod;
return 0;
}
......@@ -1338,7 +1318,7 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
}
static struct snd_soc_platform_driver rsnd_soc_platform = {
static const struct snd_soc_platform_driver rsnd_soc_platform = {
.ops = &rsnd_pcm_ops,
.pcm_new = rsnd_pcm_new,
};
......@@ -1421,10 +1401,8 @@ static int rsnd_probe(struct platform_device *pdev)
* init priv data
*/
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(dev, "priv allocate failed\n");
if (!priv)
return -ENODEV;
}
priv->pdev = pdev;
priv->flags = (unsigned long)of_device_get_match_data(dev);
......
......@@ -394,13 +394,16 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(np);
goto rsnd_ctu_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
clk, rsnd_mod_get_status, RSND_MOD_CTU, i);
if (ret)
if (ret) {
of_node_put(np);
goto rsnd_ctu_probe_done;
}
i++;
}
......
......@@ -604,8 +604,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
dma_addr_t in_addr;
} dma_addrs[3][2][3] = {
/* SRC */
/* Capture */
{{{ 0, 0 },
/* Capture */
{ RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
{ RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } },
/* Playback */
......
......@@ -380,13 +380,16 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(np);
goto rsnd_dvc_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
clk, rsnd_mod_get_status, RSND_MOD_DVC, i);
if (ret)
if (ret) {
of_node_put(np);
goto rsnd_dvc_probe_done;
}
i++;
}
......
......@@ -406,10 +406,8 @@ int rsnd_gen_probe(struct rsnd_priv *priv)
int ret;
gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
if (!gen) {
dev_err(dev, "GEN allocate failed\n");
if (!gen)
return -ENOMEM;
}
priv->gen = gen;
......
......@@ -168,13 +168,16 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(np);
goto rsnd_mix_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
clk, rsnd_mod_get_status, RSND_MOD_MIX, i);
if (ret)
if (ret) {
of_node_put(np);
goto rsnd_mix_probe_done;
}
i++;
}
......
......@@ -614,6 +614,7 @@ struct rsnd_kctrl_cfg {
struct rsnd_dai_stream *io;
struct snd_card *card;
struct snd_kcontrol *kctrl;
struct rsnd_mod *mod;
};
#define RSND_MAX_CHANNELS 8
......
......@@ -27,7 +27,6 @@ struct rsnd_src {
#define RSND_SRC_NAME_SIZE 16
#define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
#define rsnd_src_to_dma(src) ((src)->dma)
#define rsnd_src_nr(priv) ((priv)->src_nr)
#define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val)
......@@ -108,7 +107,6 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
int is_play = rsnd_io_is_play(io);
/*
*
* Playback
* runtime_rate -> [SRC] -> convert_rate
*
......@@ -203,13 +201,13 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
/*
* SRC_ADINR
* SRC_ADINR
*/
adinr = rsnd_get_adinr_bit(mod, io) |
rsnd_runtime_channel_original(io);
/*
* SRC_IFSCR / SRC_IFSVR
* SRC_IFSCR / SRC_IFSVR
*/
ifscr = 0;
fsrate = 0;
......@@ -223,7 +221,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
}
/*
* SRC_SRCCR / SRC_ROUTE_MODE0
* SRC_SRCCR / SRC_ROUTE_MODE0
*/
cr = 0x00011110;
route = 0x0;
......@@ -581,20 +579,24 @@ int rsnd_src_probe(struct rsnd_priv *priv)
src->irq = irq_of_parse_and_map(np, 0);
if (!src->irq) {
ret = -EINVAL;
of_node_put(np);
goto rsnd_src_probe_done;
}
clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(np);
goto rsnd_src_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(src),
&rsnd_src_ops, clk, rsnd_mod_get_status,
RSND_MOD_SRC, i);
if (ret)
if (ret) {
of_node_put(np);
goto rsnd_src_probe_done;
}
skip:
i++;
......
......@@ -90,6 +90,7 @@ struct rsnd_ssi {
#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
#define RSND_SSI_HDMI0 (1 << 2) /* for HDMI0 */
#define RSND_SSI_HDMI1 (1 << 3) /* for HDMI1 */
#define RSND_SSI_PROBED (1 << 4)
#define for_each_rsnd_ssi(pos, priv, i) \
for (i = 0; \
......@@ -98,25 +99,27 @@ struct rsnd_ssi {
i++)
#define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
#define rsnd_ssi_to_dma(mod) ((ssi)->dma)
#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
#define rsnd_ssi_mode_flags(p) ((p)->flags)
#define rsnd_ssi_flags_has(p, f) ((p)->flags & f)
#define rsnd_ssi_flags_set(p, f) ((p)->flags |= f)
#define rsnd_ssi_flags_del(p, f) ((p)->flags = ((p)->flags & ~f))
#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
#define rsnd_ssi_is_multi_slave(mod, io) \
(rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod)))
#define rsnd_ssi_is_run_mods(mod, io) \
(rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
#define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod))
int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io)
{
struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
if (rsnd_ssi_mode_flags(ssi) & RSND_SSI_HDMI0)
if (rsnd_ssi_flags_has(ssi, RSND_SSI_HDMI0))
return RSND_SSI_HDMI_PORT0;
if (rsnd_ssi_mode_flags(ssi) & RSND_SSI_HDMI1)
if (rsnd_ssi_flags_has(ssi, RSND_SSI_HDMI1))
return RSND_SSI_HDMI_PORT1;
return 0;
......@@ -131,7 +134,7 @@ int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
if (!rsnd_ssi_is_dma_mode(mod))
return 0;
if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF))
if (!(rsnd_ssi_flags_has(ssi, RSND_SSI_NO_BUSIF)))
use_busif = 1;
if (rsnd_io_to_mod_src(io))
use_busif = 1;
......@@ -256,7 +259,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
int chan = rsnd_runtime_channel_for_ssi(io);
int idx, ret;
unsigned int main_rate;
......@@ -267,7 +269,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
if (!rsnd_rdai_is_clk_master(rdai))
return 0;
if (ssi_parent_mod && !rsnd_ssi_is_parent(mod, io))
if (!rsnd_ssi_can_output_clk(mod))
return 0;
if (rsnd_ssi_is_multi_slave(mod, io))
......@@ -318,12 +320,11 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod,
{
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
if (!rsnd_rdai_is_clk_master(rdai))
return;
if (ssi_parent_mod && !rsnd_ssi_is_parent(mod, io))
if (!rsnd_ssi_can_output_clk(mod))
return;
if (ssi->usrcnt > 1)
......@@ -346,6 +347,9 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
u32 wsr;
int is_tdm;
if (rsnd_ssi_is_parent(mod, io))
return;
is_tdm = rsnd_runtime_is_ssi_tdm(io);
/*
......@@ -484,8 +488,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
if (ret < 0)
return ret;
if (!rsnd_ssi_is_parent(mod, io))
rsnd_ssi_config_init(mod, io);
rsnd_ssi_config_init(mod, io);
rsnd_ssi_register_setup(mod);
......@@ -782,15 +785,47 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
/*
* SSI might be called again as PIO fallback
* It is easy to manual handling for IRQ request/free
*
* OTOH, this function might be called many times if platform is
* using MIX. It needs xxx_attach() many times on xxx_probe().
* Because of it, we can't control .probe/.remove calling count by
* mod->status.
* But it don't need to call request_irq() many times.
* Let's control it by RSND_SSI_PROBED flag.
*/
ret = request_irq(ssi->irq,
rsnd_ssi_interrupt,
IRQF_SHARED,
dev_name(dev), mod);
if (!rsnd_ssi_flags_has(ssi, RSND_SSI_PROBED)) {
ret = request_irq(ssi->irq,
rsnd_ssi_interrupt,
IRQF_SHARED,
dev_name(dev), mod);
rsnd_ssi_flags_set(ssi, RSND_SSI_PROBED);
}
return ret;
}
static int rsnd_ssi_common_remove(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
/* Do nothing if non SSI (= SSI parent, multi SSI) mod */
if (pure_ssi_mod != mod)
return 0;
/* PIO will request IRQ again */
if (rsnd_ssi_flags_has(ssi, RSND_SSI_PROBED)) {
free_irq(ssi->irq, mod);
rsnd_ssi_flags_del(ssi, RSND_SSI_PROBED);
}
return 0;
}
static int rsnd_ssi_pointer(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
snd_pcm_uframes_t *pointer)
......@@ -806,6 +841,7 @@ static int rsnd_ssi_pointer(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.name = SSI_NAME,
.probe = rsnd_ssi_common_probe,
.remove = rsnd_ssi_common_remove,
.init = rsnd_ssi_init,
.quit = rsnd_ssi_quit,
.start = rsnd_ssi_start,
......@@ -840,23 +876,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
return ret;
}
static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
/* Do nothing if non SSI (= SSI parent, multi SSI) mod */
if (pure_ssi_mod != mod)
return 0;
/* PIO will request IRQ again */
free_irq(ssi->irq, mod);
return 0;
}
static int rsnd_ssi_fallback(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
......@@ -898,7 +917,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
.name = SSI_NAME,
.dma_req = rsnd_ssi_dma_req,
.probe = rsnd_ssi_dma_probe,
.remove = rsnd_ssi_dma_remove,
.remove = rsnd_ssi_common_remove,
.init = rsnd_ssi_init,
.quit = rsnd_ssi_quit,
.start = rsnd_ssi_start,
......@@ -984,13 +1003,13 @@ static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
ssi = rsnd_mod_to_ssi(mod);
if (strstr(remote_ep->full_name, "hdmi0")) {
ssi->flags |= RSND_SSI_HDMI0;
rsnd_ssi_flags_set(ssi, RSND_SSI_HDMI0);
dev_dbg(dev, "%s[%d] connected to HDMI0\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
if (strstr(remote_ep->full_name, "hdmi1")) {
ssi->flags |= RSND_SSI_HDMI1;
rsnd_ssi_flags_set(ssi, RSND_SSI_HDMI1);
dev_dbg(dev, "%s[%d] connected to HDMI1\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
......@@ -1023,7 +1042,7 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
return !!(rsnd_ssi_flags_has(ssi, RSND_SSI_CLK_PIN_SHARE));
}
static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
......@@ -1101,18 +1120,20 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(np);
goto rsnd_ssi_probe_done;
}
if (of_get_property(np, "shared-pin", NULL))
ssi->flags |= RSND_SSI_CLK_PIN_SHARE;
rsnd_ssi_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE);
if (of_get_property(np, "no-busif", NULL))
ssi->flags |= RSND_SSI_NO_BUSIF;
rsnd_ssi_flags_set(ssi, RSND_SSI_NO_BUSIF);
ssi->irq = irq_of_parse_and_map(np, 0);
if (!ssi->irq) {
ret = -EINVAL;
of_node_put(np);
goto rsnd_ssi_probe_done;
}
......@@ -1123,8 +1144,10 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
rsnd_ssi_get_status, RSND_MOD_SSI, i);
if (ret)
if (ret) {
of_node_put(np);
goto rsnd_ssi_probe_done;
}
i++;
}
......
......@@ -250,7 +250,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ssiu *ssiu;
static struct rsnd_mod_ops *ops;
struct rsnd_mod_ops *ops;
int i, nr, ret;
/* same number to SSI */
......
......@@ -333,7 +333,7 @@ static void siu_dai_spbstop(struct siu_port *port_info)
/* API functions */
/* Playback and capture hardware properties are identical */
static struct snd_pcm_hardware siu_dai_pcm_hw = {
static const struct snd_pcm_hardware siu_dai_pcm_hw = {
.info = SNDRV_PCM_INFO_INTERLEAVED,
.formats = SNDRV_PCM_FMTBIT_S16,
.rates = SNDRV_PCM_RATE_8000_48000,
......
......@@ -593,7 +593,7 @@ static void siu_pcm_free(struct snd_pcm *pcm)
dev_dbg(pcm->card->dev, "%s\n", __func__);
}
static struct snd_pcm_ops siu_pcm_ops = {
static const struct snd_pcm_ops siu_pcm_ops = {
.open = siu_pcm_open,
.close = siu_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
......
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