Skip to content

Commit

Permalink
ASoC: rsnd: add DPCM based sampling rate convert
Browse files Browse the repository at this point in the history
This patch supports DPCM based sampling rate convert on Renesas sound
driver. It assumes...
 1. SRC is implemented as FE
 2. BE dai_link supports .be_hw_params_fixup

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Kuninori Morimoto authored and Mark Brown committed Mar 27, 2015
1 parent b543b52 commit 3b7843f
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 5 deletions.
11 changes: 10 additions & 1 deletion sound/soc/sh/rcar/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
({ \
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \
struct device *dev = rsnd_priv_to_dev(priv); \
u32 mask = 1 << __rsnd_mod_shift_##func; \
u32 mask = (1 << __rsnd_mod_shift_##func) & ~(1 << 31); \
u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func; \
int ret = 0; \
if ((mod->status & mask) == call) { \
Expand Down Expand Up @@ -728,6 +728,15 @@ static int rsnd_pcm_open(struct snd_pcm_substream *substream)
static int rsnd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
int ret;

ret = rsnd_dai_call(hw_params, io, substream, hw_params);
if (ret)
return ret;

return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
Expand Down
8 changes: 8 additions & 0 deletions sound/soc/sh/rcar/rsnd.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ struct rsnd_mod_ops {
struct rsnd_priv *priv);
int (*pcm_new)(struct rsnd_mod *mod,
struct snd_soc_pcm_runtime *rtd);
int (*hw_params)(struct rsnd_mod *mod,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params);
int (*fallback)(struct rsnd_mod *mod,
struct rsnd_priv *priv);
};
Expand All @@ -262,6 +265,9 @@ struct rsnd_mod {
* 2 0: start 1: stop
* 3 0: pcm_new
* 4 0: fallback
*
* 31 bit is always called (see __rsnd_mod_call)
* 31 0: hw_params
*/
#define __rsnd_mod_shift_probe 0
#define __rsnd_mod_shift_remove 0
Expand All @@ -271,6 +277,7 @@ struct rsnd_mod {
#define __rsnd_mod_shift_stop 2
#define __rsnd_mod_shift_pcm_new 3
#define __rsnd_mod_shift_fallback 4
#define __rsnd_mod_shift_hw_params 31 /* always called */

#define __rsnd_mod_call_probe 0
#define __rsnd_mod_call_remove 1
Expand All @@ -280,6 +287,7 @@ struct rsnd_mod {
#define __rsnd_mod_call_stop 1
#define __rsnd_mod_call_pcm_new 0
#define __rsnd_mod_call_fallback 0
#define __rsnd_mod_call_hw_params 0

#define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod)))
#define rsnd_mod_to_dma(mod) (&(mod)->dma)
Expand Down
49 changes: 45 additions & 4 deletions sound/soc/sh/rcar/src.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@
struct rsnd_src {
struct rsnd_src_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
u32 convert_rate; /* sampling rate convert */
int err;
};

#define RSND_SRC_NAME_SIZE 16

#define rsnd_src_convert_rate(p) ((p)->info->convert_rate)
#define rsnd_src_convert_rate(s) ((s)->convert_rate)
#define rsnd_src_of_node(priv) \
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src")

Expand Down Expand Up @@ -288,7 +289,43 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod)
return 0;
}

static int rsnd_src_init(struct rsnd_mod *mod)
static int rsnd_src_hw_params(struct rsnd_mod *mod,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *fe_params)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
struct snd_soc_pcm_runtime *fe = substream->private_data;

/* default value (mainly for non-DT) */
src->convert_rate = src->info->convert_rate;

/*
* SRC assumes that it is used under DPCM if user want to use
* sampling rate convert. Then, SRC should be FE.
* And then, this function will be called *after* BE settings.
* this means, each BE already has fixuped hw_params.
* see
* dpcm_fe_dai_hw_params()
* dpcm_be_dai_hw_params()
*/
if (fe->dai_link->dynamic) {
int stream = substream->stream;
struct snd_soc_dpcm *dpcm;
struct snd_pcm_hw_params *be_params;

list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
be_params = &dpcm->hw_params;

if (params_rate(fe_params) != params_rate(be_params))
src->convert_rate = params_rate(be_params);
}
}

return 0;
}

static int rsnd_src_init(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);

Expand Down Expand Up @@ -317,6 +354,8 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
dev_warn(dev, "%s[%d] under/over flow err = %d\n",
rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);

src->convert_rate = 0;

return 0;
}

Expand Down Expand Up @@ -465,7 +504,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod,
{
int ret;

ret = rsnd_src_init(mod);
ret = rsnd_src_init(mod, priv);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -511,6 +550,7 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
.quit = rsnd_src_quit,
.start = rsnd_src_start_gen1,
.stop = rsnd_src_stop_gen1,
.hw_params = rsnd_src_hw_params,
};

/*
Expand Down Expand Up @@ -736,7 +776,7 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod,
{
int ret;

ret = rsnd_src_init(mod);
ret = rsnd_src_init(mod, priv);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -780,6 +820,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = {
.quit = rsnd_src_quit,
.start = rsnd_src_start_gen2,
.stop = rsnd_src_stop_gen2,
.hw_params = rsnd_src_hw_params,
};

struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
Expand Down

0 comments on commit 3b7843f

Please sign in to comment.