kirkwood-i2s.c (dbc517bf32985f2438ff706204a6dd1476b3dc98) | kirkwood-i2s.c (d8d11ba566761625e2b5ab716dca920725f3dc0b) |
---|---|
1/* 2 * kirkwood-i2s.c 3 * 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the --- 99 unchanged lines hidden (view full) --- 108 return 0; 109} 110 111static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, 112 struct snd_pcm_hw_params *params, 113 struct snd_soc_dai *dai) 114{ 115 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | 1/* 2 * kirkwood-i2s.c 3 * 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the --- 99 unchanged lines hidden (view full) --- 108 return 0; 109} 110 111static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, 112 struct snd_pcm_hw_params *params, 113 struct snd_soc_dai *dai) 114{ 115 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); |
116 unsigned int i2s_reg, reg; 117 unsigned long i2s_value, value; | 116 uint32_t ctl_play, ctl_rec; 117 unsigned int i2s_reg; 118 unsigned long i2s_value; |
118 119 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 120 i2s_reg = KIRKWOOD_I2S_PLAYCTL; | 119 120 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 121 i2s_reg = KIRKWOOD_I2S_PLAYCTL; |
121 reg = KIRKWOOD_PLAYCTL; | |
122 } else { 123 i2s_reg = KIRKWOOD_I2S_RECCTL; | 122 } else { 123 i2s_reg = KIRKWOOD_I2S_RECCTL; |
124 reg = KIRKWOOD_RECCTL; | |
125 } 126 127 /* set dco conf */ 128 kirkwood_set_dco(priv->io, params_rate(params)); 129 130 i2s_value = readl(priv->io+i2s_reg); 131 i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK; 132 | 124 } 125 126 /* set dco conf */ 127 kirkwood_set_dco(priv->io, params_rate(params)); 128 129 i2s_value = readl(priv->io+i2s_reg); 130 i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK; 131 |
133 value = readl(priv->io+reg); 134 value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK; 135 | |
136 /* 137 * Size settings in play/rec i2s control regs and play/rec control 138 * regs must be the same. 139 */ 140 switch (params_format(params)) { 141 case SNDRV_PCM_FORMAT_S16_LE: 142 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16; | 132 /* 133 * Size settings in play/rec i2s control regs and play/rec control 134 * regs must be the same. 135 */ 136 switch (params_format(params)) { 137 case SNDRV_PCM_FORMAT_S16_LE: 138 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16; |
143 value |= KIRKWOOD_PLAYCTL_SIZE_16_C; | 139 ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C | 140 KIRKWOOD_PLAYCTL_I2S_EN; 141 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C | 142 KIRKWOOD_RECCTL_I2S_EN; |
144 break; 145 /* 146 * doesn't work... S20_3LE != kirkwood 20bit format ? 147 * 148 case SNDRV_PCM_FORMAT_S20_3LE: 149 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20; | 143 break; 144 /* 145 * doesn't work... S20_3LE != kirkwood 20bit format ? 146 * 147 case SNDRV_PCM_FORMAT_S20_3LE: 148 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20; |
150 value |= KIRKWOOD_PLAYCTL_SIZE_20; | 149 ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 | 150 KIRKWOOD_PLAYCTL_I2S_EN; 151 ctl_rec = KIRKWOOD_RECCTL_SIZE_20 | 152 KIRKWOOD_RECCTL_I2S_EN; |
151 break; 152 */ 153 case SNDRV_PCM_FORMAT_S24_LE: 154 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24; | 153 break; 154 */ 155 case SNDRV_PCM_FORMAT_S24_LE: 156 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24; |
155 value |= KIRKWOOD_PLAYCTL_SIZE_24; | 157 ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 | 158 KIRKWOOD_PLAYCTL_I2S_EN; 159 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 | 160 KIRKWOOD_RECCTL_I2S_EN; |
156 break; 157 case SNDRV_PCM_FORMAT_S32_LE: 158 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; | 161 break; 162 case SNDRV_PCM_FORMAT_S32_LE: 163 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; |
159 value |= KIRKWOOD_PLAYCTL_SIZE_32; | 164 ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 | 165 KIRKWOOD_PLAYCTL_I2S_EN; 166 ctl_rec = KIRKWOOD_RECCTL_SIZE_32 | 167 KIRKWOOD_RECCTL_I2S_EN; |
160 break; 161 default: 162 return -EINVAL; 163 } 164 165 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 168 break; 169 default: 170 return -EINVAL; 171 } 172 173 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
166 value &= ~KIRKWOOD_PLAYCTL_MONO_MASK; | |
167 if (params_channels(params) == 1) | 174 if (params_channels(params) == 1) |
168 value |= KIRKWOOD_PLAYCTL_MONO_BOTH; | 175 ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH; |
169 else | 176 else |
170 value |= KIRKWOOD_PLAYCTL_MONO_OFF; | 177 ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; 178 179 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | 180 KIRKWOOD_PLAYCTL_I2S_EN | 181 KIRKWOOD_PLAYCTL_SPDIF_EN | 182 KIRKWOOD_PLAYCTL_SIZE_MASK); 183 priv->ctl_play |= ctl_play; 184 } else { 185 priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK; 186 priv->ctl_rec |= ctl_rec; |
171 } 172 173 writel(i2s_value, priv->io+i2s_reg); | 187 } 188 189 writel(i2s_value, priv->io+i2s_reg); |
174 writel(value, priv->io+reg); | |
175 176 return 0; 177} 178 179static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 180 int cmd, struct snd_soc_dai *dai) 181{ 182 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); --- 17 unchanged lines hidden (view full) --- 200 201 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) 202 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", 203 ctl); 204 } 205 206 switch (cmd) { 207 case SNDRV_PCM_TRIGGER_START: | 190 191 return 0; 192} 193 194static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 195 int cmd, struct snd_soc_dai *dai) 196{ 197 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); --- 17 unchanged lines hidden (view full) --- 215 216 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) 217 dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", 218 ctl); 219 } 220 221 switch (cmd) { 222 case SNDRV_PCM_TRIGGER_START: |
223 /* configure */ 224 ctl = priv->ctl_play; 225 value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN | 226 KIRKWOOD_PLAYCTL_SPDIF_EN); 227 writel(value, priv->io + KIRKWOOD_PLAYCTL); 228 229 /* enable interrupts */ |
|
208 value = readl(priv->io + KIRKWOOD_INT_MASK); 209 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; 210 writel(value, priv->io + KIRKWOOD_INT_MASK); 211 | 230 value = readl(priv->io + KIRKWOOD_INT_MASK); 231 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; 232 writel(value, priv->io + KIRKWOOD_INT_MASK); 233 |
212 /* configure audio & enable i2s playback */ 213 ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK; 214 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE 215 | KIRKWOOD_PLAYCTL_SPDIF_EN); 216 217 if (priv->burst == 32) 218 ctl |= KIRKWOOD_PLAYCTL_BURST_32; 219 else 220 ctl |= KIRKWOOD_PLAYCTL_BURST_128; 221 ctl |= KIRKWOOD_PLAYCTL_I2S_EN; | 234 /* enable playback */ |
222 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 223 break; 224 225 case SNDRV_PCM_TRIGGER_STOP: 226 /* stop audio, disable interrupts */ 227 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; 228 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 229 --- 24 unchanged lines hidden (view full) --- 254 255 return 0; 256} 257 258static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 259 int cmd, struct snd_soc_dai *dai) 260{ 261 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); | 235 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 236 break; 237 238 case SNDRV_PCM_TRIGGER_STOP: 239 /* stop audio, disable interrupts */ 240 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; 241 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 242 --- 24 unchanged lines hidden (view full) --- 267 268 return 0; 269} 270 271static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 272 int cmd, struct snd_soc_dai *dai) 273{ 274 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); |
262 unsigned long value; | 275 uint32_t ctl, value; |
263 264 value = readl(priv->io + KIRKWOOD_RECCTL); 265 266 switch (cmd) { 267 case SNDRV_PCM_TRIGGER_START: | 276 277 value = readl(priv->io + KIRKWOOD_RECCTL); 278 279 switch (cmd) { 280 case SNDRV_PCM_TRIGGER_START: |
281 /* configure */ 282 ctl = priv->ctl_rec; 283 value = ctl & ~KIRKWOOD_RECCTL_I2S_EN; 284 writel(value, priv->io + KIRKWOOD_RECCTL); 285 286 /* enable interrupts */ |
|
268 value = readl(priv->io + KIRKWOOD_INT_MASK); 269 value |= KIRKWOOD_INT_CAUSE_REC_BYTES; 270 writel(value, priv->io + KIRKWOOD_INT_MASK); 271 | 287 value = readl(priv->io + KIRKWOOD_INT_MASK); 288 value |= KIRKWOOD_INT_CAUSE_REC_BYTES; 289 writel(value, priv->io + KIRKWOOD_INT_MASK); 290 |
272 /* configure audio & enable i2s record */ 273 value = readl(priv->io + KIRKWOOD_RECCTL); 274 value &= ~KIRKWOOD_RECCTL_BURST_MASK; 275 value &= ~KIRKWOOD_RECCTL_MONO; 276 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE 277 | KIRKWOOD_RECCTL_SPDIF_EN); 278 279 if (priv->burst == 32) 280 value |= KIRKWOOD_RECCTL_BURST_32; 281 else 282 value |= KIRKWOOD_RECCTL_BURST_128; 283 value |= KIRKWOOD_RECCTL_I2S_EN; 284 285 writel(value, priv->io + KIRKWOOD_RECCTL); | 291 /* enable record */ 292 writel(ctl, priv->io + KIRKWOOD_RECCTL); |
286 break; 287 288 case SNDRV_PCM_TRIGGER_STOP: 289 /* stop audio, disable interrupts */ 290 value = readl(priv->io + KIRKWOOD_RECCTL); 291 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 292 writel(value, priv->io + KIRKWOOD_RECCTL); 293 --- 149 unchanged lines hidden (view full) --- 443 dev_err(&pdev->dev, "no clock\n"); 444 return PTR_ERR(priv->clk); 445 } 446 447 err = clk_prepare_enable(priv->clk); 448 if (err < 0) 449 return err; 450 | 293 break; 294 295 case SNDRV_PCM_TRIGGER_STOP: 296 /* stop audio, disable interrupts */ 297 value = readl(priv->io + KIRKWOOD_RECCTL); 298 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; 299 writel(value, priv->io + KIRKWOOD_RECCTL); 300 --- 149 unchanged lines hidden (view full) --- 450 dev_err(&pdev->dev, "no clock\n"); 451 return PTR_ERR(priv->clk); 452 } 453 454 err = clk_prepare_enable(priv->clk); 455 if (err < 0) 456 return err; 457 |
458 priv->extclk = clk_get(&pdev->dev, "extclk"); 459 if (!IS_ERR(priv->extclk)) { 460 if (priv->extclk == priv->clk) { 461 clk_put(priv->extclk); 462 priv->extclk = ERR_PTR(-EINVAL); 463 } else { 464 dev_info(&pdev->dev, "found external clock\n"); 465 clk_prepare_enable(priv->extclk); 466 soc_dai = &kirkwood_i2s_dai_extclk; 467 } 468 } 469 470 /* Some sensible defaults - this reflects the powerup values */ 471 priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24; 472 priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24; 473 474 /* Select the burst size */ 475 if (data->burst == 32) { 476 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32; 477 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32; 478 } else { 479 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128; 480 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; 481 } 482 |
|
451 err = snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai); 452 if (!err) 453 return 0; 454 dev_err(&pdev->dev, "snd_soc_register_dai failed\n"); 455 456 clk_disable_unprepare(priv->clk); 457 458 return err; --- 29 unchanged lines hidden --- | 483 err = snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai); 484 if (!err) 485 return 0; 486 dev_err(&pdev->dev, "snd_soc_register_dai failed\n"); 487 488 clk_disable_unprepare(priv->clk); 489 490 return err; --- 29 unchanged lines hidden --- |