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

This commit is contained in:
Mark Brown 2015-09-23 11:01:25 -07:00
28 changed files with 347 additions and 229 deletions

View File

@ -4,10 +4,12 @@ Required properties:
- compatible : "renesas,rcar_sound-<soctype>", fallbacks
"renesas,rcar_sound-gen1" if generation1, and
"renesas,rcar_sound-gen2" if generation2
"renesas,rcar_sound-gen3" if generation3
Examples with soctypes are:
- "renesas,rcar_sound-r8a7778" (R-Car M1A)
- "renesas,rcar_sound-r8a7790" (R-Car H2)
- "renesas,rcar_sound-r8a7791" (R-Car M2-W)
- "renesas,rcar_sound-r8a7795" (R-Car H3)
- reg : Should contain the register physical address.
required register is
SRU/ADG/SSI if generation1
@ -30,6 +32,11 @@ Required properties:
- rcar_sound,dai : DAI contents.
The number of DAI subnode should be same as HW.
see below for detail.
- #sound-dai-cells : it must be 0 if your system is using single DAI
it must be 1 if your system is using multi DAI
- #clock-cells : it must be 0 if your system has audio_clkout
it must be 1 if your system has audio_clkout0/1/2/3
- clock-frequency : for all audio_clkout0/1/2/3
SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer

View File

@ -12,7 +12,6 @@
#ifndef RCAR_SND_H
#define RCAR_SND_H
#include <linux/sh_clk.h>
#define RSND_GEN1_SRU 0
#define RSND_GEN1_ADG 1

View File

@ -116,26 +116,19 @@ static int brownstone_probe(struct platform_device *pdev)
int ret;
brownstone.dev = &pdev->dev;
ret = snd_soc_register_card(&brownstone);
ret = devm_snd_soc_register_card(&pdev->dev, &brownstone);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
return ret;
}
static int brownstone_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&brownstone);
return 0;
}
static struct platform_driver mmp_driver = {
.driver = {
.name = "brownstone-audio",
.pm = &snd_soc_pm_ops,
},
.probe = brownstone_probe,
.remove = brownstone_remove,
};
module_platform_driver(mmp_driver);

View File

@ -295,28 +295,19 @@ static int corgi_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
return ret;
}
static int corgi_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
return 0;
}
static struct platform_driver corgi_driver = {
.driver = {
.name = "corgi-audio",
.pm = &snd_soc_pm_ops,
},
.probe = corgi_probe,
.remove = corgi_remove,
};
module_platform_driver(corgi_driver);

View File

@ -138,7 +138,7 @@ static int e740_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
@ -149,10 +149,7 @@ static int e740_probe(struct platform_device *pdev)
static int e740_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
gpio_free_array(e740_audio_gpios, ARRAY_SIZE(e740_audio_gpios));
snd_soc_unregister_card(card);
return 0;
}

View File

@ -120,7 +120,7 @@ static int e750_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
@ -131,10 +131,7 @@ static int e750_probe(struct platform_device *pdev)
static int e750_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
gpio_free_array(e750_audio_gpios, ARRAY_SIZE(e750_audio_gpios));
snd_soc_unregister_card(card);
return 0;
}

View File

@ -119,7 +119,7 @@ static int e800_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
@ -130,10 +130,7 @@ static int e800_probe(struct platform_device *pdev)
static int e800_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
gpio_free_array(e800_audio_gpios, ARRAY_SIZE(e800_audio_gpios));
snd_soc_unregister_card(card);
return 0;
}

View File

@ -193,7 +193,7 @@ static int hx4700_audio_probe(struct platform_device *pdev)
return ret;
snd_soc_card_hx4700.dev = &pdev->dev;
ret = snd_soc_register_card(&snd_soc_card_hx4700);
ret = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_hx4700);
if (ret)
gpio_free_array(hx4700_audio_gpios,
ARRAY_SIZE(hx4700_audio_gpios));
@ -203,8 +203,6 @@ static int hx4700_audio_probe(struct platform_device *pdev)
static int hx4700_audio_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&snd_soc_card_hx4700);
gpio_set_value(GPIO92_HX4700_HP_DRIVER, 0);
gpio_set_value(GPIO107_HX4700_SPK_nSD, 0);

View File

@ -72,28 +72,19 @@ static int imote2_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
return ret;
}
static int imote2_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
return 0;
}
static struct platform_driver imote2_driver = {
.driver = {
.name = "imote2-audio",
.pm = &snd_soc_pm_ops,
},
.probe = imote2_probe,
.remove = imote2_remove,
};
module_platform_driver(imote2_driver);

View File

@ -181,7 +181,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
return -ENODEV;
mioa701.dev = &pdev->dev;
rc = snd_soc_register_card(&mioa701);
rc = devm_snd_soc_register_card(&pdev->dev, &mioa701);
if (!rc)
dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will"
"lead to overheating and possible destruction of your device."
@ -189,17 +189,8 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
return rc;
}
static int mioa701_wm9713_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
return 0;
}
static struct platform_driver mioa701_wm9713_driver = {
.probe = mioa701_wm9713_probe,
.remove = mioa701_wm9713_remove,
.driver = {
.name = "mioa701-wm9713",
.pm = &snd_soc_pm_ops,

View File

@ -140,22 +140,15 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
palm27x_asoc.dev = &pdev->dev;
ret = snd_soc_register_card(&palm27x_asoc);
ret = devm_snd_soc_register_card(&pdev->dev, &palm27x_asoc);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
return ret;
}
static int palm27x_asoc_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&palm27x_asoc);
return 0;
}
static struct platform_driver palm27x_wm9712_driver = {
.probe = palm27x_asoc_probe,
.remove = palm27x_asoc_remove,
.driver = {
.name = "palm27x-asoc",
.pm = &snd_soc_pm_ops,

View File

@ -267,28 +267,19 @@ static int poodle_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
return ret;
}
static int poodle_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
return 0;
}
static struct platform_driver poodle_driver = {
.driver = {
.name = "poodle-audio",
.pm = &snd_soc_pm_ops,
},
.probe = poodle_probe,
.remove = poodle_remove,
};
module_platform_driver(poodle_driver);

View File

@ -809,6 +809,7 @@ static const struct of_device_id pxa_ssp_of_ids[] = {
{ .compatible = "mrvl,pxa-ssp-dai" },
{}
};
MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
#endif
static int asoc_ssp_probe(struct platform_device *pdev)

View File

@ -132,6 +132,7 @@ static const struct of_device_id snd_soc_pxa_audio_match[] = {
{ .compatible = "mrvl,pxa-pcm-audio" },
{ }
};
MODULE_DEVICE_TABLE(of, snd_soc_pxa_audio_match);
#endif
static struct platform_driver pxa_pcm_driver = {

View File

@ -305,7 +305,7 @@ static int spitz_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
@ -322,9 +322,6 @@ err1:
static int spitz_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
gpio_free(spitz_mic_gpio);
return 0;
}

View File

@ -233,7 +233,7 @@ static int tosa_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
@ -244,10 +244,7 @@ static int tosa_probe(struct platform_device *pdev)
static int tosa_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
gpio_free(TOSA_GPIO_L_MUTE);
snd_soc_unregister_card(card);
return 0;
}

View File

@ -128,7 +128,7 @@ static int ttc_dkb_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
@ -136,22 +136,12 @@ static int ttc_dkb_probe(struct platform_device *pdev)
return ret;
}
static int ttc_dkb_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
return 0;
}
static struct platform_driver ttc_dkb_driver = {
.driver = {
.name = "ttc-dkb-audio",
.pm = &snd_soc_pm_ops,
},
.probe = ttc_dkb_probe,
.remove = ttc_dkb_remove,
};
module_platform_driver(ttc_dkb_driver);

View File

@ -438,7 +438,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) {
dev_err(&pdev->dev,
"%s() error getting mi2s-bit-clk: %ld\n",
__func__, PTR_ERR(drvdata->mi2s_bit_clk[i]));
__func__,
PTR_ERR(drvdata->mi2s_bit_clk[dai_id]));
return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
}
}

View File

@ -17,7 +17,7 @@ config SND_SOC_ROCKCHIP_I2S
config SND_SOC_ROCKCHIP_MAX98090
tristate "ASoC support for Rockchip boards using a MAX98090 codec"
depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB
depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_MAX98090
select SND_SOC_TS3A227E
@ -27,7 +27,7 @@ config SND_SOC_ROCKCHIP_MAX98090
config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec"
depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB
depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP
select SND_SOC_ROCKCHIP_I2S
select SND_SOC_RT5645
help

View File

@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support"
depends on DMA_OF
depends on COMMON_CLK
select SND_SIMPLE_CARD
select REGMAP_MMIO
help

View File

