Commit e32efed3 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/pxa', 'asoc/topic/qcom',...

Merge remote-tracking branches 'asoc/topic/pxa', 'asoc/topic/qcom', 'asoc/topic/rcar' and 'asoc/topic/rockchip' into asoc-next
...@@ -4,10 +4,12 @@ Required properties: ...@@ -4,10 +4,12 @@ Required properties:
- compatible : "renesas,rcar_sound-<soctype>", fallbacks - compatible : "renesas,rcar_sound-<soctype>", fallbacks
"renesas,rcar_sound-gen1" if generation1, and "renesas,rcar_sound-gen1" if generation1, and
"renesas,rcar_sound-gen2" if generation2 "renesas,rcar_sound-gen2" if generation2
"renesas,rcar_sound-gen3" if generation3
Examples with soctypes are: Examples with soctypes are:
- "renesas,rcar_sound-r8a7778" (R-Car M1A) - "renesas,rcar_sound-r8a7778" (R-Car M1A)
- "renesas,rcar_sound-r8a7790" (R-Car H2) - "renesas,rcar_sound-r8a7790" (R-Car H2)
- "renesas,rcar_sound-r8a7791" (R-Car M2-W) - "renesas,rcar_sound-r8a7791" (R-Car M2-W)
- "renesas,rcar_sound-r8a7795" (R-Car H3)
- reg : Should contain the register physical address. - reg : Should contain the register physical address.
required register is required register is
SRU/ADG/SSI if generation1 SRU/ADG/SSI if generation1
...@@ -30,6 +32,11 @@ Required properties: ...@@ -30,6 +32,11 @@ Required properties:
- rcar_sound,dai : DAI contents. - rcar_sound,dai : DAI contents.
The number of DAI subnode should be same as HW. The number of DAI subnode should be same as HW.
see below for detail. 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: SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer - interrupts : Should contain SSI interrupt for PIO transfer
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef RCAR_SND_H #ifndef RCAR_SND_H
#define RCAR_SND_H #define RCAR_SND_H
#include <linux/sh_clk.h>
#define RSND_GEN1_SRU 0 #define RSND_GEN1_SRU 0
#define RSND_GEN1_ADG 1 #define RSND_GEN1_ADG 1
......
...@@ -116,26 +116,19 @@ static int brownstone_probe(struct platform_device *pdev) ...@@ -116,26 +116,19 @@ static int brownstone_probe(struct platform_device *pdev)
int ret; int ret;
brownstone.dev = &pdev->dev; brownstone.dev = &pdev->dev;
ret = snd_soc_register_card(&brownstone); ret = devm_snd_soc_register_card(&pdev->dev, &brownstone);
if (ret) if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
return ret; return ret;
} }
static int brownstone_remove(struct platform_device *pdev)
{
snd_soc_unregister_card(&brownstone);
return 0;
}
static struct platform_driver mmp_driver = { static struct platform_driver mmp_driver = {
.driver = { .driver = {
.name = "brownstone-audio", .name = "brownstone-audio",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
}, },
.probe = brownstone_probe, .probe = brownstone_probe,
.remove = brownstone_remove,
}; };
module_platform_driver(mmp_driver); module_platform_driver(mmp_driver);
......
...@@ -295,28 +295,19 @@ static int corgi_probe(struct platform_device *pdev) ...@@ -295,28 +295,19 @@ static int corgi_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
return 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 = { static struct platform_driver corgi_driver = {
.driver = { .driver = {
.name = "corgi-audio", .name = "corgi-audio",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
}, },
.probe = corgi_probe, .probe = corgi_probe,
.remove = corgi_remove,
}; };
module_platform_driver(corgi_driver); module_platform_driver(corgi_driver);
......
...@@ -138,7 +138,7 @@ static int e740_probe(struct platform_device *pdev) ...@@ -138,7 +138,7 @@ static int e740_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
...@@ -149,10 +149,7 @@ static int e740_probe(struct platform_device *pdev) ...@@ -149,10 +149,7 @@ static int e740_probe(struct platform_device *pdev)
static int e740_remove(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)); gpio_free_array(e740_audio_gpios, ARRAY_SIZE(e740_audio_gpios));
snd_soc_unregister_card(card);
return 0; return 0;
} }
......
...@@ -120,7 +120,7 @@ static int e750_probe(struct platform_device *pdev) ...@@ -120,7 +120,7 @@ static int e750_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
...@@ -131,10 +131,7 @@ static int e750_probe(struct platform_device *pdev) ...@@ -131,10 +131,7 @@ static int e750_probe(struct platform_device *pdev)
static int e750_remove(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)); gpio_free_array(e750_audio_gpios, ARRAY_SIZE(e750_audio_gpios));
snd_soc_unregister_card(card);
return 0; return 0;
} }
......
...@@ -119,7 +119,7 @@ static int e800_probe(struct platform_device *pdev) ...@@ -119,7 +119,7 @@ static int e800_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
...@@ -130,10 +130,7 @@ static int e800_probe(struct platform_device *pdev) ...@@ -130,10 +130,7 @@ static int e800_probe(struct platform_device *pdev)
static int e800_remove(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)); gpio_free_array(e800_audio_gpios, ARRAY_SIZE(e800_audio_gpios));
snd_soc_unregister_card(card);
return 0; return 0;
} }
......
...@@ -193,7 +193,7 @@ static int hx4700_audio_probe(struct platform_device *pdev) ...@@ -193,7 +193,7 @@ static int hx4700_audio_probe(struct platform_device *pdev)
return ret; return ret;
snd_soc_card_hx4700.dev = &pdev->dev; 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) if (ret)
gpio_free_array(hx4700_audio_gpios, gpio_free_array(hx4700_audio_gpios,
ARRAY_SIZE(hx4700_audio_gpios)); ARRAY_SIZE(hx4700_audio_gpios));
...@@ -203,8 +203,6 @@ static int hx4700_audio_probe(struct platform_device *pdev) ...@@ -203,8 +203,6 @@ static int hx4700_audio_probe(struct platform_device *pdev)
static int hx4700_audio_remove(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(GPIO92_HX4700_HP_DRIVER, 0);
gpio_set_value(GPIO107_HX4700_SPK_nSD, 0); gpio_set_value(GPIO107_HX4700_SPK_nSD, 0);
......
...@@ -72,28 +72,19 @@ static int imote2_probe(struct platform_device *pdev) ...@@ -72,28 +72,19 @@ static int imote2_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
return 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 = { static struct platform_driver imote2_driver = {
.driver = { .driver = {
.name = "imote2-audio", .name = "imote2-audio",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
}, },
.probe = imote2_probe, .probe = imote2_probe,
.remove = imote2_remove,
}; };
module_platform_driver(imote2_driver); module_platform_driver(imote2_driver);
......
...@@ -181,7 +181,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev) ...@@ -181,7 +181,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
mioa701.dev = &pdev->dev; mioa701.dev = &pdev->dev;
rc = snd_soc_register_card(&mioa701); rc = devm_snd_soc_register_card(&pdev->dev, &mioa701);
if (!rc) if (!rc)
dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will"
"lead to overheating and possible destruction of your device." "lead to overheating and possible destruction of your device."
...@@ -189,17 +189,8 @@ static int mioa701_wm9713_probe(struct platform_device *pdev) ...@@ -189,17 +189,8 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
return rc; 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 = { static struct platform_driver mioa701_wm9713_driver = {
.probe = mioa701_wm9713_probe, .probe = mioa701_wm9713_probe,
.remove = mioa701_wm9713_remove,
.driver = { .driver = {
.name = "mioa701-wm9713", .name = "mioa701-wm9713",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
......
...@@ -140,22 +140,15 @@ static int palm27x_asoc_probe(struct platform_device *pdev) ...@@ -140,22 +140,15 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
palm27x_asoc.dev = &pdev->dev; palm27x_asoc.dev = &pdev->dev;
ret = snd_soc_register_card(&palm27x_asoc); ret = devm_snd_soc_register_card(&pdev->dev, &palm27x_asoc);
if (ret) if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
return 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 = { static struct platform_driver palm27x_wm9712_driver = {
.probe = palm27x_asoc_probe, .probe = palm27x_asoc_probe,
.remove = palm27x_asoc_remove,
.driver = { .driver = {
.name = "palm27x-asoc", .name = "palm27x-asoc",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
......
...@@ -267,28 +267,19 @@ static int poodle_probe(struct platform_device *pdev) ...@@ -267,28 +267,19 @@ static int poodle_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
return 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 = { static struct platform_driver poodle_driver = {
.driver = { .driver = {
.name = "poodle-audio", .name = "poodle-audio",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
}, },
.probe = poodle_probe, .probe = poodle_probe,
.remove = poodle_remove,
}; };
module_platform_driver(poodle_driver); module_platform_driver(poodle_driver);
......
...@@ -809,6 +809,7 @@ static const struct of_device_id pxa_ssp_of_ids[] = { ...@@ -809,6 +809,7 @@ static const struct of_device_id pxa_ssp_of_ids[] = {
{ .compatible = "mrvl,pxa-ssp-dai" }, { .compatible = "mrvl,pxa-ssp-dai" },
{} {}
}; };
MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
#endif #endif
static int asoc_ssp_probe(struct platform_device *pdev) static int asoc_ssp_probe(struct platform_device *pdev)
......
...@@ -132,6 +132,7 @@ static const struct of_device_id snd_soc_pxa_audio_match[] = { ...@@ -132,6 +132,7 @@ static const struct of_device_id snd_soc_pxa_audio_match[] = {
{ .compatible = "mrvl,pxa-pcm-audio" }, { .compatible = "mrvl,pxa-pcm-audio" },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, snd_soc_pxa_audio_match);
#endif #endif
static struct platform_driver pxa_pcm_driver = { static struct platform_driver pxa_pcm_driver = {
......
...@@ -305,7 +305,7 @@ static int spitz_probe(struct platform_device *pdev) ...@@ -305,7 +305,7 @@ static int spitz_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
...@@ -322,9 +322,6 @@ static int spitz_probe(struct platform_device *pdev) ...@@ -322,9 +322,6 @@ static int spitz_probe(struct platform_device *pdev)
static int spitz_remove(struct platform_device *pdev) 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); gpio_free(spitz_mic_gpio);
return 0; return 0;
} }
......
...@@ -233,7 +233,7 @@ static int tosa_probe(struct platform_device *pdev) ...@@ -233,7 +233,7 @@ static int tosa_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
...@@ -244,10 +244,7 @@ static int tosa_probe(struct platform_device *pdev) ...@@ -244,10 +244,7 @@ static int tosa_probe(struct platform_device *pdev)
static int tosa_remove(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); gpio_free(TOSA_GPIO_L_MUTE);
snd_soc_unregister_card(card);
return 0; return 0;
} }
......
...@@ -128,7 +128,7 @@ static int ttc_dkb_probe(struct platform_device *pdev) ...@@ -128,7 +128,7 @@ static int ttc_dkb_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret); ret);
...@@ -136,22 +136,12 @@ static int ttc_dkb_probe(struct platform_device *pdev) ...@@ -136,22 +136,12 @@ static int ttc_dkb_probe(struct platform_device *pdev)
return ret; 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 = { static struct platform_driver ttc_dkb_driver = {
.driver = { .driver = {
.name = "ttc-dkb-audio", .name = "ttc-dkb-audio",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
}, },
.probe = ttc_dkb_probe, .probe = ttc_dkb_probe,
.remove = ttc_dkb_remove,
}; };
module_platform_driver(ttc_dkb_driver); module_platform_driver(ttc_dkb_driver);
......
...@@ -438,7 +438,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) ...@@ -438,7 +438,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"%s() error getting mi2s-bit-clk: %ld\n", "%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]); return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]);
} }
} }
......
...@@ -17,7 +17,7 @@ config SND_SOC_ROCKCHIP_I2S ...@@ -17,7 +17,7 @@ config SND_SOC_ROCKCHIP_I2S
config SND_SOC_ROCKCHIP_MAX98090 config SND_SOC_ROCKCHIP_MAX98090
tristate "ASoC support for Rockchip boards using a MAX98090 codec" 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_ROCKCHIP_I2S
select SND_SOC_MAX98090 select SND_SOC_MAX98090
select SND_SOC_TS3A227E select SND_SOC_TS3A227E
...@@ -27,7 +27,7 @@ config SND_SOC_ROCKCHIP_MAX98090 ...@@ -27,7 +27,7 @@ config SND_SOC_ROCKCHIP_MAX98090
config SND_SOC_ROCKCHIP_RT5645 config SND_SOC_ROCKCHIP_RT5645
tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec" 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_ROCKCHIP_I2S
select SND_SOC_RT5645 select SND_SOC_RT5645
help help
......
...@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU ...@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support" tristate "R-Car series SRU/SCU/SSIU/SSI support"
depends on DMA_OF depends on DMA_OF
depends on COMMON_CLK
select SND_SIMPLE_CARD select SND_SIMPLE_CARD
select REGMAP_MMIO select REGMAP_MMIO
help help
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#include <linux/sh_clk.h> #include <linux/clk-provider.h>
#include "rsnd.h" #include "rsnd.h"
#define CLKA 0 #define CLKA 0
...@@ -16,12 +16,26 @@ ...@@ -16,12 +16,26 @@
#define CLKI 3 #define CLKI 3
#define CLKMAX 4 #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 rsnd_adg {
struct clk *clk[CLKMAX]; 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 rbga_rate_for_441khz; /* RBGA */
int rbgb_rate_for_48khz_div_6; /* RBGB */ int rbgb_rate_for_48khz; /* RBGB */
u32 ckr;
}; };
#define for_each_rsnd_clk(pos, adg, i) \ #define for_each_rsnd_clk(pos, adg, i) \
...@@ -29,8 +43,28 @@ struct rsnd_adg { ...@@ -29,8 +43,28 @@ struct rsnd_adg {
(i < CLKMAX) && \ (i < CLKMAX) && \
((pos) = adg->clk[i]); \ ((pos) = adg->clk[i]); \
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) #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) 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) ...@@ -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, int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io) 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 id = rsnd_mod_id(mod);
int shift = (id % 2) ? 16 : 0; int shift = (id % 2) ? 16 : 0;
u32 mask, val; u32 mask, val;
...@@ -69,21 +106,26 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod, ...@@ -69,21 +106,26 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
val = val << shift; val = val << shift;
mask = 0xffff << shift; mask = 0xffff << shift;
rsnd_mod_bset(mod, CMDOUT_TIMSEL, mask, val); rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);
return 0; 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, struct rsnd_dai_stream *io,
u32 timsel) 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 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; int shift = (id % 2) ? 16 : 0;
u32 mask, ws; u32 mask, ws;
u32 in, out; u32 in, out;
rsnd_mod_confirm_src(src_mod);
ws = rsnd_adg_ssi_ws_timing_gen2(io); ws = rsnd_adg_ssi_ws_timing_gen2(io);
in = (is_play) ? timsel : ws; in = (is_play) ? timsel : ws;
...@@ -95,37 +137,38 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *mod, ...@@ -95,37 +137,38 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *mod,
switch (id / 2) { switch (id / 2) {
case 0: case 0:
rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); rsnd_mod_bset(adg_mod, SRCIN_TIMSEL0, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL0, mask, out);
break; break;
case 1: case 1:
rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); rsnd_mod_bset(adg_mod, SRCIN_TIMSEL1, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL1, mask, out);
break; break;
case 2: case 2:
rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); rsnd_mod_bset(adg_mod, SRCIN_TIMSEL2, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL2, mask, out);
break; break;
case 3: case 3:
rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); rsnd_mod_bset(adg_mod, SRCIN_TIMSEL3, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL3, mask, out);
break; break;
case 4: case 4:
rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); rsnd_mod_bset(adg_mod, SRCIN_TIMSEL4, mask, in);
rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL4, mask, out);
break; break;
} }
return 0; 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, struct rsnd_dai_stream *io,
unsigned int src_rate, unsigned int src_rate,
unsigned int dst_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_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
int idx, sel, div, step, ret; int idx, sel, div, step, ret;
u32 val, en; u32 val, en;
...@@ -134,10 +177,12 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, ...@@ -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[CLKA]), /* 0000: CLKA */
clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */
adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ adg->rbga_rate_for_441khz, /* 0011: RBGA */
adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ adg->rbgb_rate_for_48khz, /* 0100: RBGB */
}; };
rsnd_mod_confirm_src(src_mod);
min = ~0; min = ~0;
val = 0; val = 0;
en = 0; en = 0;
...@@ -175,25 +220,27 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, ...@@ -175,25 +220,27 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
return -EIO; 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) { if (ret < 0) {
dev_err(dev, "timsel error\n"); dev_err(dev, "timsel error\n");
return ret; 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); dev_dbg(dev, "convert rate %d <-> %d\n", src_rate, dst_rate);
return 0; 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) struct rsnd_dai_stream *io)
{ {
u32 val = rsnd_adg_ssi_ws_timing_gen2(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, 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, ...@@ -202,6 +249,7 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
unsigned int dst_rate) unsigned int dst_rate)
{ {
struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 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); struct device *dev = rsnd_priv_to_dev(priv);
int idx, sel, div, shift; int idx, sel, div, shift;
u32 mask, val; u32 mask, val;
...@@ -211,8 +259,8 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, ...@@ -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[CLKB]), /* 001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */ clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */
0, /* 011: MLBCLK (not used) */ 0, /* 011: MLBCLK (not used) */
adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */ adg->rbga_rate_for_441khz, /* 100: RBGA */
adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */ adg->rbgb_rate_for_48khz, /* 101: RBGB */
}; };
/* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */ /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */
...@@ -238,13 +286,13 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, ...@@ -238,13 +286,13 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
switch (id / 4) { switch (id / 4) {
case 0: case 0:
rsnd_mod_bset(mod, AUDIO_CLK_SEL3, mask, val); rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL3, mask, val);
break; break;
case 1: case 1:
rsnd_mod_bset(mod, AUDIO_CLK_SEL4, mask, val); rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL4, mask, val);
break; break;
case 2: case 2:
rsnd_mod_bset(mod, AUDIO_CLK_SEL5, mask, val); rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL5, mask, val);
break; break;
} }
...@@ -257,12 +305,17 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, ...@@ -257,12 +305,17 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
return 0; 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; int shift = (id % 4) * 8;
u32 mask = 0xFF << shift; u32 mask = 0xFF << shift;
rsnd_mod_confirm_ssi(ssi_mod);
val = val << shift; val = val << shift;
/* /*
...@@ -274,13 +327,13 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) ...@@ -274,13 +327,13 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val)
switch (id / 4) { switch (id / 4) {
case 0: case 0:
rsnd_mod_bset(mod, AUDIO_CLK_SEL0, mask, val); rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL0, mask, val);
break; break;
case 1: case 1:
rsnd_mod_bset(mod, AUDIO_CLK_SEL1, mask, val); rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL1, mask, val);
break; break;
case 2: case 2:
rsnd_mod_bset(mod, AUDIO_CLK_SEL2, mask, val); rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL2, mask, val);
break; break;
} }
} }
...@@ -326,14 +379,14 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) ...@@ -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; data = 0x10;
goto found_clock; goto found_clock;
} }
if (rate == adg->rbgb_rate_for_48khz_div_6) { if (rate == adg->rbgb_rate_for_48khz) {
data = 0x20; data = 0x20;
goto found_clock; goto found_clock;
} }
...@@ -342,29 +395,60 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) ...@@ -342,29 +395,60 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
found_clock: 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. * This "mod" = "ssi" here.
* we can get "ssi id" from mod * we can get "ssi id" from mod
*/ */
rsnd_adg_set_ssi_clk(mod, data); rsnd_adg_set_ssi_clk(mod, data);
dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n",
rsnd_mod_id(mod), i, rate); rsnd_mod_name(mod), rsnd_mod_id(mod),
data, rate);
return 0; 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; struct clk *clk;
unsigned long rate; static const char * const clk_name[] = {
u32 ckr; [CLKA] = "clk_a",
[CLKB] = "clk_b",
[CLKC] = "clk_c",
[CLKI] = "clk_i",
};
int 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;
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[] = { int brg_table[] = {
[CLKA] = 0x0, [CLKA] = 0x0,
[CLKB] = 0x1, [CLKB] = 0x1,
...@@ -372,19 +456,34 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -372,19 +456,34 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
[CLKI] = 0x2, [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 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
* have 44.1kHz or 48kHz base clocks for now. * have 44.1kHz or 48kHz base clocks for now.
* *
* SSI itself can divide parent clock by 1/1 - 1/16 * 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 * see
* rsnd_adg_ssi_clk_try_start() * rsnd_adg_ssi_clk_try_start()
* rsnd_ssi_master_clk_start()
*/ */
ckr = 0; ckr = 0;
adg->rbga_rate_for_441khz_div_6 = 0; rbga = 2; /* default 1/6 */
adg->rbgb_rate_for_48khz_div_6 = 0; rbgb = 2; /* default 1/6 */
adg->rbga_rate_for_441khz = 0;
adg->rbgb_rate_for_48khz = 0;
for_each_rsnd_clk(clk, adg, i) { for_each_rsnd_clk(clk, adg, i) {
rate = clk_get_rate(clk); rate = clk_get_rate(clk);
...@@ -392,19 +491,86 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -392,19 +491,86 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
continue; continue;
/* RBGA */ /* RBGA */
if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) { if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) {
adg->rbga_rate_for_441khz_div_6 = rate / 6; 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; ckr |= brg_table[i] << 20;
if (req_441kHz_rate)
parent_clk_name = __clk_get_name(clk);
}
} }
/* RBGB */ /* RBGB */
if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) { if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) {
adg->rbgb_rate_for_48khz_div_6 = rate / 6; 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; ckr |= brg_table[i] << 16;
if (req_48kHz_rate) {
parent_clk_name = __clk_get_name(clk);
ckr |= 0x80000000;
}
} }
} }
}
/*
* ADG supports BRRA/BRRB output only.
* this means all clkout0/1/2/3 will be * same rate
*/
adg->ckr = ckr; /*
* 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, int rsnd_adg_probe(struct platform_device *pdev,
...@@ -413,8 +579,6 @@ 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 rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct clk *clk;
int i;
adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
if (!adg) { if (!adg) {
...@@ -422,15 +586,16 @@ int rsnd_adg_probe(struct platform_device *pdev, ...@@ -422,15 +586,16 @@ int rsnd_adg_probe(struct platform_device *pdev,
return -ENOMEM; return -ENOMEM;
} }
adg->clk[CLKA] = devm_clk_get(dev, "clk_a"); /*
adg->clk[CLKB] = devm_clk_get(dev, "clk_b"); * ADG is special module.
adg->clk[CLKC] = devm_clk_get(dev, "clk_c"); * Use ADG mod without rsnd_mod_init() to make debug easy
adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); * for rsnd_write/rsnd_read
*/
for_each_rsnd_clk(clk, adg, i) adg->mod.ops = &adg_ops;
dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk)); adg->mod.priv = priv;
rsnd_adg_ssi_clk_init(priv, adg); rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg);
priv->adg = adg; priv->adg = adg;
......
...@@ -110,6 +110,7 @@ static const struct rsnd_of_data rsnd_of_data_gen2 = { ...@@ -110,6 +110,7 @@ static const struct rsnd_of_data rsnd_of_data_gen2 = {
static const struct of_device_id rsnd_of_match[] = { static const struct of_device_id rsnd_of_match[] = {
{ .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 }, { .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 },
{ .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 }, { .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); MODULE_DEVICE_TABLE(of, rsnd_of_match);
...@@ -126,6 +127,17 @@ 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) \ #define rsnd_info_id(priv, io, name) \
((io)->info->name - priv->info->name##_info) ((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 * rsnd_mod functions
*/ */
......
...@@ -66,7 +66,7 @@ struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) ...@@ -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))) if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
id = 0; 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, static void rsnd_of_parse_ctu(struct platform_device *pdev,
...@@ -150,7 +150,7 @@ int rsnd_ctu_probe(struct platform_device *pdev, ...@@ -150,7 +150,7 @@ int rsnd_ctu_probe(struct platform_device *pdev,
ctu->info = &info->ctu_info[i]; 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); clk, RSND_MOD_CTU, i);
if (ret) if (ret)
return ret; return ret;
...@@ -166,6 +166,6 @@ void rsnd_ctu_remove(struct platform_device *pdev, ...@@ -166,6 +166,6 @@ void rsnd_ctu_remove(struct platform_device *pdev,
int i; int i;
for_each_rsnd_ctu(ctu, priv, 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) ...@@ -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))) if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
id = 0; 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, static void rsnd_of_parse_dvc(struct platform_device *pdev,
...@@ -361,7 +361,7 @@ int rsnd_dvc_probe(struct platform_device *pdev, ...@@ -361,7 +361,7 @@ int rsnd_dvc_probe(struct platform_device *pdev,
dvc->info = &info->dvc_info[i]; 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); clk, RSND_MOD_DVC, i);
if (ret) if (ret)
return ret; return ret;
...@@ -377,6 +377,6 @@ void rsnd_dvc_remove(struct platform_device *pdev, ...@@ -377,6 +377,6 @@ void rsnd_dvc_remove(struct platform_device *pdev,
int i; int i;
for_each_rsnd_dvc(dvc, priv, 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) ...@@ -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))) if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
id = 0; 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, static void rsnd_of_parse_mix(struct platform_device *pdev,
...@@ -179,7 +179,7 @@ int rsnd_mix_probe(struct platform_device *pdev, ...@@ -179,7 +179,7 @@ int rsnd_mix_probe(struct platform_device *pdev,
mix->info = &info->mix_info[i]; 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); clk, RSND_MOD_MIX, i);
if (ret) if (ret)
return ret; return ret;
...@@ -195,6 +195,6 @@ void rsnd_mix_remove(struct platform_device *pdev, ...@@ -195,6 +195,6 @@ void rsnd_mix_remove(struct platform_device *pdev,
int i; int i;
for_each_rsnd_mix(mix, priv, 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 { ...@@ -214,6 +214,7 @@ struct rsnd_dma {
}; };
#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) #define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp) #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_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
void rsnd_dma_stop(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, ...@@ -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 dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
struct rsnd_mod *mod, char *name); struct rsnd_mod *mod, char *name);
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
/* /*
* R-Car sound mod * R-Car sound mod
*/ */
...@@ -332,6 +331,7 @@ struct rsnd_mod { ...@@ -332,6 +331,7 @@ struct rsnd_mod {
#define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1) #define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1)
#define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk)
#define rsnd_mod_hw_stop(mod) clk_disable((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, int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod, struct rsnd_mod *mod,
...@@ -627,4 +627,15 @@ void rsnd_dvc_remove(struct platform_device *pdev, ...@@ -627,4 +627,15 @@ void rsnd_dvc_remove(struct platform_device *pdev,
struct rsnd_priv *priv); struct rsnd_priv *priv);
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); 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 #endif
...@@ -918,11 +918,10 @@ static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io, ...@@ -918,11 +918,10 @@ static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io,
rsnd_mod_write(mod, SRC_IFSVR, fsrate); 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 rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd) 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_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_src *src = rsnd_mod_to_src(mod); struct rsnd_src *src = rsnd_mod_to_src(mod);
int ret; int ret;
...@@ -931,12 +930,6 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, ...@@ -931,12 +930,6 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
* enable SRC sync convert if possible * enable SRC sync convert if possible
*/ */
/*
* Gen1 is not supported
*/
if (rsnd_is_gen1(priv))
return 0;
/* /*
* SRC sync convert needs clock master * SRC sync convert needs clock master
*/ */
...@@ -975,7 +968,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = { ...@@ -975,7 +968,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = {
.start = rsnd_src_start_gen2, .start = rsnd_src_start_gen2,
.stop = rsnd_src_stop_gen2, .stop = rsnd_src_stop_gen2,
.hw_params = rsnd_src_hw_params, .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) 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) ...@@ -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))) if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
id = 0; 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, static void rsnd_of_parse_src(struct platform_device *pdev,
...@@ -1078,7 +1071,7 @@ int rsnd_src_probe(struct platform_device *pdev, ...@@ -1078,7 +1071,7 @@ int rsnd_src_probe(struct platform_device *pdev,
src->info = &info->src_info[i]; 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) if (ret)
return ret; return ret;
} }
...@@ -1093,6 +1086,6 @@ void rsnd_src_remove(struct platform_device *pdev, ...@@ -1093,6 +1086,6 @@ void rsnd_src_remove(struct platform_device *pdev,
int i; int i;
for_each_rsnd_src(src, priv, 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, ...@@ -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 rsnd_priv *priv = rsnd_io_to_priv(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
int i, j, ret; struct rsnd_mod *mod = rsnd_mod_get(ssi);
int adg_clk_div_table[] = { int j, ret;
1, 6, /* see adg.c */
};
int ssi_clk_mul_table[] = { int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12, 1, 2, 4, 8, 16, 6, 12,
}; };
...@@ -141,7 +139,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -141,7 +139,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
/* /*
* Find best clock, and try to start ADG * 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++) {
/* /*
...@@ -149,22 +146,20 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -149,22 +146,20 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
* system word is 64fs (= 2 x 32bit) * system word is 64fs (= 2 x 32bit)
* see rsnd_ssi_init() * see rsnd_ssi_init()
*/ */
main_rate = rate / adg_clk_div_table[i] main_rate = rate * 32 * 2 * ssi_clk_mul_table[j];
* 32 * 2 * ssi_clk_mul_table[j];
ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate); ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
if (0 == ret) { if (0 == ret) {
ssi->cr_clk = FORCE | SWL_32 | ssi->cr_clk = FORCE | SWL_32 |
SCKD | SWSD | CKDV(j); SCKD | SWSD | CKDV(j);
dev_dbg(dev, "%s[%d] outputs %u Hz\n", dev_dbg(dev, "%s[%d] outputs %u Hz\n",
rsnd_mod_name(&ssi->mod), rsnd_mod_name(mod),
rsnd_mod_id(&ssi->mod), rate); rsnd_mod_id(mod), rate);
return 0; return 0;
} }
} }
}
dev_err(dev, "unsupported clock rate\n"); dev_err(dev, "unsupported clock rate\n");
return -EIO; return -EIO;
...@@ -172,8 +167,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -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) static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi)
{ {
struct rsnd_mod *mod = rsnd_mod_get(ssi);
ssi->cr_clk = 0; 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, static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
...@@ -182,11 +179,12 @@ 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_priv *priv = rsnd_io_to_priv(io);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mod *mod = rsnd_mod_get(ssi);
u32 cr_mode; u32 cr_mode;
u32 cr; u32 cr;
if (0 == ssi->usrcnt) { if (0 == ssi->usrcnt) {
rsnd_mod_hw_start(&ssi->mod); rsnd_mod_hw_start(mod);
if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_rdai_is_clk_master(rdai)) {
struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
...@@ -198,7 +196,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *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 */ cr_mode = UIEN | OIEN | /* over/under run */
DMEN; /* DMA : enable DMA */ DMEN; /* DMA : enable DMA */
} else { } else {
...@@ -210,24 +208,25 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, ...@@ -210,24 +208,25 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
cr_mode | cr_mode |
EN; EN;
rsnd_mod_write(&ssi->mod, SSICR, cr); rsnd_mod_write(mod, SSICR, cr);
/* enable WS continue */ /* enable WS continue */
if (rsnd_rdai_is_clk_master(rdai)) if (rsnd_rdai_is_clk_master(rdai))
rsnd_mod_write(&ssi->mod, SSIWSR, CONT); rsnd_mod_write(mod, SSIWSR, CONT);
/* clear error status */ /* clear error status */
rsnd_mod_write(&ssi->mod, SSISR, 0); rsnd_mod_write(mod, SSISR, 0);
ssi->usrcnt++; ssi->usrcnt++;
dev_dbg(dev, "%s[%d] hw started\n", 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) 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 rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
u32 cr; u32 cr;
...@@ -247,15 +246,15 @@ static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi) ...@@ -247,15 +246,15 @@ static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi)
cr = ssi->cr_own | cr = ssi->cr_own |
ssi->cr_clk; ssi->cr_clk;
rsnd_mod_write(&ssi->mod, SSICR, cr | EN); rsnd_mod_write(mod, SSICR, cr | EN);
rsnd_ssi_status_check(&ssi->mod, DIRQ); rsnd_ssi_status_check(mod, DIRQ);
/* /*
* disable SSI, * disable SSI,
* and, wait idle state * and, wait idle state
*/ */
rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ rsnd_mod_write(mod, SSICR, cr); /* disabled all */
rsnd_ssi_status_check(&ssi->mod, IIRQ); rsnd_ssi_status_check(mod, IIRQ);
if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_rdai_is_clk_master(rdai)) {
struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); 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) ...@@ -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_ssi_master_clk_stop(ssi);
} }
rsnd_mod_hw_stop(&ssi->mod); rsnd_mod_hw_stop(mod);
ssi->chan = 0; ssi->chan = 0;
} }
dev_dbg(dev, "%s[%d] hw stopped\n", 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, ...@@ -371,7 +370,7 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
/* It will be removed on rsnd_ssi_hw_stop */ /* It will be removed on rsnd_ssi_hw_stop */
ssi->chan = chan; ssi->chan = chan;
if (ssi_parent) 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); substream, params);
return 0; return 0;
...@@ -379,12 +378,14 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod, ...@@ -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) static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
{ {
struct rsnd_mod *mod = rsnd_mod_get(ssi);
/* under/over flow error */ /* under/over flow error */
if (status & (UIRQ | OIRQ)) { if (status & (UIRQ | OIRQ)) {
ssi->err++; ssi->err++;
/* clear error status */ /* 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) ...@@ -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))) if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
id = 0; 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) int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
...@@ -668,10 +669,12 @@ 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) 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; return;
switch (rsnd_mod_id(&ssi->mod)) { switch (rsnd_mod_id(mod)) {
case 1: case 1:
case 2: case 2:
ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0)); ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0));
...@@ -794,7 +797,8 @@ int rsnd_ssi_probe(struct platform_device *pdev, ...@@ -794,7 +797,8 @@ int rsnd_ssi_probe(struct platform_device *pdev,
else if (rsnd_ssi_pio_available(ssi)) else if (rsnd_ssi_pio_available(ssi))
ops = &rsnd_ssi_pio_ops; 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) if (ret)
return ret; return ret;
...@@ -811,6 +815,6 @@ void rsnd_ssi_remove(struct platform_device *pdev, ...@@ -811,6 +815,6 @@ void rsnd_ssi_remove(struct platform_device *pdev,
int i; int i;
for_each_rsnd_ssi(ssi, priv, i) { for_each_rsnd_ssi(ssi, priv, i) {
rsnd_mod_quit(&ssi->mod); rsnd_mod_quit(rsnd_mod_get(ssi));
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment