linux/sound/soc/zte/zx-tdm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ZTE's TDM driver
   4 *
   5 * Copyright (C) 2017 ZTE Ltd
   6 *
   7 * Author: Baoyou Xie <baoyou.xie@linaro.org>
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/io.h>
  12#include <linux/mfd/syscon.h>
  13#include <linux/module.h>
  14#include <sound/dmaengine_pcm.h>
  15#include <sound/pcm_params.h>
  16#include <sound/soc.h>
  17#include <sound/soc-dai.h>
  18
  19#define REG_TIMING_CTRL         0x04
  20#define REG_TX_FIFO_CTRL        0x0C
  21#define REG_RX_FIFO_CTRL        0x10
  22#define REG_INT_EN              0x1C
  23#define REG_INT_STATUS          0x20
  24#define REG_DATABUF             0x24
  25#define REG_TS_MASK0            0x44
  26#define REG_PROCESS_CTRL        0x54
  27
  28#define FIFO_CTRL_TX_RST        BIT(0)
  29#define FIFO_CTRL_RX_RST        BIT(0)
  30#define DEAGULT_FIFO_THRES      GENMASK(4, 2)
  31
  32#define FIFO_CTRL_TX_DMA_EN     BIT(1)
  33#define FIFO_CTRL_RX_DMA_EN     BIT(1)
  34
  35#define TX_FIFO_RST_MASK        BIT(0)
  36#define RX_FIFO_RST_MASK        BIT(0)
  37
  38#define FIFOCTRL_TX_FIFO_RST    BIT(0)
  39#define FIFOCTRL_RX_FIFO_RST    BIT(0)
  40
  41#define TXTH_MASK               GENMASK(5, 2)
  42#define RXTH_MASK               GENMASK(5, 2)
  43
  44#define FIFOCTRL_THRESHOLD(x)   ((x) << 2)
  45
  46#define TIMING_MS_MASK          BIT(1)
  47/*
  48 * 00: 8 clk cycles every timeslot
  49 * 01: 16 clk cycles every timeslot
  50 * 10: 32 clk cycles every timeslot
  51 */
  52#define TIMING_SYNC_WIDTH_MASK  GENMASK(6, 5)
  53#define TIMING_WIDTH_SHIFT      5
  54#define TIMING_DEFAULT_WIDTH    0
  55#define TIMING_TS_WIDTH(x)      ((x) << TIMING_WIDTH_SHIFT)
  56#define TIMING_WIDTH_FACTOR     8
  57
  58#define TIMING_MASTER_MODE      BIT(21)
  59#define TIMING_LSB_FIRST        BIT(20)
  60#define TIMING_TS_NUM(x)        (((x) - 1) << 7)
  61#define TIMING_CLK_SEL_MASK     GENMASK(2, 0)
  62#define TIMING_CLK_SEL_DEF      BIT(2)
  63
  64#define PROCESS_TX_EN           BIT(0)
  65#define PROCESS_RX_EN           BIT(1)
  66#define PROCESS_TDM_EN          BIT(2)
  67#define PROCESS_DISABLE_ALL     0
  68
  69#define INT_DISABLE_ALL         0
  70#define INT_STATUS_MASK         GENMASK(6, 0)
  71
  72struct zx_tdm_info {
  73        struct snd_dmaengine_dai_dma_data       dma_playback;
  74        struct snd_dmaengine_dai_dma_data       dma_capture;
  75        resource_size_t                         phy_addr;
  76        void __iomem                            *regbase;
  77        struct clk                              *dai_wclk;
  78        struct clk                              *dai_pclk;
  79        int                                     master;
  80        struct device                           *dev;
  81};
  82
  83static inline u32 zx_tdm_readl(struct zx_tdm_info *tdm, u16 reg)
  84{
  85        return readl_relaxed(tdm->regbase + reg);
  86}
  87
  88static inline void zx_tdm_writel(struct zx_tdm_info *tdm, u16 reg, u32 val)
  89{
  90        writel_relaxed(val, tdm->regbase + reg);
  91}
  92
  93static void zx_tdm_tx_en(struct zx_tdm_info *tdm, bool on)
  94{
  95        unsigned long val;
  96
  97        val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
  98        if (on)
  99                val |= PROCESS_TX_EN | PROCESS_TDM_EN;
 100        else
 101                val &= ~(PROCESS_TX_EN | PROCESS_TDM_EN);
 102        zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
 103}
 104
 105static void zx_tdm_rx_en(struct zx_tdm_info *tdm, bool on)
 106{
 107        unsigned long val;
 108
 109        val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
 110        if (on)
 111                val |= PROCESS_RX_EN | PROCESS_TDM_EN;
 112        else
 113                val &= ~(PROCESS_RX_EN | PROCESS_TDM_EN);
 114        zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
 115}
 116
 117static void zx_tdm_tx_dma_en(struct zx_tdm_info *tdm, bool on)
 118{
 119        unsigned long val;
 120
 121        val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
 122        val |= FIFO_CTRL_TX_RST | DEAGULT_FIFO_THRES;
 123        if (on)
 124                val |= FIFO_CTRL_TX_DMA_EN;
 125        else
 126                val &= ~FIFO_CTRL_TX_DMA_EN;
 127        zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
 128}
 129
 130static void zx_tdm_rx_dma_en(struct zx_tdm_info *tdm, bool on)
 131{
 132        unsigned long val;
 133
 134        val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
 135        val |= FIFO_CTRL_RX_RST | DEAGULT_FIFO_THRES;
 136        if (on)
 137                val |= FIFO_CTRL_RX_DMA_EN;
 138        else
 139                val &= ~FIFO_CTRL_RX_DMA_EN;
 140        zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
 141}
 142
 143#define ZX_TDM_RATES    (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
 144
 145#define ZX_TDM_FMTBIT \
 146        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \
 147        SNDRV_PCM_FMTBIT_A_LAW)
 148
 149static int zx_tdm_dai_probe(struct snd_soc_dai *dai)
 150{
 151        struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
 152
 153        snd_soc_dai_set_drvdata(dai, zx_tdm);
 154        zx_tdm->dma_playback.addr = zx_tdm->phy_addr + REG_DATABUF;
 155        zx_tdm->dma_playback.maxburst = 16;
 156        zx_tdm->dma_capture.addr = zx_tdm->phy_addr + REG_DATABUF;
 157        zx_tdm->dma_capture.maxburst = 16;
 158        snd_soc_dai_init_dma_data(dai, &zx_tdm->dma_playback,
 159                                  &zx_tdm->dma_capture);
 160        return 0;
 161}
 162
 163static int zx_tdm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 164{
 165        struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(cpu_dai);
 166        unsigned long val;
 167
 168        val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
 169        val &= ~(TIMING_SYNC_WIDTH_MASK | TIMING_MS_MASK);
 170        val |= TIMING_DEFAULT_WIDTH << TIMING_WIDTH_SHIFT;
 171
 172        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 173        case SND_SOC_DAIFMT_CBM_CFM:
 174                tdm->master = 1;
 175                val |= TIMING_MASTER_MODE;
 176                break;
 177        case SND_SOC_DAIFMT_CBS_CFS:
 178                tdm->master = 0;
 179                val &= ~TIMING_MASTER_MODE;
 180                break;
 181        default:
 182                dev_err(cpu_dai->dev, "Unknown master/slave format\n");
 183                return -EINVAL;
 184        }
 185
 186
 187        zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
 188
 189        return 0;
 190}
 191
 192static int zx_tdm_hw_params(struct snd_pcm_substream *substream,
 193                            struct snd_pcm_hw_params *params,
 194                            struct snd_soc_dai *socdai)
 195{
 196        struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(socdai);
 197        struct snd_dmaengine_dai_dma_data *dma_data;
 198        unsigned int ts_width = TIMING_DEFAULT_WIDTH;
 199        unsigned int ch_num = 32;
 200        unsigned int mask = 0;
 201        unsigned int ret = 0;
 202        unsigned long val;
 203
 204        dma_data = snd_soc_dai_get_dma_data(socdai, substream);
 205        dma_data->addr_width = ch_num >> 3;
 206
 207        switch (params_format(params)) {
 208        case SNDRV_PCM_FORMAT_MU_LAW:
 209        case SNDRV_PCM_FORMAT_A_LAW:
 210        case SNDRV_PCM_FORMAT_S16_LE:
 211                ts_width = 1;
 212                break;
 213        default:
 214                dev_err(socdai->dev, "Unknown data format\n");
 215                return -EINVAL;
 216        }
 217
 218        val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
 219        val |= TIMING_TS_WIDTH(ts_width) | TIMING_TS_NUM(1);
 220        zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
 221        zx_tdm_writel(tdm, REG_TS_MASK0, mask);
 222
 223        if (tdm->master)
 224                ret = clk_set_rate(tdm->dai_wclk,
 225                        params_rate(params) * TIMING_WIDTH_FACTOR * ch_num);
 226
 227        return ret;
 228}
 229
 230static int zx_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
 231                          struct snd_soc_dai *dai)
 232{
 233        int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
 234        struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
 235        unsigned int val;
 236        int ret = 0;
 237
 238        switch (cmd) {
 239        case SNDRV_PCM_TRIGGER_START:
 240                if (capture) {
 241                        val = zx_tdm_readl(zx_tdm, REG_RX_FIFO_CTRL);
 242                        val |= FIFOCTRL_RX_FIFO_RST;
 243                        zx_tdm_writel(zx_tdm, REG_RX_FIFO_CTRL, val);
 244
 245                        zx_tdm_rx_dma_en(zx_tdm, true);
 246                } else {
 247                        val = zx_tdm_readl(zx_tdm, REG_TX_FIFO_CTRL);
 248                        val |= FIFOCTRL_TX_FIFO_RST;
 249                        zx_tdm_writel(zx_tdm, REG_TX_FIFO_CTRL, val);
 250
 251                        zx_tdm_tx_dma_en(zx_tdm, true);
 252                }
 253                break;
 254        case SNDRV_PCM_TRIGGER_RESUME:
 255        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 256                if (capture)
 257                        zx_tdm_rx_en(zx_tdm, true);
 258                else
 259                        zx_tdm_tx_en(zx_tdm, true);
 260                break;
 261        case SNDRV_PCM_TRIGGER_STOP:
 262                if (capture)
 263                        zx_tdm_rx_dma_en(zx_tdm, false);
 264                else
 265                        zx_tdm_tx_dma_en(zx_tdm, false);
 266                break;
 267        case SNDRV_PCM_TRIGGER_SUSPEND:
 268        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 269                if (capture)
 270                        zx_tdm_rx_en(zx_tdm, false);
 271                else
 272                        zx_tdm_tx_en(zx_tdm, false);
 273                break;
 274        default:
 275                ret = -EINVAL;
 276                break;
 277        }
 278
 279        return ret;
 280}
 281
 282static int zx_tdm_startup(struct snd_pcm_substream *substream,
 283                          struct snd_soc_dai *dai)
 284{
 285        struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
 286        int ret;
 287
 288        ret = clk_prepare_enable(zx_tdm->dai_wclk);
 289        if (ret)
 290                return ret;
 291
 292        ret = clk_prepare_enable(zx_tdm->dai_pclk);
 293        if (ret) {
 294                clk_disable_unprepare(zx_tdm->dai_wclk);
 295                return ret;
 296        }
 297
 298        return 0;
 299}
 300
 301static void zx_tdm_shutdown(struct snd_pcm_substream *substream,
 302                            struct snd_soc_dai *dai)
 303{
 304        struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
 305
 306        clk_disable_unprepare(zx_tdm->dai_pclk);
 307        clk_disable_unprepare(zx_tdm->dai_wclk);
 308}
 309
 310static const struct snd_soc_dai_ops zx_tdm_dai_ops = {
 311        .trigger        = zx_tdm_trigger,
 312        .hw_params      = zx_tdm_hw_params,
 313        .set_fmt        = zx_tdm_set_fmt,
 314        .startup        = zx_tdm_startup,
 315        .shutdown       = zx_tdm_shutdown,
 316};
 317
 318static const struct snd_soc_component_driver zx_tdm_component = {
 319        .name                   = "zx-tdm",
 320};
 321
 322static void zx_tdm_init_state(struct zx_tdm_info *tdm)
 323{
 324        unsigned int val;
 325
 326        zx_tdm_writel(tdm, REG_PROCESS_CTRL, PROCESS_DISABLE_ALL);
 327
 328        val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
 329        val |= TIMING_LSB_FIRST;
 330        val &= ~TIMING_CLK_SEL_MASK;
 331        val |= TIMING_CLK_SEL_DEF;
 332        zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
 333
 334        zx_tdm_writel(tdm, REG_INT_EN, INT_DISABLE_ALL);
 335        /*
 336         * write INT_STATUS register to clear it.
 337         */
 338        zx_tdm_writel(tdm, REG_INT_STATUS, INT_STATUS_MASK);
 339        zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, FIFOCTRL_RX_FIFO_RST);
 340        zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, FIFOCTRL_TX_FIFO_RST);
 341
 342        val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
 343        val &= ~(RXTH_MASK | RX_FIFO_RST_MASK);
 344        val |= FIFOCTRL_THRESHOLD(8);
 345        zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
 346
 347        val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
 348        val &= ~(TXTH_MASK | TX_FIFO_RST_MASK);
 349        val |= FIFOCTRL_THRESHOLD(8);
 350        zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
 351}
 352
 353static struct snd_soc_dai_driver zx_tdm_dai = {
 354        .name   = "zx-tdm-dai",
 355        .id     = 0,
 356        .probe  = zx_tdm_dai_probe,
 357        .playback   = {
 358                .channels_min   = 1,
 359                .channels_max   = 4,
 360                .rates          = ZX_TDM_RATES,
 361                .formats        = ZX_TDM_FMTBIT,
 362        },
 363        .capture = {
 364                .channels_min   = 1,
 365                .channels_max   = 4,
 366                .rates          = ZX_TDM_RATES,
 367                .formats        = ZX_TDM_FMTBIT,
 368        },
 369        .ops    = &zx_tdm_dai_ops,
 370};
 371
 372static int zx_tdm_probe(struct platform_device *pdev)
 373{
 374        struct of_phandle_args out_args;
 375        unsigned int dma_reg_offset;
 376        struct zx_tdm_info *zx_tdm;
 377        unsigned int dma_mask;
 378        struct resource *res;
 379        struct regmap *regmap_sysctrl;
 380        int ret;
 381
 382        zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL);
 383        if (!zx_tdm)
 384                return -ENOMEM;
 385
 386        zx_tdm->dev = &pdev->dev;
 387
 388        zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
 389        if (IS_ERR(zx_tdm->dai_wclk)) {
 390                dev_err(&pdev->dev, "Fail to get wclk\n");
 391                return PTR_ERR(zx_tdm->dai_wclk);
 392        }
 393
 394        zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
 395        if (IS_ERR(zx_tdm->dai_pclk)) {
 396                dev_err(&pdev->dev, "Fail to get pclk\n");
 397                return PTR_ERR(zx_tdm->dai_pclk);
 398        }
 399
 400        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 401        zx_tdm->phy_addr = res->start;
 402        zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res);
 403        if (IS_ERR(zx_tdm->regbase))
 404                return PTR_ERR(zx_tdm->regbase);
 405
 406        ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
 407                                "zte,tdm-dma-sysctrl", 2, 0, &out_args);
 408        if (ret) {
 409                dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n");
 410                return ret;
 411        }
 412
 413        dma_reg_offset = out_args.args[0];
 414        dma_mask = out_args.args[1];
 415        regmap_sysctrl = syscon_node_to_regmap(out_args.np);
 416        if (IS_ERR(regmap_sysctrl)) {
 417                of_node_put(out_args.np);
 418                return PTR_ERR(regmap_sysctrl);
 419        }
 420
 421        regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask);
 422        of_node_put(out_args.np);
 423
 424        zx_tdm_init_state(zx_tdm);
 425        platform_set_drvdata(pdev, zx_tdm);
 426
 427        ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component,
 428                                                &zx_tdm_dai, 1);
 429        if (ret) {
 430                dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
 431                return ret;
 432        }
 433
 434        ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 435        if (ret)
 436                dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
 437
 438        return ret;
 439}
 440
 441static const struct of_device_id zx_tdm_dt_ids[] = {
 442        { .compatible = "zte,zx296718-tdm", },
 443        {}
 444};
 445MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids);
 446
 447static struct platform_driver tdm_driver = {
 448        .probe = zx_tdm_probe,
 449        .driver = {
 450                .name = "zx-tdm",
 451                .of_match_table = zx_tdm_dt_ids,
 452        },
 453};
 454module_platform_driver(tdm_driver);
 455
 456MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
 457MODULE_DESCRIPTION("ZTE TDM DAI driver");
 458MODULE_LICENSE("GPL v2");
 459