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:
@@ -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:
|
|||||||
- 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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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[] = {
|
|||||||
{ .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[] = {
|
|||||||
{ .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)
|
|||||||
|
|
||||||
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 @@ err1:
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
#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 {
|
|||||||
(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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 @@ find_rate:
|
|||||||
|
|
||||||
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 @@ find_rate:
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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;
|
||||||
|
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;
|
struct clk *clk;
|
||||||
unsigned long rate;
|
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
|
||||||
u32 ckr;
|
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;
|
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)
|
|||||||
[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)
|
|||||||
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->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,
|
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,
|
|||||||
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
|
||||||
|
*/
|
||||||
|
adg->mod.ops = &adg_ops;
|
||||||
|
adg->mod.priv = priv;
|
||||||
|
|
||||||
for_each_rsnd_clk(clk, adg, i)
|
rsnd_adg_get_clkin(priv, adg);
|
||||||
dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
|
rsnd_adg_get_clkout(priv, adg);
|
||||||
|
|
||||||
rsnd_adg_ssi_clk_init(priv, adg);
|
|
||||||
|
|
||||||
priv->adg = 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[] = {
|
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);
|
|||||||
#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)
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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 {
|
|||||||
};
|
};
|
||||||
#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,
|
|||||||
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 {
|
|||||||
#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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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 = {
|
|||||||
.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)
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user