@ -7,7 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/sh_clk.h>
#include <linux/clk-provider.h>
#include "rsnd.h"
#define CLKA 0
@ -16,12 +16,26 @@
#define CLKI 3
#define CLKMAX 4
#define CLKOUT 0
#define CLKOUT1 1
#define CLKOUT2 2
#define CLKOUT3 3
#define CLKOUTMAX 4
#define BRRx_MASK(x) (0x3FF & x)
static struct rsnd_mod_ops adg_ops = {
.name = "adg",
};
struct rsnd_adg {
struct clk *clk[CLKMAX];
struct clk *clkout[CLKOUTMAX];
struct clk_onecell_data onecell;
struct rsnd_mod mod;
int rbga_rate_for_441khz_div_6; /* RBGA */
int rbgb_rate_for_48khz_div_6; /* RBGB */
u32 ckr;
int rbga_rate_for_441khz; /* RBGA */
int rbgb_rate_for_48khz; /* RBGB */
};
#define for_each_rsnd_clk(pos, adg, i) \
@ -29,8 +43,28 @@ struct rsnd_adg {
(i < CLKMAX) && \
((pos) = adg->clk[i]); \
i++)
#define for_each_rsnd_clkout(pos, adg, i) \
for (i = 0; \
(i < CLKOUTMAX) && \
((pos) = adg->clkout[i]); \
i++)
#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
static u32 rsnd_adg_calculate_rbgx(unsigned long div)
{
int i, ratio;
if (!div)
return 0;
for (i = 3; i >= 0; i--) {
ratio = 2 << (i * 2);
if (0 == (div % ratio))
return (u32)((i << 8) | ((div / ratio) - 1));
}
return ~0;
}
static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
{
@ -60,6 +94,9 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
int id = rsnd_mod_id(mod);
int shift = (id % 2) ? 16 : 0;
u32 mask, val;
@ -69,21 +106,26 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
val = val << shift;
mask = 0xffff << shift;
rsnd_mod_bset(mod, CMDOUT_TIMSEL, mask, val);
rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);
return 0;
}
static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *mod,
static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *src_mod,
struct rsnd_dai_stream *io,
u32 timsel)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
int is_play = rsnd_io_is_play(io);
int id = rsnd_mod_id(mod);
int id = rsnd_mod_id(src_mod);
int shift = (id % 2) ? 16 : 0;
u32 mask, ws;
u32 in, out;
rsnd_mod_confirm_src(src_mod);
ws = rsnd_adg_ssi_ws_timing_gen2(io);
in = (is_play) ? timsel : ws;
@ -95,37 +137,38 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *mod,
switch (id / 2) {
case 0:
rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out);
rsnd_mod_bset(adg_mod, SRCIN_TIMSEL0, mask, in);
rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL0, mask, out);
break;
case 1:
rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out);
rsnd_mod_bset(adg_mod, SRCIN_TIMSEL1, mask, in);
rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL1, mask, out);
break;
case 2:
rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out);
rsnd_mod_bset(adg_mod, SRCIN_TIMSEL2, mask, in);
rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL2, mask, out);
break;
case 3:
rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out);
rsnd_mod_bset(adg_mod, SRCIN_TIMSEL3, mask, in);
rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL3, mask, out);
break;
case 4:
rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out);
rsnd_mod_bset(adg_mod, SRCIN_TIMSEL4, mask, in);
rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL4, mask, out);
break;
}
return 0;
}
int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *src_mod,
struct rsnd_dai_stream *io,
unsigned int src_rate,
unsigned int dst_rate)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
struct device *dev = rsnd_priv_to_dev(priv);
int idx, sel, div, step, ret;
u32 val, en;
@ -134,10 +177,12 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */
clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */
adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */
adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */
adg->rbga_rate_for_441khz, /* 0011: RBGA */
adg->rbgb_rate_for_48khz, /* 0100: RBGB */
};
rsnd_mod_confirm_src(src_mod);
min = ~0;
val = 0;
en = 0;
@ -175,25 +220,27 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
return -EIO;
}
ret = rsnd_adg_set_src_timsel_gen2(mod, io, val);
ret = rsnd_adg_set_src_timsel_gen2(src_mod, io, val);
if (ret < 0) {
dev_err(dev, "timsel error\n");
return ret;
}
rsnd_mod_bset(mod, DIV_EN, en, en);
rsnd_mod_bset(adg_mod, DIV_EN, en, en);
dev_dbg(dev, "convert rate %d <-> %d\n", src_rate, dst_rate);
return 0;
}
int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *src_mod,
struct rsnd_dai_stream *io)
{
u32 val = rsnd_adg_ssi_ws_timing_gen2(io);
return rsnd_adg_set_src_timsel_gen2(mod, io, val);
rsnd_mod_confirm_src(src_mod);
return rsnd_adg_set_src_timsel_gen2(src_mod, io, val);
}
int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
@ -202,6 +249,7 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
unsigned int dst_rate)
{
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
struct device *dev = rsnd_priv_to_dev(priv);
int idx, sel, div, shift;
u32 mask, val;
@ -211,8 +259,8 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */
0, /* 011: MLBCLK (not used) */
adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */
adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */
adg->rbga_rate_for_441khz, /* 100: RBGA */
adg->rbgb_rate_for_48khz, /* 101: RBGB */
};
/* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */
@ -238,13 +286,13 @@ find_rate:
switch (id / 4) {
case 0:
rsnd_mod_bset(mod, AUDIO_CLK_SEL3, mask, val);
rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL3, mask, val);
break;
case 1:
rsnd_mod_bset(mod, AUDIO_CLK_SEL4, mask, val);
rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL4, mask, val);
break;
case 2:
rsnd_mod_bset(mod, AUDIO_CLK_SEL5, mask, val);
rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL5, mask, val);
break;
}
@ -257,12 +305,17 @@ find_rate:
return 0;
}
static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val)
static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
{
int id = rsnd_mod_id(mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
int id = rsnd_mod_id(ssi_mod);
int shift = (id % 4) * 8;
u32 mask = 0xFF << shift;
rsnd_mod_confirm_ssi(ssi_mod);
val = val << shift;
/*
@ -274,13 +327,13 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val)
switch (id / 4) {
case 0:
rsnd_mod_bset(mod, AUDIO_CLK_SEL0, mask, val);
rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL0, mask, val);
break;
case 1:
rsnd_mod_bset(mod, AUDIO_CLK_SEL1, mask, val);
rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL1, mask, val);
break;
case 2:
rsnd_mod_bset(mod, AUDIO_CLK_SEL2, mask, val);
rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL2, mask, val);
break;
}
}
@ -326,14 +379,14 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
}
/*
* find 1/6 clock from BRGA/BRGB
* find divided clock from BRGA/BRGB
*/
if (rate == adg->rbga_rate_for_441khz_div_6) {
if (rate == adg->rbga_rate_for_441khz) {
data = 0x10;
goto found_clock;
}
if (rate == adg->rbgb_rate_for_48khz_div_6) {
if (rate == adg->rbgb_rate_for_48khz) {
data = 0x20;
goto found_clock;
}
@ -342,29 +395,60 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
found_clock:
/* see rsnd_adg_ssi_clk_init() */
rsnd_mod_bset(mod, SSICKR, 0x00FF0000, adg->ckr);
rsnd_mod_write(mod, BRRA, 0x00000002); /* 1/6 */
rsnd_mod_write(mod, BRRB, 0x00000002); /* 1/6 */
/*
* This "mod" = "ssi" here.
* we can get "ssi id" from mod
*/
rsnd_adg_set_ssi_clk(mod, data);
dev_dbg(dev, "ADG: ssi%d selects clk%d = %d",
rsnd_mod_id(mod), i, rate);
dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n",
rsnd_mod_name(mod), rsnd_mod_id(mod),
data, rate);
return 0;
}
static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
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;
static const char * const clk_name[] = {
[CLKA] = "clk_a",
[CLKB] = "clk_b",
[CLKC] = "clk_c",
[CLKI] = "clk_i",
};
int i;
for (i = 0; i < CLKMAX; i++) {
clk = devm_clk_get(dev, clk_name[i]);
adg->clk[i] = IS_ERR(clk) ? NULL : clk;
}
for_each_rsnd_clk(clk, adg, i)
dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
}
static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
struct rsnd_adg *adg)
{
struct clk *clk;
unsigned long rate;
u32 ckr;
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
u32 ckr, rbgx, rbga, rbgb;
u32 rate, req_rate, div;
uint32_t count = 0;
unsigned long req_48kHz_rate, req_441kHz_rate;
int i;
const char *parent_clk_name = NULL;
static const char * const clkout_name[] = {
[CLKOUT] = "audio_clkout",
[CLKOUT1] = "audio_clkout1",
[CLKOUT2] = "audio_clkout2",
[CLKOUT3] = "audio_clkout3",
};
int brg_table[] = {
[CLKA] = 0x0,
[CLKB] = 0x1,
@ -372,19 +456,34 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
[CLKI] = 0x2,
};
of_property_read_u32(np, "#clock-cells", &count);
/*
* ADG supports BRRA/BRRB output only
* this means all clkout0/1/2/3 will be same rate
*/
of_property_read_u32(np, "clock-frequency", &req_rate);
req_48kHz_rate = 0;
req_441kHz_rate = 0;
if (0 == (req_rate % 44100))
req_441kHz_rate = req_rate;
if (0 == (req_rate % 48000))
req_48kHz_rate = req_rate;
/*
* This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
* have 44.1kHz or 48kHz base clocks for now.
*
* SSI itself can divide parent clock by 1/1 - 1/16
* So, BRGA outputs 44.1kHz base parent clock 1/32,
* and, BRGB outputs 48.0kHz base parent clock 1/32 here.
* see
* rsnd_adg_ssi_clk_try_start()
* rsnd_ssi_master_clk_start()
*/
ckr = 0;
adg->rbga_rate_for_441khz_div_6 = 0;
adg->rbgb_rate_for_48khz_div_6 = 0;
rbga = 2; /* default 1/6 */
rbgb = 2; /* default 1/6 */
adg->rbga_rate_for_441khz = 0;
adg->rbgb_rate_for_48khz = 0;
for_each_rsnd_clk(clk, adg, i) {
rate = clk_get_rate(clk);
@ -392,19 +491,86 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
continue;
/* RBGA */
if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) {
adg->rbga_rate_for_441khz_div_6 = rate / 6;
ckr |= brg_table[i] << 20;
if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) {
div = 6;
if (req_441kHz_rate)
div = rate / req_441kHz_rate;
rbgx = rsnd_adg_calculate_rbgx(div);
if (BRRx_MASK(rbgx) == rbgx) {
rbga = rbgx;
adg->rbga_rate_for_441khz = rate / div;
ckr |= brg_table[i] << 20;
if (req_441kHz_rate)
parent_clk_name = __clk_get_name(clk);
}
}
/* RBGB */
if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) {
adg->rbgb_rate_for_48khz_div_6 = rate / 6;
ckr |= brg_table[i] << 16;
if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) {
div = 6;
if (req_48kHz_rate)
div = rate / req_48kHz_rate;
rbgx = rsnd_adg_calculate_rbgx(div);
if (BRRx_MASK(rbgx) == rbgx) {
rbgb = rbgx;
adg->rbgb_rate_for_48khz = rate / div;
ckr |= brg_table[i] << 16;
if (req_48kHz_rate) {
parent_clk_name = __clk_get_name(clk);
ckr |= 0x80000000;
}
}
}
}
adg->ckr = ckr;
/*
* ADG supports BRRA/BRRB output only.
* this means all clkout0/1/2/3 will be * same rate
*/
/*
* for clkout
*/
if (!count) {
clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
parent_clk_name,
(parent_clk_name) ?
0 : CLK_IS_ROOT, req_rate);
if (!IS_ERR(clk)) {
adg->clkout[CLKOUT] = clk;
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
}
/*
* for clkout0/1/2/3
*/
else {
for (i = 0; i < CLKOUTMAX; i++) {
clk = clk_register_fixed_rate(dev, clkout_name[i],
parent_clk_name,
(parent_clk_name) ?
0 : CLK_IS_ROOT,
req_rate);
if (!IS_ERR(clk)) {
adg->onecell.clks = adg->clkout;
adg->onecell.clk_num = CLKOUTMAX;
adg->clkout[i] = clk;
of_clk_add_provider(np, of_clk_src_onecell_get,
&adg->onecell);
}
}
}
rsnd_mod_bset(adg_mod, SSICKR, 0x00FF0000, ckr);
rsnd_mod_write(adg_mod, BRRA, rbga);
rsnd_mod_write(adg_mod, BRRB, rbgb);
for_each_rsnd_clkout(clk, adg, i)
dev_dbg(dev, "clkout %d : %p : %ld\n", i, clk, clk_get_rate(clk));
dev_dbg(dev, "SSICKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
ckr, rbga, rbgb);
}
int rsnd_adg_probe(struct platform_device *pdev,
@ -413,8 +579,6 @@ int rsnd_adg_probe(struct platform_device *pdev,
{
struct rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv);
struct clk *clk;
int i;
adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
if (!adg) {
@ -422,15 +586,16 @@ int rsnd_adg_probe(struct platform_device *pdev,
return -ENOMEM;
}
adg->clk[CLKA] = devm_clk_get(dev, "clk_a");
adg->clk[CLKB] = devm_clk_get(dev, "clk_b");
adg->clk[CLKC] = devm_clk_get(dev, "clk_c");
adg->clk[CLKI] = devm_clk_get(dev, "clk_i");
/*
* ADG is special module.
* Use ADG mod without rsnd_mod_init() to make debug easy
* for rsnd_write/rsnd_read
*/
adg->mod.ops = &adg_ops;
adg->mod.priv = priv;
for_each_rsnd_clk(clk, adg, i)
dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
rsnd_adg_ssi_clk_init(priv, adg);
rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg);
priv->adg = adg;

View File

@ -110,6 +110,7 @@ static const struct rsnd_of_data rsnd_of_data_gen2 = {
static const struct of_device_id rsnd_of_match[] = {
{ .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 },
{ .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 },
{ .compatible = "renesas,rcar_sound-gen3", .data = &rsnd_of_data_gen2 }, /* gen2 compatible */
{},
};
MODULE_DEVICE_TABLE(of, rsnd_of_match);
@ -126,6 +127,17 @@ MODULE_DEVICE_TABLE(of, rsnd_of_match);
#define rsnd_info_id(priv, io, name) \
((io)->info->name - priv->info->name##_info)
void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
{
if (mod->type != type) {
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
dev_warn(dev, "%s[%d] is not your expected module\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
}
/*
* rsnd_mod functions
*/

View File

@ -66,7 +66,7 @@ struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
id = 0;
return &((struct rsnd_ctu *)(priv->ctu) + id)->mod;
return rsnd_mod_get((struct rsnd_ctu *)(priv->ctu) + id);
}
static void rsnd_of_parse_ctu(struct platform_device *pdev,
@ -150,7 +150,7 @@ int rsnd_ctu_probe(struct platform_device *pdev,
ctu->info = &info->ctu_info[i];
ret = rsnd_mod_init(priv, &ctu->mod, &rsnd_ctu_ops,
ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
clk, RSND_MOD_CTU, i);
if (ret)
return ret;
@ -166,6 +166,6 @@ void rsnd_ctu_remove(struct platform_device *pdev,
int i;
for_each_rsnd_ctu(ctu, priv, i) {
rsnd_mod_quit(&ctu->mod);
rsnd_mod_quit(rsnd_mod_get(ctu));
}
}

View File

@ -282,7 +282,7 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
id = 0;
return &((struct rsnd_dvc *)(priv->dvc) + id)->mod;
return rsnd_mod_get((struct rsnd_dvc *)(priv->dvc) + id);
}
static void rsnd_of_parse_dvc(struct platform_device *pdev,
@ -361,7 +361,7 @@ int rsnd_dvc_probe(struct platform_device *pdev,
dvc->info = &info->dvc_info[i];
ret = rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops,
ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
clk, RSND_MOD_DVC, i);
if (ret)
return ret;
@ -377,6 +377,6 @@ void rsnd_dvc_remove(struct platform_device *pdev,
int i;
for_each_rsnd_dvc(dvc, priv, i) {
rsnd_mod_quit(&dvc->mod);
rsnd_mod_quit(rsnd_mod_get(dvc));
}
}

View File

@ -99,7 +99,7 @@ struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
id = 0;
return &((struct rsnd_mix *)(priv->mix) + id)->mod;
return rsnd_mod_get((struct rsnd_mix *)(priv->mix) + id);
}
static void rsnd_of_parse_mix(struct platform_device *pdev,
@ -179,7 +179,7 @@ int rsnd_mix_probe(struct platform_device *pdev,
mix->info = &info->mix_info[i];
ret = rsnd_mod_init(priv, &mix->mod, &rsnd_mix_ops,
ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
clk, RSND_MOD_MIX, i);
if (ret)
return ret;
@ -195,6 +195,6 @@ void rsnd_mix_remove(struct platform_device *pdev,
int i;
for_each_rsnd_mix(mix, priv, i) {
rsnd_mod_quit(&mix->mod);
rsnd_mod_quit(rsnd_mod_get(mix));
}
}

View File

@ -214,6 +214,7 @@ struct rsnd_dma {
};
#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
@ -225,8 +226,6 @@ int rsnd_dma_probe(struct platform_device *pdev,
struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
struct rsnd_mod *mod, char *name);
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
/*
* R-Car sound mod
*/
@ -332,6 +331,7 @@ struct rsnd_mod {
#define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1)
#define rsnd_mod_hw_start(mod) clk_enable((mod)->clk)
#define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk)
#define rsnd_mod_get(ip) (&(ip)->mod)
int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
@ -627,4 +627,15 @@ void rsnd_dvc_remove(struct platform_device *pdev,
struct rsnd_priv *priv);
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
#ifdef DEBUG
void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type);
#define rsnd_mod_confirm_ssi(mssi) rsnd_mod_make_sure(mssi, RSND_MOD_SSI)
#define rsnd_mod_confirm_src(msrc) rsnd_mod_make_sure(msrc, RSND_MOD_SRC)
#define rsnd_mod_confirm_dvc(mdvc) rsnd_mod_make_sure(mdvc, RSND_MOD_DVC)
#else
#define rsnd_mod_confirm_ssi(mssi)
#define rsnd_mod_confirm_src(msrc)
#define rsnd_mod_confirm_dvc(mdvc)
#endif
#endif

View File

@ -918,11 +918,10 @@ static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io,
rsnd_mod_write(mod, SRC_IFSVR, fsrate);
}
static int rsnd_src_pcm_new(struct rsnd_mod *mod,
static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_src *src = rsnd_mod_to_src(mod);
int ret;
@ -931,12 +930,6 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
* enable SRC sync convert if possible
*/
/*
* Gen1 is not supported
*/
if (rsnd_is_gen1(priv))
return 0;
/*
* SRC sync convert needs clock master
*/
@ -975,7 +968,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = {
.start = rsnd_src_start_gen2,
.stop = rsnd_src_stop_gen2,
.hw_params = rsnd_src_hw_params,
.pcm_new = rsnd_src_pcm_new,
.pcm_new = rsnd_src_pcm_new_gen2,
};
struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
@ -983,7 +976,7 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
id = 0;
return &((struct rsnd_src *)(priv->src) + id)->mod;
return rsnd_mod_get((struct rsnd_src *)(priv->src) + id);
}
static void rsnd_of_parse_src(struct platform_device *pdev,
@ -1078,7 +1071,7 @@ int rsnd_src_probe(struct platform_device *pdev,
src->info = &info->src_info[i];
ret = rsnd_mod_init(priv, &src->mod, ops, clk, RSND_MOD_SRC, i);
ret = rsnd_mod_init(priv, rsnd_mod_get(src), ops, clk, RSND_MOD_SRC, i);
if (ret)
return ret;
}
@ -1093,6 +1086,6 @@ void rsnd_src_remove(struct platform_device *pdev,
int i;
for_each_rsnd_src(src, priv, i) {
rsnd_mod_quit(&src->mod);
rsnd_mod_quit(rsnd_mod_get(src));
}
}

View File

@ -128,10 +128,8 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
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;
int adg_clk_div_table[] = {
1, 6, /* see adg.c */
};
struct rsnd_mod *mod = rsnd_mod_get(ssi);
int j, ret;
int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12,
};
@ -141,28 +139,25 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
/*
* Find best clock, and try to start ADG
*/
for (i = 0; i < ARRAY_SIZE(adg_clk_div_table); i++) {
for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
/*
* this driver is assuming that
* system word is 64fs (= 2 x 32bit)
* see rsnd_ssi_init()
*/
main_rate = rate / adg_clk_div_table[i]
* 32 * 2 * ssi_clk_mul_table[j];
/*
* this driver is assuming that
* system word is 64fs (= 2 x 32bit)
* see rsnd_ssi_init()
*/
main_rate = rate * 32 * 2 * ssi_clk_mul_table[j];
ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate);
if (0 == ret) {
ssi->cr_clk = FORCE | SWL_32 |
SCKD | SWSD | CKDV(j);
ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
if (0 == ret) {
ssi->cr_clk = FORCE | SWL_32 |
SCKD | SWSD | CKDV(j);
dev_dbg(dev, "%s[%d] outputs %u Hz\n",
rsnd_mod_name(&ssi->mod),
rsnd_mod_id(&ssi->mod), rate);
dev_dbg(dev, "%s[%d] outputs %u Hz\n",
rsnd_mod_name(mod),
rsnd_mod_id(mod), rate);
return 0;
}
return 0;
}
}
@ -172,8 +167,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi)
{
struct rsnd_mod *mod = rsnd_mod_get(ssi);
ssi->cr_clk = 0;
rsnd_adg_ssi_clk_stop(&ssi->mod);
rsnd_adg_ssi_clk_stop(mod);
}
static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
@ -182,11 +179,12 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
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);
struct rsnd_mod *mod = rsnd_mod_get(ssi);
u32 cr_mode;
u32 cr;
if (0 == ssi->usrcnt) {
rsnd_mod_hw_start(&ssi->mod);
rsnd_mod_hw_start(mod);
if (rsnd_rdai_is_clk_master(rdai)) {
struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
@ -198,7 +196,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
}
}
if (rsnd_ssi_is_dma_mode(&ssi->mod)) {
if (rsnd_ssi_is_dma_mode(mod)) {
cr_mode = UIEN | OIEN | /* over/under run */
DMEN; /* DMA : enable DMA */
} else {
@ -210,24 +208,25 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
cr_mode |
EN;
rsnd_mod_write(&ssi->mod, SSICR, cr);
rsnd_mod_write(mod, SSICR, cr);
/* enable WS continue */
if (rsnd_rdai_is_clk_master(rdai))
rsnd_mod_write(&ssi->mod, SSIWSR, CONT);
rsnd_mod_write(mod, SSIWSR, CONT);
/* clear error status */
rsnd_mod_write(&ssi->mod, SSISR, 0);
rsnd_mod_write(mod, SSISR, 0);
ssi->usrcnt++;
dev_dbg(dev, "%s[%d] hw started\n",
rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod));
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
struct rsnd_mod *mod = rsnd_mod_get(ssi);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct device *dev = rsnd_priv_to_dev(priv);
u32 cr;
@ -247,15 +246,15 @@ static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi)
cr = ssi->cr_own |
ssi->cr_clk;
rsnd_mod_write(&ssi->mod, SSICR, cr | EN);
rsnd_ssi_status_check(&ssi->mod, DIRQ);
rsnd_mod_write(mod, SSICR, cr | EN);
rsnd_ssi_status_check(mod, DIRQ);
/*
* disable SSI,
* and, wait idle state
*/
rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */
rsnd_ssi_status_check(&ssi->mod, IIRQ);
rsnd_mod_write(mod, SSICR, cr); /* disabled all */
rsnd_ssi_status_check(mod, IIRQ);
if (rsnd_rdai_is_clk_master(rdai)) {
struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
@ -266,13 +265,13 @@ static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi)
rsnd_ssi_master_clk_stop(ssi);
}
rsnd_mod_hw_stop(&ssi->mod);
rsnd_mod_hw_stop(mod);
ssi->chan = 0;
}
dev_dbg(dev, "%s[%d] hw stopped\n",
rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod));
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
/*
@ -371,7 +370,7 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
/* It will be removed on rsnd_ssi_hw_stop */
ssi->chan = chan;
if (ssi_parent)
return rsnd_ssi_hw_params(&ssi_parent->mod, io,
return rsnd_ssi_hw_params(rsnd_mod_get(ssi_parent), io,
substream, params);
return 0;
@ -379,12 +378,14 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
{
struct rsnd_mod *mod = rsnd_mod_get(ssi);
/* under/over flow error */
if (status & (UIRQ | OIRQ)) {
ssi->err++;
/* clear error status */
rsnd_mod_write(&ssi->mod, SSISR, 0);
rsnd_mod_write(mod, SSISR, 0);
}
}
@ -656,7 +657,7 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
id = 0;
return &((struct rsnd_ssi *)(priv->ssi) + id)->mod;
return rsnd_mod_get((struct rsnd_ssi *)(priv->ssi) + id);
}
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
@ -668,10 +669,12 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
static void rsnd_ssi_parent_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi)
{
if (!rsnd_ssi_is_pin_sharing(&ssi->mod))
struct rsnd_mod *mod = rsnd_mod_get(ssi);
if (!rsnd_ssi_is_pin_sharing(mod))
return;
switch (rsnd_mod_id(&ssi->mod)) {
switch (rsnd_mod_id(mod)) {
case 1:
case 2:
ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0));
@ -794,7 +797,8 @@ int rsnd_ssi_probe(struct platform_device *pdev,
else if (rsnd_ssi_pio_available(ssi))
ops = &rsnd_ssi_pio_ops;
ret = rsnd_mod_init(priv, &ssi->mod, ops, clk, RSND_MOD_SSI, i);
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
RSND_MOD_SSI, i);
if (ret)
return ret;
@ -811,6 +815,6 @@ void rsnd_ssi_remove(struct platform_device *pdev,
int i;
for_each_rsnd_ssi(ssi, priv, i) {
rsnd_mod_quit(&ssi->mod);
rsnd_mod_quit(rsnd_mod_get(ssi));
}
}