linux/sound/soc/zte/zx-i2s.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Linaro
   3 *
   4 * Author: Jun Nie <jun.nie@linaro.org>
   5 *
   6 * License terms: GNU General Public License (GPL) version 2
   7 */
   8
   9#include <linux/clk.h>
  10#include <linux/device.h>
  11#include <linux/init.h>
  12#include <linux/io.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <sound/pcm.h>
  16#include <sound/pcm_params.h>
  17#include <sound/soc.h>
  18#include <sound/soc-dai.h>
  19
  20#include <sound/core.h>
  21#include <sound/dmaengine_pcm.h>
  22#include <sound/initval.h>
  23
  24#define ZX_I2S_PROCESS_CTRL     0x04
  25#define ZX_I2S_TIMING_CTRL      0x08
  26#define ZX_I2S_FIFO_CTRL        0x0C
  27#define ZX_I2S_FIFO_STATUS      0x10
  28#define ZX_I2S_INT_EN           0x14
  29#define ZX_I2S_INT_STATUS       0x18
  30#define ZX_I2S_DATA             0x1C
  31#define ZX_I2S_FRAME_CNTR       0x20
  32
  33#define I2S_DEAGULT_FIFO_THRES  (0x10)
  34#define I2S_MAX_FIFO_THRES      (0x20)
  35
  36#define ZX_I2S_PROCESS_TX_EN    (1 << 0)
  37#define ZX_I2S_PROCESS_TX_DIS   (0 << 0)
  38#define ZX_I2S_PROCESS_RX_EN    (1 << 1)
  39#define ZX_I2S_PROCESS_RX_DIS   (0 << 1)
  40#define ZX_I2S_PROCESS_I2S_EN   (1 << 2)
  41#define ZX_I2S_PROCESS_I2S_DIS  (0 << 2)
  42
  43#define ZX_I2S_TIMING_MAST              (1 << 0)
  44#define ZX_I2S_TIMING_SLAVE             (0 << 0)
  45#define ZX_I2S_TIMING_MS_MASK           (1 << 0)
  46#define ZX_I2S_TIMING_LOOP              (1 << 1)
  47#define ZX_I2S_TIMING_NOR               (0 << 1)
  48#define ZX_I2S_TIMING_LOOP_MASK         (1 << 1)
  49#define ZX_I2S_TIMING_PTNR              (1 << 2)
  50#define ZX_I2S_TIMING_NTPR              (0 << 2)
  51#define ZX_I2S_TIMING_PHASE_MASK        (1 << 2)
  52#define ZX_I2S_TIMING_TDM               (1 << 3)
  53#define ZX_I2S_TIMING_I2S               (0 << 3)
  54#define ZX_I2S_TIMING_TIMING_MASK       (1 << 3)
  55#define ZX_I2S_TIMING_LONG_SYNC         (1 << 4)
  56#define ZX_I2S_TIMING_SHORT_SYNC        (0 << 4)
  57#define ZX_I2S_TIMING_SYNC_MASK         (1 << 4)
  58#define ZX_I2S_TIMING_TEAK_EN           (1 << 5)
  59#define ZX_I2S_TIMING_TEAK_DIS          (0 << 5)
  60#define ZX_I2S_TIMING_TEAK_MASK         (1 << 5)
  61#define ZX_I2S_TIMING_STD_I2S           (0 << 6)
  62#define ZX_I2S_TIMING_MSB_JUSTIF        (1 << 6)
  63#define ZX_I2S_TIMING_LSB_JUSTIF        (2 << 6)
  64#define ZX_I2S_TIMING_ALIGN_MASK        (3 << 6)
  65#define ZX_I2S_TIMING_CHN_MASK          (7 << 8)
  66#define ZX_I2S_TIMING_CHN(x)            ((x - 1) << 8)
  67#define ZX_I2S_TIMING_LANE_MASK         (3 << 11)
  68#define ZX_I2S_TIMING_LANE(x)           ((x - 1) << 11)
  69#define ZX_I2S_TIMING_TSCFG_MASK        (7 << 13)
  70#define ZX_I2S_TIMING_TSCFG(x)          (x << 13)
  71#define ZX_I2S_TIMING_TS_WIDTH_MASK     (0x1f << 16)
  72#define ZX_I2S_TIMING_TS_WIDTH(x)       ((x - 1) << 16)
  73#define ZX_I2S_TIMING_DATA_SIZE_MASK    (0x1f << 21)
  74#define ZX_I2S_TIMING_DATA_SIZE(x)      ((x - 1) << 21)
  75#define ZX_I2S_TIMING_CFG_ERR_MASK      (1 << 31)
  76
  77#define ZX_I2S_FIFO_CTRL_TX_RST         (1 << 0)
  78#define ZX_I2S_FIFO_CTRL_TX_RST_MASK    (1 << 0)
  79#define ZX_I2S_FIFO_CTRL_RX_RST         (1 << 1)
  80#define ZX_I2S_FIFO_CTRL_RX_RST_MASK    (1 << 1)
  81#define ZX_I2S_FIFO_CTRL_TX_DMA_EN      (1 << 4)
  82#define ZX_I2S_FIFO_CTRL_TX_DMA_DIS     (0 << 4)
  83#define ZX_I2S_FIFO_CTRL_TX_DMA_MASK    (1 << 4)
  84#define ZX_I2S_FIFO_CTRL_RX_DMA_EN      (1 << 5)
  85#define ZX_I2S_FIFO_CTRL_RX_DMA_DIS     (0 << 5)
  86#define ZX_I2S_FIFO_CTRL_RX_DMA_MASK    (1 << 5)
  87#define ZX_I2S_FIFO_CTRL_TX_THRES_MASK  (0x1F << 8)
  88#define ZX_I2S_FIFO_CTRL_RX_THRES_MASK  (0x1F << 16)
  89
  90#define CLK_RAT (32 * 4)
  91
  92struct zx_i2s_info {
  93        struct snd_dmaengine_dai_dma_data       dma_playback;
  94        struct snd_dmaengine_dai_dma_data       dma_capture;
  95        struct clk                              *dai_wclk;
  96        struct clk                              *dai_pclk;
  97        void __iomem                            *reg_base;
  98        int                                     master;
  99        resource_size_t                         mapbase;
 100};
 101
 102static void zx_i2s_tx_en(void __iomem *base, bool on)
 103{
 104        unsigned long val;
 105
 106        val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL);
 107        if (on)
 108                val |= ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN;
 109        else
 110                val &= ~(ZX_I2S_PROCESS_TX_EN | ZX_I2S_PROCESS_I2S_EN);
 111        writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL);
 112}
 113
 114static void zx_i2s_rx_en(void __iomem *base, bool on)
 115{
 116        unsigned long val;
 117
 118        val = readl_relaxed(base + ZX_I2S_PROCESS_CTRL);
 119        if (on)
 120                val |= ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN;
 121        else
 122                val &= ~(ZX_I2S_PROCESS_RX_EN | ZX_I2S_PROCESS_I2S_EN);
 123        writel_relaxed(val, base + ZX_I2S_PROCESS_CTRL);
 124}
 125
 126static void zx_i2s_tx_dma_en(void __iomem *base, bool on)
 127{
 128        unsigned long val;
 129
 130        val = readl_relaxed(base + ZX_I2S_FIFO_CTRL);
 131        val |= ZX_I2S_FIFO_CTRL_TX_RST | (I2S_DEAGULT_FIFO_THRES << 8);
 132        if (on)
 133                val |= ZX_I2S_FIFO_CTRL_TX_DMA_EN;
 134        else
 135                val &= ~ZX_I2S_FIFO_CTRL_TX_DMA_EN;
 136        writel_relaxed(val, base + ZX_I2S_FIFO_CTRL);
 137}
 138
 139static void zx_i2s_rx_dma_en(void __iomem *base, bool on)
 140{
 141        unsigned long val;
 142
 143        val = readl_relaxed(base + ZX_I2S_FIFO_CTRL);
 144        val |= ZX_I2S_FIFO_CTRL_RX_RST | (I2S_DEAGULT_FIFO_THRES << 16);
 145        if (on)
 146                val |= ZX_I2S_FIFO_CTRL_RX_DMA_EN;
 147        else
 148                val &= ~ZX_I2S_FIFO_CTRL_RX_DMA_EN;
 149        writel_relaxed(val, base + ZX_I2S_FIFO_CTRL);
 150}
 151
 152#define ZX_I2S_RATES \
 153        (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
 154         SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 155         SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000| \
 156         SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
 157
 158#define ZX_I2S_FMTBIT \
 159        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
 160        SNDRV_PCM_FMTBIT_S32_LE)
 161
 162static int zx_i2s_dai_probe(struct snd_soc_dai *dai)
 163{
 164        struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
 165
 166        snd_soc_dai_set_drvdata(dai, zx_i2s);
 167        zx_i2s->dma_playback.addr = zx_i2s->mapbase + ZX_I2S_DATA;
 168        zx_i2s->dma_playback.maxburst = 16;
 169        zx_i2s->dma_capture.addr = zx_i2s->mapbase + ZX_I2S_DATA;
 170        zx_i2s->dma_capture.maxburst = 16;
 171        snd_soc_dai_init_dma_data(dai, &zx_i2s->dma_playback,
 172                                  &zx_i2s->dma_capture);
 173        return 0;
 174}
 175
 176static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 177{
 178        struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
 179        unsigned long val;
 180
 181        val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL);
 182        val &= ~(ZX_I2S_TIMING_TIMING_MASK | ZX_I2S_TIMING_ALIGN_MASK |
 183                        ZX_I2S_TIMING_TEAK_MASK | ZX_I2S_TIMING_SYNC_MASK |
 184                        ZX_I2S_TIMING_MS_MASK);
 185
 186        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 187        case SND_SOC_DAIFMT_I2S:
 188                val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_STD_I2S);
 189                break;
 190        case SND_SOC_DAIFMT_LEFT_J:
 191                val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_MSB_JUSTIF);
 192                break;
 193        case SND_SOC_DAIFMT_RIGHT_J:
 194                val |= (ZX_I2S_TIMING_I2S | ZX_I2S_TIMING_LSB_JUSTIF);
 195                break;
 196        default:
 197                dev_err(cpu_dai->dev, "Unknown i2s timing\n");
 198                return -EINVAL;
 199        }
 200
 201        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 202        case SND_SOC_DAIFMT_CBM_CFM:
 203                /* Codec is master, and I2S is slave. */
 204                i2s->master = 0;
 205                val |= ZX_I2S_TIMING_SLAVE;
 206                break;
 207        case SND_SOC_DAIFMT_CBS_CFS:
 208                /* Codec is slave, and I2S is master. */
 209                i2s->master = 1;
 210                val |= ZX_I2S_TIMING_MAST;
 211                break;
 212        default:
 213                dev_err(cpu_dai->dev, "Unknown master/slave format\n");
 214                return -EINVAL;
 215        }
 216
 217        writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL);
 218        return 0;
 219}
 220
 221static int zx_i2s_hw_params(struct snd_pcm_substream *substream,
 222                            struct snd_pcm_hw_params *params,
 223                            struct snd_soc_dai *socdai)
 224{
 225        struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai);
 226        struct snd_dmaengine_dai_dma_data *dma_data;
 227        unsigned int lane, ch_num, len, ret = 0;
 228        unsigned int ts_width = 32;
 229        unsigned long val;
 230        unsigned long chn_cfg;
 231
 232        dma_data = snd_soc_dai_get_dma_data(socdai, substream);
 233        dma_data->addr_width = ts_width >> 3;
 234
 235        val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL);
 236        val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK |
 237                ZX_I2S_TIMING_LANE_MASK | ZX_I2S_TIMING_CHN_MASK |
 238                ZX_I2S_TIMING_TSCFG_MASK);
 239
 240        switch (params_format(params)) {
 241        case SNDRV_PCM_FORMAT_S16_LE:
 242                len = 16;
 243                break;
 244        case SNDRV_PCM_FORMAT_S24_LE:
 245                len = 24;
 246                break;
 247        case SNDRV_PCM_FORMAT_S32_LE:
 248                len = 32;
 249                break;
 250        default:
 251                dev_err(socdai->dev, "Unknown data format\n");
 252                return -EINVAL;
 253        }
 254        val |= ZX_I2S_TIMING_TS_WIDTH(ts_width) | ZX_I2S_TIMING_DATA_SIZE(len);
 255
 256        ch_num = params_channels(params);
 257        switch (ch_num) {
 258        case 1:
 259                lane = 1;
 260                chn_cfg = 2;
 261                break;
 262        case 2:
 263        case 4:
 264        case 6:
 265        case 8:
 266                lane = ch_num / 2;
 267                chn_cfg = 3;
 268                break;
 269        default:
 270                dev_err(socdai->dev, "Not support channel num %d\n", ch_num);
 271                return -EINVAL;
 272        }
 273        val |= ZX_I2S_TIMING_LANE(lane);
 274        val |= ZX_I2S_TIMING_TSCFG(chn_cfg);
 275        val |= ZX_I2S_TIMING_CHN(ch_num);
 276        writel_relaxed(val, i2s->reg_base + ZX_I2S_TIMING_CTRL);
 277
 278        if (i2s->master)
 279                ret = clk_set_rate(i2s->dai_wclk,
 280                                params_rate(params) * ch_num * CLK_RAT);
 281
 282        return ret;
 283}
 284
 285static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 286                          struct snd_soc_dai *dai)
 287{
 288        struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
 289        int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
 290        int ret = 0;
 291
 292        switch (cmd) {
 293        case SNDRV_PCM_TRIGGER_START:
 294                if (capture)
 295                        zx_i2s_rx_dma_en(zx_i2s->reg_base, true);
 296                else
 297                        zx_i2s_tx_dma_en(zx_i2s->reg_base, true);
 298        /* fall thru */
 299        case SNDRV_PCM_TRIGGER_RESUME:
 300        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 301                if (capture)
 302                        zx_i2s_rx_en(zx_i2s->reg_base, true);
 303                else
 304                        zx_i2s_tx_en(zx_i2s->reg_base, true);
 305                break;
 306
 307        case SNDRV_PCM_TRIGGER_STOP:
 308                if (capture)
 309                        zx_i2s_rx_dma_en(zx_i2s->reg_base, false);
 310                else
 311                        zx_i2s_tx_dma_en(zx_i2s->reg_base, false);
 312        /* fall thru */
 313        case SNDRV_PCM_TRIGGER_SUSPEND:
 314        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 315                if (capture)
 316                        zx_i2s_rx_en(zx_i2s->reg_base, false);
 317                else
 318                        zx_i2s_tx_en(zx_i2s->reg_base, false);
 319                break;
 320
 321        default:
 322                ret = -EINVAL;
 323                break;
 324        }
 325
 326        return ret;
 327}
 328
 329static int zx_i2s_startup(struct snd_pcm_substream *substream,
 330                          struct snd_soc_dai *dai)
 331{
 332        struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
 333        int ret;
 334
 335        ret = clk_prepare_enable(zx_i2s->dai_wclk);
 336        if (ret)
 337                return ret;
 338
 339        ret = clk_prepare_enable(zx_i2s->dai_pclk);
 340        if (ret) {
 341                clk_disable_unprepare(zx_i2s->dai_wclk);
 342                return ret;
 343        }
 344
 345        return ret;
 346}
 347
 348static void zx_i2s_shutdown(struct snd_pcm_substream *substream,
 349                            struct snd_soc_dai *dai)
 350{
 351        struct zx_i2s_info *zx_i2s = dev_get_drvdata(dai->dev);
 352
 353        clk_disable_unprepare(zx_i2s->dai_wclk);
 354        clk_disable_unprepare(zx_i2s->dai_pclk);
 355}
 356
 357static const struct snd_soc_dai_ops zx_i2s_dai_ops = {
 358        .trigger        = zx_i2s_trigger,
 359        .hw_params      = zx_i2s_hw_params,
 360        .set_fmt        = zx_i2s_set_fmt,
 361        .startup        = zx_i2s_startup,
 362        .shutdown       = zx_i2s_shutdown,
 363};
 364
 365static const struct snd_soc_component_driver zx_i2s_component = {
 366        .name                   = "zx-i2s",
 367};
 368
 369static struct snd_soc_dai_driver zx_i2s_dai = {
 370        .name   = "zx-i2s-dai",
 371        .id     = 0,
 372        .probe  = zx_i2s_dai_probe,
 373        .playback   = {
 374                .channels_min   = 1,
 375                .channels_max   = 8,
 376                .rates          = ZX_I2S_RATES,
 377                .formats        = ZX_I2S_FMTBIT,
 378        },
 379        .capture = {
 380                .channels_min   = 1,
 381                .channels_max   = 2,
 382                .rates          = ZX_I2S_RATES,
 383                .formats        = ZX_I2S_FMTBIT,
 384        },
 385        .ops    = &zx_i2s_dai_ops,
 386};
 387
 388static int zx_i2s_probe(struct platform_device *pdev)
 389{
 390        struct resource *res;
 391        struct zx_i2s_info *zx_i2s;
 392        int ret;
 393
 394        zx_i2s = devm_kzalloc(&pdev->dev, sizeof(*zx_i2s), GFP_KERNEL);
 395        if (!zx_i2s)
 396                return -ENOMEM;
 397
 398        zx_i2s->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
 399        if (IS_ERR(zx_i2s->dai_wclk)) {
 400                dev_err(&pdev->dev, "Fail to get wclk\n");
 401                return PTR_ERR(zx_i2s->dai_wclk);
 402        }
 403
 404        zx_i2s->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
 405        if (IS_ERR(zx_i2s->dai_pclk)) {
 406                dev_err(&pdev->dev, "Fail to get pclk\n");
 407                return PTR_ERR(zx_i2s->dai_pclk);
 408        }
 409
 410        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 411        zx_i2s->mapbase = res->start;
 412        zx_i2s->reg_base = devm_ioremap_resource(&pdev->dev, res);
 413        if (IS_ERR(zx_i2s->reg_base)) {
 414                dev_err(&pdev->dev, "ioremap failed!\n");
 415                return PTR_ERR(zx_i2s->reg_base);
 416        }
 417
 418        writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL);
 419        platform_set_drvdata(pdev, zx_i2s);
 420
 421        ret = devm_snd_soc_register_component(&pdev->dev, &zx_i2s_component,
 422                                              &zx_i2s_dai, 1);
 423        if (ret) {
 424                dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
 425                return ret;
 426        }
 427
 428        ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 429        if (ret)
 430                dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
 431
 432        return ret;
 433}
 434
 435static const struct of_device_id zx_i2s_dt_ids[] = {
 436        { .compatible = "zte,zx296702-i2s", },
 437        {}
 438};
 439MODULE_DEVICE_TABLE(of, zx_i2s_dt_ids);
 440
 441static struct platform_driver i2s_driver = {
 442        .probe = zx_i2s_probe,
 443        .driver = {
 444                .name = "zx-i2s",
 445                .of_match_table = zx_i2s_dt_ids,
 446        },
 447};
 448
 449module_platform_driver(i2s_driver);
 450
 451MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
 452MODULE_DESCRIPTION("ZTE I2S SoC DAI");
 453MODULE_LICENSE("GPL");
 454