| OLD | NEW |
| 1 /* | 1 /* |
| 2 * linux/sound/soc/ep93xx-i2s.c | 2 * linux/sound/soc/ep93xx-i2s.c |
| 3 * EP93xx I2S driver | 3 * EP93xx I2S driver |
| 4 * | 4 * |
| 5 * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> | 5 * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> |
| 6 * | 6 * |
| 7 * Based on the original driver by: | 7 * Based on the original driver by: |
| 8 * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail> | 8 * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail> |
| 9 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> | 9 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> |
| 10 * | 10 * |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 default: | 260 default: |
| 261 return -EINVAL; | 261 return -EINVAL; |
| 262 } | 262 } |
| 263 | 263 |
| 264 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 264 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 265 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); | 265 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); |
| 266 else | 266 else |
| 267 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); | 267 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); |
| 268 | 268 |
| 269 /* | 269 /* |
| 270 » * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values. | 270 » * EP93xx I2S module can be setup so SCLK / LRCLK value can be |
| 271 » * If the lrclk is pulse length is larger than the word size, then the | 271 » * 32, 64, 128. MCLK / SCLK value can be 2 and 4. |
| 272 » * bit clock will be gated for the unused bits. | 272 » * We set LRCLK equal to `rate' and minimum SCLK / LRCLK |
| 273 » * value is 64, because our sample size is 32 bit * 2 channels. |
| 274 » * I2S standard permits us to transmit more bits than |
| 275 » * the codec uses. |
| 273 */ | 276 */ |
| 274 » div = (clk_get_rate(info->mclk) / params_rate(params)) * | 277 » div = clk_get_rate(info->mclk) / params_rate(params); |
| 275 » » params_channels(params); | |
| 276 for (sdiv = 2; sdiv <= 4; sdiv += 2) | 278 for (sdiv = 2; sdiv <= 4; sdiv += 2) |
| 277 » » for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1) | 279 » » for (lrdiv = 64; lrdiv <= 128; lrdiv <<= 1) |
| 278 if (sdiv * lrdiv == div) { | 280 if (sdiv * lrdiv == div) { |
| 279 found = 1; | 281 found = 1; |
| 280 goto out; | 282 goto out; |
| 281 } | 283 } |
| 282 out: | 284 out: |
| 283 if (!found) | 285 if (!found) |
| 284 return -EINVAL; | 286 return -EINVAL; |
| 285 | 287 |
| 286 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); | 288 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); |
| 287 if (err) | 289 if (err) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 #endif | 336 #endif |
| 335 | 337 |
| 336 static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { | 338 static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { |
| 337 .startup = ep93xx_i2s_startup, | 339 .startup = ep93xx_i2s_startup, |
| 338 .shutdown = ep93xx_i2s_shutdown, | 340 .shutdown = ep93xx_i2s_shutdown, |
| 339 .hw_params = ep93xx_i2s_hw_params, | 341 .hw_params = ep93xx_i2s_hw_params, |
| 340 .set_sysclk = ep93xx_i2s_set_sysclk, | 342 .set_sysclk = ep93xx_i2s_set_sysclk, |
| 341 .set_fmt = ep93xx_i2s_set_dai_fmt, | 343 .set_fmt = ep93xx_i2s_set_dai_fmt, |
| 342 }; | 344 }; |
| 343 | 345 |
| 344 #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 346 #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) |
| 345 » » » SNDRV_PCM_FMTBIT_S24_LE | \ | |
| 346 » » » SNDRV_PCM_FMTBIT_S32_LE) | |
| 347 | 347 |
| 348 static struct snd_soc_dai_driver ep93xx_i2s_dai = { | 348 static struct snd_soc_dai_driver ep93xx_i2s_dai = { |
| 349 .symmetric_rates= 1, | 349 .symmetric_rates= 1, |
| 350 .suspend = ep93xx_i2s_suspend, | 350 .suspend = ep93xx_i2s_suspend, |
| 351 .resume = ep93xx_i2s_resume, | 351 .resume = ep93xx_i2s_resume, |
| 352 .playback = { | 352 .playback = { |
| 353 .channels_min = 2, | 353 .channels_min = 2, |
| 354 .channels_max = 2, | 354 .channels_max = 2, |
| 355 » » .rates» » = SNDRV_PCM_RATE_8000_48000, | 355 » » .rates» » = SNDRV_PCM_RATE_8000_96000, |
| 356 .formats = EP93XX_I2S_FORMATS, | 356 .formats = EP93XX_I2S_FORMATS, |
| 357 }, | 357 }, |
| 358 .capture = { | 358 .capture = { |
| 359 .channels_min = 2, | 359 .channels_min = 2, |
| 360 .channels_max = 2, | 360 .channels_max = 2, |
| 361 » » .rates»» = SNDRV_PCM_RATE_8000_48000, | 361 » » .rates»» = SNDRV_PCM_RATE_8000_96000, |
| 362 .formats = EP93XX_I2S_FORMATS, | 362 .formats = EP93XX_I2S_FORMATS, |
| 363 }, | 363 }, |
| 364 .ops = &ep93xx_i2s_dai_ops, | 364 .ops = &ep93xx_i2s_dai_ops, |
| 365 }; | 365 }; |
| 366 | 366 |
| 367 static int ep93xx_i2s_probe(struct platform_device *pdev) | 367 static int ep93xx_i2s_probe(struct platform_device *pdev) |
| 368 { | 368 { |
| 369 struct ep93xx_i2s_info *info; | 369 struct ep93xx_i2s_info *info; |
| 370 struct resource *res; | 370 struct resource *res; |
| 371 int err; | 371 int err; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 platform_driver_unregister(&ep93xx_i2s_driver); | 470 platform_driver_unregister(&ep93xx_i2s_driver); |
| 471 } | 471 } |
| 472 | 472 |
| 473 module_init(ep93xx_i2s_init); | 473 module_init(ep93xx_i2s_init); |
| 474 module_exit(ep93xx_i2s_exit); | 474 module_exit(ep93xx_i2s_exit); |
| 475 | 475 |
| 476 MODULE_ALIAS("platform:ep93xx-i2s"); | 476 MODULE_ALIAS("platform:ep93xx-i2s"); |
| 477 MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); | 477 MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>"); |
| 478 MODULE_DESCRIPTION("EP93XX I2S driver"); | 478 MODULE_DESCRIPTION("EP93XX I2S driver"); |
| 479 MODULE_LICENSE("GPL"); | 479 MODULE_LICENSE("GPL"); |
| OLD | NEW |