summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-08-23 14:50:04 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2020-10-12 21:55:22 +0100
commit64ba939dd2beab5c66a5c16db9e5dfabb11a2a15 (patch)
tree36b572a2ccfeade4e71ae4873dea5dbb4dc0307f
parent01fbe7c5abe9af9054b8594f14fa55c3e6e78304 (diff)
asoc: sa11x0/assabet: use gpiod APIs for some gpios
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm/mach-sa1100/assabet.c18
-rw-r--r--arch/arm/mach-sa1100/clock.c2
-rw-r--r--sound/soc/sa11x0/assabet.c92
3 files changed, 74 insertions, 38 deletions
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 49760b630bdb..e1fa048ee782 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -454,6 +454,22 @@ static struct resource neponset_resources[] = {
};
#endif
+static struct gpiod_lookup_table assabet_uda1341_gpio_table = {
+ .dev_id = "uda134x-codec",
+ .table = {
+ GPIO_LOOKUP("assabet", 21, "qmute", GPIO_ACTIVE_HIGH),
+ { },
+ },
+};
+
+static struct gpiod_lookup_table assabet_audio_gpio_table = {
+ .dev_id = "assabet-asoc",
+ .table = {
+ GPIO_LOOKUP("assabet", 23, "spkr-shtdn", GPIO_ACTIVE_HIGH),
+ { },
+ },
+};
+
static struct gpiod_lookup_table assabet_cf_gpio_table = {
.dev_id = "sa11x0-pcmcia.1",
.table = {
@@ -553,6 +569,8 @@ static struct gpiod_lookup_table assabet_uart3_gpio_table = {
static void __init assabet_init(void)
{
gpiod_add_lookup_table(&assabet_irda_gpio_table);
+ gpiod_add_lookup_table(&assabet_uda1341_gpio_table);
+ gpiod_add_lookup_table(&assabet_audio_gpio_table);
/*
* Ensure that the power supply is in "high power" mode.
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index c4356e620c0f..a33455e2fa31 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -122,6 +122,8 @@ int __init sa11xx_clk_init(void)
clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.1");
clk_hw_register_clkdev(hw, NULL, "1800");
+ clk_hw_register_clkdev(hw, NULL, "assabet-asoc");
+
hw = clk_hw_register_mux(NULL, "tucr-mux", clk_tucr_parents,
ARRAY_SIZE(clk_tucr_parents), 0,
(void __iomem *)&TUCR, FShft(TUCR_TSEL),
diff --git a/sound/soc/sa11x0/assabet.c b/sound/soc/sa11x0/assabet.c
index 0e8bbb34ffb6..d6c9cbefc1f6 100644
--- a/sound/soc/sa11x0/assabet.c
+++ b/sound/soc/sa11x0/assabet.c
@@ -27,9 +27,10 @@
* requested sample rate; the UDA1341 driver will just fail the preparation.
* We rely on userspace (at present) to ask for the correct sample rate.
*/
-#include <linux/cpufreq.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -46,6 +47,8 @@
struct assabet_card {
struct snd_soc_card card;
+ struct clk *clk_cpu;
+ struct gpio_desc *gpio_spkr_shtdn;
};
#define GPIO_TXD 10
@@ -81,7 +84,7 @@ static void assabet_asoc_uda1341_power(int on)
* Enable the power for the UDA1341 before fixing WS.
* Also assert the mute signal.
*/
- ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON | ASSABET_BCR_QMUTE);
+ ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON);
/*
* Toggle SFRM with the codec reset signal held active.
@@ -109,9 +112,6 @@ static void assabet_asoc_uda1341_power(int on)
/* Finally, disable the audio power */
ASSABET_BCR_clear(ASSABET_BCR_AUDIO_ON);
-
- /* And lower the QMUTE signal to stop power draining */
- ASSABET_BCR_clear(ASSABET_BCR_QMUTE);
}
}
@@ -155,11 +155,30 @@ static int assabet_asoc_resume_pre(struct snd_soc_card *card)
return 0;
}
+/*
+ * Calculate the sysclk, which is the codec input clock. This is supplied
+ * from the SDRAM bank 2 clock, divided by 18 by the CPLD. This is then
+ * further divided by four by the CPLD, and supplied to the SA1110 GPIO19
+ * to synchronously drive the SSP block.
+ *
+ * Ideally, we would lock cpufreq against any transitions which would upset
+ * the sample rate, or have userspace renegotiate the sample rate, but let's
+ * keep this simple.
+ *
+ * We intentionally lose some precision here to avoid the codec bombing out
+ * as it claims to only do standard rates.
+ */
+static unsigned int assabet_asoc_get_sysclk(struct assabet_card *ac)
+{
+ return (clk_get_rate(ac->clk_cpu) / 18000) * 1000;
+}
+
static int
assabet_asoc_rate_constraint(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
{
+ struct assabet_card *ac = rule->private;
struct snd_interval range, *p = hw_param_interval(params, rule->var);
- unsigned int sysclk = (cpufreq_get(0) / 18) * 1000;
+ unsigned int sysclk = assabet_asoc_get_sysclk(ac);
snd_interval_any(&range);
range.min = UINT_MAX;
@@ -180,12 +199,17 @@ assabet_asoc_rate_constraint(struct snd_pcm_hw_params *params, struct snd_pcm_hw
static int assabet_asoc_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct assabet_card *ac = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret;
if (!cpu_dai->active) {
unsigned long flags;
unsigned int sysclk;
- int ret;
+
+ ret = clk_prepare_enable(ac->clk_cpu);
+ if (ret)
+ return ret;
/*
* Hand the SFRM signal over to the SSP block as it is
@@ -198,53 +222,36 @@ static int assabet_asoc_startup(struct snd_pcm_substream *substream)
assabet_asoc_init_clk();
local_irq_restore(flags);
- /*
- * Calculate the sysclk, which is the codec input clock.
- * This is supplied from the SDRAM bank 2 clock, divided by
- * 18 by the CPLD. This is then further divided by four by
- * the CPLD, and supplied to the SA1110 GPIO19 to
- * synchronously drive the SSP block.
- *
- * Ideally, we would lock cpufreq against any transitions
- * which would upset the sample rate, or have userspace
- * renegotiate the sample rate, but let's keep this simple.
- *
- * We intentionally lose some precision here to avoid the
- * codec bombing out as it claims to only do standard rates.
- */
- sysclk = (cpufreq_get(0) / 18) * 1000;
+ sysclk = assabet_asoc_get_sysclk(ac);
ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, sysclk,
SND_SOC_CLOCK_IN);
if (ret < 0)
- return ret;
+ goto err;
ret = snd_soc_dai_set_sysclk(cpu_dai, SA11X0_SSP_CLK_EXT,
sysclk / 4, SND_SOC_CLOCK_IN);
if (ret < 0)
- return ret;
+ goto err;
}
- /* Release the mute */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ASSABET_BCR_clear(ASSABET_BCR_QMUTE);
-
snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- assabet_asoc_rate_constraint, NULL,
+ assabet_asoc_rate_constraint, ac,
SNDRV_PCM_HW_PARAM_RATE, -1);
return 0;
+
+err:
+ clk_disable_unprepare(ac->clk_cpu);
+ return ret;
}
static void assabet_asoc_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct assabet_card *ac = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- /* Apply the output mute */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ASSABET_BCR_set(ASSABET_BCR_QMUTE);
-
if (!cpu_dai->active) {
unsigned long flags;
@@ -255,6 +262,8 @@ static void assabet_asoc_shutdown(struct snd_pcm_substream *substream)
local_irq_save(flags);
GAFR &= ~GPIO_SSP_SFRM;
local_irq_restore(flags);
+
+ clk_disable_unprepare(ac->clk_cpu);
}
}
@@ -279,10 +288,9 @@ static int
assabet_pwramp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k,
int event)
{
- if (SND_SOC_DAPM_EVENT_ON(event))
- ASSABET_BCR_clear(ASSABET_BCR_SPK_OFF);
- else
- ASSABET_BCR_set(ASSABET_BCR_SPK_OFF);
+ struct assabet_card *ac = snd_soc_card_get_drvdata(w->dapm->card);
+
+ gpiod_set_value(ac->gpio_spkr_shtdn, !SND_SOC_DAPM_EVENT_ON(event));
return 0;
}
@@ -381,6 +389,15 @@ static int assabet_asoc_probe(struct platform_device *pdev)
memcpy(&ac->card, &snd_soc_assabet, sizeof(ac->card));
ac->card.dev = &pdev->dev;
+ ac->clk_cpu = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ac->clk_cpu))
+ return PTR_ERR(ac->clk_cpu);
+
+ ac->gpio_spkr_shtdn = devm_gpiod_get(&pdev->dev, "spkr-shtdn",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ac->gpio_spkr_shtdn))
+ return PTR_ERR(ac->gpio_spkr_shtdn);
+
snd_soc_card_set_drvdata(&ac->card, ac);
return snd_soc_register_card(&ac->card);
@@ -434,7 +451,6 @@ static int assabet_init(void)
* and it defaults to logic 1. So, first release the reset,
* and then toggle the SFRM signal to set LRCK to zero.
*/
- ASSABET_BCR_set(ASSABET_BCR_SPK_OFF);
ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB);
assabet_uda1341_reset(0);