mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
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:
commit
e32efed3ea
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user