FILE
ep93xx-i2s.c
File preview with syntax highlighting.
linux-6.19.14/sound/soc/cirrus/ep93xx-i2s.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/sound/soc/ep93xx-i2s.c 4 * EP93xx I2S driver 5 * 6 * Copyright (C) 2010 Ryan Mallon 7 * 8 * Based on the original driver by: 9 * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail> 10 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 11 */ 12 13#include <linux/module.h> 14#include <linux/init.h> 15#include <linux/slab.h> 16#include <linux/clk.h> 17#include <linux/io.h> 18#include <linux/of.h> 19 20#include <sound/core.h> 21#include <sound/dmaengine_pcm.h> 22#include <sound/pcm.h> 23#include <sound/pcm_params.h> 24#include <sound/initval.h> 25#include <sound/soc.h> 26 27#include <linux/soc/cirrus/ep93xx.h> 28 29#include "ep93xx-pcm.h" 30 31#define EP93XX_I2S_TXCLKCFG 0x00 32#define EP93XX_I2S_RXCLKCFG 0x04 33#define EP93XX_I2S_GLSTS 0x08 34#define EP93XX_I2S_GLCTRL 0x0C 35 36#define EP93XX_I2S_I2STX0LFT 0x10 37#define EP93XX_I2S_I2STX0RT 0x14 38 39#define EP93XX_I2S_TXLINCTRLDATA 0x28 40#define EP93XX_I2S_TXCTRL 0x2C 41#define EP93XX_I2S_TXWRDLEN 0x30 42#define EP93XX_I2S_TX0EN 0x34 43 44#define EP93XX_I2S_RXLINCTRLDATA 0x58 45#define EP93XX_I2S_RXCTRL 0x5C 46#define EP93XX_I2S_RXWRDLEN 0x60 47#define EP93XX_I2S_RX0EN 0x64 48 49#define EP93XX_I2S_WRDLEN_16 (0 << 0) 50#define EP93XX_I2S_WRDLEN_24 (1 << 0) 51#define EP93XX_I2S_WRDLEN_32 (2 << 0) 52 53#define EP93XX_I2S_RXLINCTRLDATA_R_JUST BIT(1) /* Right justify */ 54 55#define EP93XX_I2S_TXLINCTRLDATA_R_JUST BIT(2) /* Right justify */ 56 57/* 58 * Transmit empty interrupt level select: 59 * 0 - Generate interrupt when FIFO is half empty 60 * 1 - Generate interrupt when FIFO is empty 61 */ 62#define EP93XX_I2S_TXCTRL_TXEMPTY_LVL BIT(0) 63#define EP93XX_I2S_TXCTRL_TXUFIE BIT(1) /* Transmit interrupt enable */ 64 65#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ 66#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ 67#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */ 68#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */ 69#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */ 70 71#define EP93XX_I2S_GLSTS_TX0_FIFO_FULL BIT(12) 72 73struct ep93xx_i2s_info { 74 struct clk *mclk; 75 struct clk *sclk; 76 struct clk *lrclk; 77 void __iomem *regs; 78 struct snd_dmaengine_dai_dma_data dma_params_rx; 79 struct snd_dmaengine_dai_dma_data dma_params_tx; 80}; 81 82static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info, 83 unsigned reg, unsigned val) 84{ 85 __raw_writel(val, info->regs + reg); 86} 87 88static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info, 89 unsigned reg) 90{ 91 return __raw_readl(info->regs + reg); 92} 93 94static int ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream) 95{ 96 unsigned base_reg; 97 int err; 98 99 if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && 100 (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { 101 /* Enable clocks */ 102 err = clk_prepare_enable(info->mclk); 103 if (err) 104 return err; 105 err = clk_prepare_enable(info->sclk); 106 if (err) { 107 clk_disable_unprepare(info->mclk); 108 return err; 109 } 110 err = clk_prepare_enable(info->lrclk); 111 if (err) { 112 clk_disable_unprepare(info->sclk); 113 clk_disable_unprepare(info->mclk); 114 return err; 115 } 116 117 /* Enable i2s */ 118 ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1); 119 } 120 121 /* Enable fifo */ 122 if (stream == SNDRV_PCM_STREAM_PLAYBACK) 123 base_reg = EP93XX_I2S_TX0EN; 124 else 125 base_reg = EP93XX_I2S_RX0EN; 126 ep93xx_i2s_write_reg(info, base_reg, 1); 127 128 /* Enable TX IRQs (FIFO empty or underflow) */ 129 if (IS_ENABLED(CONFIG_SND_EP93XX_SOC_I2S_WATCHDOG) && 130 stream == SNDRV_PCM_STREAM_PLAYBACK) 131 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCTRL, 132 EP93XX_I2S_TXCTRL_TXEMPTY_LVL | 133 EP93XX_I2S_TXCTRL_TXUFIE); 134 135 return 0; 136} 137 138static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) 139{ 140 unsigned base_reg; 141 142 /* Disable IRQs */ 143 if (IS_ENABLED(CONFIG_SND_EP93XX_SOC_I2S_WATCHDOG) && 144 stream == SNDRV_PCM_STREAM_PLAYBACK) 145 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCTRL, 0); 146 147 /* Disable fifo */ 148 if (stream == SNDRV_PCM_STREAM_PLAYBACK) 149 base_reg = EP93XX_I2S_TX0EN; 150 else 151 base_reg = EP93XX_I2S_RX0EN; 152 ep93xx_i2s_write_reg(info, base_reg, 0); 153 154 if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && 155 (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { 156 /* Disable i2s */ 157 ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0); 158 159 /* Disable clocks */ 160 clk_disable_unprepare(info->lrclk); 161 clk_disable_unprepare(info->sclk); 162 clk_disable_unprepare(info->mclk); 163 } 164} 165 166/* 167 * According to documentation I2S controller can handle underflow conditions 168 * just fine, but in reality the state machine is sometimes confused so that 169 * the whole stream is shifted by one byte. The watchdog below disables the TX 170 * FIFO, fills the buffer with zeroes and re-enables the FIFO. State machine 171 * is being reset and by filling the buffer we get some time before next 172 * underflow happens. 173 */ 174static irqreturn_t ep93xx_i2s_interrupt(int irq, void *dev_id) 175{ 176 struct ep93xx_i2s_info *info = dev_id; 177 178 /* Disable FIFO */ 179 ep93xx_i2s_write_reg(info, EP93XX_I2S_TX0EN, 0); 180 /* 181 * Fill TX FIFO with zeroes, this way we can defer next IRQs as much as 182 * possible and get more time for DMA to catch up. Actually there are 183 * only 8 samples in this FIFO, so even on 8kHz maximum deferral here is 184 * 1ms. 185 */ 186 while (!(ep93xx_i2s_read_reg(info, EP93XX_I2S_GLSTS) & 187 EP93XX_I2S_GLSTS_TX0_FIFO_FULL)) { 188 ep93xx_i2s_write_reg(info, EP93XX_I2S_I2STX0LFT, 0); 189 ep93xx_i2s_write_reg(info, EP93XX_I2S_I2STX0RT, 0); 190 } 191 /* Re-enable FIFO */ 192 ep93xx_i2s_write_reg(info, EP93XX_I2S_TX0EN, 1); 193 194 return IRQ_HANDLED; 195} 196 197static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai) 198{ 199 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); 200 201 snd_soc_dai_init_dma_data(dai, &info->dma_params_tx, 202 &info->dma_params_rx); 203 204 return 0; 205} 206 207static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, 208 struct snd_soc_dai *dai) 209{ 210 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); 211 212 return ep93xx_i2s_enable(info, substream->stream); 213} 214 215static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, 216 struct snd_soc_dai *dai) 217{ 218 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); 219 220 ep93xx_i2s_disable(info, substream->stream); 221} 222 223static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 224 unsigned int fmt) 225{ 226 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); 227 unsigned int clk_cfg; 228 unsigned int txlin_ctrl = 0; 229 unsigned int rxlin_ctrl = 0; 230 231 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); 232 233 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 234 case SND_SOC_DAIFMT_I2S: 235 clk_cfg |= EP93XX_I2S_CLKCFG_REL; 236 break; 237 238 case SND_SOC_DAIFMT_LEFT_J: 239 clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; 240 break; 241 242 case SND_SOC_DAIFMT_RIGHT_J: 243 clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; 244 rxlin_ctrl |= EP93XX_I2S_RXLINCTRLDATA_R_JUST; 245 txlin_ctrl |= EP93XX_I2S_TXLINCTRLDATA_R_JUST; 246 break; 247 248 default: 249 return -EINVAL; 250 } 251 252 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 253 case SND_SOC_DAIFMT_BP_FP: 254 /* CPU is provider */ 255 clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; 256 break; 257 258 case SND_SOC_DAIFMT_BC_FC: 259 /* Codec is provider */ 260 clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; 261 break; 262 263 default: 264 return -EINVAL; 265 } 266 267 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 268 case SND_SOC_DAIFMT_NB_NF: 269 /* Negative bit clock, lrclk low on left word */ 270 clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS); 271 break; 272 273 case SND_SOC_DAIFMT_NB_IF: 274 /* Negative bit clock, lrclk low on right word */ 275 clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; 276 clk_cfg |= EP93XX_I2S_CLKCFG_LRS; 277 break; 278 279 case SND_SOC_DAIFMT_IB_NF: 280 /* Positive bit clock, lrclk low on left word */ 281 clk_cfg |= EP93XX_I2S_CLKCFG_CKP; 282 clk_cfg &= ~EP93XX_I2S_CLKCFG_LRS; 283 break; 284 285 case SND_SOC_DAIFMT_IB_IF: 286 /* Positive bit clock, lrclk low on right word */ 287 clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS; 288 break; 289 } 290 291 /* Write new register values */ 292 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); 293 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); 294 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, rxlin_ctrl); 295 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, txlin_ctrl); 296 return 0; 297} 298 299static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, 300 struct snd_pcm_hw_params *params, 301 struct snd_soc_dai *dai) 302{ 303 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); 304 unsigned word_len, div, sdiv, lrdiv; 305 int err; 306 307 switch (params_format(params)) { 308 case SNDRV_PCM_FORMAT_S16_LE: 309 word_len = EP93XX_I2S_WRDLEN_16; 310 break; 311 312 case SNDRV_PCM_FORMAT_S24_LE: 313 word_len = EP93XX_I2S_WRDLEN_24; 314 break; 315 316 case SNDRV_PCM_FORMAT_S32_LE: 317 word_len = EP93XX_I2S_WRDLEN_32; 318 break; 319 320 default: 321 return -EINVAL; 322 } 323 324 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 325 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); 326 else 327 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); 328 329 /* 330 * EP93xx I2S module can be setup so SCLK / LRCLK value can be 331 * 32, 64, 128. MCLK / SCLK value can be 2 and 4. 332 * We set LRCLK equal to `rate' and minimum SCLK / LRCLK 333 * value is 64, because our sample size is 32 bit * 2 channels. 334 * I2S standard permits us to transmit more bits than 335 * the codec uses. 336 */ 337 div = clk_get_rate(info->mclk) / params_rate(params); 338 sdiv = 4; 339 if (div > (256 + 512) / 2) { 340 lrdiv = 128; 341 } else { 342 lrdiv = 64; 343 if (div < (128 + 256) / 2) 344 sdiv = 2; 345 } 346 347 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); 348 if (err) 349 return err; 350 351 err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv); 352 if (err) 353 return err; 354 355 return 0; 356} 357 358static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 359 unsigned int freq, int dir) 360{ 361 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); 362 363 if (dir == SND_SOC_CLOCK_IN || clk_id != 0) 364 return -EINVAL; 365 if (!freq) 366 return 0; 367 368 return clk_set_rate(info->mclk, freq); 369} 370 371#ifdef CONFIG_PM 372static int ep93xx_i2s_suspend(struct snd_soc_component *component) 373{ 374 struct ep93xx_i2s_info *info = snd_soc_component_get_drvdata(component); 375 376 if (!snd_soc_component_active(component)) 377 return 0; 378 379 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); 380 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); 381 382 return 0; 383} 384 385static int ep93xx_i2s_resume(struct snd_soc_component *component) 386{ 387 struct ep93xx_i2s_info *info = snd_soc_component_get_drvdata(component); 388 int err; 389 390 if (!snd_soc_component_active(component)) 391 return 0; 392 393 err = ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); 394 if (err) 395 return err; 396 397 return ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); 398} 399#else 400#define ep93xx_i2s_suspend NULL 401#define ep93xx_i2s_resume NULL 402#endif 403 404static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { 405 .probe = ep93xx_i2s_dai_probe, 406 .startup = ep93xx_i2s_startup, 407 .shutdown = ep93xx_i2s_shutdown, 408 .hw_params = ep93xx_i2s_hw_params, 409 .set_sysclk = ep93xx_i2s_set_sysclk, 410 .set_fmt = ep93xx_i2s_set_dai_fmt, 411}; 412 413#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) 414 415static struct snd_soc_dai_driver ep93xx_i2s_dai = { 416 .symmetric_rate = 1, 417 .playback = { 418 .channels_min = 2, 419 .channels_max = 2, 420 .rates = SNDRV_PCM_RATE_8000_192000, 421 .formats = EP93XX_I2S_FORMATS, 422 }, 423 .capture = { 424 .channels_min = 2, 425 .channels_max = 2, 426 .rates = SNDRV_PCM_RATE_8000_192000, 427 .formats = EP93XX_I2S_FORMATS, 428 }, 429 .ops = &ep93xx_i2s_dai_ops, 430}; 431 432static const struct snd_soc_component_driver ep93xx_i2s_component = { 433 .name = "ep93xx-i2s", 434 .suspend = ep93xx_i2s_suspend, 435 .resume = ep93xx_i2s_resume, 436 .legacy_dai_naming = 1, 437}; 438 439static int ep93xx_i2s_probe(struct platform_device *pdev) 440{ 441 struct ep93xx_i2s_info *info; 442 int err; 443 444 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 445 if (!info) 446 return -ENOMEM; 447 448 info->regs = devm_platform_ioremap_resource(pdev, 0); 449 if (IS_ERR(info->regs)) 450 return PTR_ERR(info->regs); 451 452 if (IS_ENABLED(CONFIG_SND_EP93XX_SOC_I2S_WATCHDOG)) { 453 int irq = platform_get_irq(pdev, 0); 454 if (irq <= 0) 455 return irq < 0 ? irq : -ENODEV; 456 457 err = devm_request_irq(&pdev->dev, irq, ep93xx_i2s_interrupt, 0, 458 pdev->name, info); 459 if (err) 460 return err; 461 } 462 463 info->mclk = clk_get(&pdev->dev, "mclk"); 464 if (IS_ERR(info->mclk)) { 465 err = PTR_ERR(info->mclk); 466 goto fail; 467 } 468 469 info->sclk = clk_get(&pdev->dev, "sclk"); 470 if (IS_ERR(info->sclk)) { 471 err = PTR_ERR(info->sclk); 472 goto fail_put_mclk; 473 } 474 475 info->lrclk = clk_get(&pdev->dev, "lrclk"); 476 if (IS_ERR(info->lrclk)) { 477 err = PTR_ERR(info->lrclk); 478 goto fail_put_sclk; 479 } 480 481 dev_set_drvdata(&pdev->dev, info); 482 483 err = devm_snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, 484 &ep93xx_i2s_dai, 1); 485 if (err) 486 goto fail_put_lrclk; 487 488 err = devm_ep93xx_pcm_platform_register(&pdev->dev); 489 if (err) 490 goto fail_put_lrclk; 491 492 return 0; 493 494fail_put_lrclk: 495 clk_put(info->lrclk); 496fail_put_sclk: 497 clk_put(info->sclk); 498fail_put_mclk: 499 clk_put(info->mclk); 500fail: 501 return err; 502} 503 504static void ep93xx_i2s_remove(struct platform_device *pdev) 505{ 506 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); 507 508 clk_put(info->lrclk); 509 clk_put(info->sclk); 510 clk_put(info->mclk); 511} 512 513static const struct of_device_id ep93xx_i2s_of_ids[] = { 514 { .compatible = "cirrus,ep9301-i2s" }, 515 {} 516}; 517MODULE_DEVICE_TABLE(of, ep93xx_i2s_of_ids); 518 519static struct platform_driver ep93xx_i2s_driver = { 520 .probe = ep93xx_i2s_probe, 521 .remove = ep93xx_i2s_remove, 522 .driver = { 523 .name = "ep93xx-i2s", 524 .of_match_table = ep93xx_i2s_of_ids, 525 }, 526}; 527 528module_platform_driver(ep93xx_i2s_driver); 529 530MODULE_ALIAS("platform:ep93xx-i2s"); 531MODULE_AUTHOR("Ryan Mallon"); 532MODULE_DESCRIPTION("EP93XX I2S driver"); 533MODULE_LICENSE("GPL");
~/
Read-only file preview.