1029 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// tegra210_i2s.c - Tegra210 I2S driver4//5// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.6 7#include <linux/clk.h>8#include <linux/device.h>9#include <linux/mod_devicetable.h>10#include <linux/module.h>11#include <linux/of_graph.h>12#include <linux/platform_device.h>13#include <linux/pm_runtime.h>14#include <linux/regmap.h>15#include <sound/core.h>16#include <sound/pcm_params.h>17#include <sound/simple_card_utils.h>18#include <sound/soc.h>19#include "tegra210_i2s.h"20#include "tegra_cif.h"21 22static const struct reg_default tegra210_i2s_reg_defaults[] = {23 { TEGRA210_I2S_RX_INT_MASK, 0x00000003 },24 { TEGRA210_I2S_RX_CIF_CTRL, 0x00007700 },25 { TEGRA210_I2S_TX_INT_MASK, 0x00000003 },26 { TEGRA210_I2S_TX_CIF_CTRL, 0x00007700 },27 { TEGRA210_I2S_CG, 0x1 },28 { TEGRA210_I2S_TIMING, 0x0000001f },29 { TEGRA210_I2S_ENABLE, 0x1 },30 /*31 * Below update does not have any effect on Tegra186 and Tegra194.32 * On Tegra210, I2S4 has "i2s4a" and "i2s4b" pins and below update33 * is required to select i2s4b for it to be functional for I2S34 * operation.35 */36 { TEGRA210_I2S_CYA, 0x1 },37};38 39static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap,40 unsigned int total_slots,41 unsigned int tx_slot_mask,42 unsigned int rx_slot_mask)43{44 regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1);45 regmap_write(regmap, TEGRA210_I2S_TX_SLOT_CTRL, tx_slot_mask);46 regmap_write(regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask);47}48 49static int tegra210_i2s_set_clock_rate(struct device *dev,50 unsigned int clock_rate)51{52 struct tegra210_i2s *i2s = dev_get_drvdata(dev);53 unsigned int val;54 int err;55 56 regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);57 58 /* No need to set rates if I2S is being operated in slave */59 if (!(val & I2S_CTRL_MASTER_EN))60 return 0;61 62 err = clk_set_rate(i2s->clk_i2s, clock_rate);63 if (err) {64 dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n",65 clock_rate, err);66 return err;67 }68 69 if (!IS_ERR(i2s->clk_sync_input)) {70 /*71 * Other I/O modules in AHUB can use i2s bclk as reference72 * clock. Below sets sync input clock rate as per bclk,73 * which can be used as input to other I/O modules.74 */75 err = clk_set_rate(i2s->clk_sync_input, clock_rate);76 if (err) {77 dev_err(dev,78 "can't set I2S sync input rate %u, err = %d\n",79 clock_rate, err);80 return err;81 }82 }83 84 return 0;85}86 87static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt,88 int stream)89{90 struct device *dev = compnt->dev;91 struct tegra210_i2s *i2s = dev_get_drvdata(dev);92 unsigned int reset_mask = I2S_SOFT_RESET_MASK;93 unsigned int reset_en = I2S_SOFT_RESET_EN;94 unsigned int reset_reg, cif_reg, stream_reg;95 unsigned int cif_ctrl, stream_ctrl, i2s_ctrl, val;96 int err;97 98 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {99 reset_reg = TEGRA210_I2S_RX_SOFT_RESET;100 cif_reg = TEGRA210_I2S_RX_CIF_CTRL;101 stream_reg = TEGRA210_I2S_RX_CTRL;102 } else {103 reset_reg = TEGRA210_I2S_TX_SOFT_RESET;104 cif_reg = TEGRA210_I2S_TX_CIF_CTRL;105 stream_reg = TEGRA210_I2S_TX_CTRL;106 }107 108 /* Store CIF and I2S control values */109 regmap_read(i2s->regmap, cif_reg, &cif_ctrl);110 regmap_read(i2s->regmap, stream_reg, &stream_ctrl);111 regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl);112 113 /* Reset to make sure the previous transactions are clean */114 regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en);115 116 err = regmap_read_poll_timeout(i2s->regmap, reset_reg, val,117 !(val & reset_mask & reset_en),118 10, 10000);119 if (err) {120 dev_err(dev, "timeout: failed to reset I2S for %s\n",121 snd_pcm_direction_name(stream));122 return err;123 }124 125 /* Restore CIF and I2S control values */126 regmap_write(i2s->regmap, cif_reg, cif_ctrl);127 regmap_write(i2s->regmap, stream_reg, stream_ctrl);128 regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl);129 130 return 0;131}132 133static int tegra210_i2s_init(struct snd_soc_dapm_widget *w,134 struct snd_kcontrol *kcontrol, int event)135{136 struct snd_soc_component *compnt = snd_soc_dapm_to_component(w->dapm);137 struct device *dev = compnt->dev;138 struct tegra210_i2s *i2s = dev_get_drvdata(dev);139 unsigned int val, status_reg;140 int stream;141 int err;142 143 switch (w->reg) {144 case TEGRA210_I2S_RX_ENABLE:145 stream = SNDRV_PCM_STREAM_PLAYBACK;146 status_reg = TEGRA210_I2S_RX_STATUS;147 break;148 case TEGRA210_I2S_TX_ENABLE:149 stream = SNDRV_PCM_STREAM_CAPTURE;150 status_reg = TEGRA210_I2S_TX_STATUS;151 break;152 default:153 return -EINVAL;154 }155 156 /* Ensure I2S is in disabled state before new session */157 err = regmap_read_poll_timeout(i2s->regmap, status_reg, val,158 !(val & I2S_EN_MASK & I2S_EN),159 10, 10000);160 if (err) {161 dev_err(dev, "timeout: previous I2S %s is still active\n",162 snd_pcm_direction_name(stream));163 return err;164 }165 166 return tegra210_i2s_sw_reset(compnt, stream);167}168 169static int __maybe_unused tegra210_i2s_runtime_suspend(struct device *dev)170{171 struct tegra210_i2s *i2s = dev_get_drvdata(dev);172 173 regcache_cache_only(i2s->regmap, true);174 regcache_mark_dirty(i2s->regmap);175 176 clk_disable_unprepare(i2s->clk_i2s);177 178 return 0;179}180 181static int __maybe_unused tegra210_i2s_runtime_resume(struct device *dev)182{183 struct tegra210_i2s *i2s = dev_get_drvdata(dev);184 int err;185 186 err = clk_prepare_enable(i2s->clk_i2s);187 if (err) {188 dev_err(dev, "failed to enable I2S bit clock, err: %d\n", err);189 return err;190 }191 192 regcache_cache_only(i2s->regmap, false);193 regcache_sync(i2s->regmap);194 195 return 0;196}197 198static void tegra210_i2s_set_data_offset(struct tegra210_i2s *i2s,199 unsigned int data_offset)200{201 /* Capture path */202 regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL,203 I2S_CTRL_DATA_OFFSET_MASK,204 data_offset << I2S_DATA_SHIFT);205 206 /* Playback path */207 regmap_update_bits(i2s->regmap, TEGRA210_I2S_RX_CTRL,208 I2S_CTRL_DATA_OFFSET_MASK,209 data_offset << I2S_DATA_SHIFT);210}211 212static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai,213 unsigned int fmt)214{215 struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);216 unsigned int mask, val;217 218 mask = I2S_CTRL_MASTER_EN_MASK;219 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {220 case SND_SOC_DAIFMT_BC_FC:221 val = 0;222 break;223 case SND_SOC_DAIFMT_BP_FP:224 val = I2S_CTRL_MASTER_EN;225 break;226 default:227 return -EINVAL;228 }229 230 mask |= I2S_CTRL_FRAME_FMT_MASK | I2S_CTRL_LRCK_POL_MASK;231 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {232 case SND_SOC_DAIFMT_DSP_A:233 val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE;234 val |= I2S_CTRL_LRCK_POL_HIGH;235 tegra210_i2s_set_data_offset(i2s, 1);236 break;237 case SND_SOC_DAIFMT_DSP_B:238 val |= I2S_CTRL_FRAME_FMT_FSYNC_MODE;239 val |= I2S_CTRL_LRCK_POL_HIGH;240 tegra210_i2s_set_data_offset(i2s, 0);241 break;242 /* I2S mode has data offset of 1 */243 case SND_SOC_DAIFMT_I2S:244 val |= I2S_CTRL_FRAME_FMT_LRCK_MODE;245 val |= I2S_CTRL_LRCK_POL_LOW;246 tegra210_i2s_set_data_offset(i2s, 1);247 break;248 /*249 * For RJ mode data offset is dependent on the sample size250 * and the bclk ratio, and so is set when hw_params is called.251 */252 case SND_SOC_DAIFMT_RIGHT_J:253 val |= I2S_CTRL_FRAME_FMT_LRCK_MODE;254 val |= I2S_CTRL_LRCK_POL_HIGH;255 break;256 case SND_SOC_DAIFMT_LEFT_J:257 val |= I2S_CTRL_FRAME_FMT_LRCK_MODE;258 val |= I2S_CTRL_LRCK_POL_HIGH;259 tegra210_i2s_set_data_offset(i2s, 0);260 break;261 default:262 return -EINVAL;263 }264 265 mask |= I2S_CTRL_EDGE_CTRL_MASK;266 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {267 case SND_SOC_DAIFMT_NB_NF:268 val |= I2S_CTRL_EDGE_CTRL_POS_EDGE;269 break;270 case SND_SOC_DAIFMT_NB_IF:271 val |= I2S_CTRL_EDGE_CTRL_POS_EDGE;272 val ^= I2S_CTRL_LRCK_POL_MASK;273 break;274 case SND_SOC_DAIFMT_IB_NF:275 val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE;276 break;277 case SND_SOC_DAIFMT_IB_IF:278 val |= I2S_CTRL_EDGE_CTRL_NEG_EDGE;279 val ^= I2S_CTRL_LRCK_POL_MASK;280 break;281 default:282 return -EINVAL;283 }284 285 regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val);286 287 i2s->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;288 289 return 0;290}291 292static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai,293 unsigned int tx_mask, unsigned int rx_mask,294 int slots, int slot_width)295{296 struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);297 298 /* Copy the required tx and rx mask */299 i2s->tx_mask = (tx_mask > DEFAULT_I2S_SLOT_MASK) ?300 DEFAULT_I2S_SLOT_MASK : tx_mask;301 i2s->rx_mask = (rx_mask > DEFAULT_I2S_SLOT_MASK) ?302 DEFAULT_I2S_SLOT_MASK : rx_mask;303 304 return 0;305}306 307static int tegra210_i2s_get_loopback(struct snd_kcontrol *kcontrol,308 struct snd_ctl_elem_value *ucontrol)309{310 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);311 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);312 313 ucontrol->value.integer.value[0] = i2s->loopback;314 315 return 0;316}317 318static int tegra210_i2s_put_loopback(struct snd_kcontrol *kcontrol,319 struct snd_ctl_elem_value *ucontrol)320{321 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);322 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);323 int value = ucontrol->value.integer.value[0];324 325 if (value == i2s->loopback)326 return 0;327 328 i2s->loopback = value;329 330 regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK,331 i2s->loopback << I2S_CTRL_LPBK_SHIFT);332 333 return 1;334}335 336static int tegra210_i2s_get_fsync_width(struct snd_kcontrol *kcontrol,337 struct snd_ctl_elem_value *ucontrol)338{339 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);340 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);341 342 ucontrol->value.integer.value[0] = i2s->fsync_width;343 344 return 0;345}346 347static int tegra210_i2s_put_fsync_width(struct snd_kcontrol *kcontrol,348 struct snd_ctl_elem_value *ucontrol)349{350 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);351 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);352 int value = ucontrol->value.integer.value[0];353 354 if (value == i2s->fsync_width)355 return 0;356 357 i2s->fsync_width = value;358 359 /*360 * Frame sync width is used only for FSYNC modes and not361 * applicable for LRCK modes. Reset value for this field is "0",362 * which means the width is one bit clock wide.363 * The width requirement may depend on the codec and in such364 * cases mixer control is used to update custom values. A value365 * of "N" here means, width is "N + 1" bit clock wide.366 */367 regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,368 I2S_CTRL_FSYNC_WIDTH_MASK,369 i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT);370 371 return 1;372}373 374static int tegra210_i2s_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,375 struct snd_ctl_elem_value *ucontrol)376{377 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);378 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);379 380 ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_TX_PATH];381 382 return 0;383}384 385static int tegra210_i2s_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,386 struct snd_ctl_elem_value *ucontrol)387{388 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);389 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);390 unsigned int value = ucontrol->value.enumerated.item[0];391 392 if (value == i2s->stereo_to_mono[I2S_TX_PATH])393 return 0;394 395 i2s->stereo_to_mono[I2S_TX_PATH] = value;396 397 return 1;398}399 400static int tegra210_i2s_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,401 struct snd_ctl_elem_value *ucontrol)402{403 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);404 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);405 406 ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_TX_PATH];407 408 return 0;409}410 411static int tegra210_i2s_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,412 struct snd_ctl_elem_value *ucontrol)413{414 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);415 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);416 unsigned int value = ucontrol->value.enumerated.item[0];417 418 if (value == i2s->mono_to_stereo[I2S_TX_PATH])419 return 0;420 421 i2s->mono_to_stereo[I2S_TX_PATH] = value;422 423 return 1;424}425 426static int tegra210_i2s_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,427 struct snd_ctl_elem_value *ucontrol)428{429 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);430 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);431 432 ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_RX_PATH];433 434 return 0;435}436 437static int tegra210_i2s_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,438 struct snd_ctl_elem_value *ucontrol)439{440 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);441 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);442 unsigned int value = ucontrol->value.enumerated.item[0];443 444 if (value == i2s->stereo_to_mono[I2S_RX_PATH])445 return 0;446 447 i2s->stereo_to_mono[I2S_RX_PATH] = value;448 449 return 1;450}451 452static int tegra210_i2s_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,453 struct snd_ctl_elem_value *ucontrol)454{455 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);456 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);457 458 ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_RX_PATH];459 460 return 0;461}462 463static int tegra210_i2s_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,464 struct snd_ctl_elem_value *ucontrol)465{466 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);467 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);468 unsigned int value = ucontrol->value.enumerated.item[0];469 470 if (value == i2s->mono_to_stereo[I2S_RX_PATH])471 return 0;472 473 i2s->mono_to_stereo[I2S_RX_PATH] = value;474 475 return 1;476}477 478static int tegra210_i2s_pget_fifo_th(struct snd_kcontrol *kcontrol,479 struct snd_ctl_elem_value *ucontrol)480{481 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);482 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);483 484 ucontrol->value.integer.value[0] = i2s->rx_fifo_th;485 486 return 0;487}488 489static int tegra210_i2s_pput_fifo_th(struct snd_kcontrol *kcontrol,490 struct snd_ctl_elem_value *ucontrol)491{492 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);493 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);494 int value = ucontrol->value.integer.value[0];495 496 if (value == i2s->rx_fifo_th)497 return 0;498 499 i2s->rx_fifo_th = value;500 501 return 1;502}503 504static int tegra210_i2s_get_bclk_ratio(struct snd_kcontrol *kcontrol,505 struct snd_ctl_elem_value *ucontrol)506{507 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);508 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);509 510 ucontrol->value.integer.value[0] = i2s->bclk_ratio;511 512 return 0;513}514 515static int tegra210_i2s_put_bclk_ratio(struct snd_kcontrol *kcontrol,516 struct snd_ctl_elem_value *ucontrol)517{518 struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);519 struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);520 int value = ucontrol->value.integer.value[0];521 522 if (value == i2s->bclk_ratio)523 return 0;524 525 i2s->bclk_ratio = value;526 527 return 1;528}529 530static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai,531 unsigned int ratio)532{533 struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);534 535 i2s->bclk_ratio = ratio;536 537 return 0;538}539 540static int tegra210_i2s_set_timing_params(struct device *dev,541 unsigned int sample_size,542 unsigned int srate,543 unsigned int channels)544{545 struct tegra210_i2s *i2s = dev_get_drvdata(dev);546 unsigned int val, bit_count, bclk_rate, num_bclk = sample_size;547 int err;548 549 if (i2s->bclk_ratio)550 num_bclk *= i2s->bclk_ratio;551 552 if (i2s->dai_fmt == SND_SOC_DAIFMT_RIGHT_J)553 tegra210_i2s_set_data_offset(i2s, num_bclk - sample_size);554 555 /* I2S bit clock rate */556 bclk_rate = srate * channels * num_bclk;557 558 err = tegra210_i2s_set_clock_rate(dev, bclk_rate);559 if (err) {560 dev_err(dev, "can't set I2S bit clock rate %u, err: %d\n",561 bclk_rate, err);562 return err;563 }564 565 regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);566 567 /*568 * For LRCK mode, channel bit count depends on number of bit clocks569 * on the left channel, where as for FSYNC mode bit count depends on570 * the number of bit clocks in both left and right channels for DSP571 * mode or the number of bit clocks in one TDM frame.572 *573 */574 switch (val & I2S_CTRL_FRAME_FMT_MASK) {575 case I2S_CTRL_FRAME_FMT_LRCK_MODE:576 bit_count = (bclk_rate / (srate * 2)) - 1;577 break;578 case I2S_CTRL_FRAME_FMT_FSYNC_MODE:579 bit_count = (bclk_rate / srate) - 1;580 581 tegra210_i2s_set_slot_ctrl(i2s->regmap, channels,582 i2s->tx_mask, i2s->rx_mask);583 break;584 default:585 dev_err(dev, "invalid I2S frame format\n");586 return -EINVAL;587 }588 589 if (bit_count > I2S_TIMING_CH_BIT_CNT_MASK) {590 dev_err(dev, "invalid I2S channel bit count %u\n", bit_count);591 return -EINVAL;592 }593 594 regmap_write(i2s->regmap, TEGRA210_I2S_TIMING,595 bit_count << I2S_TIMING_CH_BIT_CNT_SHIFT);596 597 return 0;598}599 600static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,601 struct snd_pcm_hw_params *params,602 struct snd_soc_dai *dai)603{604 struct device *dev = dai->dev;605 struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);606 unsigned int sample_size, channels, srate, val, reg, path;607 struct tegra_cif_conf cif_conf;608 snd_pcm_format_t sample_format;609 610 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));611 612 channels = params_channels(params);613 if (channels < 1) {614 dev_err(dev, "invalid I2S %d channel configuration\n",615 channels);616 return -EINVAL;617 }618 619 cif_conf.audio_ch = channels;620 cif_conf.client_ch = channels;621 if (i2s->client_channels)622 cif_conf.client_ch = i2s->client_channels;623 624 /* AHUB CIF Audio bits configs */625 switch (params_format(params)) {626 case SNDRV_PCM_FORMAT_S8:627 cif_conf.audio_bits = TEGRA_ACIF_BITS_8;628 break;629 case SNDRV_PCM_FORMAT_S16_LE:630 cif_conf.audio_bits = TEGRA_ACIF_BITS_16;631 break;632 case SNDRV_PCM_FORMAT_S32_LE:633 cif_conf.audio_bits = TEGRA_ACIF_BITS_32;634 break;635 default:636 dev_err(dev, "unsupported params audio bit format!\n");637 return -EOPNOTSUPP;638 }639 640 sample_format = params_format(params);641 if (i2s->client_sample_format >= 0)642 sample_format = (snd_pcm_format_t)i2s->client_sample_format;643 644 /*645 * Format of the I2S for sending/receiving the audio646 * to/from external device.647 */648 switch (sample_format) {649 case SNDRV_PCM_FORMAT_S8:650 val = I2S_BITS_8;651 sample_size = 8;652 cif_conf.client_bits = TEGRA_ACIF_BITS_8;653 break;654 case SNDRV_PCM_FORMAT_S16_LE:655 val = I2S_BITS_16;656 sample_size = 16;657 cif_conf.client_bits = TEGRA_ACIF_BITS_16;658 break;659 case SNDRV_PCM_FORMAT_S32_LE:660 val = I2S_BITS_32;661 sample_size = 32;662 cif_conf.client_bits = TEGRA_ACIF_BITS_32;663 break;664 default:665 dev_err(dev, "unsupported client bit format!\n");666 return -EOPNOTSUPP;667 }668 669 /* Program sample size */670 regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,671 I2S_CTRL_BIT_SIZE_MASK, val);672 673 srate = params_rate(params);674 675 /* For playback I2S RX-CIF and for capture TX-CIF is used */676 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)677 path = I2S_RX_PATH;678 else679 path = I2S_TX_PATH;680 681 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {682 unsigned int max_th;683 684 /* FIFO threshold in terms of frames */685 max_th = (I2S_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1;686 687 if (i2s->rx_fifo_th > max_th)688 i2s->rx_fifo_th = max_th;689 690 cif_conf.threshold = i2s->rx_fifo_th;691 692 reg = TEGRA210_I2S_RX_CIF_CTRL;693 } else {694 reg = TEGRA210_I2S_TX_CIF_CTRL;695 }696 697 cif_conf.mono_conv = i2s->mono_to_stereo[path];698 cif_conf.stereo_conv = i2s->stereo_to_mono[path];699 700 tegra_set_cif(i2s->regmap, reg, &cif_conf);701 702 return tegra210_i2s_set_timing_params(dev, sample_size, srate,703 cif_conf.client_ch);704}705 706static const struct snd_soc_dai_ops tegra210_i2s_dai_ops = {707 .set_fmt = tegra210_i2s_set_fmt,708 .hw_params = tegra210_i2s_hw_params,709 .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio,710 .set_tdm_slot = tegra210_i2s_set_tdm_slot,711};712 713static struct snd_soc_dai_driver tegra210_i2s_dais[] = {714 {715 .name = "I2S-CIF",716 .playback = {717 .stream_name = "CIF-Playback",718 .channels_min = 1,719 .channels_max = 16,720 .rates = SNDRV_PCM_RATE_8000_192000,721 .formats = SNDRV_PCM_FMTBIT_S8 |722 SNDRV_PCM_FMTBIT_S16_LE |723 SNDRV_PCM_FMTBIT_S32_LE,724 },725 .capture = {726 .stream_name = "CIF-Capture",727 .channels_min = 1,728 .channels_max = 16,729 .rates = SNDRV_PCM_RATE_8000_192000,730 .formats = SNDRV_PCM_FMTBIT_S8 |731 SNDRV_PCM_FMTBIT_S16_LE |732 SNDRV_PCM_FMTBIT_S32_LE,733 },734 },735 {736 .name = "I2S-DAP",737 .playback = {738 .stream_name = "DAP-Playback",739 .channels_min = 1,740 .channels_max = 16,741 .rates = SNDRV_PCM_RATE_8000_192000,742 .formats = SNDRV_PCM_FMTBIT_S8 |743 SNDRV_PCM_FMTBIT_S16_LE |744 SNDRV_PCM_FMTBIT_S32_LE,745 },746 .capture = {747 .stream_name = "DAP-Capture",748 .channels_min = 1,749 .channels_max = 16,750 .rates = SNDRV_PCM_RATE_8000_192000,751 .formats = SNDRV_PCM_FMTBIT_S8 |752 SNDRV_PCM_FMTBIT_S16_LE |753 SNDRV_PCM_FMTBIT_S32_LE,754 },755 .ops = &tegra210_i2s_dai_ops,756 .symmetric_rate = 1,757 },758};759 760static const char * const tegra210_i2s_stereo_conv_text[] = {761 "CH0", "CH1", "AVG",762};763 764static const char * const tegra210_i2s_mono_conv_text[] = {765 "Zero", "Copy",766};767 768static const struct soc_enum tegra210_i2s_mono_conv_enum =769 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_mono_conv_text),770 tegra210_i2s_mono_conv_text);771 772static const struct soc_enum tegra210_i2s_stereo_conv_enum =773 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_i2s_stereo_conv_text),774 tegra210_i2s_stereo_conv_text);775 776static const struct snd_kcontrol_new tegra210_i2s_controls[] = {777 SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_loopback,778 tegra210_i2s_put_loopback),779 SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0,780 tegra210_i2s_get_fsync_width,781 tegra210_i2s_put_fsync_width),782 SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum,783 tegra210_i2s_cget_stereo_to_mono,784 tegra210_i2s_cput_stereo_to_mono),785 SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum,786 tegra210_i2s_cget_mono_to_stereo,787 tegra210_i2s_cput_mono_to_stereo),788 SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum,789 tegra210_i2s_pget_mono_to_stereo,790 tegra210_i2s_pput_mono_to_stereo),791 SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum,792 tegra210_i2s_pget_stereo_to_mono,793 tegra210_i2s_pput_stereo_to_mono),794 SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1,795 0, tegra210_i2s_pget_fifo_th, tegra210_i2s_pput_fifo_th),796 SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0,797 tegra210_i2s_get_bclk_ratio,798 tegra210_i2s_put_bclk_ratio),799};800 801static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = {802 SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE,803 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU),804 SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, TEGRA210_I2S_TX_ENABLE,805 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU),806 SND_SOC_DAPM_MIC("MIC", NULL),807 SND_SOC_DAPM_SPK("SPK", NULL),808};809 810static const struct snd_soc_dapm_route tegra210_i2s_routes[] = {811 /* Playback route from XBAR */812 { "XBAR-Playback", NULL, "XBAR-TX" },813 { "CIF-Playback", NULL, "XBAR-Playback" },814 { "RX", NULL, "CIF-Playback" },815 { "DAP-Playback", NULL, "RX" },816 { "SPK", NULL, "DAP-Playback" },817 /* Capture route to XBAR */818 { "XBAR-RX", NULL, "XBAR-Capture" },819 { "XBAR-Capture", NULL, "CIF-Capture" },820 { "CIF-Capture", NULL, "TX" },821 { "TX", NULL, "DAP-Capture" },822 { "DAP-Capture", NULL, "MIC" },823};824 825static const struct snd_soc_component_driver tegra210_i2s_cmpnt = {826 .dapm_widgets = tegra210_i2s_widgets,827 .num_dapm_widgets = ARRAY_SIZE(tegra210_i2s_widgets),828 .dapm_routes = tegra210_i2s_routes,829 .num_dapm_routes = ARRAY_SIZE(tegra210_i2s_routes),830 .controls = tegra210_i2s_controls,831 .num_controls = ARRAY_SIZE(tegra210_i2s_controls),832};833 834static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg)835{836 switch (reg) {837 case TEGRA210_I2S_RX_ENABLE ... TEGRA210_I2S_RX_SOFT_RESET:838 case TEGRA210_I2S_RX_INT_MASK ... TEGRA210_I2S_RX_CLK_TRIM:839 case TEGRA210_I2S_TX_ENABLE ... TEGRA210_I2S_TX_SOFT_RESET:840 case TEGRA210_I2S_TX_INT_MASK ... TEGRA210_I2S_TX_CLK_TRIM:841 case TEGRA210_I2S_ENABLE ... TEGRA210_I2S_CG:842 case TEGRA210_I2S_CTRL ... TEGRA210_I2S_CYA:843 return true;844 default:845 return false;846 }847}848 849static bool tegra210_i2s_rd_reg(struct device *dev, unsigned int reg)850{851 if (tegra210_i2s_wr_reg(dev, reg))852 return true;853 854 switch (reg) {855 case TEGRA210_I2S_RX_STATUS:856 case TEGRA210_I2S_RX_INT_STATUS:857 case TEGRA210_I2S_RX_CIF_FIFO_STATUS:858 case TEGRA210_I2S_TX_STATUS:859 case TEGRA210_I2S_TX_INT_STATUS:860 case TEGRA210_I2S_TX_CIF_FIFO_STATUS:861 case TEGRA210_I2S_STATUS:862 case TEGRA210_I2S_INT_STATUS:863 return true;864 default:865 return false;866 }867}868 869static bool tegra210_i2s_volatile_reg(struct device *dev, unsigned int reg)870{871 switch (reg) {872 case TEGRA210_I2S_RX_STATUS:873 case TEGRA210_I2S_RX_INT_STATUS:874 case TEGRA210_I2S_RX_CIF_FIFO_STATUS:875 case TEGRA210_I2S_TX_STATUS:876 case TEGRA210_I2S_TX_INT_STATUS:877 case TEGRA210_I2S_TX_CIF_FIFO_STATUS:878 case TEGRA210_I2S_STATUS:879 case TEGRA210_I2S_INT_STATUS:880 case TEGRA210_I2S_RX_SOFT_RESET:881 case TEGRA210_I2S_TX_SOFT_RESET:882 return true;883 default:884 return false;885 }886}887 888static const struct regmap_config tegra210_i2s_regmap_config = {889 .reg_bits = 32,890 .reg_stride = 4,891 .val_bits = 32,892 .max_register = TEGRA210_I2S_CYA,893 .writeable_reg = tegra210_i2s_wr_reg,894 .readable_reg = tegra210_i2s_rd_reg,895 .volatile_reg = tegra210_i2s_volatile_reg,896 .reg_defaults = tegra210_i2s_reg_defaults,897 .num_reg_defaults = ARRAY_SIZE(tegra210_i2s_reg_defaults),898 .cache_type = REGCACHE_FLAT,899};900 901/*902 * The AHUB HW modules are interconnected with CIF which are capable of903 * supporting Channel and Sample bit format conversion. This needs different904 * CIF Audio and client configuration. As one of the config comes from905 * params_channels() or params_format(), the extra configuration is passed from906 * CIF Port of DT I2S node which can help to perform this conversion.907 *908 * 4ch audio = 4ch client = 2ch 2ch909 * -----> ADMAIF -----------> CIF -------------> I2S ---->910 */911static void tegra210_parse_client_convert(struct device *dev)912{913 struct tegra210_i2s *i2s = dev_get_drvdata(dev);914 struct device_node *ports, *ep;915 struct simple_util_data data = {};916 int cif_port = 0;917 918 ports = of_get_child_by_name(dev->of_node, "ports");919 if (ports) {920 ep = of_graph_get_endpoint_by_regs(ports, cif_port, -1);921 if (ep) {922 simple_util_parse_convert(ep, NULL, &data);923 of_node_put(ep);924 }925 of_node_put(ports);926 }927 928 if (data.convert_channels)929 i2s->client_channels = data.convert_channels;930 931 if (data.convert_sample_format)932 i2s->client_sample_format = simple_util_get_sample_fmt(&data);933}934 935static int tegra210_i2s_probe(struct platform_device *pdev)936{937 struct device *dev = &pdev->dev;938 struct tegra210_i2s *i2s;939 void __iomem *regs;940 int err;941 942 i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);943 if (!i2s)944 return -ENOMEM;945 946 i2s->rx_fifo_th = DEFAULT_I2S_RX_FIFO_THRESHOLD;947 i2s->tx_mask = DEFAULT_I2S_SLOT_MASK;948 i2s->rx_mask = DEFAULT_I2S_SLOT_MASK;949 i2s->loopback = false;950 i2s->client_sample_format = -EINVAL;951 952 dev_set_drvdata(dev, i2s);953 954 i2s->clk_i2s = devm_clk_get(dev, "i2s");955 if (IS_ERR(i2s->clk_i2s)) {956 dev_err(dev, "can't retrieve I2S bit clock\n");957 return PTR_ERR(i2s->clk_i2s);958 }959 960 /*961 * Not an error, as this clock is needed only when some other I/O962 * requires input clock from current I2S instance, which is963 * configurable from DT.964 */965 i2s->clk_sync_input = devm_clk_get(dev, "sync_input");966 if (IS_ERR(i2s->clk_sync_input))967 dev_dbg(dev, "can't retrieve I2S sync input clock\n");968 969 regs = devm_platform_ioremap_resource(pdev, 0);970 if (IS_ERR(regs))971 return PTR_ERR(regs);972 973 i2s->regmap = devm_regmap_init_mmio(dev, regs,974 &tegra210_i2s_regmap_config);975 if (IS_ERR(i2s->regmap)) {976 dev_err(dev, "regmap init failed\n");977 return PTR_ERR(i2s->regmap);978 }979 980 tegra210_parse_client_convert(dev);981 982 regcache_cache_only(i2s->regmap, true);983 984 err = devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt,985 tegra210_i2s_dais,986 ARRAY_SIZE(tegra210_i2s_dais));987 if (err) {988 dev_err(dev, "can't register I2S component, err: %d\n", err);989 return err;990 }991 992 pm_runtime_enable(dev);993 994 return 0;995}996 997static void tegra210_i2s_remove(struct platform_device *pdev)998{999 pm_runtime_disable(&pdev->dev);1000}1001 1002static const struct dev_pm_ops tegra210_i2s_pm_ops = {1003 SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend,1004 tegra210_i2s_runtime_resume, NULL)1005 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,1006 pm_runtime_force_resume)1007};1008 1009static const struct of_device_id tegra210_i2s_of_match[] = {1010 { .compatible = "nvidia,tegra210-i2s" },1011 {},1012};1013MODULE_DEVICE_TABLE(of, tegra210_i2s_of_match);1014 1015static struct platform_driver tegra210_i2s_driver = {1016 .driver = {1017 .name = "tegra210-i2s",1018 .of_match_table = tegra210_i2s_of_match,1019 .pm = &tegra210_i2s_pm_ops,1020 },1021 .probe = tegra210_i2s_probe,1022 .remove = tegra210_i2s_remove,1023};1024module_platform_driver(tegra210_i2s_driver)1025 1026MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");1027MODULE_DESCRIPTION("Tegra210 ASoC I2S driver");1028MODULE_LICENSE("GPL v2");1029