linux/sound/soc/zte/zx-spdif.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/dmaengine.h>
  11#include <linux/init.h>
  12#include <linux/io.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/of_address.h>
  16#include <sound/asoundef.h>
  17#include <sound/core.h>
  18#include <sound/dmaengine_pcm.h>
  19#include <sound/initval.h>
  20#include <sound/pcm.h>
  21#include <sound/pcm_params.h>
  22#include <sound/soc.h>
  23#include <sound/soc-dai.h>
  24
  25#define ZX_CTRL                         0x04
  26#define ZX_FIFOCTRL                     0x08
  27#define ZX_INT_STATUS                   0x10
  28#define ZX_INT_MASK                     0x14
  29#define ZX_DATA                         0x18
  30#define ZX_VALID_BIT                    0x1c
  31#define ZX_CH_STA_1                     0x20
  32#define ZX_CH_STA_2                     0x24
  33#define ZX_CH_STA_3                     0x28
  34#define ZX_CH_STA_4                     0x2c
  35#define ZX_CH_STA_5                     0x30
  36#define ZX_CH_STA_6                     0x34
  37
  38#define ZX_CTRL_MODA_16                 (0 << 6)
  39#define ZX_CTRL_MODA_18                 BIT(6)
  40#define ZX_CTRL_MODA_20                 (2 << 6)
  41#define ZX_CTRL_MODA_24                 (3 << 6)
  42#define ZX_CTRL_MODA_MASK               (3 << 6)
  43
  44#define ZX_CTRL_ENB                     BIT(4)
  45#define ZX_CTRL_DNB                     (0 << 4)
  46#define ZX_CTRL_ENB_MASK                BIT(4)
  47
  48#define ZX_CTRL_TX_OPEN                 BIT(0)
  49#define ZX_CTRL_TX_CLOSE                (0 << 0)
  50#define ZX_CTRL_TX_MASK                 BIT(0)
  51
  52#define ZX_CTRL_OPEN                    (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)
  53#define ZX_CTRL_CLOSE                   (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)
  54
  55#define ZX_CTRL_DOUBLE_TRACK            (0 << 8)
  56#define ZX_CTRL_LEFT_TRACK              BIT(8)
  57#define ZX_CTRL_RIGHT_TRACK             (2 << 8)
  58#define ZX_CTRL_TRACK_MASK              (3 << 8)
  59
  60#define ZX_FIFOCTRL_TXTH_MASK           (0x1f << 8)
  61#define ZX_FIFOCTRL_TXTH(x)             (x << 8)
  62#define ZX_FIFOCTRL_TX_DMA_EN           BIT(2)
  63#define ZX_FIFOCTRL_TX_DMA_DIS          (0 << 2)
  64#define ZX_FIFOCTRL_TX_DMA_EN_MASK      BIT(2)
  65#define ZX_FIFOCTRL_TX_FIFO_RST         BIT(0)
  66#define ZX_FIFOCTRL_TX_FIFO_RST_MASK    BIT(0)
  67
  68#define ZX_VALID_DOUBLE_TRACK           (0 << 0)
  69#define ZX_VALID_LEFT_TRACK             BIT(1)
  70#define ZX_VALID_RIGHT_TRACK            (2 << 0)
  71#define ZX_VALID_TRACK_MASK             (3 << 0)
  72
  73#define ZX_SPDIF_CLK_RAT                (2 * 32)
  74
  75struct zx_spdif_info {
  76        struct snd_dmaengine_dai_dma_data       dma_data;
  77        struct clk                              *dai_clk;
  78        void __iomem                            *reg_base;
  79        resource_size_t                         mapbase;
  80};
  81
  82static int zx_spdif_dai_probe(struct snd_soc_dai *dai)
  83{
  84        struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
  85
  86        snd_soc_dai_set_drvdata(dai, zx_spdif);
  87        zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA;
  88        zx_spdif->dma_data.maxburst = 8;
  89        snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL);
  90        return 0;
  91}
  92
  93static int zx_spdif_chanstats(void __iomem *base, unsigned int rate)
  94{
  95        u32 cstas1;
  96
  97        switch (rate) {
  98        case 22050:
  99                cstas1 = IEC958_AES3_CON_FS_22050;
 100                break;
 101        case 24000:
 102                cstas1 = IEC958_AES3_CON_FS_24000;
 103                break;
 104        case 32000:
 105                cstas1 = IEC958_AES3_CON_FS_32000;
 106                break;
 107        case 44100:
 108                cstas1 = IEC958_AES3_CON_FS_44100;
 109                break;
 110        case 48000:
 111                cstas1 = IEC958_AES3_CON_FS_48000;
 112                break;
 113        case 88200:
 114                cstas1 = IEC958_AES3_CON_FS_88200;
 115                break;
 116        case 96000:
 117                cstas1 = IEC958_AES3_CON_FS_96000;
 118                break;
 119        case 176400:
 120                cstas1 = IEC958_AES3_CON_FS_176400;
 121                break;
 122        case 192000:
 123                cstas1 = IEC958_AES3_CON_FS_192000;
 124                break;
 125        default:
 126                return -EINVAL;
 127        }
 128        cstas1 = cstas1 << 24;
 129        cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT;
 130
 131        writel_relaxed(cstas1, base + ZX_CH_STA_1);
 132        return 0;
 133}
 134
 135static int zx_spdif_hw_params(struct snd_pcm_substream *substream,
 136                              struct snd_pcm_hw_params *params,
 137                              struct snd_soc_dai *socdai)
 138{
 139        struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev);
 140        struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai);
 141        struct snd_dmaengine_dai_dma_data *dma_data =
 142                snd_soc_dai_get_dma_data(socdai, substream);
 143        u32 val, ch_num, rate;
 144        int ret;
 145
 146        dma_data->addr_width = params_width(params) >> 3;
 147
 148        val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL);
 149        val &= ~ZX_CTRL_MODA_MASK;
 150        switch (params_format(params)) {
 151        case SNDRV_PCM_FORMAT_S16_LE:
 152                val |= ZX_CTRL_MODA_16;
 153                break;
 154
 155        case SNDRV_PCM_FORMAT_S18_3LE:
 156                val |= ZX_CTRL_MODA_18;
 157                break;
 158
 159        case SNDRV_PCM_FORMAT_S20_3LE:
 160                val |= ZX_CTRL_MODA_20;
 161                break;
 162
 163        case SNDRV_PCM_FORMAT_S24_LE:
 164                val |= ZX_CTRL_MODA_24;
 165                break;
 166        default:
 167                dev_err(socdai->dev, "Format not support!\n");
 168                return -EINVAL;
 169        }
 170
 171        ch_num = params_channels(params);
 172        if (ch_num == 2)
 173                val |= ZX_CTRL_DOUBLE_TRACK;
 174        else
 175                val |= ZX_CTRL_LEFT_TRACK;
 176        writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL);
 177
 178        val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT);
 179        val &= ~ZX_VALID_TRACK_MASK;
 180        if (ch_num == 2)
 181                val |= ZX_VALID_DOUBLE_TRACK;
 182        else
 183                val |= ZX_VALID_RIGHT_TRACK;
 184        writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT);
 185
 186        rate = params_rate(params);
 187        ret = zx_spdif_chanstats(zx_spdif->reg_base, rate);
 188        if (ret)
 189                return ret;
 190        return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT);
 191}
 192
 193static void zx_spdif_cfg_tx(void __iomem *base, int on)
 194{
 195        u32 val;
 196
 197        val = readl_relaxed(base + ZX_CTRL);
 198        val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK);
 199        val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE;
 200        writel_relaxed(val, base + ZX_CTRL);
 201
 202        val = readl_relaxed(base + ZX_FIFOCTRL);
 203        val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK;
 204        if (on)
 205                val |= ZX_FIFOCTRL_TX_DMA_EN;
 206        writel_relaxed(val, base + ZX_FIFOCTRL);
 207}
 208
 209static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
 210                            struct snd_soc_dai *dai)
 211{
 212        u32 val;
 213        struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
 214        int  ret = 0;
 215
 216        switch (cmd) {
 217        case SNDRV_PCM_TRIGGER_START:
 218                val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL);
 219                val |= ZX_FIFOCTRL_TX_FIFO_RST;
 220                writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL);
 221        /* fall thru */
 222        case SNDRV_PCM_TRIGGER_RESUME:
 223        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 224                zx_spdif_cfg_tx(zx_spdif->reg_base, true);
 225                break;
 226
 227        case SNDRV_PCM_TRIGGER_STOP:
 228        case SNDRV_PCM_TRIGGER_SUSPEND:
 229        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 230                zx_spdif_cfg_tx(zx_spdif->reg_base, false);
 231                break;
 232
 233        default:
 234                ret = -EINVAL;
 235                break;
 236        }
 237
 238        return ret;
 239}
 240
 241static int zx_spdif_startup(struct snd_pcm_substream *substream,
 242                            struct snd_soc_dai *dai)
 243{
 244        struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
 245
 246        return clk_prepare_enable(zx_spdif->dai_clk);
 247}
 248
 249static void zx_spdif_shutdown(struct snd_pcm_substream *substream,
 250                              struct snd_soc_dai *dai)
 251{
 252        struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
 253
 254        clk_disable_unprepare(zx_spdif->dai_clk);
 255}
 256
 257#define ZX_RATES \
 258        (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 259        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
 260        SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
 261
 262#define ZX_FORMAT \
 263        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \
 264        | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
 265
 266static const struct snd_soc_dai_ops zx_spdif_dai_ops = {
 267        .trigger        = zx_spdif_trigger,
 268        .startup        = zx_spdif_startup,
 269        .shutdown       = zx_spdif_shutdown,
 270        .hw_params      = zx_spdif_hw_params,
 271};
 272
 273static struct snd_soc_dai_driver zx_spdif_dai = {
 274        .name = "spdif",
 275        .id = 0,
 276        .probe = zx_spdif_dai_probe,
 277        .playback = {
 278                .channels_min = 1,
 279                .channels_max = 2,
 280                .rates = ZX_RATES,
 281                .formats = ZX_FORMAT,
 282        },
 283        .ops = &zx_spdif_dai_ops,
 284};
 285
 286static const struct snd_soc_component_driver zx_spdif_component = {
 287        .name   = "spdif",
 288};
 289
 290static void zx_spdif_dev_init(void __iomem *base)
 291{
 292        u32 val;
 293
 294        writel_relaxed(0, base + ZX_CTRL);
 295        writel_relaxed(0, base + ZX_INT_MASK);
 296        writel_relaxed(0xf, base + ZX_INT_STATUS);
 297        writel_relaxed(0x1, base + ZX_FIFOCTRL);
 298
 299        val = readl_relaxed(base + ZX_FIFOCTRL);
 300        val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK);
 301        val |= ZX_FIFOCTRL_TXTH(8);
 302        writel_relaxed(val, base + ZX_FIFOCTRL);
 303}
 304
 305static int zx_spdif_probe(struct platform_device *pdev)
 306{
 307        struct resource *res;
 308        struct zx_spdif_info *zx_spdif;
 309        int ret;
 310
 311        zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL);
 312        if (!zx_spdif)
 313                return -ENOMEM;
 314
 315        zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx");
 316        if (IS_ERR(zx_spdif->dai_clk)) {
 317                dev_err(&pdev->dev, "Fail to get clk\n");
 318                return PTR_ERR(zx_spdif->dai_clk);
 319        }
 320
 321        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 322        zx_spdif->mapbase = res->start;
 323        zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res);
 324        if (IS_ERR(zx_spdif->reg_base)) {
 325                dev_err(&pdev->dev, "ioremap failed!\n");
 326                return PTR_ERR(zx_spdif->reg_base);
 327        }
 328
 329        zx_spdif_dev_init(zx_spdif->reg_base);
 330        platform_set_drvdata(pdev, zx_spdif);
 331
 332        ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component,
 333                                         &zx_spdif_dai, 1);
 334        if (ret) {
 335                dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
 336                return ret;
 337        }
 338
 339        ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 340        if (ret)
 341                dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
 342
 343        return ret;
 344}
 345
 346static const struct of_device_id zx_spdif_dt_ids[] = {
 347        { .compatible = "zte,zx296702-spdif", },
 348        {}
 349};
 350MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids);
 351
 352static struct platform_driver spdif_driver = {
 353        .probe = zx_spdif_probe,
 354        .driver = {
 355                .name = "zx-spdif",
 356                .of_match_table = zx_spdif_dt_ids,
 357        },
 358};
 359
 360module_platform_driver(spdif_driver);
 361
 362MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
 363MODULE_DESCRIPTION("ZTE SPDIF SoC DAI");
 364MODULE_LICENSE("GPL");
 365