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