diff options
| -rw-r--r-- | include/linux/atmel-ssc.h | 12 | ||||
| -rw-r--r-- | sound/soc/atmel/atmel_ssc_dai.c | 34 |
2 files changed, 30 insertions, 16 deletions
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h index e8dd40873d55..7c0f6549898b 100644 --- a/include/linux/atmel-ssc.h +++ b/include/linux/atmel-ssc.h | |||
| @@ -72,6 +72,12 @@ void ssc_free(struct ssc_device *ssc); | |||
| 72 | #define SSC_RFMR_DATNB_OFFSET 8 | 72 | #define SSC_RFMR_DATNB_OFFSET 8 |
| 73 | #define SSC_RFMR_FSEDGE_SIZE 1 | 73 | #define SSC_RFMR_FSEDGE_SIZE 1 |
| 74 | #define SSC_RFMR_FSEDGE_OFFSET 24 | 74 | #define SSC_RFMR_FSEDGE_OFFSET 24 |
| 75 | /* | ||
| 76 | * The FSLEN_EXT exist on at91sam9rl, at91sam9g10, | ||
| 77 | * at91sam9g20, and at91sam9g45 and newer SoCs | ||
| 78 | */ | ||
| 79 | #define SSC_RFMR_FSLEN_EXT_SIZE 4 | ||
| 80 | #define SSC_RFMR_FSLEN_EXT_OFFSET 28 | ||
| 75 | #define SSC_RFMR_FSLEN_SIZE 4 | 81 | #define SSC_RFMR_FSLEN_SIZE 4 |
| 76 | #define SSC_RFMR_FSLEN_OFFSET 16 | 82 | #define SSC_RFMR_FSLEN_OFFSET 16 |
| 77 | #define SSC_RFMR_FSOS_SIZE 4 | 83 | #define SSC_RFMR_FSOS_SIZE 4 |
| @@ -110,6 +116,12 @@ void ssc_free(struct ssc_device *ssc); | |||
| 110 | #define SSC_TFMR_FSDEN_OFFSET 23 | 116 | #define SSC_TFMR_FSDEN_OFFSET 23 |
| 111 | #define SSC_TFMR_FSEDGE_SIZE 1 | 117 | #define SSC_TFMR_FSEDGE_SIZE 1 |
| 112 | #define SSC_TFMR_FSEDGE_OFFSET 24 | 118 | #define SSC_TFMR_FSEDGE_OFFSET 24 |
| 119 | /* | ||
| 120 | * The FSLEN_EXT exist on at91sam9rl, at91sam9g10, | ||
| 121 | * at91sam9g20, and at91sam9g45 and newer SoCs | ||
| 122 | */ | ||
| 123 | #define SSC_TFMR_FSLEN_EXT_SIZE 4 | ||
| 124 | #define SSC_TFMR_FSLEN_EXT_OFFSET 28 | ||
| 113 | #define SSC_TFMR_FSLEN_SIZE 4 | 125 | #define SSC_TFMR_FSLEN_SIZE 4 |
| 114 | #define SSC_TFMR_FSLEN_OFFSET 16 | 126 | #define SSC_TFMR_FSLEN_OFFSET 16 |
| 115 | #define SSC_TFMR_FSOS_SIZE 3 | 127 | #define SSC_TFMR_FSOS_SIZE 3 |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index de433cfd044c..f403f399808a 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
| @@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 347 | u32 tfmr, rfmr, tcmr, rcmr; | 347 | u32 tfmr, rfmr, tcmr, rcmr; |
| 348 | int start_event; | 348 | int start_event; |
| 349 | int ret; | 349 | int ret; |
| 350 | int fslen, fslen_ext; | ||
| 350 | 351 | ||
| 351 | /* | 352 | /* |
| 352 | * Currently, there is only one set of dma params for | 353 | * Currently, there is only one set of dma params for |
| @@ -388,18 +389,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 388 | } | 389 | } |
| 389 | 390 | ||
| 390 | /* | 391 | /* |
| 391 | * The SSC only supports up to 16-bit samples in I2S format, due | ||
| 392 | * to the size of the Frame Mode Register FSLEN field. | ||
| 393 | */ | ||
| 394 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S | ||
| 395 | && bits > 16) { | ||
| 396 | printk(KERN_WARNING | ||
| 397 | "atmel_ssc_dai: sample size %d " | ||
| 398 | "is too large for I2S\n", bits); | ||
| 399 | return -EINVAL; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* | ||
| 403 | * Compute SSC register settings. | 392 | * Compute SSC register settings. |
| 404 | */ | 393 | */ |
| 405 | switch (ssc_p->daifmt | 394 | switch (ssc_p->daifmt |
| @@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 413 | * from the MCK divider, and the BCLK signal | 402 | * from the MCK divider, and the BCLK signal |
| 414 | * is output on the SSC TK line. | 403 | * is output on the SSC TK line. |
| 415 | */ | 404 | */ |
| 405 | |||
| 406 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | ||
| 407 | dev_err(dai->dev, | ||
| 408 | "sample size %d is too large for SSC device\n", | ||
| 409 | bits); | ||
| 410 | return -EINVAL; | ||
| 411 | } | ||
| 412 | |||
| 413 | fslen_ext = (bits - 1) / 16; | ||
| 414 | fslen = (bits - 1) % 16; | ||
| 415 | |||
| 416 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | 416 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
| 417 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 417 | | SSC_BF(RCMR_STTDLY, START_DELAY) |
| 418 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | 418 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
| @@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 420 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | 420 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
| 421 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | 421 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); |
| 422 | 422 | ||
| 423 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 423 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) |
| 424 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
| 424 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | 425 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
| 425 | | SSC_BF(RFMR_FSLEN, (bits - 1)) | 426 | | SSC_BF(RFMR_FSLEN, fslen) |
| 426 | | SSC_BF(RFMR_DATNB, (channels - 1)) | 427 | | SSC_BF(RFMR_DATNB, (channels - 1)) |
| 427 | | SSC_BIT(RFMR_MSBF) | 428 | | SSC_BIT(RFMR_MSBF) |
| 428 | | SSC_BF(RFMR_LOOP, 0) | 429 | | SSC_BF(RFMR_LOOP, 0) |
| @@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
| 435 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | 436 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
| 436 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | 437 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); |
| 437 | 438 | ||
| 438 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 439 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) |
| 440 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
| 439 | | SSC_BF(TFMR_FSDEN, 0) | 441 | | SSC_BF(TFMR_FSDEN, 0) |
| 440 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | 442 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
| 441 | | SSC_BF(TFMR_FSLEN, (bits - 1)) | 443 | | SSC_BF(TFMR_FSLEN, fslen) |
| 442 | | SSC_BF(TFMR_DATNB, (channels - 1)) | 444 | | SSC_BF(TFMR_DATNB, (channels - 1)) |
| 443 | | SSC_BIT(TFMR_MSBF) | 445 | | SSC_BIT(TFMR_MSBF) |
| 444 | | SSC_BF(TFMR_DATDEF, 0) | 446 | | SSC_BF(TFMR_DATDEF, 0) |
