linux/sound/soc/kirkwood/kirkwood-i2s.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * kirkwood-i2s.c
   4 *
   5 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
   6 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
   7 */
   8
   9#include <linux/init.h>
  10#include <linux/module.h>
  11#include <linux/platform_device.h>
  12#include <linux/io.h>
  13#include <linux/slab.h>
  14#include <linux/mbus.h>
  15#include <linux/delay.h>
  16#include <linux/clk.h>
  17#include <sound/pcm.h>
  18#include <sound/pcm_params.h>
  19#include <sound/soc.h>
  20#include <linux/platform_data/asoc-kirkwood.h>
  21#include <linux/of.h>
  22
  23#include "kirkwood.h"
  24
  25#define KIRKWOOD_I2S_FORMATS \
  26        (SNDRV_PCM_FMTBIT_S16_LE | \
  27         SNDRV_PCM_FMTBIT_S24_LE | \
  28         SNDRV_PCM_FMTBIT_S32_LE)
  29
  30#define KIRKWOOD_SPDIF_FORMATS \
  31        (SNDRV_PCM_FMTBIT_S16_LE | \
  32         SNDRV_PCM_FMTBIT_S24_LE)
  33
  34static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
  35                unsigned int fmt)
  36{
  37        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
  38        unsigned long mask;
  39        unsigned long value;
  40
  41        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  42        case SND_SOC_DAIFMT_RIGHT_J:
  43                mask = KIRKWOOD_I2S_CTL_RJ;
  44                break;
  45        case SND_SOC_DAIFMT_LEFT_J:
  46                mask = KIRKWOOD_I2S_CTL_LJ;
  47                break;
  48        case SND_SOC_DAIFMT_I2S:
  49                mask = KIRKWOOD_I2S_CTL_I2S;
  50                break;
  51        default:
  52                return -EINVAL;
  53        }
  54
  55        /*
  56         * Set same format for playback and record
  57         * This avoids some troubles.
  58         */
  59        value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
  60        value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
  61        value |= mask;
  62        writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
  63
  64        value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
  65        value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
  66        value |= mask;
  67        writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
  68
  69        return 0;
  70}
  71
  72static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
  73{
  74        unsigned long value;
  75
  76        value = KIRKWOOD_DCO_CTL_OFFSET_0;
  77        switch (rate) {
  78        default:
  79        case 44100:
  80                value |= KIRKWOOD_DCO_CTL_FREQ_11;
  81                break;
  82        case 48000:
  83                value |= KIRKWOOD_DCO_CTL_FREQ_12;
  84                break;
  85        case 96000:
  86                value |= KIRKWOOD_DCO_CTL_FREQ_24;
  87                break;
  88        }
  89        writel(value, io + KIRKWOOD_DCO_CTL);
  90
  91        /* wait for dco locked */
  92        do {
  93                cpu_relax();
  94                value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
  95                value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
  96        } while (value == 0);
  97}
  98
  99static void kirkwood_set_rate(struct snd_soc_dai *dai,
 100        struct kirkwood_dma_data *priv, unsigned long rate)
 101{
 102        uint32_t clks_ctrl;
 103
 104        if (IS_ERR(priv->extclk)) {
 105                /* use internal dco for the supported rates
 106                 * defined in kirkwood_i2s_dai */
 107                dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
 108                        __func__, rate);
 109                kirkwood_set_dco(priv->io, rate);
 110
 111                clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
 112        } else {
 113                /* use the external clock for the other rates
 114                 * defined in kirkwood_i2s_dai_extclk */
 115                dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
 116                        __func__, rate, 256 * rate);
 117                clk_set_rate(priv->extclk, 256 * rate);
 118
 119                clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
 120        }
 121        writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
 122}
 123
 124static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
 125                struct snd_soc_dai *dai)
 126{
 127        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
 128
 129        snd_soc_dai_set_dma_data(dai, substream, priv);
 130        return 0;
 131}
 132
 133static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
 134                                 struct snd_pcm_hw_params *params,
 135                                 struct snd_soc_dai *dai)
 136{
 137        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
 138        uint32_t ctl_play, ctl_rec;
 139        unsigned int i2s_reg;
 140        unsigned long i2s_value;
 141
 142        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 143                i2s_reg = KIRKWOOD_I2S_PLAYCTL;
 144        } else {
 145                i2s_reg = KIRKWOOD_I2S_RECCTL;
 146        }
 147
 148        kirkwood_set_rate(dai, priv, params_rate(params));
 149
 150        i2s_value = readl(priv->io+i2s_reg);
 151        i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
 152
 153        /*
 154         * Size settings in play/rec i2s control regs and play/rec control
 155         * regs must be the same.
 156         */
 157        switch (params_format(params)) {
 158        case SNDRV_PCM_FORMAT_S16_LE:
 159                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
 160                ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
 161                           KIRKWOOD_PLAYCTL_I2S_EN |
 162                           KIRKWOOD_PLAYCTL_SPDIF_EN;
 163                ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
 164                          KIRKWOOD_RECCTL_I2S_EN |
 165                          KIRKWOOD_RECCTL_SPDIF_EN;
 166                break;
 167        /*
 168         * doesn't work... S20_3LE != kirkwood 20bit format ?
 169         *
 170        case SNDRV_PCM_FORMAT_S20_3LE:
 171                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
 172                ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
 173                           KIRKWOOD_PLAYCTL_I2S_EN;
 174                ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
 175                          KIRKWOOD_RECCTL_I2S_EN;
 176                break;
 177        */
 178        case SNDRV_PCM_FORMAT_S24_LE:
 179                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
 180                ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
 181                           KIRKWOOD_PLAYCTL_I2S_EN |
 182                           KIRKWOOD_PLAYCTL_SPDIF_EN;
 183                ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
 184                          KIRKWOOD_RECCTL_I2S_EN |
 185                          KIRKWOOD_RECCTL_SPDIF_EN;
 186                break;
 187        case SNDRV_PCM_FORMAT_S32_LE:
 188                i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
 189                ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
 190                           KIRKWOOD_PLAYCTL_I2S_EN;
 191                ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
 192                          KIRKWOOD_RECCTL_I2S_EN;
 193                break;
 194        default:
 195                return -EINVAL;
 196        }
 197
 198        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 199                if (params_channels(params) == 1)
 200                        ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
 201                else
 202                        ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
 203
 204                priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
 205                                    KIRKWOOD_PLAYCTL_ENABLE_MASK |
 206                                    KIRKWOOD_PLAYCTL_SIZE_MASK);
 207                priv->ctl_play |= ctl_play;
 208        } else {
 209                priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
 210                                   KIRKWOOD_RECCTL_SIZE_MASK);
 211                priv->ctl_rec |= ctl_rec;
 212        }
 213
 214        writel(i2s_value, priv->io+i2s_reg);
 215
 216        return 0;
 217}
 218
 219static unsigned kirkwood_i2s_play_mute(unsigned ctl)
 220{
 221        if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
 222                ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
 223        if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
 224                ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
 225        return ctl;
 226}
 227
 228static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 229                                int cmd, struct snd_soc_dai *dai)
 230{
 231        struct snd_pcm_runtime *runtime = substream->runtime;
 232        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
 233        uint32_t ctl, value;
 234
 235        ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
 236        if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
 237                unsigned timeout = 5000;
 238                /*
 239                 * The Armada510 spec says that if we enter pause mode, the
 240                 * busy bit must be read back as clear _twice_.  Make sure
 241                 * we respect that otherwise we get DMA underruns.
 242                 */
 243                do {
 244                        value = ctl;
 245                        ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
 246                        if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
 247                                break;
 248                        udelay(1);
 249                } while (timeout--);
 250
 251                if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
 252                        dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
 253                                   ctl);
 254        }
 255
 256        switch (cmd) {
 257        case SNDRV_PCM_TRIGGER_START:
 258                /* configure */
 259                ctl = priv->ctl_play;
 260                if (dai->id == 0)
 261                        ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
 262                else
 263                        ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
 264                ctl = kirkwood_i2s_play_mute(ctl);
 265                value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 266                writel(value, priv->io + KIRKWOOD_PLAYCTL);
 267
 268                /* enable interrupts */
 269                if (!runtime->no_period_wakeup) {
 270                        value = readl(priv->io + KIRKWOOD_INT_MASK);
 271                        value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
 272                        writel(value, priv->io + KIRKWOOD_INT_MASK);
 273                }
 274
 275                /* enable playback */
 276                writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 277                break;
 278
 279        case SNDRV_PCM_TRIGGER_STOP:
 280                /* stop audio, disable interrupts */
 281                ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
 282                                KIRKWOOD_PLAYCTL_SPDIF_MUTE;
 283                writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 284
 285                value = readl(priv->io + KIRKWOOD_INT_MASK);
 286                value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
 287                writel(value, priv->io + KIRKWOOD_INT_MASK);
 288
 289                /* disable all playbacks */
 290                ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 291                writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 292                break;
 293
 294        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 295        case SNDRV_PCM_TRIGGER_SUSPEND:
 296                ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
 297                                KIRKWOOD_PLAYCTL_SPDIF_MUTE;
 298                writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 299                break;
 300
 301        case SNDRV_PCM_TRIGGER_RESUME:
 302        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 303                ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
 304                                KIRKWOOD_PLAYCTL_SPDIF_MUTE);
 305                ctl = kirkwood_i2s_play_mute(ctl);
 306                writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 307                break;
 308
 309        default:
 310                return -EINVAL;
 311        }
 312
 313        return 0;
 314}
 315
 316static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 317                                int cmd, struct snd_soc_dai *dai)
 318{
 319        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
 320        uint32_t ctl, value;
 321
 322        value = readl(priv->io + KIRKWOOD_RECCTL);
 323
 324        switch (cmd) {
 325        case SNDRV_PCM_TRIGGER_START:
 326                /* configure */
 327                ctl = priv->ctl_rec;
 328                if (dai->id == 0)
 329                        ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN;       /* i2s */
 330                else
 331                        ctl &= ~KIRKWOOD_RECCTL_I2S_EN;         /* spdif */
 332
 333                value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
 334                writel(value, priv->io + KIRKWOOD_RECCTL);
 335
 336                /* enable interrupts */
 337                value = readl(priv->io + KIRKWOOD_INT_MASK);
 338                value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
 339                writel(value, priv->io + KIRKWOOD_INT_MASK);
 340
 341                /* enable record */
 342                writel(ctl, priv->io + KIRKWOOD_RECCTL);
 343                break;
 344
 345        case SNDRV_PCM_TRIGGER_STOP:
 346                /* stop audio, disable interrupts */
 347                value = readl(priv->io + KIRKWOOD_RECCTL);
 348                value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
 349                writel(value, priv->io + KIRKWOOD_RECCTL);
 350
 351                value = readl(priv->io + KIRKWOOD_INT_MASK);
 352                value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
 353                writel(value, priv->io + KIRKWOOD_INT_MASK);
 354
 355                /* disable all records */
 356                value = readl(priv->io + KIRKWOOD_RECCTL);
 357                value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
 358                writel(value, priv->io + KIRKWOOD_RECCTL);
 359                break;
 360
 361        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 362        case SNDRV_PCM_TRIGGER_SUSPEND:
 363                value = readl(priv->io + KIRKWOOD_RECCTL);
 364                value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
 365                writel(value, priv->io + KIRKWOOD_RECCTL);
 366                break;
 367
 368        case SNDRV_PCM_TRIGGER_RESUME:
 369        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 370                value = readl(priv->io + KIRKWOOD_RECCTL);
 371                value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
 372                writel(value, priv->io + KIRKWOOD_RECCTL);
 373                break;
 374
 375        default:
 376                return -EINVAL;
 377        }
 378
 379        return 0;
 380}
 381
 382static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 383                               struct snd_soc_dai *dai)
 384{
 385        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 386                return kirkwood_i2s_play_trigger(substream, cmd, dai);
 387        else
 388                return kirkwood_i2s_rec_trigger(substream, cmd, dai);
 389
 390        return 0;
 391}
 392
 393static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
 394{
 395        unsigned long value;
 396        unsigned int reg_data;
 397
 398        /* put system in a "safe" state : */
 399        /* disable audio interrupts */
 400        writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
 401        writel(0, priv->io + KIRKWOOD_INT_MASK);
 402
 403        reg_data = readl(priv->io + 0x1200);
 404        reg_data &= (~(0x333FF8));
 405        reg_data |= 0x111D18;
 406        writel(reg_data, priv->io + 0x1200);
 407
 408        msleep(500);
 409
 410        reg_data = readl(priv->io + 0x1200);
 411        reg_data &= (~(0x333FF8));
 412        reg_data |= 0x111D18;
 413        writel(reg_data, priv->io + 0x1200);
 414
 415        /* disable playback/record */
 416        value = readl(priv->io + KIRKWOOD_PLAYCTL);
 417        value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
 418        writel(value, priv->io + KIRKWOOD_PLAYCTL);
 419
 420        value = readl(priv->io + KIRKWOOD_RECCTL);
 421        value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
 422        writel(value, priv->io + KIRKWOOD_RECCTL);
 423
 424        return 0;
 425
 426}
 427
 428static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
 429        .startup        = kirkwood_i2s_startup,
 430        .trigger        = kirkwood_i2s_trigger,
 431        .hw_params      = kirkwood_i2s_hw_params,
 432        .set_fmt        = kirkwood_i2s_set_fmt,
 433};
 434
 435static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
 436    {
 437        .name = "i2s",
 438        .id = 0,
 439        .playback = {
 440                .channels_min = 1,
 441                .channels_max = 2,
 442                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 443                                SNDRV_PCM_RATE_96000,
 444                .formats = KIRKWOOD_I2S_FORMATS,
 445        },
 446        .capture = {
 447                .channels_min = 1,
 448                .channels_max = 2,
 449                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 450                                SNDRV_PCM_RATE_96000,
 451                .formats = KIRKWOOD_I2S_FORMATS,
 452        },
 453        .ops = &kirkwood_i2s_dai_ops,
 454    },
 455    {
 456        .name = "spdif",
 457        .id = 1,
 458        .playback = {
 459                .channels_min = 1,
 460                .channels_max = 2,
 461                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 462                                SNDRV_PCM_RATE_96000,
 463                .formats = KIRKWOOD_SPDIF_FORMATS,
 464        },
 465        .capture = {
 466                .channels_min = 1,
 467                .channels_max = 2,
 468                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
 469                                SNDRV_PCM_RATE_96000,
 470                .formats = KIRKWOOD_SPDIF_FORMATS,
 471        },
 472        .ops = &kirkwood_i2s_dai_ops,
 473    },
 474};
 475
 476static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
 477    {
 478        .name = "i2s",
 479        .id = 0,
 480        .playback = {
 481                .channels_min = 1,
 482                .channels_max = 2,
 483                .rates = SNDRV_PCM_RATE_CONTINUOUS,
 484                .rate_min = 5512,
 485                .rate_max = 192000,
 486                .formats = KIRKWOOD_I2S_FORMATS,
 487        },
 488        .capture = {
 489                .channels_min = 1,
 490                .channels_max = 2,
 491                .rates = SNDRV_PCM_RATE_CONTINUOUS,
 492                .rate_min = 5512,
 493                .rate_max = 192000,
 494                .formats = KIRKWOOD_I2S_FORMATS,
 495        },
 496        .ops = &kirkwood_i2s_dai_ops,
 497    },
 498    {
 499        .name = "spdif",
 500        .id = 1,
 501        .playback = {
 502                .channels_min = 1,
 503                .channels_max = 2,
 504                .rates = SNDRV_PCM_RATE_CONTINUOUS,
 505                .rate_min = 5512,
 506                .rate_max = 192000,
 507                .formats = KIRKWOOD_SPDIF_FORMATS,
 508        },
 509        .capture = {
 510                .channels_min = 1,
 511                .channels_max = 2,
 512                .rates = SNDRV_PCM_RATE_CONTINUOUS,
 513                .rate_min = 5512,
 514                .rate_max = 192000,
 515                .formats = KIRKWOOD_SPDIF_FORMATS,
 516        },
 517        .ops = &kirkwood_i2s_dai_ops,
 518    },
 519};
 520
 521static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 522{
 523        struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
 524        struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
 525        struct kirkwood_dma_data *priv;
 526        struct resource *mem;
 527        struct device_node *np = pdev->dev.of_node;
 528        int err;
 529
 530        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 531        if (!priv)
 532                return -ENOMEM;
 533
 534        dev_set_drvdata(&pdev->dev, priv);
 535
 536        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 537        priv->io = devm_ioremap_resource(&pdev->dev, mem);
 538        if (IS_ERR(priv->io))
 539                return PTR_ERR(priv->io);
 540
 541        priv->irq = platform_get_irq(pdev, 0);
 542        if (priv->irq < 0) {
 543                dev_err(&pdev->dev, "platform_get_irq failed: %d\n", priv->irq);
 544                return priv->irq;
 545        }
 546
 547        if (np) {
 548                priv->burst = 128;              /* might be 32 or 128 */
 549        } else if (data) {
 550                priv->burst = data->burst;
 551        } else {
 552                dev_err(&pdev->dev, "no DT nor platform data ?!\n");
 553                return -EINVAL;
 554        }
 555
 556        priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
 557        if (IS_ERR(priv->clk)) {
 558                dev_err(&pdev->dev, "no clock\n");
 559                return PTR_ERR(priv->clk);
 560        }
 561
 562        err = clk_prepare_enable(priv->clk);
 563        if (err < 0)
 564                return err;
 565
 566        priv->extclk = devm_clk_get(&pdev->dev, "extclk");
 567        if (IS_ERR(priv->extclk)) {
 568                if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
 569                        return -EPROBE_DEFER;
 570        } else {
 571                if (clk_is_match(priv->extclk, priv->clk)) {
 572                        devm_clk_put(&pdev->dev, priv->extclk);
 573                        priv->extclk = ERR_PTR(-EINVAL);
 574                } else {
 575                        dev_info(&pdev->dev, "found external clock\n");
 576                        clk_prepare_enable(priv->extclk);
 577                        soc_dai = kirkwood_i2s_dai_extclk;
 578                }
 579        }
 580
 581        /* Some sensible defaults - this reflects the powerup values */
 582        priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
 583        priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
 584
 585        /* Select the burst size */
 586        if (priv->burst == 32) {
 587                priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
 588                priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
 589        } else {
 590                priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
 591                priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
 592        }
 593
 594        err = devm_snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
 595                                         soc_dai, 2);
 596        if (err) {
 597                dev_err(&pdev->dev, "snd_soc_register_component failed\n");
 598                goto err_component;
 599        }
 600
 601        kirkwood_i2s_init(priv);
 602
 603        return 0;
 604
 605 err_component:
 606        if (!IS_ERR(priv->extclk))
 607                clk_disable_unprepare(priv->extclk);
 608        clk_disable_unprepare(priv->clk);
 609
 610        return err;
 611}
 612
 613static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 614{
 615        struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
 616
 617        if (!IS_ERR(priv->extclk))
 618                clk_disable_unprepare(priv->extclk);
 619        clk_disable_unprepare(priv->clk);
 620
 621        return 0;
 622}
 623
 624#ifdef CONFIG_OF
 625static const struct of_device_id mvebu_audio_of_match[] = {
 626        { .compatible = "marvell,kirkwood-audio" },
 627        { .compatible = "marvell,dove-audio" },
 628        { .compatible = "marvell,armada370-audio" },
 629        { }
 630};
 631MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
 632#endif
 633
 634static struct platform_driver kirkwood_i2s_driver = {
 635        .probe  = kirkwood_i2s_dev_probe,
 636        .remove = kirkwood_i2s_dev_remove,
 637        .driver = {
 638                .name = DRV_NAME,
 639                .of_match_table = of_match_ptr(mvebu_audio_of_match),
 640        },
 641};
 642
 643module_platform_driver(kirkwood_i2s_driver);
 644
 645/* Module information */
 646MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
 647MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
 648MODULE_LICENSE("GPL");
 649MODULE_ALIAS("platform:mvebu-audio");
 650