[PATCH v6 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
Bhushan Bharat-R65777
R65777 at freescale.com
Mon Aug 19 14:38:11 EST 2013
> -----Original Message-----
> From: Chen Guangyu-B42378
> Sent: Monday, August 19, 2013 8:38 AM
> To: Bhushan Bharat-R65777
> Cc: broonie at kernel.org; lars at metafoo.de; p.zabel at pengutronix.de;
> s.hauer at pengutronix.de; mark.rutland at arm.com; devicetree at vger.kernel.org; alsa-
> devel at alsa-project.org; swarren at wwwdotorg.org; festevam at gmail.com;
> timur at tabi.org; rob.herring at calxeda.com; tomasz.figa at gmail.com;
> shawn.guo at linaro.org; linuxppc-dev at lists.ozlabs.org
> Subject: Re: [PATCH v6 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver
>
> Hi Bhushan,
>
> Thank you for the comments :)
> I'll fix some in v7.
>
> Here is my some replies to you.
>
> On Sat, Aug 17, 2013 at 02:24:19AM +0800, Bhushan Bharat-R65777 wrote:
> > > This patch add S/PDIF controller driver for Freescale SoC.
> >
> > Please give some more description of the driver?
>
> I've referred some ASoC drivers, all of them seem to be brief as mine.
> So I'm not sure what else information I should provide here. It's already kinda
> okay to me.
Other does not have description does not mean we also should not add description here.
Please describe in few lines about this driver and devices it handles?
>
>
> > > +struct spdif_mixer_control {
> > > + /* buffer ptrs for writer */
> > > + u32 upos;
> > > + u32 qpos;
> >
> > They does not look like pointer?
>
> They are more like offsets to get the correspond pointer.
> But I'll change the confusing comments.
>
>
> > > +/* U/Q Channel receive register full */ static void
> > > +spdif_irq_uqrx_full(struct fsl_spdif_priv *spdif_priv, char name) {
> > > + struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
> > > + struct regmap *regmap = spdif_priv->regmap;
> > > + struct platform_device *pdev = spdif_priv->pdev;
> > > + u32 *pos, size, val, reg;
> > > +
> > > + switch (name) {
> > > + case 'U':
> > > + pos = &ctrl->upos;
> > > + size = SPDIF_UBITS_SIZE;
> > > + reg = REG_SPDIF_SRU;
> > > + break;
> > > + case 'Q':
> > > + pos = &ctrl->qpos;
> > > + size = SPDIF_QSUB_SIZE;
> > > + reg = REG_SPDIF_SRQ;
> > > + break;
> > > + default:
> > > + return;
> >
> > Should return error.
>
> IMHO, this should be fine. It's a void type function and being used in the
> isr(). The params 'name' is totally controlled by driver itself, so basically we
> don't need to worry about the default path.
Silently returning on potential error is bad. At least add a printk/BUGON or something similar which points that some unexpected parameter is passed.
>
> > > + if (*pos >= size * 2) {
> > > + *pos = 0;
> > > + } else if (unlikely((*pos % size) + 3 > size)) {
> > > + dev_err(&pdev->dev, "User bit receivce buffer overflow\n");
> > > + return;
> >
> > Should return error.
>
> Ditto, it's being used in isr(), we don't need to detect the return value, just
> use dev_err() to warn users and let the driver clear the irq.
Same as above
>
>
> > > +/* U/Q Channel framing error */
> > > +static void spdif_irq_uq_err(struct fsl_spdif_priv *spdif_priv) {
> > > + struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
> > > + struct regmap *regmap = spdif_priv->regmap;
> > > + struct platform_device *pdev = spdif_priv->pdev;
> > > + u32 val;
> > > +
> > > + dev_dbg(&pdev->dev, "isr: U/Q Channel framing error\n");
> > > +
> > > + /* read U/Q data and do buffer reset */
> > > + regmap_read(regmap, REG_SPDIF_SRU, &val);
> > > + regmap_read(regmap, REG_SPDIF_SRQ, &val);
> >
> > Above prints says read u/q data and buffer reset, what is buffer reset? Is
> that read on clear?
>
> That's the behavior needed by IP, according to the reference manual:
> "U Channel receive register full, can't be cleared with reg. IntClear.
> To clear it, read from U Rx reg." and "Q Channel receive register full, can't be
> cleared with reg. IntClear. To clear it, read from Q Rx reg."
Then please add this behavior in comment.
>
>
> > > +static void spdif_softreset(struct fsl_spdif_priv *spdif_priv) {
> > > + struct regmap *regmap = spdif_priv->regmap;
> > > + u32 val, cycle = 1000;
> > > +
> > > + regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET);
> > > + regcache_sync(regmap);
> > > +
> > > + /* RESET bit would be cleared after finishing its reset procedure */
> > > + do {
> > > + regmap_read(regmap, REG_SPDIF_SCR, &val);
> > > + } while ((val & SCR_SOFT_RESET) && cycle--);
> >
> > What if reset is not cleared and timeout happen?
>
> We here suppose the reset bit would be cleared -- "The software reset will last
> 8 cycles." from RM, so if this happened to be a failure, the whole IP module
> won't be normally working as well.
Also add a comment describing this against why cycle = 1000 is selected.
>
> Well, but I don't mind to put here an extra failed return to make it clear.
>
>
> > > +static u8 reverse_bits(u8 input)
> > > +{
> > > + u8 tmp = input;
> > > +
> > > + tmp = ((tmp & 0b10101010) >> 1) | ((tmp << 1) & 0b10101010);
> > > + tmp = ((tmp & 0b11001100) >> 2) | ((tmp << 2) & 0b11001100);
> > > + tmp = ((tmp & 0b11110000) >> 4) | ((tmp << 4) & 0b11110000);
> >
> > What is this logic, can the hardcoding be removed and some description on
> above calculation?
>
> This was provided by Philipp Zabel in his review at patch v3.
> It's pretty clear to me that it just reverses the bits for u8.
This is not obvious. Why not use bitrev8() ?
> I don't think this logic has any problem and the mask here doesn't look like any
> hardcode to me.
>
>
> > > +static bool fsl_spdif_volatile_reg(struct device *dev, unsigned int reg)
> > > +{
> > > + /* Sync all registers after reset */
> >
> > Where us sync :) ?
>
> The "return true" would do that. For volatile registers, if no "return true"
> here, the whole regmap would use the value in cache, while for some bits
> we need to trace its true value from the physical registers not from cache.
Where will be device registers cached? Do not we program them to be non-cacheable in core?
-Bharat
>
>
> Best regards,
> Nicolin Chen
More information about the Linuxppc-dev
mailing list