From: Arnaud Pouliquen <arnaud.pouliquen@st.com>
To: Mark Brown <broonie@kernel.org>
Cc: alsa-devel@alsa-project.org, lgirdwood@gmail.com
Subject: Re: [PATCH 3/7] Asoc: sti: add CPU DAI driver for playback
Date: Mon, 27 Apr 2015 15:58:56 +0200 [thread overview]
Message-ID: <553E40A0.4030904@st.com> (raw)
In-Reply-To: <20150424181528.GF22845@sirena.org.uk>
On 04/24/2015 08:15 PM, Mark Brown wrote:
> On Tue, Apr 14, 2015 at 03:35:27PM +0200, Arnaud Pouliquen wrote:
>
>> +const struct snd_pcm_hardware uni_player_pcm_hw = {
>> + .info = (
>> + SNDRV_PCM_INFO_INTERLEAVED |
>> + SNDRV_PCM_INFO_BLOCK_TRANSFER |
>> + SNDRV_PCM_INFO_PAUSE),
>> + .formats = (SNDRV_PCM_FMTBIT_S32_LE |
>> + SNDRV_PCM_FMTBIT_S16_LE),
> Please use the normal kernel coding style, standard indentation and no
> brackets.
>
>> + .rates = SNDRV_PCM_RATE_CONTINUOUS,
>> + .rate_min = UNIPERIF_MIN_RATE,
>> + .rate_max = UNIPERIF_MAX_RATE,
>> +
>> + .channels_min = UNIPERIF_MIN_CHANNELS,
>> + .channels_max = UNIPERIF_MAX_CHANNELS,
>> +
>> + .periods_min = UNIPERIF_PERIODS_MIN,
>> + .periods_max = UNIPERIF_PERIODS_MAX,
>> +
>> + .period_bytes_min = UNIPERIF_PERIODS_BYTES_MIN,
>> + .period_bytes_max = UNIPERIF_PERIODS_BYTES_MAX,
>> + .buffer_bytes_max = UNIPERIF_BUFFER_BYTES_MAX
> Just use the values directly, the indirection is just making it harder
> to find what's actually set.
>
>> +static inline int reset_player(struct uniperif *player)
>> +{
>> + int count = 10;
>> +
>> + if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
>> + while (GET_UNIPERIF_SOFT_RST_SOFT_RST(player) && count) {
>> + udelay(5);
>> + count--;
>> + }
> Braces for the if too. A cpu_relax() wouldn't go amiss in here either.
>
>> +static inline int get_property_hdl(struct device *dev, struct device_node *np,
>> + const char *prop, int idx)
>> +{
> This is very suspicous - why do you need this and if you need it why not
> add it to the generic DT code?
>
>> +static void uni_player_work(struct work_struct *work)
>> +{
>> + struct uniperif *player =
>> + container_of(work, struct uniperif, delayed_work.work);
>> +
>> + spin_lock(&player->lock);
>> + if (uni_player_suspend(player))
>> + dev_err(player->dev, "%s: failed to suspend player", __func__);
>> + spin_unlock(&player->lock);
>> +}
> What is this for, and why is there a spinlock which isn't IRQ safe? If
> it's sensible to do this under a spinlock it seems like it might not
> need to be done in a workqueue...
>
> There's a lot of very coarse grained spinlock usage in this driver which
> I'm having a hard time understanding, at the very least the decisions
> about locking need to be documented much more clearly and I suspect that
> either things need to be finer grained, we should be using mutexes more
> or both.
>
This part is linked to the standby mode described in binding ( patch[1/7])
it manage a runtime suspend, because ASOC runtime suspend is dedicated
to DAPM.
As you recommend i will try to change it by a DAPM linked to CPU_DAI.
Just need to find a wait
to retrieve CPU_DAI context in DAPM..
Concerning spinlock
I use it to protect context ( called by IRQ, on suspend, by user...). As
some code is called in atomic i can not use mutex.
I will review it and document it.
>> +static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
>> +{
>> + irqreturn_t ret = IRQ_NONE;
>> + struct uniperif *player = dev_id;
>> + unsigned int status;
>> + unsigned int tmp;
>> +
>> + /* Get interrupt status & clear them immediately */
>> + preempt_disable();
>> + status = GET_UNIPERIF_ITS(player);
>> + SET_UNIPERIF_ITS_BCLR(player, status);
>> + preempt_enable();
> preempt_disable()? Why is this being done, if you're doing unusual
> stuff like this the code needs to be very clear about what the locking
> rules are?
This is used to be sure to not miss an interrupt. If preempted between both
instruction i can clear an interruption flag before treat it. In this
case i will receive
a second interrupt with all flag to 0.
>
>> +
>> + if ((player->state == UNIPERIF_STATE_STANDBY) ||
>> + (player->state == UNIPERIF_STATE_STOPPED)) {
>> + /* unexpected IRQ: do nothing */
>> + dev_warn(player->dev, "unexpected IRQ: status flag: %#x",
>> + status);
>> + return IRQ_HANDLED;
> We didn't handle it, we ignored it (after acknowledging it...). I'd
> expect this check to be before we look at the hardware if it's needed.
>
>> + };
> Extra semicolon here.
>
>> + snd_pcm_stream_lock(player->substream);
> Again please explain the locking if we're doing something unusual.
This protect from a race condition, if application request a stop while
we receive Error from IP.
I call it here to avoid toprotect all snd_pcm_stop calls... but i can
protect only the snd_pcm_stop
calls if more clear
>
>> + /* Check for fifo error (under run) */
>> + if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(player))) {
>> + dev_err(player->dev, "FIFO underflow error detected");
>> +
>> + /* Interrupt is just for information when underflow recovery */
>> + if (player->info->underflow_enabled) {
>> + /* Update state to underflow */
>> + player->state = UNIPERIF_STATE_UNDERFLOW;
> Why would underflow recovery be optional?
To propose 2 strategies:
- stop on underrun ( because plop will occurs)
- try to recover it: time is recovered when new data is available (
sample dropping)
>
>> + if (clk_set_rate(player->clk, rate_adjusted) < 0) {
>> + dev_err(player->dev, "Failed to clk set rate %d !\n",
>> + rate_adjusted);
>> + return -EINVAL;
>> + }
> Pass back the error code you got.
>
>> + rate_achieved = clk_get_rate(player->clk);
>> + if (!rate_achieved)
>> + return -EINVAL;
> That check doesn't seem right - if the clock was set to 1Hz instead of
> 1MHz it'll report success. Either trust that clk_set_rate() will give
> you an error if it fails or have some sort of reasonable check on the
> actual set value if that's important.
>
>> +static int snd_sti_clk_adjustment_get(struct snd_kcontrol *kcontrol,
>> + struct snd_ctl_elem_value *ucontrol)
>> +{
>> + struct uniperif *player = snd_kcontrol_chip(kcontrol);
>> +
>> + spin_lock(&player->lock);
>> + ucontrol->value.integer.value[0] = player->clk_adj;
>> + spin_unlock(&player->lock);
>> +
>> + return 0;
>> +}
> There was some discussion of interfaces for fine tuning clock rates with
> some other drivers recently, we need to think about this in some
> standard fashion. Please split this out into a separate patch. In
> general it's best to introduce unusual/new things like this and the IEC
> setting in separate patches to simplify review and allow the easy bits
> to get merged without being held up by complicated things like this.
Ok i will add Clk and IEC controls in separate patches
>> + of_property_read_u32(pnode, "version", &info->ver);
>> +
>> + of_property_read_u32(pnode, "uniperiph-id", &info->uni_num);
> We can't read this stuff from the hardware?
Unfortunately No...
next prev parent reply other threads:[~2015-04-27 13:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-14 13:35 [PATCH 0/7] asoc: Add audio for sti platforms Arnaud Pouliquen
2015-04-14 13:35 ` [PATCH 1/7] ASoC: sti: add binding for ASoc driver Arnaud Pouliquen
2015-04-18 13:12 ` Mark Brown
2015-04-14 13:35 ` [PATCH 2/7] Asoc: sti: add uniperipheral header file Arnaud Pouliquen
2015-07-10 18:08 ` Applied "ASoC: sti: Add uniperipheral header file" to the asoc tree Mark Brown
2015-04-14 13:35 ` [PATCH 3/7] Asoc: sti: add CPU DAI driver for playback Arnaud Pouliquen
2015-04-24 18:15 ` Mark Brown
2015-04-27 13:58 ` Arnaud Pouliquen [this message]
2015-04-27 19:46 ` Mark Brown
2015-04-14 13:35 ` [PATCH 4/7] Asoc: sti: add CPU DAI driver for capture Arnaud Pouliquen
2015-04-24 18:20 ` Mark Brown
2015-04-27 14:53 ` Arnaud Pouliquen
2015-04-27 20:00 ` Mark Brown
2015-04-14 13:35 ` [PATCH 5/7] Asoc: sti: Add platform driver Arnaud Pouliquen
2015-04-14 13:35 ` [PATCH 6/7] ASoc: Add ability to build sti drivers Arnaud Pouliquen
2015-04-14 13:35 ` [PATCH 7/7] ASoc: Codec: add sti platform codec Arnaud Pouliquen
2015-04-18 13:09 ` Mark Brown
2015-04-20 9:13 ` Arnaud Pouliquen
2015-04-20 20:33 ` Mark Brown
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=553E40A0.4030904@st.com \
--to=arnaud.pouliquen@st.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=lgirdwood@gmail.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox