linux/sound/soc/sirf/sirf-usp.c
<<
>>
Prefs
   1/*
   2 * SiRF USP in I2S/DSP mode
   3 *
   4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
   5 *
   6 * Licensed under GPLv2 or later.
   7 */
   8#include <linux/module.h>
   9#include <linux/io.h>
  10#include <linux/of.h>
  11#include <linux/clk.h>
  12#include <linux/pm_runtime.h>
  13#include <sound/soc.h>
  14#include <sound/pcm_params.h>
  15#include <sound/dmaengine_pcm.h>
  16
  17#include "sirf-usp.h"
  18
  19struct sirf_usp {
  20        struct regmap *regmap;
  21        struct clk *clk;
  22        u32 mode1_reg;
  23        u32 mode2_reg;
  24        int daifmt_format;
  25        struct snd_dmaengine_dai_dma_data playback_dma_data;
  26        struct snd_dmaengine_dai_dma_data capture_dma_data;
  27};
  28
  29static void sirf_usp_tx_enable(struct sirf_usp *usp)
  30{
  31        regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
  32                USP_TX_FIFO_RESET, USP_TX_FIFO_RESET);
  33        regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
  34
  35        regmap_update_bits(usp->regmap, USP_TX_FIFO_OP,
  36                USP_TX_FIFO_START, USP_TX_FIFO_START);
  37
  38        regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
  39                USP_TX_ENA, USP_TX_ENA);
  40}
  41
  42static void sirf_usp_tx_disable(struct sirf_usp *usp)
  43{
  44        regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
  45                USP_TX_ENA, ~USP_TX_ENA);
  46        /* FIFO stop */
  47        regmap_write(usp->regmap, USP_TX_FIFO_OP, 0);
  48}
  49
  50static void sirf_usp_rx_enable(struct sirf_usp *usp)
  51{
  52        regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
  53                USP_RX_FIFO_RESET, USP_RX_FIFO_RESET);
  54        regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
  55
  56        regmap_update_bits(usp->regmap, USP_RX_FIFO_OP,
  57                USP_RX_FIFO_START, USP_RX_FIFO_START);
  58
  59        regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
  60                USP_RX_ENA, USP_RX_ENA);
  61}
  62
  63static void sirf_usp_rx_disable(struct sirf_usp *usp)
  64{
  65        regmap_update_bits(usp->regmap, USP_TX_RX_ENABLE,
  66                USP_RX_ENA, ~USP_RX_ENA);
  67        /* FIFO stop */
  68        regmap_write(usp->regmap, USP_RX_FIFO_OP, 0);
  69}
  70
  71static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai)
  72{
  73        struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
  74
  75        snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data,
  76                        &usp->capture_dma_data);
  77        return 0;
  78}
  79
  80static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai,
  81                unsigned int fmt)
  82{
  83        struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
  84
  85        /* set master/slave audio interface */
  86        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  87        case SND_SOC_DAIFMT_CBM_CFM:
  88                break;
  89        default:
  90                dev_err(dai->dev, "Only CBM and CFM supported\n");
  91                return -EINVAL;
  92        }
  93
  94        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  95        case SND_SOC_DAIFMT_I2S:
  96        case SND_SOC_DAIFMT_DSP_A:
  97                usp->daifmt_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
  98                break;
  99        default:
 100                dev_err(dai->dev, "Only I2S and DSP_A format supported\n");
 101                return -EINVAL;
 102        }
 103
 104        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 105        case SND_SOC_DAIFMT_NB_NF:
 106                break;
 107        case SND_SOC_DAIFMT_IB_NF:
 108                usp->daifmt_format |= (fmt & SND_SOC_DAIFMT_INV_MASK);
 109                break;
 110        default:
 111                return -EINVAL;
 112        }
 113
 114        return 0;
 115}
 116
 117static void sirf_usp_i2s_init(struct sirf_usp *usp)
 118{
 119        /* Configure RISC mode */
 120        regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE,
 121                USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL);
 122
 123        /*
 124         * Configure DMA IO Length register
 125         * Set no limit, USP can receive data continuously until it is diabled
 126         */
 127        regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0);
 128        regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0);
 129
 130        /* Configure Mode2 register */
 131        regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) |
 132                (0 << USP_TXD_DELAY_LEN_OFFSET) |
 133                USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE);
 134
 135        /* Configure Mode1 register */
 136        regmap_write(usp->regmap, USP_MODE1,
 137                USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING |
 138                USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 |
 139                USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE);
 140
 141        /* Configure RX DMA IO Control register */
 142        regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0);
 143
 144        /* Congiure RX FIFO Control register */
 145        regmap_write(usp->regmap, USP_RX_FIFO_CTRL,
 146                (USP_RX_FIFO_THRESHOLD << USP_RX_FIFO_THD_OFFSET) |
 147                (USP_TX_RX_FIFO_WIDTH_DWORD << USP_RX_FIFO_WIDTH_OFFSET));
 148
 149        /* Congiure RX FIFO Level Check register */
 150        regmap_write(usp->regmap, USP_RX_FIFO_LEVEL_CHK,
 151                RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B));
 152
 153        /* Configure TX DMA IO Control register*/
 154        regmap_write(usp->regmap, USP_TX_DMA_IO_CTRL, 0);
 155
 156        /* Configure TX FIFO Control register */
 157        regmap_write(usp->regmap, USP_TX_FIFO_CTRL,
 158                (USP_TX_FIFO_THRESHOLD << USP_TX_FIFO_THD_OFFSET) |
 159                (USP_TX_RX_FIFO_WIDTH_DWORD << USP_TX_FIFO_WIDTH_OFFSET));
 160        /* Congiure TX FIFO Level Check register */
 161        regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK,
 162                TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04));
 163}
 164
 165static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream,
 166                struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 167{
 168        struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
 169        u32 data_len, frame_len, shifter_len;
 170
 171        switch (params_format(params)) {
 172        case SNDRV_PCM_FORMAT_S16_LE:
 173                data_len = 16;
 174                frame_len = 16;
 175                break;
 176        case SNDRV_PCM_FORMAT_S24_LE:
 177                data_len = 24;
 178                frame_len = 32;
 179                break;
 180        case SNDRV_PCM_FORMAT_S24_3LE:
 181                data_len = 24;
 182                frame_len = 24;
 183                break;
 184        default:
 185                dev_err(dai->dev, "Format unsupported\n");
 186                return -EINVAL;
 187        }
 188
 189        shifter_len = data_len;
 190
 191        switch (usp->daifmt_format & SND_SOC_DAIFMT_FORMAT_MASK) {
 192        case SND_SOC_DAIFMT_I2S:
 193                regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
 194                        USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG);
 195                break;
 196        case SND_SOC_DAIFMT_DSP_A:
 197                regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
 198                        USP_I2S_SYNC_CHG, 0);
 199                frame_len = data_len * params_channels(params);
 200                data_len = frame_len;
 201                break;
 202        default:
 203                dev_err(dai->dev, "Only support I2S and DSP_A mode\n");
 204                return -EINVAL;
 205        }
 206
 207        switch (usp->daifmt_format & SND_SOC_DAIFMT_INV_MASK) {
 208        case SND_SOC_DAIFMT_NB_NF:
 209                break;
 210        case SND_SOC_DAIFMT_IB_NF:
 211                regmap_update_bits(usp->regmap, USP_MODE1,
 212                        USP_RXD_ACT_EDGE_FALLING | USP_TXD_ACT_EDGE_FALLING,
 213                        USP_RXD_ACT_EDGE_FALLING);
 214                break;
 215        default:
 216                return -EINVAL;
 217        }
 218
 219        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 220                regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL,
 221                        USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK
 222                        | USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE,
 223                        ((data_len - 1) << USP_TXC_DATA_LEN_OFFSET)
 224                        | ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET)
 225                        | ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET)
 226                        | USP_TXC_SLAVE_CLK_SAMPLE);
 227        else
 228                regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL,
 229                        USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK
 230                        | USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE,
 231                        ((data_len - 1) << USP_RXC_DATA_LEN_OFFSET)
 232                        | ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET)
 233                        | ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET)
 234                        | USP_SINGLE_SYNC_MODE);
 235
 236        return 0;
 237}
 238
 239static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
 240                                struct snd_soc_dai *dai)
 241{
 242        struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
 243
 244        switch (cmd) {
 245        case SNDRV_PCM_TRIGGER_START:
 246        case SNDRV_PCM_TRIGGER_RESUME:
 247        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 248                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 249                        sirf_usp_tx_enable(usp);
 250                else
 251                        sirf_usp_rx_enable(usp);
 252                break;
 253        case SNDRV_PCM_TRIGGER_STOP:
 254        case SNDRV_PCM_TRIGGER_SUSPEND:
 255        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 256                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 257                        sirf_usp_tx_disable(usp);
 258                else
 259                        sirf_usp_rx_disable(usp);
 260                break;
 261        }
 262
 263        return 0;
 264}
 265
 266static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = {
 267        .trigger = sirf_usp_pcm_trigger,
 268        .set_fmt = sirf_usp_pcm_set_dai_fmt,
 269        .hw_params = sirf_usp_pcm_hw_params,
 270};
 271
 272static struct snd_soc_dai_driver sirf_usp_pcm_dai = {
 273        .probe = sirf_usp_pcm_dai_probe,
 274        .name = "sirf-usp-pcm",
 275        .id = 0,
 276        .playback = {
 277                .stream_name = "SiRF USP PCM Playback",
 278                .channels_min = 1,
 279                .channels_max = 2,
 280                .rates = SNDRV_PCM_RATE_8000_192000,
 281                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
 282                        SNDRV_PCM_FMTBIT_S24_3LE,
 283        },
 284        .capture = {
 285                .stream_name = "SiRF USP PCM Capture",
 286                .channels_min = 1,
 287                .channels_max = 2,
 288                .rates = SNDRV_PCM_RATE_8000_192000,
 289                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
 290                        SNDRV_PCM_FMTBIT_S24_3LE,
 291        },
 292        .ops = &sirf_usp_pcm_dai_ops,
 293};
 294
 295static int sirf_usp_pcm_runtime_suspend(struct device *dev)
 296{
 297        struct sirf_usp *usp = dev_get_drvdata(dev);
 298
 299        clk_disable_unprepare(usp->clk);
 300        return 0;
 301}
 302
 303static int sirf_usp_pcm_runtime_resume(struct device *dev)
 304{
 305        struct sirf_usp *usp = dev_get_drvdata(dev);
 306        int ret;
 307
 308        ret = clk_prepare_enable(usp->clk);
 309        if (ret) {
 310                dev_err(dev, "clk_enable failed: %d\n", ret);
 311                return ret;
 312        }
 313        sirf_usp_i2s_init(usp);
 314        return 0;
 315}
 316
 317#ifdef CONFIG_PM_SLEEP
 318static int sirf_usp_pcm_suspend(struct device *dev)
 319{
 320        struct sirf_usp *usp = dev_get_drvdata(dev);
 321
 322        if (!pm_runtime_status_suspended(dev)) {
 323                regmap_read(usp->regmap, USP_MODE1, &usp->mode1_reg);
 324                regmap_read(usp->regmap, USP_MODE2, &usp->mode2_reg);
 325                sirf_usp_pcm_runtime_suspend(dev);
 326        }
 327        return 0;
 328}
 329
 330static int sirf_usp_pcm_resume(struct device *dev)
 331{
 332        struct sirf_usp *usp = dev_get_drvdata(dev);
 333        int ret;
 334
 335        if (!pm_runtime_status_suspended(dev)) {
 336                ret = sirf_usp_pcm_runtime_resume(dev);
 337                if (ret)
 338                        return ret;
 339                regmap_write(usp->regmap, USP_MODE1, usp->mode1_reg);
 340                regmap_write(usp->regmap, USP_MODE2, usp->mode2_reg);
 341        }
 342        return 0;
 343}
 344#endif
 345
 346static const struct snd_soc_component_driver sirf_usp_component = {
 347        .name           = "sirf-usp",
 348};
 349
 350static const struct regmap_config sirf_usp_regmap_config = {
 351        .reg_bits = 32,
 352        .reg_stride = 4,
 353        .val_bits = 32,
 354        .max_register = USP_RX_FIFO_DATA,
 355        .cache_type = REGCACHE_NONE,
 356};
 357
 358static int sirf_usp_pcm_probe(struct platform_device *pdev)
 359{
 360        int ret;
 361        struct sirf_usp *usp;
 362        void __iomem *base;
 363        struct resource *mem_res;
 364
 365        usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp),
 366                        GFP_KERNEL);
 367        if (!usp)
 368                return -ENOMEM;
 369
 370        platform_set_drvdata(pdev, usp);
 371
 372        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 373        base = devm_ioremap(&pdev->dev, mem_res->start,
 374                resource_size(mem_res));
 375        if (base == NULL)
 376                return -ENOMEM;
 377        usp->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 378                                            &sirf_usp_regmap_config);
 379        if (IS_ERR(usp->regmap))
 380                return PTR_ERR(usp->regmap);
 381
 382        usp->clk = devm_clk_get(&pdev->dev, NULL);
 383        if (IS_ERR(usp->clk)) {
 384                dev_err(&pdev->dev, "Get clock failed.\n");
 385                return PTR_ERR(usp->clk);
 386        }
 387
 388        pm_runtime_enable(&pdev->dev);
 389        if (!pm_runtime_enabled(&pdev->dev)) {
 390                ret = sirf_usp_pcm_runtime_resume(&pdev->dev);
 391                if (ret)
 392                        return ret;
 393        }
 394
 395        ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component,
 396                &sirf_usp_pcm_dai, 1);
 397        if (ret) {
 398                dev_err(&pdev->dev, "Register Audio SoC dai failed.\n");
 399                return ret;
 400        }
 401        return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 402}
 403
 404static int sirf_usp_pcm_remove(struct platform_device *pdev)
 405{
 406        if (!pm_runtime_enabled(&pdev->dev))
 407                sirf_usp_pcm_runtime_suspend(&pdev->dev);
 408        else
 409                pm_runtime_disable(&pdev->dev);
 410        return 0;
 411}
 412
 413static const struct of_device_id sirf_usp_pcm_of_match[] = {
 414        { .compatible = "sirf,prima2-usp-pcm", },
 415        {}
 416};
 417MODULE_DEVICE_TABLE(of, sirf_usp_pcm_of_match);
 418
 419static const struct dev_pm_ops sirf_usp_pcm_pm_ops = {
 420        SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend,
 421                sirf_usp_pcm_runtime_resume, NULL)
 422        SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend, sirf_usp_pcm_resume)
 423};
 424
 425static struct platform_driver sirf_usp_pcm_driver = {
 426        .driver = {
 427                .name = "sirf-usp-pcm",
 428                .of_match_table = sirf_usp_pcm_of_match,
 429                .pm = &sirf_usp_pcm_pm_ops,
 430        },
 431        .probe = sirf_usp_pcm_probe,
 432        .remove = sirf_usp_pcm_remove,
 433};
 434
 435module_platform_driver(sirf_usp_pcm_driver);
 436
 437MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver");
 438MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
 439MODULE_LICENSE("GPL v2");
 440