[alsa-devel] [PATCH 2/8] sound:asoc: Add support for synopsys i2s controller as per ASoC framework.
Rajeev kumar
rajeev-dlh.kumar at st.com
Mon Mar 26 11:03:22 CEST 2012
Hello Mark
On 3/20/2012 9:14 PM, Mark Brown wrote:
> On Tue, Mar 20, 2012 at 05:03:46PM +0530, Rajeev Kumar wrote:
>> This patch add support for synopsys I2S controller as per the ASoC framework.
>
> If this really is a generic Synopsys block shouldn't it be in a Synopsys
> directory, possibly with a wrapper in the SPEAr directory for the
> platform integration?
>
I will create a new directory by name dwc.
>> +struct i2s_platform_data {
>> + #define PLAY (1<< 0)
>> + #define RECORD (1<< 1)
>
> Namespacing here and with most of the other defines in the header (and
> the driver, though the ones in the code are less important). Normally
> ALSA headers go in include/sound.
>
OK I will move it in include/sound/.
Next Patch will contains name spacing also.
>> +
>> + if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
>> + i2s_write_reg(dev->i2s_base, TCR(ch), dev->xfer_resolution);
>> + i2s_write_reg(dev->i2s_base, TFCR(ch), 0x02);
>> + irq = i2s_read_reg(dev->i2s_base, IMR(ch));
>> + i2s_write_reg(dev->i2s_base, IMR(ch), irq& ~0x30);
>> + i2s_write_reg(dev->i2s_base, TER(ch), 1);
>> + } else {
>> + i2s_write_reg(dev->i2s_base, RCR(ch), dev->xfer_resolution);
>> + i2s_write_reg(dev->i2s_base, RFCR(ch), 0x07);
>> + irq = i2s_read_reg(dev->i2s_base, IMR(ch));
>> + i2s_write_reg(dev->i2s_base, IMR(ch), irq& ~0x03);
>> + i2s_write_reg(dev->i2s_base, RER(ch), 1);
>> + }
>
> It would be good to split out the bits that are common from the bits
> that vary per stream.
>
OK,
>> + if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
>> + for (i = 0; i< 4; i++)
>> + i2s_write_reg(dev->i2s_base, TER(i), 0);
>> + } else {
>> + for (i = 0; i< 4; i++)
>> + i2s_write_reg(dev->i2s_base, RER(i), 0);
>
> Magic numbers!
>
will be replaced with macro
>> +static irqreturn_t dw_i2s_play_irq(int irq, void *_dev)
>> +{
>> + struct dw_i2s_dev *dev = (struct dw_i2s_dev *)_dev;
>> + u32 ch0, ch1;
>> +
>> + /* check for the tx data overrun condition */
>> + ch0 = i2s_read_reg(dev->i2s_base, ISR(0))& 0x20;
>> + ch1 = i2s_read_reg(dev->i2s_base, ISR(1))& 0x20;
>> + if (ch0 || ch1) {
>> + /* disable i2s block */
>> + i2s_write_reg(dev->i2s_base, IER, 0);
>> +
>> + /* disable tx block */
>> + i2s_write_reg(dev->i2s_base, ITER, 0);
>> +
>> + /* flush all the tx fifo */
>> + i2s_write_reg(dev->i2s_base, TXFFR, 1);
>> +
>> + /* clear tx data overrun interrupt */
>> + i2s_clear_irqs(dev, SNDRV_PCM_STREAM_PLAYBACK);
>> +
>> + /* enable rx block */
>> + i2s_write_reg(dev->i2s_base, ITER, 1);
>> +
>> + /* enable i2s block */
>> + i2s_write_reg(dev->i2s_base, IER, 1);
>> + }
>
> This is somewhat unusual - normally ALSA detects underrun and overrun
> and restarts the stream at the application layer. This looks like it
> attempts to mask information about errors from the application which
> probably isn't waht we want to do. Why is the normal ALSA handling not5
> sufficient?
>
Normal ALSA handling is sufficient for underrun and overrun. This
handler is not required.
>> +
>> + return IRQ_HANDLED;
>
> This unconditionally says it handled the interrupt even if it didn't.
>
Removing handler will remove this too.
>> +static int
>> +dw_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
>> +{
>> + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
>> + struct dma_data *dma_data = NULL;
>> +
>> + if (!(dev->capability& RECORD)&&
>> + (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
>> + return -EINVAL;
>
> Indentation.
>
Ok
>> +
>> + if (dev->i2s_clk_cfg) {
>> + if (dev->i2s_clk_cfg(config)) {
>> + dev_err(dev->dev, "runtime audio clk config fail\n");
>> + if (cpu_dai->driver->ops->trigger) {
>> + int ret =
>> + cpu_dai->driver->ops->trigger(substream,
>> + SNDRV_PCM_TRIGGER_STOP,
>> + cpu_dai);
>> + if (ret< 0) {
>> + dev_err(dev->dev,
>> + "trigger stop fail\n");
>> + return ret;
>> + }
>> + }
>
> No, return an error if you encounter an error!
>
You need not to stop controller in case clock fail ?
>> +static void
>> +dw_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
>
> Indentation - throughout the kernel the type goes on the same line asi2s
> the function name.
>
Ok
>> +static const struct dev_pm_ops dw_i2s_dev_pm_ops = {
>> + .suspend = dw_i2s_suspend,
>> + .resume = dw_i2s_resume,
>> +};
>
> No, do this at the ASoC level like other CPU drivers (runtime PM
> callbacks are OK).
>
Ok,
>> + cap = pdata->cap;
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (!res) {
>> + dev_err(&pdev->dev, "no i2s resource defined\n");
>> + return -ENODEV;
>> + }
>> +
>> + if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
>> + dev_err(&pdev->dev, "i2s region already claimed\n");
>> + return -EBUSY;
>> + }
>
> There's devm_ versions of this stuff too.
>
OK
>> + dev = kzalloc(sizeof(*dev), GFP_KERNEL);
>
> devm_kzalloc()
>
Ok
>> + dev->i2s_base = ioremap(res->start, resource_size(res));
>> + if (!dev->i2s_base) {
>
> devm_ioremap().
>
Ok
>> + if (dev->play_irq< 0)
>> + dev_warn(&pdev->dev, "play irq not defined\n");
>> + else {
>
> Braces on both sides of the if.
>
Ok,
Best Regards
Rajeev
>> +static int __init dw_i2s_init(void)
>
> module_platform_driver().
More information about the Alsa-devel
mailing list