1
2
3
4
5
6#define LOG_CATEGORY UCLASS_I2S
7#define LOG_DEBUG
8
9#include <common.h>
10#include <dm.h>
11#include <i2s.h>
12#include <log.h>
13#include <misc.h>
14#include <sound.h>
15#include <asm/io.h>
16#include <asm/arch-tegra/tegra_i2s.h>
17#include "tegra_i2s_priv.h"
18
19int tegra_i2s_set_cif_tx_ctrl(struct udevice *dev, u32 value)
20{
21 struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
22 struct i2s_ctlr *regs = (struct i2s_ctlr *)priv->base_address;
23
24 writel(value, ®s->cif_tx_ctrl);
25
26 return 0;
27}
28
29static void tegra_i2s_transmit_enable(struct i2s_ctlr *regs, int on)
30{
31 clrsetbits_le32(®s->ctrl, I2S_CTRL_XFER_EN_TX,
32 on ? I2S_CTRL_XFER_EN_TX : 0);
33}
34
35static int i2s_tx_init(struct i2s_uc_priv *pi2s_tx)
36{
37 struct i2s_ctlr *regs = (struct i2s_ctlr *)pi2s_tx->base_address;
38 u32 audio_bits = (pi2s_tx->bitspersample >> 2) - 1;
39 u32 ctrl = readl(®s->ctrl);
40
41
42 ctrl &= ~(I2S_CTRL_FRAME_FORMAT_MASK | I2S_CTRL_LRCK_MASK);
43 ctrl |= I2S_CTRL_FRAME_FORMAT_LRCK;
44 ctrl |= I2S_CTRL_LRCK_L_LOW;
45
46
47 ctrl &= ~(I2S_CTRL_XFER_EN_TX | I2S_CTRL_XFER_EN_RX);
48
49
50 ctrl |= I2S_CTRL_MASTER_ENABLE;
51
52
53 ctrl &= ~I2S_CTRL_BIT_SIZE_MASK;
54 ctrl |= audio_bits << I2S_CTRL_BIT_SIZE_SHIFT;
55 writel(ctrl, ®s->ctrl);
56
57
58 writel(pi2s_tx->bitspersample, ®s->timing);
59
60
61 writel(((1 << I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
62 (1 << I2S_OFFSET_TX_DATA_OFFSET_SHIFT)), ®s->offset);
63
64
65 writel((2 - 1) << I2S_CH_CTRL_FSYNC_WIDTH_SHIFT, ®s->ch_ctrl);
66
67 return 0;
68}
69
70static int tegra_i2s_tx_data(struct udevice *dev, void *data, uint data_size)
71{
72 struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
73 struct i2s_ctlr *regs = (struct i2s_ctlr *)priv->base_address;
74 int ret;
75
76 tegra_i2s_transmit_enable(regs, 1);
77 ret = misc_write(dev_get_parent(dev), 0, data, data_size);
78 tegra_i2s_transmit_enable(regs, 0);
79 if (ret < 0)
80 return ret;
81 else if (ret < data_size)
82 return -EIO;
83
84 return 0;
85}
86
87static int tegra_i2s_probe(struct udevice *dev)
88{
89 struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
90 ulong base;
91
92 base = dev_read_addr(dev);
93 if (base == FDT_ADDR_T_NONE) {
94 debug("%s: Missing i2s base\n", __func__);
95 return -EINVAL;
96 }
97 priv->base_address = base;
98 priv->id = 1;
99 priv->audio_pll_clk = 4800000;
100 priv->samplingrate = 48000;
101 priv->bitspersample = 16;
102 priv->channels = 2;
103 priv->rfs = 256;
104 priv->bfs = 32;
105
106 return i2s_tx_init(priv);
107}
108
109static const struct i2s_ops tegra_i2s_ops = {
110 .tx_data = tegra_i2s_tx_data,
111};
112
113static const struct udevice_id tegra_i2s_ids[] = {
114 { .compatible = "nvidia,tegra124-i2s" },
115 { }
116};
117
118U_BOOT_DRIVER(tegra_i2s) = {
119 .name = "tegra_i2s",
120 .id = UCLASS_I2S,
121 .of_match = tegra_i2s_ids,
122 .probe = tegra_i2s_probe,
123 .ops = &tegra_i2s_ops,
124};
125