aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra/tegra30_i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra/tegra30_i2s.c')
-rw-r--r--sound/soc/tegra/tegra30_i2s.c85
1 files changed, 43 insertions, 42 deletions
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 8596032985dc..b68e27a14608 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -44,18 +44,6 @@
44 44
45#define DRV_NAME "tegra30-i2s" 45#define DRV_NAME "tegra30-i2s"
46 46
47static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val)
48{
49 regmap_write(i2s->regmap, reg, val);
50}
51
52static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg)
53{
54 u32 val;
55 regmap_read(i2s->regmap, reg, &val);
56 return val;
57}
58
59static int tegra30_i2s_runtime_suspend(struct device *dev) 47static int tegra30_i2s_runtime_suspend(struct device *dev)
60{ 48{
61 struct tegra30_i2s *i2s = dev_get_drvdata(dev); 49 struct tegra30_i2s *i2s = dev_get_drvdata(dev);
@@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
128 unsigned int fmt) 116 unsigned int fmt)
129{ 117{
130 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); 118 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
119 unsigned int mask, val;
131 120
132 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 121 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
133 case SND_SOC_DAIFMT_NB_NF: 122 case SND_SOC_DAIFMT_NB_NF:
@@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
136 return -EINVAL; 125 return -EINVAL;
137 } 126 }
138 127
139 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE; 128 mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
140 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 129 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
141 case SND_SOC_DAIFMT_CBS_CFS: 130 case SND_SOC_DAIFMT_CBS_CFS:
142 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE; 131 val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
143 break; 132 break;
144 case SND_SOC_DAIFMT_CBM_CFM: 133 case SND_SOC_DAIFMT_CBM_CFM:
145 break; 134 break;
@@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
147 return -EINVAL; 136 return -EINVAL;
148 } 137 }
149 138
150 i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | 139 mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
151 TEGRA30_I2S_CTRL_LRCK_MASK); 140 TEGRA30_I2S_CTRL_LRCK_MASK;
152 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 141 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
153 case SND_SOC_DAIFMT_DSP_A: 142 case SND_SOC_DAIFMT_DSP_A:
154 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; 143 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
155 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 144 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
156 break; 145 break;
157 case SND_SOC_DAIFMT_DSP_B: 146 case SND_SOC_DAIFMT_DSP_B:
158 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; 147 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
159 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW; 148 val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
160 break; 149 break;
161 case SND_SOC_DAIFMT_I2S: 150 case SND_SOC_DAIFMT_I2S:
162 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; 151 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
163 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 152 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
164 break; 153 break;
165 case SND_SOC_DAIFMT_RIGHT_J: 154 case SND_SOC_DAIFMT_RIGHT_J:
166 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; 155 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
167 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 156 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
168 break; 157 break;
169 case SND_SOC_DAIFMT_LEFT_J: 158 case SND_SOC_DAIFMT_LEFT_J:
170 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; 159 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
171 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 160 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
172 break; 161 break;
173 default: 162 default:
174 return -EINVAL; 163 return -EINVAL;
175 } 164 }
176 165
166 pm_runtime_get_sync(dai->dev);
167 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
168 pm_runtime_put(dai->dev);
169
177 return 0; 170 return 0;
178} 171}
179 172
@@ -181,24 +174,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
181 struct snd_pcm_hw_params *params, 174 struct snd_pcm_hw_params *params,
182 struct snd_soc_dai *dai) 175 struct snd_soc_dai *dai)
183{ 176{
184 struct device *dev = substream->pcm->card->dev; 177 struct device *dev = dai->dev;
185 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); 178 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
186 u32 val; 179 unsigned int mask, val, reg;
187 int ret, sample_size, srate, i2sclock, bitcnt; 180 int ret, sample_size, srate, i2sclock, bitcnt;
188 181
189 if (params_channels(params) != 2) 182 if (params_channels(params) != 2)
190 return -EINVAL; 183 return -EINVAL;
191 184
192 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK; 185 mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
193 switch (params_format(params)) { 186 switch (params_format(params)) {
194 case SNDRV_PCM_FORMAT_S16_LE: 187 case SNDRV_PCM_FORMAT_S16_LE:
195 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16; 188 val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
196 sample_size = 16; 189 sample_size = 16;
197 break; 190 break;
198 default: 191 default:
199 return -EINVAL; 192 return -EINVAL;
200 } 193 }
201 194
195 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
196
202 srate = params_rate(params); 197 srate = params_rate(params);
203 198
204 /* Final "* 2" required by Tegra hardware */ 199 /* Final "* 2" required by Tegra hardware */
@@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
219 if (i2sclock % (2 * srate)) 214 if (i2sclock % (2 * srate))
220 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE; 215 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
221 216
222 tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val); 217 regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
223 218
224 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 219 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
225 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | 220 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
@@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
229 224
230 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 225 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
231 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; 226 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
232 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val); 227 reg = TEGRA30_I2S_CIF_RX_CTRL;
233 } else { 228 } else {
234 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; 229 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
235 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val); 230 reg = TEGRA30_I2S_CIF_RX_CTRL;
236 } 231 }
237 232
233 regmap_write(i2s->regmap, reg, val);
234
238 val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | 235 val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
239 (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); 236 (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
240 tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val); 237 regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
241 238
242 return 0; 239 return 0;
243} 240}
@@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
245static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s) 242static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
246{ 243{
247 tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif); 244 tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
248 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX; 245 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
249 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 246 TEGRA30_I2S_CTRL_XFER_EN_TX,
247 TEGRA30_I2S_CTRL_XFER_EN_TX);
250} 248}
251 249
252static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s) 250static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
253{ 251{
254 tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif); 252 tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
255 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX; 253 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
256 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 254 TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
257} 255}
258 256
259static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s) 257static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
260{ 258{
261 tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif); 259 tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
262 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX; 260 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
263 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 261 TEGRA30_I2S_CTRL_XFER_EN_RX,
262 TEGRA30_I2S_CTRL_XFER_EN_RX);
264} 263}
265 264
266static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s) 265static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
267{ 266{
268 tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif); 267 tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
269 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX; 268 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
270 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 269 TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
271} 270}
272 271
273static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 272static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -320,12 +319,14 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
320static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { 319static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
321 .probe = tegra30_i2s_probe, 320 .probe = tegra30_i2s_probe,
322 .playback = { 321 .playback = {
322 .stream_name = "Playback",
323 .channels_min = 2, 323 .channels_min = 2,
324 .channels_max = 2, 324 .channels_max = 2,
325 .rates = SNDRV_PCM_RATE_8000_96000, 325 .rates = SNDRV_PCM_RATE_8000_96000,
326 .formats = SNDRV_PCM_FMTBIT_S16_LE, 326 .formats = SNDRV_PCM_FMTBIT_S16_LE,
327 }, 327 },
328 .capture = { 328 .capture = {
329 .stream_name = "Capture",
329 .channels_min = 2, 330 .channels_min = 2,
330 .channels_max = 2, 331 .channels_max = 2,
331 .rates = SNDRV_PCM_RATE_8000_96000, 332 .rates = SNDRV_PCM_RATE_8000_96000,