From: Lars-Peter Clausen <lars@metafoo.de>
To: Florian Meier <florian.meier@koalo.de>
Cc: Mark Brown <broonie@kernel.org>,
Liam Girdwood <lgirdwood@gmail.com>,
swarren@wwwdotorg.org, alsa-devel@alsa-project.org,
linux-kernel@vger.kernel.org,
linux-rpi-kernel@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>
Subject: Re: [PATCH] ASoC: Add support for BCM2708
Date: Wed, 22 May 2013 19:26:53 +0200 [thread overview]
Message-ID: <519CFFDD.4080203@metafoo.de> (raw)
In-Reply-To: <519CD1CC.8070507@koalo.de>
On 05/22/2013 04:10 PM, Florian Meier wrote:
[...]
> diff --git a/sound/soc/bcm2708/bcm2708-i2s.c b/sound/soc/bcm2708/bcm2708-i2s.c
> new file mode 100644
> index 0000000..a8e995f
> --- /dev/null
> +++ b/sound/soc/bcm2708/bcm2708-i2s.c
> @@ -0,0 +1,964 @@
[...]
> +static int bcm2708_i2s_startup(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
> +
> + if (!dev->first_stream) {
> + dev->first_stream = substream;
> +
> + /* should this still be running stop it */
> + bcm2708_i2s_stop_clock(dev);
> +
> + /* enable PCM block */
> + bcm2708_i2s_set_bits(dev, BCM2708_I2S_CS_A_REG, BCM2708_I2S_EN);
> +
> + /*
> + * Disable STBY
> + * Requires at least 4 PCM clock cycles to take effect
> + */
> + bcm2708_i2s_set_bits(dev, BCM2708_I2S_CS_A_REG,
> + BCM2708_I2S_STBY);
> + } else {
> + struct snd_pcm_runtime *first_runtime =
> + dev->first_stream->runtime;
> +
> + /*
> + * This is the second stream open, so we need to impose
> + * sample size and sampling rate constraints.
> + * This is because frame length and clock cannot be specified
> + * seperately.
> + *
> + * Note that this can cause a race condition if the
> + * second stream is opened before the first stream is
> + * fully initialized. We provide some protection by
> + * checking to make sure the first stream is
> + * initialized, but it's not perfect. ALSA sometimes
> + * re-initializes the driver with a different sample
> + * rate or size. If the second stream is opened
> + * before the first stream has received its final
> + * parameters, then the second stream may be
> + * constrained to the wrong sample rate or size.
> + *
> + * We will continue in case of failure and recheck the
> + * constraint in hw_params.
> + */
> + if (!first_runtime->format) {
> + dev_err(substream->pcm->card->dev,
> + "Set format in %s stream first! "
> + "Initialization may fail.\n",
> + substream->stream ==
> + SNDRV_PCM_STREAM_PLAYBACK
> + ? "capture" : "playback");
> + } else {
> + snd_pcm_hw_constraint_minmax(substream->runtime,
> + SNDRV_PCM_HW_PARAM_FORMAT,
> + first_runtime->format,
> + first_runtime->format);
> + }
> +
> + if (!first_runtime->rate) {
> + dev_err(substream->pcm->card->dev,
> + "Set sampling rate in %s stream first! "
> + "Initialization may fail!\n",
> + substream->stream ==
> + SNDRV_PCM_STREAM_PLAYBACK
> + ? "capture" : "playback");
> + } else {
> + snd_pcm_hw_constraint_minmax(substream->runtime,
> + SNDRV_PCM_HW_PARAM_RATE,
> + first_runtime->rate,
> + first_runtime->rate);
> + }
Setting the symmetric_rates lets the core take care of setting the proper
constraints on the rate. It probably makes sense to also add a
symmetric_formats since this isn't the only driver that has the requirement
that the formats for playback and capture match.
> +
> + dev->second_stream = substream;
> + }
> +
> + snd_soc_dai_set_dma_data(dai, substream,
> + &dev->dma_params[substream->stream]);
> +
> + return 0;
> +}
> +
> +static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
> +
> + bcm2708_i2s_stop(dev, substream);
> +
> + if (dev->first_stream == substream)
> + dev->first_stream = dev->second_stream;
> +
> + dev->second_stream = NULL;
> +
> + /* If both streams are stopped, disable module and clock */
> + if (!dev->first_stream) {
> + /* Disable the module */
> + bcm2708_i2s_clear_bits(dev, BCM2708_I2S_CS_A_REG,
> + BCM2708_I2S_EN);
> +
> + /*
> + * Stopping clock is necessary, because stop does
> + * not stop the clock when SND_SOC_DAIFMT_CONT
> + */
> + bcm2708_i2s_stop_clock(dev);
> + }
> +}
[...]
> diff --git a/sound/soc/bcm2708/bcm2708-pcm.c b/sound/soc/bcm2708/bcm2708-pcm.c
> new file mode 100644
> index 0000000..4b3e688
> --- /dev/null
> +++ b/sound/soc/bcm2708/bcm2708-pcm.c
> @@ -0,0 +1,303 @@
I think you should be able to remove the bulk of this driver by using the
generic PCM dmaengine driver.
[...]
> +
> +#include "bcm2708-pcm.h"
> +
> +static const struct snd_pcm_hardware bcm2708_pcm_hardware = {
> + .info = SNDRV_PCM_INFO_MMAP |
> + SNDRV_PCM_INFO_MMAP_VALID |
> + SNDRV_PCM_INFO_INTERLEAVED |
> + SNDRV_PCM_INFO_PAUSE |
> + SNDRV_PCM_INFO_RESUME |
> + SNDRV_PCM_INFO_JOINT_DUPLEX |
> + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
I don't think you actually support the last one, and neither pause and
resume are supported.
> + .formats = SNDRV_PCM_FMTBIT_S16_LE |
> + SNDRV_PCM_FMTBIT_S32_LE,
> + .period_bytes_min = 32,
> + .period_bytes_max = 64 * 1024,
> + .periods_min = 2,
> + .periods_max = 255,
> + .buffer_bytes_max = 128 * 1024,
> +};
> +
[...]
WARNING: multiple messages have this Message-ID (diff)
From: lars@metafoo.de (Lars-Peter Clausen)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] ASoC: Add support for BCM2708
Date: Wed, 22 May 2013 19:26:53 +0200 [thread overview]
Message-ID: <519CFFDD.4080203@metafoo.de> (raw)
In-Reply-To: <519CD1CC.8070507@koalo.de>
On 05/22/2013 04:10 PM, Florian Meier wrote:
[...]
> diff --git a/sound/soc/bcm2708/bcm2708-i2s.c b/sound/soc/bcm2708/bcm2708-i2s.c
> new file mode 100644
> index 0000000..a8e995f
> --- /dev/null
> +++ b/sound/soc/bcm2708/bcm2708-i2s.c
> @@ -0,0 +1,964 @@
[...]
> +static int bcm2708_i2s_startup(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
> +
> + if (!dev->first_stream) {
> + dev->first_stream = substream;
> +
> + /* should this still be running stop it */
> + bcm2708_i2s_stop_clock(dev);
> +
> + /* enable PCM block */
> + bcm2708_i2s_set_bits(dev, BCM2708_I2S_CS_A_REG, BCM2708_I2S_EN);
> +
> + /*
> + * Disable STBY
> + * Requires at least 4 PCM clock cycles to take effect
> + */
> + bcm2708_i2s_set_bits(dev, BCM2708_I2S_CS_A_REG,
> + BCM2708_I2S_STBY);
> + } else {
> + struct snd_pcm_runtime *first_runtime =
> + dev->first_stream->runtime;
> +
> + /*
> + * This is the second stream open, so we need to impose
> + * sample size and sampling rate constraints.
> + * This is because frame length and clock cannot be specified
> + * seperately.
> + *
> + * Note that this can cause a race condition if the
> + * second stream is opened before the first stream is
> + * fully initialized. We provide some protection by
> + * checking to make sure the first stream is
> + * initialized, but it's not perfect. ALSA sometimes
> + * re-initializes the driver with a different sample
> + * rate or size. If the second stream is opened
> + * before the first stream has received its final
> + * parameters, then the second stream may be
> + * constrained to the wrong sample rate or size.
> + *
> + * We will continue in case of failure and recheck the
> + * constraint in hw_params.
> + */
> + if (!first_runtime->format) {
> + dev_err(substream->pcm->card->dev,
> + "Set format in %s stream first! "
> + "Initialization may fail.\n",
> + substream->stream ==
> + SNDRV_PCM_STREAM_PLAYBACK
> + ? "capture" : "playback");
> + } else {
> + snd_pcm_hw_constraint_minmax(substream->runtime,
> + SNDRV_PCM_HW_PARAM_FORMAT,
> + first_runtime->format,
> + first_runtime->format);
> + }
> +
> + if (!first_runtime->rate) {
> + dev_err(substream->pcm->card->dev,
> + "Set sampling rate in %s stream first! "
> + "Initialization may fail!\n",
> + substream->stream ==
> + SNDRV_PCM_STREAM_PLAYBACK
> + ? "capture" : "playback");
> + } else {
> + snd_pcm_hw_constraint_minmax(substream->runtime,
> + SNDRV_PCM_HW_PARAM_RATE,
> + first_runtime->rate,
> + first_runtime->rate);
> + }
Setting the symmetric_rates lets the core take care of setting the proper
constraints on the rate. It probably makes sense to also add a
symmetric_formats since this isn't the only driver that has the requirement
that the formats for playback and capture match.
> +
> + dev->second_stream = substream;
> + }
> +
> + snd_soc_dai_set_dma_data(dai, substream,
> + &dev->dma_params[substream->stream]);
> +
> + return 0;
> +}
> +
> +static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream,
> + struct snd_soc_dai *dai)
> +{
> + struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
> +
> + bcm2708_i2s_stop(dev, substream);
> +
> + if (dev->first_stream == substream)
> + dev->first_stream = dev->second_stream;
> +
> + dev->second_stream = NULL;
> +
> + /* If both streams are stopped, disable module and clock */
> + if (!dev->first_stream) {
> + /* Disable the module */
> + bcm2708_i2s_clear_bits(dev, BCM2708_I2S_CS_A_REG,
> + BCM2708_I2S_EN);
> +
> + /*
> + * Stopping clock is necessary, because stop does
> + * not stop the clock when SND_SOC_DAIFMT_CONT
> + */
> + bcm2708_i2s_stop_clock(dev);
> + }
> +}
[...]
> diff --git a/sound/soc/bcm2708/bcm2708-pcm.c b/sound/soc/bcm2708/bcm2708-pcm.c
> new file mode 100644
> index 0000000..4b3e688
> --- /dev/null
> +++ b/sound/soc/bcm2708/bcm2708-pcm.c
> @@ -0,0 +1,303 @@
I think you should be able to remove the bulk of this driver by using the
generic PCM dmaengine driver.
[...]
> +
> +#include "bcm2708-pcm.h"
> +
> +static const struct snd_pcm_hardware bcm2708_pcm_hardware = {
> + .info = SNDRV_PCM_INFO_MMAP |
> + SNDRV_PCM_INFO_MMAP_VALID |
> + SNDRV_PCM_INFO_INTERLEAVED |
> + SNDRV_PCM_INFO_PAUSE |
> + SNDRV_PCM_INFO_RESUME |
> + SNDRV_PCM_INFO_JOINT_DUPLEX |
> + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
I don't think you actually support the last one, and neither pause and
resume are supported.
> + .formats = SNDRV_PCM_FMTBIT_S16_LE |
> + SNDRV_PCM_FMTBIT_S32_LE,
> + .period_bytes_min = 32,
> + .period_bytes_max = 64 * 1024,
> + .periods_min = 2,
> + .periods_max = 255,
> + .buffer_bytes_max = 128 * 1024,
> +};
> +
[...]
next prev parent reply other threads:[~2013-05-22 17:26 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-22 14:10 [PATCH] ASoC: Add support for BCM2708 Florian Meier
2013-05-22 14:10 ` Florian Meier
2013-05-22 15:22 ` Stephen Warren
2013-05-22 15:22 ` Stephen Warren
2013-05-22 16:08 ` Florian Meier
2013-05-22 16:08 ` Florian Meier
2013-05-22 16:15 ` Stephen Warren
2013-05-22 16:15 ` Stephen Warren
2013-05-22 17:11 ` Florian Meier
2013-05-22 17:11 ` Florian Meier
2013-05-22 16:42 ` Mark Brown
2013-05-22 16:42 ` Mark Brown
2013-05-22 16:42 ` Mark Brown
2013-05-22 16:39 ` Mark Brown
2013-05-22 16:39 ` Mark Brown
2013-05-22 16:39 ` Mark Brown
2013-05-22 17:16 ` Florian Meier
2013-05-22 17:16 ` Florian Meier
2013-05-22 17:26 ` Lars-Peter Clausen [this message]
2013-05-22 17:26 ` Lars-Peter Clausen
2013-05-24 15:32 ` Florian Meier
2013-05-24 15:32 ` Florian Meier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=519CFFDD.4080203@metafoo.de \
--to=lars@metafoo.de \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=florian.meier@koalo.de \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rpi-kernel@lists.infradead.org \
--cc=perex@perex.cz \
--cc=swarren@wwwdotorg.org \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.