diff options
Diffstat (limited to 'sound/soc/sh/rcar')
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 15 | ||||
-rw-r--r-- | sound/soc/sh/rcar/cmd.c | 15 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 103 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ctu.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 6 | ||||
-rw-r--r-- | sound/soc/sh/rcar/src.c | 9 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 267 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssiu.c | 22 |
8 files changed, 246 insertions, 193 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index abdfd9cf91e2..0b8ae3eee148 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -64,13 +64,13 @@ static const char * const clk_name[] = { static u32 rsnd_adg_calculate_rbgx(unsigned long div) { - int i, ratio; + int i; if (!div) return 0; for (i = 3; i >= 0; i--) { - ratio = 2 << (i * 2); + int ratio = 2 << (i * 2); if (0 == (div % ratio)) return (u32)((i << 8) | ((div / ratio) - 1)); } @@ -111,7 +111,7 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); - int idx, sel, div, step; + int sel; unsigned int val, en; unsigned int min, diff; unsigned int sel_rate[] = { @@ -126,8 +126,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, val = 0; en = 0; for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { - idx = 0; - step = 2; + int idx = 0; + int step = 2; + int div; if (!sel_rate[sel]) continue; @@ -394,11 +395,11 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv, struct rsnd_adg *adg) { struct device *dev = rsnd_priv_to_dev(priv); - struct clk *clk; int i; for (i = 0; i < CLKMAX; i++) { - clk = devm_clk_get(dev, clk_name[i]); + struct clk *clk = devm_clk_get(dev, clk_name[i]); + adg->clk[i] = IS_ERR(clk) ? NULL : clk; } } diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index e6bb6a9a0684..9fdb37c2cbc2 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -43,8 +43,6 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, if (mix) { struct rsnd_dai *rdai; - struct rsnd_mod *src; - struct rsnd_dai_stream *tio; int i; /* @@ -54,8 +52,9 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, */ data = 0; for_each_rsnd_dai(rdai, priv, i) { - tio = &rdai->playback; - src = rsnd_io_to_mod_src(tio); + struct rsnd_dai_stream *tio = &rdai->playback; + struct rsnd_mod *src = rsnd_io_to_mod_src(tio); + if (mix == rsnd_io_to_mod_mix(tio)) data |= path[rsnd_mod_id(src)]; @@ -142,7 +141,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_cmd *cmd; - int i, nr, ret; + int i, nr; /* This driver doesn't support Gen1 at this point */ if (rsnd_is_gen1(priv)) @@ -161,9 +160,9 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) priv->cmd = cmd; for_each_rsnd_cmd(cmd, priv, i) { - ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), - &rsnd_cmd_ops, NULL, - RSND_MOD_CMD, i); + int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), + &rsnd_cmd_ops, NULL, + RSND_MOD_CMD, i); if (ret) return ret; } diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1029d8d9d800..8696a993c478 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -216,7 +216,7 @@ int rsnd_mod_init(struct rsnd_priv *priv, mod->clk = clk; mod->priv = priv; - return ret; + return 0; } void rsnd_mod_quit(struct rsnd_mod *mod) @@ -230,12 +230,12 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod, struct rsnd_dai_stream *io)) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io; struct rsnd_dai *rdai; int i; for_each_rsnd_dai(rdai, priv, i) { - io = &rdai->playback; + struct rsnd_dai_stream *io = &rdai->playback; + if (mod == io->mod[mod->type]) callback(mod, io); @@ -486,13 +486,12 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, enum rsnd_mod_type *array, int array_size) { - struct rsnd_mod *mod; - enum rsnd_mod_type type; int max = array ? array_size : RSND_MOD_MAX; for (; *iterator < max; (*iterator)++) { - type = (array) ? array[*iterator] : *iterator; - mod = rsnd_io_to_mod(io, type); + enum rsnd_mod_type type = (array) ? array[*iterator] : *iterator; + struct rsnd_mod *mod = rsnd_io_to_mod(io, type); + if (mod) return mod; } @@ -1061,7 +1060,7 @@ static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, struct device_node *ssiu_np = rsnd_ssiu_of_node(priv); struct device_node *np; int is_play = rsnd_io_is_play(io); - int i, j; + int i; if (!ssiu_np) return; @@ -1078,13 +1077,11 @@ static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, if (!node) break; - j = 0; for_each_child_of_node(ssiu_np, np) { if (np == node) { rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT); dev_dbg(dev, "%s is part of TDM Split\n", io->name); } - j++; } of_node_put(node); @@ -1140,7 +1137,6 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, { struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); struct device_node *np; - struct rsnd_mod *mod; int i; if (!node) @@ -1148,7 +1144,8 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, i = 0; for_each_child_of_node(node, np) { - mod = mod_get(priv, i); + struct rsnd_mod *mod = mod_get(priv, i); + if (np == playback) rsnd_dai_connect(mod, &rdai->playback, mod->type); if (np == capture) @@ -1258,7 +1255,6 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, struct device_node *dai_np, int dai_i) { - struct device_node *playback, *capture; struct rsnd_dai_stream *io_playback; struct rsnd_dai_stream *io_capture; struct snd_soc_dai_driver *drv; @@ -1301,8 +1297,8 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, rsnd_rdai_width_set(rdai, 32); /* default 32bit width */ for (io_i = 0;; io_i++) { - playback = of_parse_phandle(dai_np, "playback", io_i); - capture = of_parse_phandle(dai_np, "capture", io_i); + struct device_node *playback = of_parse_phandle(dai_np, "playback", io_i); + struct device_node *capture = of_parse_phandle(dai_np, "capture", io_i); if (!playback && !capture) break; @@ -1366,7 +1362,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) for_each_endpoint_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); if (rsnd_is_gen3(priv)) { - struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); + rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_graph(priv, &rdai->playback, dai_np); rsnd_parse_connect_graph(priv, &rdai->capture, dai_np); @@ -1377,7 +1373,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) for_each_child_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); if (rsnd_is_gen3(priv)) { - struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); + rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_simple(priv, &rdai->playback, dai_np); rsnd_parse_connect_simple(priv, &rdai->capture, dai_np); @@ -1416,11 +1412,11 @@ static int rsnd_hw_params(struct snd_soc_component *component, struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); struct snd_soc_dpcm *dpcm; - struct snd_pcm_hw_params *be_params; int stream = substream->stream; for_each_dpcm_be(fe, stream, dpcm) { - be_params = &dpcm->hw_params; + struct snd_pcm_hw_params *be_params = &dpcm->hw_params; + if (params_channels(hw_params) != params_channels(be_params)) io->converted_chan = params_channels(be_params); if (params_rate(hw_params) != params_rate(be_params)) @@ -1428,8 +1424,75 @@ static int rsnd_hw_params(struct snd_soc_component *component, } if (io->converted_chan) dev_dbg(dev, "convert channels = %d\n", io->converted_chan); - if (io->converted_rate) + if (io->converted_rate) { + /* + * SRC supports convert rates from params_rate(hw_params)/k_down + * to params_rate(hw_params)*k_up, where k_up is always 6, and + * k_down depends on number of channels and SRC unit. + * So all SRC units can upsample audio up to 6 times regardless + * its number of channels. And all SRC units can downsample + * 2 channel audio up to 6 times too. + */ + int k_up = 6; + int k_down = 6; + int channel; + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + dev_dbg(dev, "convert rate = %d\n", io->converted_rate); + + channel = io->converted_chan ? io->converted_chan : + params_channels(hw_params); + + switch (rsnd_mod_id(src_mod)) { + /* + * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times. + * SRC1, SRC3 and SRC4 can downsample 4 channel audio + * up to 4 times. + * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio + * no more than twice. + */ + case 1: + case 3: + case 4: + if (channel > 4) { + k_down = 2; + break; + } + fallthrough; + case 0: + if (channel > 2) + k_down = 4; + break; + + /* Other SRC units do not support more than 2 channels */ + default: + if (channel > 2) + return -EINVAL; + } + + if (params_rate(hw_params) > io->converted_rate * k_down) { + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = + io->converted_rate * k_down; + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = + io->converted_rate * k_down; + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; + } else if (params_rate(hw_params) * k_up < io->converted_rate) { + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = + (io->converted_rate + k_up - 1) / k_up; + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = + (io->converted_rate + k_up - 1) / k_up; + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; + } + + /* + * TBD: Max SRC input and output rates also depend on number + * of channels and SRC unit: + * SRC1, SRC3 and SRC4 do not support more than 128kHz + * for 6 channel and 96kHz for 8 channel audio. + * Perhaps this function should return EINVAL if the input or + * the output rate exceeds the limitation. + */ + } } return rsnd_dai_call(hw_params, io, substream, hw_params); diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 7647b3d4c0ba..20eecd088d13 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -207,6 +207,8 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, NULL, &ctu->pass, RSND_MAX_CHANNELS, 0xC); + if (ret < 0) + return ret; /* ROW0 */ ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6b519370fd64..1255a85151db 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -597,15 +597,15 @@ phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id); * R-Car ADG */ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate); -int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); -int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); +int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod); +int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate); int rsnd_adg_probe(struct rsnd_priv *priv); void rsnd_adg_remove(struct rsnd_priv *priv); int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod, struct rsnd_dai_stream *io, unsigned int in_rate, unsigned int out_rate); -int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod, +int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod, struct rsnd_dai_stream *io); #define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1) #define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 585ffba0244b..628af8f3920d 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -6,6 +6,15 @@ // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> /* + * You can use Synchronous Sampling Rate Convert (if no DVC) + * + * amixer set "SRC Out Rate" on + * aplay xxx.wav & + * amixer set "SRC Out Rate" 96000 // convert rate to 96000Hz + * amixer set "SRC Out Rate" 22050 // convert rate to 22050Hz + */ + +/* * you can enable below define if you don't need * SSI interrupt status debug message when debugging * see rsnd_dbg_irq_status() diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d0ded427a836..e29482c26d6a 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -24,23 +24,23 @@ /* * SSICR */ -#define FORCE (1 << 31) /* Fixed */ -#define DMEN (1 << 28) /* DMA Enable */ -#define UIEN (1 << 27) /* Underflow Interrupt Enable */ -#define OIEN (1 << 26) /* Overflow Interrupt Enable */ -#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */ -#define DIEN (1 << 24) /* Data Interrupt Enable */ -#define CHNL_4 (1 << 22) /* Channels */ -#define CHNL_6 (2 << 22) /* Channels */ -#define CHNL_8 (3 << 22) /* Channels */ -#define DWL_MASK (7 << 19) /* Data Word Length mask */ -#define DWL_8 (0 << 19) /* Data Word Length */ -#define DWL_16 (1 << 19) /* Data Word Length */ -#define DWL_18 (2 << 19) /* Data Word Length */ -#define DWL_20 (3 << 19) /* Data Word Length */ -#define DWL_22 (4 << 19) /* Data Word Length */ -#define DWL_24 (5 << 19) /* Data Word Length */ -#define DWL_32 (6 << 19) /* Data Word Length */ +#define FORCE (1u << 31) /* Fixed */ +#define DMEN (1u << 28) /* DMA Enable */ +#define UIEN (1u << 27) /* Underflow Interrupt Enable */ +#define OIEN (1u << 26) /* Overflow Interrupt Enable */ +#define IIEN (1u << 25) /* Idle Mode Interrupt Enable */ +#define DIEN (1u << 24) /* Data Interrupt Enable */ +#define CHNL_4 (1u << 22) /* Channels */ +#define CHNL_6 (2u << 22) /* Channels */ +#define CHNL_8 (3u << 22) /* Channels */ +#define DWL_MASK (7u << 19) /* Data Word Length mask */ +#define DWL_8 (0u << 19) /* Data Word Length */ +#define DWL_16 (1u << 19) /* Data Word Length */ +#define DWL_18 (2u << 19) /* Data Word Length */ +#define DWL_20 (3u << 19) /* Data Word Length */ +#define DWL_22 (4u << 19) /* Data Word Length */ +#define DWL_24 (5u << 19) /* Data Word Length */ +#define DWL_32 (6u << 19) /* Data Word Length */ /* * System word length @@ -167,7 +167,6 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) { - struct rsnd_mod *mod; enum rsnd_mod_type types[] = { RSND_MOD_SSIM1, RSND_MOD_SSIM2, @@ -177,7 +176,8 @@ static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) mask = 0; for (i = 0; i < ARRAY_SIZE(types); i++) { - mod = rsnd_io_to_mod(io, types[i]); + struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]); + if (!mod) continue; @@ -359,6 +359,96 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, rsnd_adg_ssi_clk_stop(mod); } +/* enable busif buffer over/under run interrupt. */ +#define rsnd_ssi_busif_err_irq_enable(mod) rsnd_ssi_busif_err_irq_ctrl(mod, 1) +#define rsnd_ssi_busif_err_irq_disable(mod) rsnd_ssi_busif_err_irq_ctrl(mod, 0) +static void rsnd_ssi_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable) +{ + u32 sys_int_enable = 0; + int id = rsnd_mod_id(mod); + int i; + + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, SSI_SYS_INT_ENABLE(i * 2)); + if (enable) + sys_int_enable |= 0xf << (id * 4); + else + sys_int_enable &= ~(0xf << (id * 4)); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE(i * 2), + sys_int_enable); + } + break; + case 9: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, SSI_SYS_INT_ENABLE((i * 2) + 1)); + if (enable) + sys_int_enable |= 0xf << 4; + else + sys_int_enable &= ~(0xf << 4); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE((i * 2) + 1), + sys_int_enable); + } + break; + } +} + +static bool rsnd_ssi_busif_err_status_clear(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + u32 status; + bool stop = false; + int id = rsnd_mod_id(mod); + int i; + + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + status = rsnd_mod_read(mod, SSI_SYS_STATUS(i * 2)); + status &= 0xf << (id * 4); + + if (status) { + rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); + rsnd_mod_write(mod, + SSI_SYS_STATUS(i * 2), + 0xf << (id * 4)); + stop = true; + } + } + break; + case 9: + for (i = 0; i < 4; i++) { + status = rsnd_mod_read(mod, SSI_SYS_STATUS((i * 2) + 1)); + status &= 0xf << 4; + + if (status) { + rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); + rsnd_mod_write(mod, + SSI_SYS_STATUS((i * 2) + 1), + 0xf << 4); + stop = true; + } + } + break; + } + + return stop; +} + static void rsnd_ssi_config_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { @@ -372,9 +462,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, u32 wsr = ssi->wsr; int width; int is_tdm, is_tdm_split; - int id = rsnd_mod_id(mod); - int i; - u32 sys_int_enable = 0; is_tdm = rsnd_runtime_is_tdm(io); is_tdm_split = rsnd_runtime_is_tdm_split(io); @@ -400,7 +487,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, * see * rsnd_ssiu_init_gen2() */ - wsr = ssi->wsr; if (is_tdm || is_tdm_split) { wsr |= WS_MODE; cr_own |= CHNL_8; @@ -451,36 +537,8 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, } /* enable busif buffer over/under run interrupt. */ - if (is_tdm || is_tdm_split) { - switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE(i * 2)); - sys_int_enable |= 0xf << (id * 4); - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE(i * 2), - sys_int_enable); - } - - break; - case 9: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1)); - sys_int_enable |= 0xf << 4; - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1), - sys_int_enable); - } - - break; - } - } + if (is_tdm || is_tdm_split) + rsnd_ssi_busif_err_irq_enable(mod); init_end: ssi->cr_own = cr_own; @@ -507,10 +565,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int ret; if (!rsnd_ssi_is_run_mods(mod, io)) return 0; + ret = rsnd_ssi_master_clk_start(mod, io); + if (ret < 0) + return ret; + ssi->usrcnt++; rsnd_mod_power_on(mod); @@ -532,9 +595,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct device *dev = rsnd_priv_to_dev(priv); int is_tdm, is_tdm_split; - int id = rsnd_mod_id(mod); - int i; - u32 sys_int_enable = 0; is_tdm = rsnd_runtime_is_tdm(io); is_tdm_split = rsnd_runtime_is_tdm_split(io); @@ -560,36 +620,8 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, } /* disable busif buffer over/under run interrupt. */ - if (is_tdm || is_tdm_split) { - switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE(i * 2)); - sys_int_enable &= ~(0xf << (id * 4)); - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE(i * 2), - sys_int_enable); - } - - break; - case 9: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1)); - sys_int_enable &= ~(0xf << 4); - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1), - sys_int_enable); - } - - break; - } - } + if (is_tdm || is_tdm_split) + rsnd_ssi_busif_err_irq_disable(mod); return 0; } @@ -743,8 +775,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, u32 status; bool elapsed = false; bool stop = false; - int id = rsnd_mod_id(mod); - int i; int is_tdm, is_tdm_split; is_tdm = rsnd_runtime_is_tdm(io); @@ -770,52 +800,8 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, stop = true; } - status = 0; - - if (is_tdm || is_tdm_split) { - switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - for (i = 0; i < 4; i++) { - status = rsnd_mod_read(mod, - SSI_SYS_STATUS(i * 2)); - status &= 0xf << (id * 4); - - if (status) { - rsnd_dbg_irq_status(dev, - "%s err status : 0x%08x\n", - rsnd_mod_name(mod), status); - rsnd_mod_write(mod, - SSI_SYS_STATUS(i * 2), - 0xf << (id * 4)); - stop = true; - break; - } - } - break; - case 9: - for (i = 0; i < 4; i++) { - status = rsnd_mod_read(mod, - SSI_SYS_STATUS((i * 2) + 1)); - status &= 0xf << 4; - - if (status) { - rsnd_dbg_irq_status(dev, - "%s err status : 0x%08x\n", - rsnd_mod_name(mod), status); - rsnd_mod_write(mod, - SSI_SYS_STATUS((i * 2) + 1), - 0xf << 4); - stop = true; - break; - } - } - break; - } - } + if (is_tdm || is_tdm_split) + stop |= rsnd_ssi_busif_err_status_clear(mod); rsnd_ssi_status_clear(mod); rsnd_ssi_interrupt_out: @@ -1060,13 +1046,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod, return 0; } -static int rsnd_ssi_prepare(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) -{ - return rsnd_ssi_master_clk_start(mod, io); -} - static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = SSI_NAME, .probe = rsnd_ssi_common_probe, @@ -1079,7 +1058,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .pointer = rsnd_ssi_pio_pointer, .pcm_new = rsnd_ssi_pcm_new, .hw_params = rsnd_ssi_hw_params, - .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, }; @@ -1166,7 +1144,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .pcm_new = rsnd_ssi_pcm_new, .fallback = rsnd_ssi_fallback, .hw_params = rsnd_ssi_hw_params, - .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, }; @@ -1210,7 +1187,6 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); struct device_node *node; struct device_node *np; - struct rsnd_mod *mod; int i; node = rsnd_ssi_of_node(priv); @@ -1219,7 +1195,8 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, i = 0; for_each_child_of_node(node, np) { - mod = rsnd_ssi_mod_get(priv, i); + struct rsnd_mod *mod = rsnd_ssi_mod_get(priv, i); + if (np == playback) rsnd_ssi_connect(mod, &rdai->playback); if (np == capture) diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index f29bd72f3a26..852cdeedf7e9 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -209,7 +209,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); struct rsnd_mod *pos; u32 val; - int i, shift; + int i; i = rsnd_mod_id(ssi_mod); @@ -221,7 +221,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, i; for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { - shift = (i * 4) + 20; + int shift = (i * 4) + 20; + val = (val & ~(0xF << shift)) | rsnd_mod_id(pos) << shift; } @@ -334,7 +335,6 @@ static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, struct rsnd_dai_stream *io) { struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); - struct rsnd_mod *mod; struct rsnd_ssiu *ssiu; int i; @@ -343,7 +343,7 @@ static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, /* select BUSIF0 */ for_each_rsnd_ssiu(ssiu, priv, i) { - mod = rsnd_mod_get(ssiu); + struct rsnd_mod *mod = rsnd_mod_get(ssiu); if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) && (rsnd_mod_id_sub(mod) == 0)) { @@ -359,17 +359,17 @@ void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai, { struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); struct device_node *node = rsnd_ssiu_of_node(priv); - struct device_node *np; - struct rsnd_mod *mod; struct rsnd_dai_stream *io_p = &rdai->playback; struct rsnd_dai_stream *io_c = &rdai->capture; - int i; /* use rcar_sound,ssiu if exist */ if (node) { - i = 0; + struct device_node *np; + int i = 0; + for_each_child_of_node(node, np) { - mod = rsnd_ssiu_mod_get(priv, i); + struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, i); + if (np == playback) rsnd_dai_connect(mod, io_p, mod->type); if (np == capture) @@ -394,7 +394,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) struct rsnd_ssiu *ssiu; struct rsnd_mod_ops *ops; const int *list = NULL; - int i, nr, ret; + int i, nr; /* * Keep DT compatibility. @@ -441,6 +441,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) } for_each_rsnd_ssiu(ssiu, priv, i) { + int ret; + if (node) { int j; |