tegra_i2s.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2018 Google LLC
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #define LOG_CATEGORY UCLASS_I2S
  7. #define LOG_DEBUG
  8. #include <common.h>
  9. #include <dm.h>
  10. #include <i2s.h>
  11. #include <log.h>
  12. #include <misc.h>
  13. #include <sound.h>
  14. #include <asm/io.h>
  15. #include <asm/arch-tegra/tegra_i2s.h>
  16. #include "tegra_i2s_priv.h"
  17. int tegra_i2s_set_cif_tx_ctrl(struct udevice *dev, u32 value)
  18. {
  19. struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
  20. struct i2s_ctlr *regs = (struct i2s_ctlr *)priv->base_address;
  21. writel(value, &regs->cif_tx_ctrl);
  22. return 0;
  23. }
  24. static void tegra_i2s_transmit_enable(struct i2s_ctlr *regs, int on)
  25. {
  26. clrsetbits_le32(&regs->ctrl, I2S_CTRL_XFER_EN_TX,
  27. on ? I2S_CTRL_XFER_EN_TX : 0);
  28. }
  29. static int i2s_tx_init(struct i2s_uc_priv *pi2s_tx)
  30. {
  31. struct i2s_ctlr *regs = (struct i2s_ctlr *)pi2s_tx->base_address;
  32. u32 audio_bits = (pi2s_tx->bitspersample >> 2) - 1;
  33. u32 ctrl = readl(&regs->ctrl);
  34. /* Set format to LRCK / Left Low */
  35. ctrl &= ~(I2S_CTRL_FRAME_FORMAT_MASK | I2S_CTRL_LRCK_MASK);
  36. ctrl |= I2S_CTRL_FRAME_FORMAT_LRCK;
  37. ctrl |= I2S_CTRL_LRCK_L_LOW;
  38. /* Disable all transmission until we are ready to transfer */
  39. ctrl &= ~(I2S_CTRL_XFER_EN_TX | I2S_CTRL_XFER_EN_RX);
  40. /* Serve as master */
  41. ctrl |= I2S_CTRL_MASTER_ENABLE;
  42. /* Configure audio bits size */
  43. ctrl &= ~I2S_CTRL_BIT_SIZE_MASK;
  44. ctrl |= audio_bits << I2S_CTRL_BIT_SIZE_SHIFT;
  45. writel(ctrl, &regs->ctrl);
  46. /* Timing in LRCK mode: */
  47. writel(pi2s_tx->bitspersample, &regs->timing);
  48. /* I2S mode has [TX/RX]_DATA_OFFSET both set to 1 */
  49. writel(((1 << I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
  50. (1 << I2S_OFFSET_TX_DATA_OFFSET_SHIFT)), &regs->offset);
  51. /* FSYNC_WIDTH = 2 clocks wide, TOTAL_SLOTS = 2 slots per fsync */
  52. writel((2 - 1) << I2S_CH_CTRL_FSYNC_WIDTH_SHIFT, &regs->ch_ctrl);
  53. return 0;
  54. }
  55. static int tegra_i2s_tx_data(struct udevice *dev, void *data, uint data_size)
  56. {
  57. struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
  58. struct i2s_ctlr *regs = (struct i2s_ctlr *)priv->base_address;
  59. int ret;
  60. tegra_i2s_transmit_enable(regs, 1);
  61. ret = misc_write(dev_get_parent(dev), 0, data, data_size);
  62. tegra_i2s_transmit_enable(regs, 0);
  63. if (ret < 0)
  64. return ret;
  65. else if (ret < data_size)
  66. return -EIO;
  67. return 0;
  68. }
  69. static int tegra_i2s_probe(struct udevice *dev)
  70. {
  71. struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
  72. ulong base;
  73. base = dev_read_addr(dev);
  74. if (base == FDT_ADDR_T_NONE) {
  75. debug("%s: Missing i2s base\n", __func__);
  76. return -EINVAL;
  77. }
  78. priv->base_address = base;
  79. priv->id = 1;
  80. priv->audio_pll_clk = 4800000;
  81. priv->samplingrate = 48000;
  82. priv->bitspersample = 16;
  83. priv->channels = 2;
  84. priv->rfs = 256;
  85. priv->bfs = 32;
  86. return i2s_tx_init(priv);
  87. }
  88. static const struct i2s_ops tegra_i2s_ops = {
  89. .tx_data = tegra_i2s_tx_data,
  90. };
  91. static const struct udevice_id tegra_i2s_ids[] = {
  92. { .compatible = "nvidia,tegra124-i2s" },
  93. { }
  94. };
  95. U_BOOT_DRIVER(tegra_i2s) = {
  96. .name = "tegra_i2s",
  97. .id = UCLASS_I2S,
  98. .of_match = tegra_i2s_ids,
  99. .probe = tegra_i2s_probe,
  100. .ops = &tegra_i2s_ops,
  101. };