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