root/sound/soc/zte/zx-tdm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zx_tdm_readl
  2. zx_tdm_writel
  3. zx_tdm_tx_en
  4. zx_tdm_rx_en
  5. zx_tdm_tx_dma_en
  6. zx_tdm_rx_dma_en
  7. zx_tdm_dai_probe
  8. zx_tdm_set_fmt
  9. zx_tdm_hw_params
  10. zx_tdm_trigger
  11. zx_tdm_startup
  12. zx_tdm_shutdown
  13. zx_tdm_init_state
  14. zx_tdm_probe

   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 
  72 struct 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 
  83 static inline u32 zx_tdm_readl(struct zx_tdm_info *tdm, u16 reg)
  84 {
  85         return readl_relaxed(tdm->regbase + reg);
  86 }
  87 
  88 static inline void zx_tdm_writel(struct zx_tdm_info *tdm, u16 reg, u32 val)
  89 {
  90         writel_relaxed(val, tdm->regbase + reg);
  91 }
  92 
  93 static 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 
 105 static 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 
 117 static 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 
 130 static 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 
 149 static 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 
 163 static 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 
 192 static 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 
 230 static 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 
 282 static 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 
 301 static 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 
 310 static 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 
 318 static const struct snd_soc_component_driver zx_tdm_component = {
 319         .name                   = "zx-tdm",
 320 };
 321 
 322 static 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 
 353 static 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 
 372 static int zx_tdm_probe(struct platform_device *pdev)
 373 {
 374         struct device *dev = &pdev->dev;
 375         struct of_phandle_args out_args;
 376         unsigned int dma_reg_offset;
 377         struct zx_tdm_info *zx_tdm;
 378         unsigned int dma_mask;
 379         struct resource *res;
 380         struct regmap *regmap_sysctrl;
 381         int ret;
 382 
 383         zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL);
 384         if (!zx_tdm)
 385                 return -ENOMEM;
 386 
 387         zx_tdm->dev = dev;
 388 
 389         zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
 390         if (IS_ERR(zx_tdm->dai_wclk)) {
 391                 dev_err(&pdev->dev, "Fail to get wclk\n");
 392                 return PTR_ERR(zx_tdm->dai_wclk);
 393         }
 394 
 395         zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
 396         if (IS_ERR(zx_tdm->dai_pclk)) {
 397                 dev_err(&pdev->dev, "Fail to get pclk\n");
 398                 return PTR_ERR(zx_tdm->dai_pclk);
 399         }
 400 
 401         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 402         zx_tdm->phy_addr = res->start;
 403         zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res);
 404         if (IS_ERR(zx_tdm->regbase))
 405                 return PTR_ERR(zx_tdm->regbase);
 406 
 407         ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
 408                                 "zte,tdm-dma-sysctrl", 2, 0, &out_args);
 409         if (ret) {
 410                 dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n");
 411                 return ret;
 412         }
 413 
 414         dma_reg_offset = out_args.args[0];
 415         dma_mask = out_args.args[1];
 416         regmap_sysctrl = syscon_node_to_regmap(out_args.np);
 417         if (IS_ERR(regmap_sysctrl)) {
 418                 of_node_put(out_args.np);
 419                 return PTR_ERR(regmap_sysctrl);
 420         }
 421 
 422         regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask);
 423         of_node_put(out_args.np);
 424 
 425         zx_tdm_init_state(zx_tdm);
 426         platform_set_drvdata(pdev, zx_tdm);
 427 
 428         ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component,
 429                                                 &zx_tdm_dai, 1);
 430         if (ret) {
 431                 dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
 432                 return ret;
 433         }
 434 
 435         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 436         if (ret)
 437                 dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
 438 
 439         return ret;
 440 }
 441 
 442 static const struct of_device_id zx_tdm_dt_ids[] = {
 443         { .compatible = "zte,zx296718-tdm", },
 444         {}
 445 };
 446 MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids);
 447 
 448 static struct platform_driver tdm_driver = {
 449         .probe = zx_tdm_probe,
 450         .driver = {
 451                 .name = "zx-tdm",
 452                 .of_match_table = zx_tdm_dt_ids,
 453         },
 454 };
 455 module_platform_driver(tdm_driver);
 456 
 457 MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
 458 MODULE_DESCRIPTION("ZTE TDM DAI driver");
 459 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */