root/sound/soc/tegra/tegra30_i2s.c

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

DEFINITIONS

This source file includes following definitions.
  1. tegra30_i2s_runtime_suspend
  2. tegra30_i2s_runtime_resume
  3. tegra30_i2s_set_fmt
  4. tegra30_i2s_hw_params
  5. tegra30_i2s_start_playback
  6. tegra30_i2s_stop_playback
  7. tegra30_i2s_start_capture
  8. tegra30_i2s_stop_capture
  9. tegra30_i2s_trigger
  10. tegra30_i2s_probe
  11. tegra30_i2s_wr_rd_reg
  12. tegra30_i2s_volatile_reg
  13. tegra30_i2s_platform_probe
  14. tegra30_i2s_platform_remove
  15. tegra30_i2s_suspend
  16. tegra30_i2s_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * tegra30_i2s.c - Tegra30 I2S driver
   4  *
   5  * Author: Stephen Warren <swarren@nvidia.com>
   6  * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
   7  *
   8  * Based on code copyright/by:
   9  *
  10  * Copyright (c) 2009-2010, NVIDIA Corporation.
  11  * Scott Peterson <speterson@nvidia.com>
  12  *
  13  * Copyright (C) 2010 Google, Inc.
  14  * Iliyan Malchev <malchev@google.com>
  15  */
  16 
  17 #include <linux/clk.h>
  18 #include <linux/device.h>
  19 #include <linux/io.h>
  20 #include <linux/module.h>
  21 #include <linux/of.h>
  22 #include <linux/of_device.h>
  23 #include <linux/platform_device.h>
  24 #include <linux/pm_runtime.h>
  25 #include <linux/regmap.h>
  26 #include <linux/slab.h>
  27 #include <sound/core.h>
  28 #include <sound/pcm.h>
  29 #include <sound/pcm_params.h>
  30 #include <sound/soc.h>
  31 #include <sound/dmaengine_pcm.h>
  32 
  33 #include "tegra30_ahub.h"
  34 #include "tegra30_i2s.h"
  35 
  36 #define DRV_NAME "tegra30-i2s"
  37 
  38 static int tegra30_i2s_runtime_suspend(struct device *dev)
  39 {
  40         struct tegra30_i2s *i2s = dev_get_drvdata(dev);
  41 
  42         regcache_cache_only(i2s->regmap, true);
  43 
  44         clk_disable_unprepare(i2s->clk_i2s);
  45 
  46         return 0;
  47 }
  48 
  49 static int tegra30_i2s_runtime_resume(struct device *dev)
  50 {
  51         struct tegra30_i2s *i2s = dev_get_drvdata(dev);
  52         int ret;
  53 
  54         ret = clk_prepare_enable(i2s->clk_i2s);
  55         if (ret) {
  56                 dev_err(dev, "clk_enable failed: %d\n", ret);
  57                 return ret;
  58         }
  59 
  60         regcache_cache_only(i2s->regmap, false);
  61 
  62         return 0;
  63 }
  64 
  65 static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
  66                                 unsigned int fmt)
  67 {
  68         struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
  69         unsigned int mask = 0, val = 0;
  70 
  71         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  72         case SND_SOC_DAIFMT_NB_NF:
  73                 break;
  74         default:
  75                 return -EINVAL;
  76         }
  77 
  78         mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
  79         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  80         case SND_SOC_DAIFMT_CBS_CFS:
  81                 val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
  82                 break;
  83         case SND_SOC_DAIFMT_CBM_CFM:
  84                 break;
  85         default:
  86                 return -EINVAL;
  87         }
  88 
  89         mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
  90                 TEGRA30_I2S_CTRL_LRCK_MASK;
  91         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  92         case SND_SOC_DAIFMT_DSP_A:
  93                 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
  94                 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
  95                 break;
  96         case SND_SOC_DAIFMT_DSP_B:
  97                 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
  98                 val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
  99                 break;
 100         case SND_SOC_DAIFMT_I2S:
 101                 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
 102                 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
 103                 break;
 104         case SND_SOC_DAIFMT_RIGHT_J:
 105                 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
 106                 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
 107                 break;
 108         case SND_SOC_DAIFMT_LEFT_J:
 109                 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
 110                 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
 111                 break;
 112         default:
 113                 return -EINVAL;
 114         }
 115 
 116         pm_runtime_get_sync(dai->dev);
 117         regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
 118         pm_runtime_put(dai->dev);
 119 
 120         return 0;
 121 }
 122 
 123 static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
 124                                  struct snd_pcm_hw_params *params,
 125                                  struct snd_soc_dai *dai)
 126 {
 127         struct device *dev = dai->dev;
 128         struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 129         unsigned int mask, val, reg;
 130         int ret, sample_size, srate, i2sclock, bitcnt;
 131         struct tegra30_ahub_cif_conf cif_conf;
 132 
 133         if (params_channels(params) != 2)
 134                 return -EINVAL;
 135 
 136         mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
 137         switch (params_format(params)) {
 138         case SNDRV_PCM_FORMAT_S16_LE:
 139                 val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
 140                 sample_size = 16;
 141                 break;
 142         default:
 143                 return -EINVAL;
 144         }
 145 
 146         regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
 147 
 148         srate = params_rate(params);
 149 
 150         /* Final "* 2" required by Tegra hardware */
 151         i2sclock = srate * params_channels(params) * sample_size * 2;
 152 
 153         bitcnt = (i2sclock / (2 * srate)) - 1;
 154         if (bitcnt < 0 || bitcnt > TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
 155                 return -EINVAL;
 156 
 157         ret = clk_set_rate(i2s->clk_i2s, i2sclock);
 158         if (ret) {
 159                 dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
 160                 return ret;
 161         }
 162 
 163         val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
 164 
 165         if (i2sclock % (2 * srate))
 166                 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
 167 
 168         regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
 169 
 170         cif_conf.threshold = 0;
 171         cif_conf.audio_channels = 2;
 172         cif_conf.client_channels = 2;
 173         cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
 174         cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
 175         cif_conf.expand = 0;
 176         cif_conf.stereo_conv = 0;
 177         cif_conf.replicate = 0;
 178         cif_conf.truncate = 0;
 179         cif_conf.mono_conv = 0;
 180 
 181         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 182                 cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
 183                 reg = TEGRA30_I2S_CIF_RX_CTRL;
 184         } else {
 185                 cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
 186                 reg = TEGRA30_I2S_CIF_TX_CTRL;
 187         }
 188 
 189         i2s->soc_data->set_audio_cif(i2s->regmap, reg, &cif_conf);
 190 
 191         val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
 192               (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
 193         regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
 194 
 195         return 0;
 196 }
 197 
 198 static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
 199 {
 200         tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
 201         regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
 202                            TEGRA30_I2S_CTRL_XFER_EN_TX,
 203                            TEGRA30_I2S_CTRL_XFER_EN_TX);
 204 }
 205 
 206 static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
 207 {
 208         tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
 209         regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
 210                            TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
 211 }
 212 
 213 static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
 214 {
 215         tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
 216         regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
 217                            TEGRA30_I2S_CTRL_XFER_EN_RX,
 218                            TEGRA30_I2S_CTRL_XFER_EN_RX);
 219 }
 220 
 221 static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
 222 {
 223         tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
 224         regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
 225                            TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
 226 }
 227 
 228 static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 229                                 struct snd_soc_dai *dai)
 230 {
 231         struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 232 
 233         switch (cmd) {
 234         case SNDRV_PCM_TRIGGER_START:
 235         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 236         case SNDRV_PCM_TRIGGER_RESUME:
 237                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 238                         tegra30_i2s_start_playback(i2s);
 239                 else
 240                         tegra30_i2s_start_capture(i2s);
 241                 break;
 242         case SNDRV_PCM_TRIGGER_STOP:
 243         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 244         case SNDRV_PCM_TRIGGER_SUSPEND:
 245                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 246                         tegra30_i2s_stop_playback(i2s);
 247                 else
 248                         tegra30_i2s_stop_capture(i2s);
 249                 break;
 250         default:
 251                 return -EINVAL;
 252         }
 253 
 254         return 0;
 255 }
 256 
 257 static int tegra30_i2s_probe(struct snd_soc_dai *dai)
 258 {
 259         struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 260 
 261         dai->capture_dma_data = &i2s->capture_dma_data;
 262         dai->playback_dma_data = &i2s->playback_dma_data;
 263 
 264         return 0;
 265 }
 266 
 267 static const struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
 268         .set_fmt        = tegra30_i2s_set_fmt,
 269         .hw_params      = tegra30_i2s_hw_params,
 270         .trigger        = tegra30_i2s_trigger,
 271 };
 272 
 273 static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
 274         .probe = tegra30_i2s_probe,
 275         .playback = {
 276                 .stream_name = "Playback",
 277                 .channels_min = 2,
 278                 .channels_max = 2,
 279                 .rates = SNDRV_PCM_RATE_8000_96000,
 280                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
 281         },
 282         .capture = {
 283                 .stream_name = "Capture",
 284                 .channels_min = 2,
 285                 .channels_max = 2,
 286                 .rates = SNDRV_PCM_RATE_8000_96000,
 287                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
 288         },
 289         .ops = &tegra30_i2s_dai_ops,
 290         .symmetric_rates = 1,
 291 };
 292 
 293 static const struct snd_soc_component_driver tegra30_i2s_component = {
 294         .name           = DRV_NAME,
 295 };
 296 
 297 static bool tegra30_i2s_wr_rd_reg(struct device *dev, unsigned int reg)
 298 {
 299         switch (reg) {
 300         case TEGRA30_I2S_CTRL:
 301         case TEGRA30_I2S_TIMING:
 302         case TEGRA30_I2S_OFFSET:
 303         case TEGRA30_I2S_CH_CTRL:
 304         case TEGRA30_I2S_SLOT_CTRL:
 305         case TEGRA30_I2S_CIF_RX_CTRL:
 306         case TEGRA30_I2S_CIF_TX_CTRL:
 307         case TEGRA30_I2S_FLOWCTL:
 308         case TEGRA30_I2S_TX_STEP:
 309         case TEGRA30_I2S_FLOW_STATUS:
 310         case TEGRA30_I2S_FLOW_TOTAL:
 311         case TEGRA30_I2S_FLOW_OVER:
 312         case TEGRA30_I2S_FLOW_UNDER:
 313         case TEGRA30_I2S_LCOEF_1_4_0:
 314         case TEGRA30_I2S_LCOEF_1_4_1:
 315         case TEGRA30_I2S_LCOEF_1_4_2:
 316         case TEGRA30_I2S_LCOEF_1_4_3:
 317         case TEGRA30_I2S_LCOEF_1_4_4:
 318         case TEGRA30_I2S_LCOEF_1_4_5:
 319         case TEGRA30_I2S_LCOEF_2_4_0:
 320         case TEGRA30_I2S_LCOEF_2_4_1:
 321         case TEGRA30_I2S_LCOEF_2_4_2:
 322                 return true;
 323         default:
 324                 return false;
 325         }
 326 }
 327 
 328 static bool tegra30_i2s_volatile_reg(struct device *dev, unsigned int reg)
 329 {
 330         switch (reg) {
 331         case TEGRA30_I2S_FLOW_STATUS:
 332         case TEGRA30_I2S_FLOW_TOTAL:
 333         case TEGRA30_I2S_FLOW_OVER:
 334         case TEGRA30_I2S_FLOW_UNDER:
 335                 return true;
 336         default:
 337                 return false;
 338         }
 339 }
 340 
 341 static const struct regmap_config tegra30_i2s_regmap_config = {
 342         .reg_bits = 32,
 343         .reg_stride = 4,
 344         .val_bits = 32,
 345         .max_register = TEGRA30_I2S_LCOEF_2_4_2,
 346         .writeable_reg = tegra30_i2s_wr_rd_reg,
 347         .readable_reg = tegra30_i2s_wr_rd_reg,
 348         .volatile_reg = tegra30_i2s_volatile_reg,
 349         .cache_type = REGCACHE_FLAT,
 350 };
 351 
 352 static const struct tegra30_i2s_soc_data tegra30_i2s_config = {
 353         .set_audio_cif = tegra30_ahub_set_cif,
 354 };
 355 
 356 static const struct tegra30_i2s_soc_data tegra124_i2s_config = {
 357         .set_audio_cif = tegra124_ahub_set_cif,
 358 };
 359 
 360 static const struct of_device_id tegra30_i2s_of_match[] = {
 361         { .compatible = "nvidia,tegra124-i2s", .data = &tegra124_i2s_config },
 362         { .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config },
 363         {},
 364 };
 365 
 366 static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 367 {
 368         struct tegra30_i2s *i2s;
 369         const struct of_device_id *match;
 370         u32 cif_ids[2];
 371         void __iomem *regs;
 372         int ret;
 373 
 374         i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_i2s), GFP_KERNEL);
 375         if (!i2s) {
 376                 ret = -ENOMEM;
 377                 goto err;
 378         }
 379         dev_set_drvdata(&pdev->dev, i2s);
 380 
 381         match = of_match_device(tegra30_i2s_of_match, &pdev->dev);
 382         if (!match) {
 383                 dev_err(&pdev->dev, "Error: No device match found\n");
 384                 ret = -ENODEV;
 385                 goto err;
 386         }
 387         i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data;
 388 
 389         i2s->dai = tegra30_i2s_dai_template;
 390         i2s->dai.name = dev_name(&pdev->dev);
 391 
 392         ret = of_property_read_u32_array(pdev->dev.of_node,
 393                                          "nvidia,ahub-cif-ids", cif_ids,
 394                                          ARRAY_SIZE(cif_ids));
 395         if (ret < 0)
 396                 goto err;
 397 
 398         i2s->playback_i2s_cif = cif_ids[0];
 399         i2s->capture_i2s_cif = cif_ids[1];
 400 
 401         i2s->clk_i2s = clk_get(&pdev->dev, NULL);
 402         if (IS_ERR(i2s->clk_i2s)) {
 403                 dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
 404                 ret = PTR_ERR(i2s->clk_i2s);
 405                 goto err;
 406         }
 407 
 408         regs = devm_platform_ioremap_resource(pdev, 0);
 409         if (IS_ERR(regs)) {
 410                 ret = PTR_ERR(regs);
 411                 goto err_clk_put;
 412         }
 413 
 414         i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
 415                                             &tegra30_i2s_regmap_config);
 416         if (IS_ERR(i2s->regmap)) {
 417                 dev_err(&pdev->dev, "regmap init failed\n");
 418                 ret = PTR_ERR(i2s->regmap);
 419                 goto err_clk_put;
 420         }
 421         regcache_cache_only(i2s->regmap, true);
 422 
 423         pm_runtime_enable(&pdev->dev);
 424         if (!pm_runtime_enabled(&pdev->dev)) {
 425                 ret = tegra30_i2s_runtime_resume(&pdev->dev);
 426                 if (ret)
 427                         goto err_pm_disable;
 428         }
 429 
 430         i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 431         i2s->playback_dma_data.maxburst = 4;
 432         ret = tegra30_ahub_allocate_tx_fifo(&i2s->playback_fifo_cif,
 433                                             i2s->playback_dma_chan,
 434                                             sizeof(i2s->playback_dma_chan),
 435                                             &i2s->playback_dma_data.addr);
 436         if (ret) {
 437                 dev_err(&pdev->dev, "Could not alloc TX FIFO: %d\n", ret);
 438                 goto err_suspend;
 439         }
 440         ret = tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
 441                                              i2s->playback_fifo_cif);
 442         if (ret) {
 443                 dev_err(&pdev->dev, "Could not route TX FIFO: %d\n", ret);
 444                 goto err_free_tx_fifo;
 445         }
 446 
 447         i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 448         i2s->capture_dma_data.maxburst = 4;
 449         ret = tegra30_ahub_allocate_rx_fifo(&i2s->capture_fifo_cif,
 450                                             i2s->capture_dma_chan,
 451                                             sizeof(i2s->capture_dma_chan),
 452                                             &i2s->capture_dma_data.addr);
 453         if (ret) {
 454                 dev_err(&pdev->dev, "Could not alloc RX FIFO: %d\n", ret);
 455                 goto err_unroute_tx_fifo;
 456         }
 457         ret = tegra30_ahub_set_rx_cif_source(i2s->capture_fifo_cif,
 458                                              i2s->capture_i2s_cif);
 459         if (ret) {
 460                 dev_err(&pdev->dev, "Could not route TX FIFO: %d\n", ret);
 461                 goto err_free_rx_fifo;
 462         }
 463 
 464         ret = snd_soc_register_component(&pdev->dev, &tegra30_i2s_component,
 465                                    &i2s->dai, 1);
 466         if (ret) {
 467                 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
 468                 ret = -ENOMEM;
 469                 goto err_unroute_rx_fifo;
 470         }
 471 
 472         ret = tegra_pcm_platform_register_with_chan_names(&pdev->dev,
 473                                 &i2s->dma_config, i2s->playback_dma_chan,
 474                                 i2s->capture_dma_chan);
 475         if (ret) {
 476                 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
 477                 goto err_unregister_component;
 478         }
 479 
 480         return 0;
 481 
 482 err_unregister_component:
 483         snd_soc_unregister_component(&pdev->dev);
 484 err_unroute_rx_fifo:
 485         tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
 486 err_free_rx_fifo:
 487         tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
 488 err_unroute_tx_fifo:
 489         tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
 490 err_free_tx_fifo:
 491         tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
 492 err_suspend:
 493         if (!pm_runtime_status_suspended(&pdev->dev))
 494                 tegra30_i2s_runtime_suspend(&pdev->dev);
 495 err_pm_disable:
 496         pm_runtime_disable(&pdev->dev);
 497 err_clk_put:
 498         clk_put(i2s->clk_i2s);
 499 err:
 500         return ret;
 501 }
 502 
 503 static int tegra30_i2s_platform_remove(struct platform_device *pdev)
 504 {
 505         struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
 506 
 507         pm_runtime_disable(&pdev->dev);
 508         if (!pm_runtime_status_suspended(&pdev->dev))
 509                 tegra30_i2s_runtime_suspend(&pdev->dev);
 510 
 511         tegra_pcm_platform_unregister(&pdev->dev);
 512         snd_soc_unregister_component(&pdev->dev);
 513 
 514         tegra30_ahub_unset_rx_cif_source(i2s->capture_fifo_cif);
 515         tegra30_ahub_free_rx_fifo(i2s->capture_fifo_cif);
 516 
 517         tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
 518         tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
 519 
 520         clk_put(i2s->clk_i2s);
 521 
 522         return 0;
 523 }
 524 
 525 #ifdef CONFIG_PM_SLEEP
 526 static int tegra30_i2s_suspend(struct device *dev)
 527 {
 528         struct tegra30_i2s *i2s = dev_get_drvdata(dev);
 529 
 530         regcache_mark_dirty(i2s->regmap);
 531 
 532         return 0;
 533 }
 534 
 535 static int tegra30_i2s_resume(struct device *dev)
 536 {
 537         struct tegra30_i2s *i2s = dev_get_drvdata(dev);
 538         int ret;
 539 
 540         ret = pm_runtime_get_sync(dev);
 541         if (ret < 0)
 542                 return ret;
 543         ret = regcache_sync(i2s->regmap);
 544         pm_runtime_put(dev);
 545 
 546         return ret;
 547 }
 548 #endif
 549 
 550 static const struct dev_pm_ops tegra30_i2s_pm_ops = {
 551         SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
 552                            tegra30_i2s_runtime_resume, NULL)
 553         SET_SYSTEM_SLEEP_PM_OPS(tegra30_i2s_suspend, tegra30_i2s_resume)
 554 };
 555 
 556 static struct platform_driver tegra30_i2s_driver = {
 557         .driver = {
 558                 .name = DRV_NAME,
 559                 .of_match_table = tegra30_i2s_of_match,
 560                 .pm = &tegra30_i2s_pm_ops,
 561         },
 562         .probe = tegra30_i2s_platform_probe,
 563         .remove = tegra30_i2s_platform_remove,
 564 };
 565 module_platform_driver(tegra30_i2s_driver);
 566 
 567 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 568 MODULE_DESCRIPTION("Tegra30 I2S ASoC driver");
 569 MODULE_LICENSE("GPL");
 570 MODULE_ALIAS("platform:" DRV_NAME);
 571 MODULE_DEVICE_TABLE(of, tegra30_i2s_of_match);

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