1440 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2// ALSA SoC Audio Layer - Rockchip I2S/TDM Controller driver3 4// Copyright (c) 2018 Rockchip Electronics Co. Ltd.5// Author: Sugar Zhang <sugar.zhang@rock-chips.com>6// Author: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>7 8#include <linux/clk.h>9#include <linux/clk-provider.h>10#include <linux/delay.h>11#include <linux/mfd/syscon.h>12#include <linux/module.h>13#include <linux/of.h>14#include <linux/pm_runtime.h>15#include <linux/regmap.h>16#include <linux/reset.h>17#include <linux/spinlock.h>18#include <sound/dmaengine_pcm.h>19#include <sound/pcm_params.h>20 21#include "rockchip_i2s_tdm.h"22 23#define DRV_NAME "rockchip-i2s-tdm"24 25#define DEFAULT_MCLK_FS 25626#define CH_GRP_MAX 4 /* The max channel 8 / 2 */27#define MULTIPLEX_CH_MAX 1028 29#define TRCM_TXRX 030#define TRCM_TX 131#define TRCM_RX 232 33struct txrx_config {34 u32 addr;35 u32 reg;36 u32 txonly;37 u32 rxonly;38};39 40struct rk_i2s_soc_data {41 u32 softrst_offset;42 u32 grf_reg_offset;43 u32 grf_shift;44 int config_count;45 const struct txrx_config *configs;46 int (*init)(struct device *dev, u32 addr);47};48 49struct rk_i2s_tdm_dev {50 struct device *dev;51 struct clk *hclk;52 struct clk *mclk_tx;53 struct clk *mclk_rx;54 struct regmap *regmap;55 struct regmap *grf;56 struct snd_dmaengine_dai_dma_data capture_dma_data;57 struct snd_dmaengine_dai_dma_data playback_dma_data;58 struct reset_control *tx_reset;59 struct reset_control *rx_reset;60 const struct rk_i2s_soc_data *soc_data;61 bool is_master_mode;62 bool io_multiplex;63 bool tdm_mode;64 unsigned int frame_width;65 unsigned int clk_trcm;66 unsigned int i2s_sdis[CH_GRP_MAX];67 unsigned int i2s_sdos[CH_GRP_MAX];68 int refcount;69 spinlock_t lock; /* xfer lock */70 bool has_playback;71 bool has_capture;72 struct snd_soc_dai_driver *dai;73};74 75static int to_ch_num(unsigned int val)76{77 switch (val) {78 case I2S_CHN_4:79 return 4;80 case I2S_CHN_6:81 return 6;82 case I2S_CHN_8:83 return 8;84 default:85 return 2;86 }87}88 89static void i2s_tdm_disable_unprepare_mclk(struct rk_i2s_tdm_dev *i2s_tdm)90{91 clk_disable_unprepare(i2s_tdm->mclk_tx);92 clk_disable_unprepare(i2s_tdm->mclk_rx);93}94 95/**96 * i2s_tdm_prepare_enable_mclk - prepare to enable all mclks, disable them on97 * failure.98 * @i2s_tdm: rk_i2s_tdm_dev struct99 *100 * This function attempts to enable all mclk clocks, but cleans up after101 * itself on failure. Guarantees to balance its calls.102 *103 * Returns success (0) or negative errno.104 */105static int i2s_tdm_prepare_enable_mclk(struct rk_i2s_tdm_dev *i2s_tdm)106{107 int ret = 0;108 109 ret = clk_prepare_enable(i2s_tdm->mclk_tx);110 if (ret)111 goto err_mclk_tx;112 ret = clk_prepare_enable(i2s_tdm->mclk_rx);113 if (ret)114 goto err_mclk_rx;115 116 return 0;117 118err_mclk_rx:119 clk_disable_unprepare(i2s_tdm->mclk_tx);120err_mclk_tx:121 return ret;122}123 124static int __maybe_unused i2s_tdm_runtime_suspend(struct device *dev)125{126 struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev);127 128 regcache_cache_only(i2s_tdm->regmap, true);129 i2s_tdm_disable_unprepare_mclk(i2s_tdm);130 131 clk_disable_unprepare(i2s_tdm->hclk);132 133 return 0;134}135 136static int __maybe_unused i2s_tdm_runtime_resume(struct device *dev)137{138 struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev);139 int ret;140 141 ret = clk_prepare_enable(i2s_tdm->hclk);142 if (ret)143 goto err_hclk;144 145 ret = i2s_tdm_prepare_enable_mclk(i2s_tdm);146 if (ret)147 goto err_mclk;148 149 regcache_cache_only(i2s_tdm->regmap, false);150 regcache_mark_dirty(i2s_tdm->regmap);151 152 ret = regcache_sync(i2s_tdm->regmap);153 if (ret)154 goto err_regcache;155 156 return 0;157 158err_regcache:159 i2s_tdm_disable_unprepare_mclk(i2s_tdm);160err_mclk:161 clk_disable_unprepare(i2s_tdm->hclk);162err_hclk:163 return ret;164}165 166static inline struct rk_i2s_tdm_dev *to_info(struct snd_soc_dai *dai)167{168 return snd_soc_dai_get_drvdata(dai);169}170 171/*172 * Makes sure that both tx and rx are reset at the same time to sync lrck173 * when clk_trcm > 0.174 */175static void rockchip_snd_xfer_sync_reset(struct rk_i2s_tdm_dev *i2s_tdm)176{177 /* This is technically race-y.178 *179 * In an ideal world, we could atomically assert both resets at the180 * same time, through an atomic bulk reset API. This API however does181 * not exist, so what the downstream vendor code used to do was182 * implement half a reset controller here and require the CRU to be183 * passed to the driver as a device tree node. Violating abstractions184 * like that is bad, especially when it influences something like the185 * bindings which are supposed to describe the hardware, not whatever186 * workarounds the driver needs, so it was dropped.187 *188 * In practice, asserting the resets one by one appears to work just189 * fine for playback. During duplex (playback + capture) operation,190 * this might become an issue, but that should be solved by the191 * implementation of the aforementioned API, not by shoving a reset192 * controller into an audio driver.193 */194 195 reset_control_assert(i2s_tdm->tx_reset);196 reset_control_assert(i2s_tdm->rx_reset);197 udelay(10);198 reset_control_deassert(i2s_tdm->tx_reset);199 reset_control_deassert(i2s_tdm->rx_reset);200 udelay(10);201}202 203static void rockchip_snd_reset(struct reset_control *rc)204{205 reset_control_assert(rc);206 udelay(10);207 reset_control_deassert(rc);208 udelay(10);209}210 211static void rockchip_snd_xfer_clear(struct rk_i2s_tdm_dev *i2s_tdm,212 unsigned int clr)213{214 unsigned int xfer_mask = 0;215 unsigned int xfer_val = 0;216 unsigned int val;217 int retry = 10;218 bool tx = clr & I2S_CLR_TXC;219 bool rx = clr & I2S_CLR_RXC;220 221 if (!(rx || tx))222 return;223 224 if (tx) {225 xfer_mask = I2S_XFER_TXS_START;226 xfer_val = I2S_XFER_TXS_STOP;227 }228 if (rx) {229 xfer_mask |= I2S_XFER_RXS_START;230 xfer_val |= I2S_XFER_RXS_STOP;231 }232 233 regmap_update_bits(i2s_tdm->regmap, I2S_XFER, xfer_mask, xfer_val);234 udelay(150);235 regmap_update_bits(i2s_tdm->regmap, I2S_CLR, clr, clr);236 237 regmap_read(i2s_tdm->regmap, I2S_CLR, &val);238 /* Wait on the clear operation to finish */239 while (val) {240 udelay(15);241 regmap_read(i2s_tdm->regmap, I2S_CLR, &val);242 retry--;243 if (!retry) {244 dev_warn(i2s_tdm->dev, "clear failed, reset %s%s\n",245 tx ? "tx" : "", rx ? "rx" : "");246 if (rx && tx)247 rockchip_snd_xfer_sync_reset(i2s_tdm);248 else if (tx)249 rockchip_snd_reset(i2s_tdm->tx_reset);250 else if (rx)251 rockchip_snd_reset(i2s_tdm->rx_reset);252 break;253 }254 }255}256 257static inline void rockchip_enable_tde(struct regmap *regmap)258{259 regmap_update_bits(regmap, I2S_DMACR, I2S_DMACR_TDE_ENABLE,260 I2S_DMACR_TDE_ENABLE);261}262 263static inline void rockchip_disable_tde(struct regmap *regmap)264{265 regmap_update_bits(regmap, I2S_DMACR, I2S_DMACR_TDE_ENABLE,266 I2S_DMACR_TDE_DISABLE);267}268 269static inline void rockchip_enable_rde(struct regmap *regmap)270{271 regmap_update_bits(regmap, I2S_DMACR, I2S_DMACR_RDE_ENABLE,272 I2S_DMACR_RDE_ENABLE);273}274 275static inline void rockchip_disable_rde(struct regmap *regmap)276{277 regmap_update_bits(regmap, I2S_DMACR, I2S_DMACR_RDE_ENABLE,278 I2S_DMACR_RDE_DISABLE);279}280 281/* only used when clk_trcm > 0 */282static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream,283 struct snd_soc_dai *dai, int on)284{285 struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);286 unsigned long flags;287 288 spin_lock_irqsave(&i2s_tdm->lock, flags);289 if (on) {290 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)291 rockchip_enable_tde(i2s_tdm->regmap);292 else293 rockchip_enable_rde(i2s_tdm->regmap);294 295 if (++i2s_tdm->refcount == 1) {296 rockchip_snd_xfer_sync_reset(i2s_tdm);297 regmap_update_bits(i2s_tdm->regmap, I2S_XFER,298 I2S_XFER_TXS_START |299 I2S_XFER_RXS_START,300 I2S_XFER_TXS_START |301 I2S_XFER_RXS_START);302 }303 } else {304 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)305 rockchip_disable_tde(i2s_tdm->regmap);306 else307 rockchip_disable_rde(i2s_tdm->regmap);308 309 if (--i2s_tdm->refcount == 0) {310 rockchip_snd_xfer_clear(i2s_tdm,311 I2S_CLR_TXC | I2S_CLR_RXC);312 }313 }314 spin_unlock_irqrestore(&i2s_tdm->lock, flags);315}316 317static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on)318{319 if (on) {320 rockchip_enable_tde(i2s_tdm->regmap);321 322 regmap_update_bits(i2s_tdm->regmap, I2S_XFER,323 I2S_XFER_TXS_START,324 I2S_XFER_TXS_START);325 } else {326 rockchip_disable_tde(i2s_tdm->regmap);327 328 rockchip_snd_xfer_clear(i2s_tdm, I2S_CLR_TXC);329 }330}331 332static void rockchip_snd_rxctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on)333{334 if (on) {335 rockchip_enable_rde(i2s_tdm->regmap);336 337 regmap_update_bits(i2s_tdm->regmap, I2S_XFER,338 I2S_XFER_RXS_START,339 I2S_XFER_RXS_START);340 } else {341 rockchip_disable_rde(i2s_tdm->regmap);342 343 rockchip_snd_xfer_clear(i2s_tdm, I2S_CLR_RXC);344 }345}346 347static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,348 unsigned int fmt)349{350 struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);351 unsigned int mask, val, tdm_val, txcr_val, rxcr_val;352 int ret;353 bool is_tdm = i2s_tdm->tdm_mode;354 355 ret = pm_runtime_resume_and_get(cpu_dai->dev);356 if (ret < 0 && ret != -EACCES)357 return ret;358 359 mask = I2S_CKR_MSS_MASK;360 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {361 case SND_SOC_DAIFMT_BP_FP:362 val = I2S_CKR_MSS_MASTER;363 i2s_tdm->is_master_mode = true;364 break;365 case SND_SOC_DAIFMT_BC_FC:366 val = I2S_CKR_MSS_SLAVE;367 i2s_tdm->is_master_mode = false;368 break;369 default:370 ret = -EINVAL;371 goto err_pm_put;372 }373 374 regmap_update_bits(i2s_tdm->regmap, I2S_CKR, mask, val);375 376 mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK;377 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {378 case SND_SOC_DAIFMT_NB_NF:379 val = I2S_CKR_CKP_NORMAL |380 I2S_CKR_TLP_NORMAL |381 I2S_CKR_RLP_NORMAL;382 break;383 case SND_SOC_DAIFMT_NB_IF:384 val = I2S_CKR_CKP_NORMAL |385 I2S_CKR_TLP_INVERTED |386 I2S_CKR_RLP_INVERTED;387 break;388 case SND_SOC_DAIFMT_IB_NF:389 val = I2S_CKR_CKP_INVERTED |390 I2S_CKR_TLP_NORMAL |391 I2S_CKR_RLP_NORMAL;392 break;393 case SND_SOC_DAIFMT_IB_IF:394 val = I2S_CKR_CKP_INVERTED |395 I2S_CKR_TLP_INVERTED |396 I2S_CKR_RLP_INVERTED;397 break;398 default:399 ret = -EINVAL;400 goto err_pm_put;401 }402 403 regmap_update_bits(i2s_tdm->regmap, I2S_CKR, mask, val);404 405 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {406 case SND_SOC_DAIFMT_RIGHT_J:407 txcr_val = I2S_TXCR_IBM_RSJM;408 rxcr_val = I2S_RXCR_IBM_RSJM;409 break;410 case SND_SOC_DAIFMT_LEFT_J:411 txcr_val = I2S_TXCR_IBM_LSJM;412 rxcr_val = I2S_RXCR_IBM_LSJM;413 break;414 case SND_SOC_DAIFMT_I2S:415 txcr_val = I2S_TXCR_IBM_NORMAL;416 rxcr_val = I2S_RXCR_IBM_NORMAL;417 break;418 case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 mode */419 txcr_val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);420 rxcr_val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);421 break;422 case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */423 txcr_val = I2S_TXCR_TFS_PCM;424 rxcr_val = I2S_RXCR_TFS_PCM;425 break;426 default:427 ret = -EINVAL;428 goto err_pm_put;429 }430 431 mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK;432 regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, mask, txcr_val);433 434 mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK;435 regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, rxcr_val);436 437 if (is_tdm) {438 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {439 case SND_SOC_DAIFMT_RIGHT_J:440 val = I2S_TXCR_TFS_TDM_I2S;441 tdm_val = TDM_SHIFT_CTRL(2);442 break;443 case SND_SOC_DAIFMT_LEFT_J:444 val = I2S_TXCR_TFS_TDM_I2S;445 tdm_val = TDM_SHIFT_CTRL(1);446 break;447 case SND_SOC_DAIFMT_I2S:448 val = I2S_TXCR_TFS_TDM_I2S;449 tdm_val = TDM_SHIFT_CTRL(0);450 break;451 case SND_SOC_DAIFMT_DSP_A:452 val = I2S_TXCR_TFS_TDM_PCM;453 tdm_val = TDM_SHIFT_CTRL(0);454 break;455 case SND_SOC_DAIFMT_DSP_B:456 val = I2S_TXCR_TFS_TDM_PCM;457 tdm_val = TDM_SHIFT_CTRL(2);458 break;459 default:460 ret = -EINVAL;461 goto err_pm_put;462 }463 464 tdm_val |= TDM_FSYNC_WIDTH_SEL1(1);465 tdm_val |= TDM_FSYNC_WIDTH_HALF_FRAME;466 467 mask = I2S_TXCR_TFS_MASK;468 regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, mask, val);469 regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val);470 471 mask = TDM_FSYNC_WIDTH_SEL1_MSK | TDM_FSYNC_WIDTH_SEL0_MSK |472 TDM_SHIFT_CTRL_MSK;473 regmap_update_bits(i2s_tdm->regmap, I2S_TDM_TXCR,474 mask, tdm_val);475 regmap_update_bits(i2s_tdm->regmap, I2S_TDM_RXCR,476 mask, tdm_val);477 }478 479err_pm_put:480 pm_runtime_put(cpu_dai->dev);481 482 return ret;483}484 485static void rockchip_i2s_tdm_xfer_pause(struct snd_pcm_substream *substream,486 struct rk_i2s_tdm_dev *i2s_tdm)487{488 int stream;489 490 stream = SNDRV_PCM_STREAM_LAST - substream->stream;491 if (stream == SNDRV_PCM_STREAM_PLAYBACK)492 rockchip_disable_tde(i2s_tdm->regmap);493 else494 rockchip_disable_rde(i2s_tdm->regmap);495 496 rockchip_snd_xfer_clear(i2s_tdm, I2S_CLR_TXC | I2S_CLR_RXC);497}498 499static void rockchip_i2s_tdm_xfer_resume(struct snd_pcm_substream *substream,500 struct rk_i2s_tdm_dev *i2s_tdm)501{502 int stream;503 504 stream = SNDRV_PCM_STREAM_LAST - substream->stream;505 if (stream == SNDRV_PCM_STREAM_PLAYBACK)506 rockchip_enable_tde(i2s_tdm->regmap);507 else508 rockchip_enable_rde(i2s_tdm->regmap);509 510 regmap_update_bits(i2s_tdm->regmap, I2S_XFER,511 I2S_XFER_TXS_START |512 I2S_XFER_RXS_START,513 I2S_XFER_TXS_START |514 I2S_XFER_RXS_START);515}516 517static int rockchip_i2s_ch_to_io(unsigned int ch, bool substream_capture)518{519 if (substream_capture) {520 switch (ch) {521 case I2S_CHN_4:522 return I2S_IO_6CH_OUT_4CH_IN;523 case I2S_CHN_6:524 return I2S_IO_4CH_OUT_6CH_IN;525 case I2S_CHN_8:526 return I2S_IO_2CH_OUT_8CH_IN;527 default:528 return I2S_IO_8CH_OUT_2CH_IN;529 }530 } else {531 switch (ch) {532 case I2S_CHN_4:533 return I2S_IO_4CH_OUT_6CH_IN;534 case I2S_CHN_6:535 return I2S_IO_6CH_OUT_4CH_IN;536 case I2S_CHN_8:537 return I2S_IO_8CH_OUT_2CH_IN;538 default:539 return I2S_IO_2CH_OUT_8CH_IN;540 }541 }542}543 544static int rockchip_i2s_io_multiplex(struct snd_pcm_substream *substream,545 struct snd_soc_dai *dai)546{547 struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);548 int usable_chs = MULTIPLEX_CH_MAX;549 unsigned int val = 0;550 551 if (!i2s_tdm->io_multiplex)552 return 0;553 554 if (IS_ERR_OR_NULL(i2s_tdm->grf)) {555 dev_err(i2s_tdm->dev,556 "io multiplex not supported for this device\n");557 return -EINVAL;558 }559 560 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {561 struct snd_pcm_str *playback_str =562 &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];563 564 if (playback_str->substream_opened) {565 regmap_read(i2s_tdm->regmap, I2S_TXCR, &val);566 val &= I2S_TXCR_CSR_MASK;567 usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val);568 }569 570 regmap_read(i2s_tdm->regmap, I2S_RXCR, &val);571 val &= I2S_RXCR_CSR_MASK;572 573 if (to_ch_num(val) > usable_chs) {574 dev_err(i2s_tdm->dev,575 "Capture channels (%d) > usable channels (%d)\n",576 to_ch_num(val), usable_chs);577 return -EINVAL;578 }579 580 rockchip_i2s_ch_to_io(val, true);581 } else {582 struct snd_pcm_str *capture_str =583 &substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE];584 585 if (capture_str->substream_opened) {586 regmap_read(i2s_tdm->regmap, I2S_RXCR, &val);587 val &= I2S_RXCR_CSR_MASK;588 usable_chs = MULTIPLEX_CH_MAX - to_ch_num(val);589 }590 591 regmap_read(i2s_tdm->regmap, I2S_TXCR, &val);592 val &= I2S_TXCR_CSR_MASK;593 594 if (to_ch_num(val) > usable_chs) {595 dev_err(i2s_tdm->dev,596 "Playback channels (%d) > usable channels (%d)\n",597 to_ch_num(val), usable_chs);598 return -EINVAL;599 }600 }601 602 val <<= i2s_tdm->soc_data->grf_shift;603 val |= (I2S_IO_DIRECTION_MASK << i2s_tdm->soc_data->grf_shift) << 16;604 regmap_write(i2s_tdm->grf, i2s_tdm->soc_data->grf_reg_offset, val);605 606 return 0;607}608 609static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,610 struct snd_soc_dai *dai,611 unsigned int div_bclk,612 unsigned int div_lrck,613 unsigned int fmt)614{615 struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);616 unsigned long flags;617 618 if (!i2s_tdm->clk_trcm)619 return 0;620 621 spin_lock_irqsave(&i2s_tdm->lock, flags);622 if (i2s_tdm->refcount)623 rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm);624 625 regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,626 I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK,627 I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk));628 regmap_update_bits(i2s_tdm->regmap, I2S_CKR,629 I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK,630 I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck));631 632 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)633 regmap_update_bits(i2s_tdm->regmap, I2S_TXCR,634 I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,635 fmt);636 else637 regmap_update_bits(i2s_tdm->regmap, I2S_RXCR,638 I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,639 fmt);640 641 if (i2s_tdm->refcount)642 rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm);643 spin_unlock_irqrestore(&i2s_tdm->lock, flags);644 645 return 0;646}647 648static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,649 struct snd_pcm_hw_params *params,650 struct snd_soc_dai *dai)651{652 struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);653 unsigned int val = 0;654 unsigned int mclk_rate, bclk_rate, div_bclk = 4, div_lrck = 64;655 int err;656 657 if (i2s_tdm->is_master_mode) {658 struct clk *mclk;659 660 if (i2s_tdm->clk_trcm == TRCM_TX) {661 mclk = i2s_tdm->mclk_tx;662 } else if (i2s_tdm->clk_trcm == TRCM_RX) {663 mclk = i2s_tdm->mclk_rx;664 } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {665 mclk = i2s_tdm->mclk_tx;666 } else {667 mclk = i2s_tdm->mclk_rx;668 }669 670 err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));671 if (err)672 return err;673 674 mclk_rate = clk_get_rate(mclk);675 bclk_rate = i2s_tdm->frame_width * params_rate(params);676 if (!bclk_rate)677 return -EINVAL;678 679 div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);680 div_lrck = bclk_rate / params_rate(params);681 }682 683 switch (params_format(params)) {684 case SNDRV_PCM_FORMAT_S8:685 val |= I2S_TXCR_VDW(8);686 break;687 case SNDRV_PCM_FORMAT_S16_LE:688 val |= I2S_TXCR_VDW(16);689 break;690 case SNDRV_PCM_FORMAT_S20_3LE:691 val |= I2S_TXCR_VDW(20);692 break;693 case SNDRV_PCM_FORMAT_S24_LE:694 val |= I2S_TXCR_VDW(24);695 break;696 case SNDRV_PCM_FORMAT_S32_LE:697 val |= I2S_TXCR_VDW(32);698 break;699 default:700 return -EINVAL;701 }702 703 switch (params_channels(params)) {704 case 8:705 val |= I2S_CHN_8;706 break;707 case 6:708 val |= I2S_CHN_6;709 break;710 case 4:711 val |= I2S_CHN_4;712 break;713 case 2:714 val |= I2S_CHN_2;715 break;716 default:717 return -EINVAL;718 }719 720 if (i2s_tdm->clk_trcm) {721 rockchip_i2s_trcm_mode(substream, dai, div_bclk, div_lrck, val);722 } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {723 regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,724 I2S_CLKDIV_TXM_MASK,725 I2S_CLKDIV_TXM(div_bclk));726 regmap_update_bits(i2s_tdm->regmap, I2S_CKR,727 I2S_CKR_TSD_MASK,728 I2S_CKR_TSD(div_lrck));729 regmap_update_bits(i2s_tdm->regmap, I2S_TXCR,730 I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,731 val);732 } else {733 regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,734 I2S_CLKDIV_RXM_MASK,735 I2S_CLKDIV_RXM(div_bclk));736 regmap_update_bits(i2s_tdm->regmap, I2S_CKR,737 I2S_CKR_RSD_MASK,738 I2S_CKR_RSD(div_lrck));739 regmap_update_bits(i2s_tdm->regmap, I2S_RXCR,740 I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK,741 val);742 }743 744 return rockchip_i2s_io_multiplex(substream, dai);745}746 747static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream,748 int cmd, struct snd_soc_dai *dai)749{750 struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);751 752 switch (cmd) {753 case SNDRV_PCM_TRIGGER_START:754 case SNDRV_PCM_TRIGGER_RESUME:755 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:756 if (i2s_tdm->clk_trcm)757 rockchip_snd_txrxctrl(substream, dai, 1);758 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)759 rockchip_snd_rxctrl(i2s_tdm, 1);760 else761 rockchip_snd_txctrl(i2s_tdm, 1);762 break;763 case SNDRV_PCM_TRIGGER_SUSPEND:764 case SNDRV_PCM_TRIGGER_STOP:765 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:766 if (i2s_tdm->clk_trcm)767 rockchip_snd_txrxctrl(substream, dai, 0);768 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)769 rockchip_snd_rxctrl(i2s_tdm, 0);770 else771 rockchip_snd_txctrl(i2s_tdm, 0);772 break;773 default:774 return -EINVAL;775 }776 777 return 0;778}779 780static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)781{782 struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);783 784 if (i2s_tdm->has_capture)785 snd_soc_dai_dma_data_set_capture(dai, &i2s_tdm->capture_dma_data);786 if (i2s_tdm->has_playback)787 snd_soc_dai_dma_data_set_playback(dai, &i2s_tdm->playback_dma_data);788 789 return 0;790}791 792static int rockchip_dai_tdm_slot(struct snd_soc_dai *dai,793 unsigned int tx_mask, unsigned int rx_mask,794 int slots, int slot_width)795{796 struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);797 unsigned int mask, val;798 799 i2s_tdm->tdm_mode = true;800 i2s_tdm->frame_width = slots * slot_width;801 mask = TDM_SLOT_BIT_WIDTH_MSK | TDM_FRAME_WIDTH_MSK;802 val = TDM_SLOT_BIT_WIDTH(slot_width) |803 TDM_FRAME_WIDTH(slots * slot_width);804 regmap_update_bits(i2s_tdm->regmap, I2S_TDM_TXCR,805 mask, val);806 regmap_update_bits(i2s_tdm->regmap, I2S_TDM_RXCR,807 mask, val);808 809 return 0;810}811 812static int rockchip_i2s_tdm_set_bclk_ratio(struct snd_soc_dai *dai,813 unsigned int ratio)814{815 struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);816 817 if (ratio < 32 || ratio > 512 || ratio % 2 == 1)818 return -EINVAL;819 820 i2s_tdm->frame_width = ratio;821 822 return 0;823}824 825static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {826 .probe = rockchip_i2s_tdm_dai_probe,827 .hw_params = rockchip_i2s_tdm_hw_params,828 .set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio,829 .set_fmt = rockchip_i2s_tdm_set_fmt,830 .set_tdm_slot = rockchip_dai_tdm_slot,831 .trigger = rockchip_i2s_tdm_trigger,832};833 834static const struct snd_soc_component_driver rockchip_i2s_tdm_component = {835 .name = DRV_NAME,836 .legacy_dai_naming = 1,837};838 839static bool rockchip_i2s_tdm_wr_reg(struct device *dev, unsigned int reg)840{841 switch (reg) {842 case I2S_TXCR:843 case I2S_RXCR:844 case I2S_CKR:845 case I2S_DMACR:846 case I2S_INTCR:847 case I2S_XFER:848 case I2S_CLR:849 case I2S_TXDR:850 case I2S_TDM_TXCR:851 case I2S_TDM_RXCR:852 case I2S_CLKDIV:853 return true;854 default:855 return false;856 }857}858 859static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg)860{861 switch (reg) {862 case I2S_TXCR:863 case I2S_RXCR:864 case I2S_CKR:865 case I2S_DMACR:866 case I2S_INTCR:867 case I2S_XFER:868 case I2S_CLR:869 case I2S_TXDR:870 case I2S_RXDR:871 case I2S_TXFIFOLR:872 case I2S_INTSR:873 case I2S_RXFIFOLR:874 case I2S_TDM_TXCR:875 case I2S_TDM_RXCR:876 case I2S_CLKDIV:877 return true;878 default:879 return false;880 }881}882 883static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg)884{885 switch (reg) {886 case I2S_TXFIFOLR:887 case I2S_INTSR:888 case I2S_CLR:889 case I2S_TXDR:890 case I2S_RXDR:891 case I2S_RXFIFOLR:892 return true;893 default:894 return false;895 }896}897 898static bool rockchip_i2s_tdm_precious_reg(struct device *dev, unsigned int reg)899{900 if (reg == I2S_RXDR)901 return true;902 return false;903}904 905static const struct reg_default rockchip_i2s_tdm_reg_defaults[] = {906 {0x00, 0x7200000f},907 {0x04, 0x01c8000f},908 {0x08, 0x00001f1f},909 {0x10, 0x001f0000},910 {0x14, 0x01f00000},911 {0x30, 0x00003eff},912 {0x34, 0x00003eff},913 {0x38, 0x00000707},914};915 916static const struct regmap_config rockchip_i2s_tdm_regmap_config = {917 .reg_bits = 32,918 .reg_stride = 4,919 .val_bits = 32,920 .max_register = I2S_CLKDIV,921 .reg_defaults = rockchip_i2s_tdm_reg_defaults,922 .num_reg_defaults = ARRAY_SIZE(rockchip_i2s_tdm_reg_defaults),923 .writeable_reg = rockchip_i2s_tdm_wr_reg,924 .readable_reg = rockchip_i2s_tdm_rd_reg,925 .volatile_reg = rockchip_i2s_tdm_volatile_reg,926 .precious_reg = rockchip_i2s_tdm_precious_reg,927 .cache_type = REGCACHE_FLAT,928};929 930static int common_soc_init(struct device *dev, u32 addr)931{932 struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev);933 const struct txrx_config *configs = i2s_tdm->soc_data->configs;934 u32 reg = 0, val = 0, trcm = i2s_tdm->clk_trcm;935 int i;936 937 if (trcm == TRCM_TXRX)938 return 0;939 940 if (IS_ERR_OR_NULL(i2s_tdm->grf)) {941 dev_err(i2s_tdm->dev,942 "no grf present but non-txrx TRCM specified\n");943 return -EINVAL;944 }945 946 for (i = 0; i < i2s_tdm->soc_data->config_count; i++) {947 if (addr != configs[i].addr)948 continue;949 reg = configs[i].reg;950 if (trcm == TRCM_TX)951 val = configs[i].txonly;952 else953 val = configs[i].rxonly;954 955 if (reg)956 regmap_write(i2s_tdm->grf, reg, val);957 }958 959 return 0;960}961 962static const struct txrx_config px30_txrx_config[] = {963 { 0xff060000, 0x184, PX30_I2S0_CLK_TXONLY, PX30_I2S0_CLK_RXONLY },964};965 966static const struct txrx_config rk1808_txrx_config[] = {967 { 0xff7e0000, 0x190, RK1808_I2S0_CLK_TXONLY, RK1808_I2S0_CLK_RXONLY },968};969 970static const struct txrx_config rk3308_txrx_config[] = {971 { 0xff300000, 0x308, RK3308_I2S0_CLK_TXONLY, RK3308_I2S0_CLK_RXONLY },972 { 0xff310000, 0x308, RK3308_I2S1_CLK_TXONLY, RK3308_I2S1_CLK_RXONLY },973};974 975static const struct txrx_config rk3568_txrx_config[] = {976 { 0xfe410000, 0x504, RK3568_I2S1_CLK_TXONLY, RK3568_I2S1_CLK_RXONLY },977 { 0xfe410000, 0x508, RK3568_I2S1_MCLK_TX_OE, RK3568_I2S1_MCLK_RX_OE },978 { 0xfe420000, 0x508, RK3568_I2S2_MCLK_OE, RK3568_I2S2_MCLK_OE },979 { 0xfe430000, 0x504, RK3568_I2S3_CLK_TXONLY, RK3568_I2S3_CLK_RXONLY },980 { 0xfe430000, 0x508, RK3568_I2S3_MCLK_TXONLY, RK3568_I2S3_MCLK_RXONLY },981 { 0xfe430000, 0x508, RK3568_I2S3_MCLK_OE, RK3568_I2S3_MCLK_OE },982};983 984static const struct txrx_config rv1126_txrx_config[] = {985 { 0xff800000, 0x10260, RV1126_I2S0_CLK_TXONLY, RV1126_I2S0_CLK_RXONLY },986};987 988static const struct rk_i2s_soc_data px30_i2s_soc_data = {989 .softrst_offset = 0x0300,990 .configs = px30_txrx_config,991 .config_count = ARRAY_SIZE(px30_txrx_config),992 .init = common_soc_init,993};994 995static const struct rk_i2s_soc_data rk1808_i2s_soc_data = {996 .softrst_offset = 0x0300,997 .configs = rk1808_txrx_config,998 .config_count = ARRAY_SIZE(rk1808_txrx_config),999 .init = common_soc_init,1000};1001 1002static const struct rk_i2s_soc_data rk3308_i2s_soc_data = {1003 .softrst_offset = 0x0400,1004 .grf_reg_offset = 0x0308,1005 .grf_shift = 5,1006 .configs = rk3308_txrx_config,1007 .config_count = ARRAY_SIZE(rk3308_txrx_config),1008 .init = common_soc_init,1009};1010 1011static const struct rk_i2s_soc_data rk3568_i2s_soc_data = {1012 .softrst_offset = 0x0400,1013 .configs = rk3568_txrx_config,1014 .config_count = ARRAY_SIZE(rk3568_txrx_config),1015 .init = common_soc_init,1016};1017 1018static const struct rk_i2s_soc_data rv1126_i2s_soc_data = {1019 .softrst_offset = 0x0300,1020 .configs = rv1126_txrx_config,1021 .config_count = ARRAY_SIZE(rv1126_txrx_config),1022 .init = common_soc_init,1023};1024 1025static const struct of_device_id rockchip_i2s_tdm_match[] = {1026 { .compatible = "rockchip,px30-i2s-tdm", .data = &px30_i2s_soc_data },1027 { .compatible = "rockchip,rk1808-i2s-tdm", .data = &rk1808_i2s_soc_data },1028 { .compatible = "rockchip,rk3308-i2s-tdm", .data = &rk3308_i2s_soc_data },1029 { .compatible = "rockchip,rk3568-i2s-tdm", .data = &rk3568_i2s_soc_data },1030 { .compatible = "rockchip,rk3588-i2s-tdm" },1031 { .compatible = "rockchip,rv1126-i2s-tdm", .data = &rv1126_i2s_soc_data },1032 {},1033};1034 1035static const struct snd_soc_dai_driver i2s_tdm_dai = {1036 .ops = &rockchip_i2s_tdm_dai_ops,1037};1038 1039static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)1040{1041 struct snd_soc_dai_driver *dai;1042 struct property *dma_names;1043 const char *dma_name;1044 u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |1045 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |1046 SNDRV_PCM_FMTBIT_S32_LE);1047 struct device_node *node = i2s_tdm->dev->of_node;1048 1049 of_property_for_each_string(node, "dma-names", dma_names, dma_name) {1050 if (!strcmp(dma_name, "tx"))1051 i2s_tdm->has_playback = true;1052 if (!strcmp(dma_name, "rx"))1053 i2s_tdm->has_capture = true;1054 }1055 1056 dai = devm_kmemdup(i2s_tdm->dev, &i2s_tdm_dai,1057 sizeof(*dai), GFP_KERNEL);1058 if (!dai)1059 return -ENOMEM;1060 1061 if (i2s_tdm->has_playback) {1062 dai->playback.stream_name = "Playback";1063 dai->playback.channels_min = 2;1064 dai->playback.channels_max = 8;1065 dai->playback.rates = SNDRV_PCM_RATE_8000_192000;1066 dai->playback.formats = formats;1067 }1068 1069 if (i2s_tdm->has_capture) {1070 dai->capture.stream_name = "Capture";1071 dai->capture.channels_min = 2;1072 dai->capture.channels_max = 8;1073 dai->capture.rates = SNDRV_PCM_RATE_8000_192000;1074 dai->capture.formats = formats;1075 }1076 1077 if (i2s_tdm->clk_trcm != TRCM_TXRX)1078 dai->symmetric_rate = 1;1079 1080 i2s_tdm->dai = dai;1081 1082 return 0;1083}1084 1085static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm,1086 int num,1087 bool is_rx_path)1088{1089 unsigned int *i2s_data;1090 int i, j;1091 1092 if (is_rx_path)1093 i2s_data = i2s_tdm->i2s_sdis;1094 else1095 i2s_data = i2s_tdm->i2s_sdos;1096 1097 for (i = 0; i < num; i++) {1098 if (i2s_data[i] > CH_GRP_MAX - 1) {1099 dev_err(i2s_tdm->dev,1100 "%s path i2s_data[%d]: %d is too high, max is: %d\n",1101 is_rx_path ? "RX" : "TX",1102 i, i2s_data[i], CH_GRP_MAX);1103 return -EINVAL;1104 }1105 1106 for (j = 0; j < num; j++) {1107 if (i == j)1108 continue;1109 1110 if (i2s_data[i] == i2s_data[j]) {1111 dev_err(i2s_tdm->dev,1112 "%s path invalid routed i2s_data: [%d]%d == [%d]%d\n",1113 is_rx_path ? "RX" : "TX",1114 i, i2s_data[i],1115 j, i2s_data[j]);1116 return -EINVAL;1117 }1118 }1119 }1120 1121 return 0;1122}1123 1124static void rockchip_i2s_tdm_tx_path_config(struct rk_i2s_tdm_dev *i2s_tdm,1125 int num)1126{1127 int idx;1128 1129 for (idx = 0; idx < num; idx++) {1130 regmap_update_bits(i2s_tdm->regmap, I2S_TXCR,1131 I2S_TXCR_PATH_MASK(idx),1132 I2S_TXCR_PATH(idx, i2s_tdm->i2s_sdos[idx]));1133 }1134}1135 1136static void rockchip_i2s_tdm_rx_path_config(struct rk_i2s_tdm_dev *i2s_tdm,1137 int num)1138{1139 int idx;1140 1141 for (idx = 0; idx < num; idx++) {1142 regmap_update_bits(i2s_tdm->regmap, I2S_RXCR,1143 I2S_RXCR_PATH_MASK(idx),1144 I2S_RXCR_PATH(idx, i2s_tdm->i2s_sdis[idx]));1145 }1146}1147 1148static void rockchip_i2s_tdm_path_config(struct rk_i2s_tdm_dev *i2s_tdm,1149 int num, bool is_rx_path)1150{1151 if (is_rx_path)1152 rockchip_i2s_tdm_rx_path_config(i2s_tdm, num);1153 else1154 rockchip_i2s_tdm_tx_path_config(i2s_tdm, num);1155}1156 1157static int rockchip_i2s_tdm_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm,1158 struct device_node *np,1159 bool is_rx_path)1160{1161 char *i2s_tx_path_prop = "rockchip,i2s-tx-route";1162 char *i2s_rx_path_prop = "rockchip,i2s-rx-route";1163 char *i2s_path_prop;1164 unsigned int *i2s_data;1165 int num, ret = 0;1166 1167 if (is_rx_path) {1168 i2s_path_prop = i2s_rx_path_prop;1169 i2s_data = i2s_tdm->i2s_sdis;1170 } else {1171 i2s_path_prop = i2s_tx_path_prop;1172 i2s_data = i2s_tdm->i2s_sdos;1173 }1174 1175 num = of_count_phandle_with_args(np, i2s_path_prop, NULL);1176 if (num < 0) {1177 if (num != -ENOENT) {1178 dev_err(i2s_tdm->dev,1179 "Failed to read '%s' num: %d\n",1180 i2s_path_prop, num);1181 ret = num;1182 }1183 return ret;1184 } else if (num != CH_GRP_MAX) {1185 dev_err(i2s_tdm->dev,1186 "The num: %d should be: %d\n", num, CH_GRP_MAX);1187 return -EINVAL;1188 }1189 1190 ret = of_property_read_u32_array(np, i2s_path_prop,1191 i2s_data, num);1192 if (ret < 0) {1193 dev_err(i2s_tdm->dev,1194 "Failed to read '%s': %d\n",1195 i2s_path_prop, ret);1196 return ret;1197 }1198 1199 ret = rockchip_i2s_tdm_path_check(i2s_tdm, num, is_rx_path);1200 if (ret < 0) {1201 dev_err(i2s_tdm->dev,1202 "Failed to check i2s data bus: %d\n", ret);1203 return ret;1204 }1205 1206 rockchip_i2s_tdm_path_config(i2s_tdm, num, is_rx_path);1207 1208 return 0;1209}1210 1211static int rockchip_i2s_tdm_tx_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm,1212 struct device_node *np)1213{1214 return rockchip_i2s_tdm_path_prepare(i2s_tdm, np, 0);1215}1216 1217static int rockchip_i2s_tdm_rx_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm,1218 struct device_node *np)1219{1220 return rockchip_i2s_tdm_path_prepare(i2s_tdm, np, 1);1221}1222 1223static int rockchip_i2s_tdm_probe(struct platform_device *pdev)1224{1225 struct device_node *node = pdev->dev.of_node;1226 struct rk_i2s_tdm_dev *i2s_tdm;1227 struct resource *res;1228 void __iomem *regs;1229 int ret;1230 1231 i2s_tdm = devm_kzalloc(&pdev->dev, sizeof(*i2s_tdm), GFP_KERNEL);1232 if (!i2s_tdm)1233 return -ENOMEM;1234 1235 i2s_tdm->dev = &pdev->dev;1236 1237 spin_lock_init(&i2s_tdm->lock);1238 i2s_tdm->soc_data = device_get_match_data(&pdev->dev);1239 i2s_tdm->frame_width = 64;1240 1241 i2s_tdm->clk_trcm = TRCM_TXRX;1242 if (of_property_read_bool(node, "rockchip,trcm-sync-tx-only"))1243 i2s_tdm->clk_trcm = TRCM_TX;1244 if (of_property_read_bool(node, "rockchip,trcm-sync-rx-only")) {1245 if (i2s_tdm->clk_trcm) {1246 dev_err(i2s_tdm->dev, "invalid trcm-sync configuration\n");1247 return -EINVAL;1248 }1249 i2s_tdm->clk_trcm = TRCM_RX;1250 }1251 1252 ret = rockchip_i2s_tdm_init_dai(i2s_tdm);1253 if (ret)1254 return ret;1255 1256 i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");1257 i2s_tdm->tx_reset = devm_reset_control_get_optional_exclusive(&pdev->dev,1258 "tx-m");1259 if (IS_ERR(i2s_tdm->tx_reset)) {1260 ret = PTR_ERR(i2s_tdm->tx_reset);1261 return dev_err_probe(i2s_tdm->dev, ret,1262 "Error in tx-m reset control\n");1263 }1264 1265 i2s_tdm->rx_reset = devm_reset_control_get_optional_exclusive(&pdev->dev,1266 "rx-m");1267 if (IS_ERR(i2s_tdm->rx_reset)) {1268 ret = PTR_ERR(i2s_tdm->rx_reset);1269 return dev_err_probe(i2s_tdm->dev, ret,1270 "Error in rx-m reset control\n");1271 }1272 1273 i2s_tdm->hclk = devm_clk_get(&pdev->dev, "hclk");1274 if (IS_ERR(i2s_tdm->hclk)) {1275 return dev_err_probe(i2s_tdm->dev, PTR_ERR(i2s_tdm->hclk),1276 "Failed to get clock hclk\n");1277 }1278 1279 i2s_tdm->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx");1280 if (IS_ERR(i2s_tdm->mclk_tx)) {1281 return dev_err_probe(i2s_tdm->dev, PTR_ERR(i2s_tdm->mclk_tx),1282 "Failed to get clock mclk_tx\n");1283 }1284 1285 i2s_tdm->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx");1286 if (IS_ERR(i2s_tdm->mclk_rx)) {1287 return dev_err_probe(i2s_tdm->dev, PTR_ERR(i2s_tdm->mclk_rx),1288 "Failed to get clock mclk_rx\n");1289 }1290 1291 i2s_tdm->io_multiplex =1292 of_property_read_bool(node, "rockchip,io-multiplex");1293 1294 regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);1295 if (IS_ERR(regs)) {1296 return dev_err_probe(i2s_tdm->dev, PTR_ERR(regs),1297 "Failed to get resource IORESOURCE_MEM\n");1298 }1299 1300 i2s_tdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs,1301 &rockchip_i2s_tdm_regmap_config);1302 if (IS_ERR(i2s_tdm->regmap)) {1303 return dev_err_probe(i2s_tdm->dev, PTR_ERR(i2s_tdm->regmap),1304 "Failed to initialise regmap\n");1305 }1306 1307 if (i2s_tdm->has_playback) {1308 i2s_tdm->playback_dma_data.addr = res->start + I2S_TXDR;1309 i2s_tdm->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;1310 i2s_tdm->playback_dma_data.maxburst = 8;1311 }1312 1313 if (i2s_tdm->has_capture) {1314 i2s_tdm->capture_dma_data.addr = res->start + I2S_RXDR;1315 i2s_tdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;1316 i2s_tdm->capture_dma_data.maxburst = 8;1317 }1318 1319 ret = rockchip_i2s_tdm_tx_path_prepare(i2s_tdm, node);1320 if (ret < 0) {1321 dev_err(&pdev->dev, "I2S TX path prepare failed: %d\n", ret);1322 return ret;1323 }1324 1325 ret = rockchip_i2s_tdm_rx_path_prepare(i2s_tdm, node);1326 if (ret < 0) {1327 dev_err(&pdev->dev, "I2S RX path prepare failed: %d\n", ret);1328 return ret;1329 }1330 1331 dev_set_drvdata(&pdev->dev, i2s_tdm);1332 1333 ret = clk_prepare_enable(i2s_tdm->hclk);1334 if (ret) {1335 return dev_err_probe(i2s_tdm->dev, ret,1336 "Failed to enable clock hclk\n");1337 }1338 1339 ret = i2s_tdm_prepare_enable_mclk(i2s_tdm);1340 if (ret) {1341 ret = dev_err_probe(i2s_tdm->dev, ret,1342 "Failed to enable one or more mclks\n");1343 goto err_disable_hclk;1344 }1345 1346 pm_runtime_enable(&pdev->dev);1347 1348 regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,1349 I2S_DMACR_TDL(16));1350 regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,1351 I2S_DMACR_RDL(16));1352 regmap_update_bits(i2s_tdm->regmap, I2S_CKR, I2S_CKR_TRCM_MASK,1353 i2s_tdm->clk_trcm << I2S_CKR_TRCM_SHIFT);1354 1355 if (i2s_tdm->soc_data && i2s_tdm->soc_data->init)1356 i2s_tdm->soc_data->init(&pdev->dev, res->start);1357 1358 ret = devm_snd_soc_register_component(&pdev->dev,1359 &rockchip_i2s_tdm_component,1360 i2s_tdm->dai, 1);1361 1362 if (ret) {1363 dev_err(&pdev->dev, "Could not register DAI\n");1364 goto err_suspend;1365 }1366 1367 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);1368 if (ret) {1369 dev_err(&pdev->dev, "Could not register PCM\n");1370 goto err_suspend;1371 }1372 1373 return 0;1374 1375err_suspend:1376 if (!pm_runtime_status_suspended(&pdev->dev))1377 i2s_tdm_runtime_suspend(&pdev->dev);1378 pm_runtime_disable(&pdev->dev);1379 1380err_disable_hclk:1381 clk_disable_unprepare(i2s_tdm->hclk);1382 1383 return ret;1384}1385 1386static void rockchip_i2s_tdm_remove(struct platform_device *pdev)1387{1388 if (!pm_runtime_status_suspended(&pdev->dev))1389 i2s_tdm_runtime_suspend(&pdev->dev);1390 1391 pm_runtime_disable(&pdev->dev);1392}1393 1394static int __maybe_unused rockchip_i2s_tdm_suspend(struct device *dev)1395{1396 struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev);1397 1398 regcache_mark_dirty(i2s_tdm->regmap);1399 1400 return 0;1401}1402 1403static int __maybe_unused rockchip_i2s_tdm_resume(struct device *dev)1404{1405 struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev);1406 int ret;1407 1408 ret = pm_runtime_resume_and_get(dev);1409 if (ret < 0)1410 return ret;1411 ret = regcache_sync(i2s_tdm->regmap);1412 pm_runtime_put(dev);1413 1414 return ret;1415}1416 1417static const struct dev_pm_ops rockchip_i2s_tdm_pm_ops = {1418 SET_RUNTIME_PM_OPS(i2s_tdm_runtime_suspend, i2s_tdm_runtime_resume,1419 NULL)1420 SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_tdm_suspend,1421 rockchip_i2s_tdm_resume)1422};1423 1424static struct platform_driver rockchip_i2s_tdm_driver = {1425 .probe = rockchip_i2s_tdm_probe,1426 .remove = rockchip_i2s_tdm_remove,1427 .driver = {1428 .name = DRV_NAME,1429 .of_match_table = rockchip_i2s_tdm_match,1430 .pm = &rockchip_i2s_tdm_pm_ops,1431 },1432};1433module_platform_driver(rockchip_i2s_tdm_driver);1434 1435MODULE_DESCRIPTION("ROCKCHIP I2S/TDM ASoC Interface");1436MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");1437MODULE_LICENSE("GPL v2");1438MODULE_ALIAS("platform:" DRV_NAME);1439MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match);1440