All of lore.kernel.org
 help / color / mirror / Atom feed
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...

  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 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.