aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2014-04-28 06:54:42 -0400
committerMark Brown <broonie@linaro.org>2014-05-20 18:02:22 -0400
commit65c961cc59345fa347173e5a1f5866bc866fd626 (patch)
tree5730034c7efc7cca2b7a378aff27d83cccb4a6f1
parent07a28dbe7ad8e72868239450ff796c90e621d46f (diff)
ASoC: fsl-ssi: Fix register values when disabling
The bits we have to clear when disabling are different when the other stream is still active. This patch fixes the calculation of new register values after disabling one stream. It also adds a more detailed description of the new register value calculation. Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Tested-By: Michael Grzeschik <mgr@pengutronix.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/fsl/fsl_ssi.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index fdb123d6817c..fadb264e4cbb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -490,6 +490,26 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
490} 490}
491 491
492/* 492/*
493 * Calculate the bits that have to be disabled for the current stream that is
494 * getting disabled. This keeps the bits enabled that are necessary for the
495 * second stream to work if 'stream_active' is true.
496 *
497 * Detailed calculation:
498 * These are the values that need to be active after disabling. For non-active
499 * second stream, this is 0:
500 * vals_stream * !!stream_active
501 *
502 * The following computes the overall differences between the setup for the
503 * to-disable stream and the active stream, a simple XOR:
504 * vals_disable ^ (vals_stream * !!(stream_active))
505 *
506 * The full expression adds a mask on all values we care about
507 */
508#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
509 ((vals_disable) & \
510 ((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active))))
511
512/*
493 * Enable/Disable a ssi configuration. You have to pass either 513 * Enable/Disable a ssi configuration. You have to pass either
494 * ssi_private->rxtx_reg_val.rx or tx as vals parameter. 514 * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
495 */ 515 */
@@ -501,6 +521,12 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
501 u32 scr_val = read_ssi(&ssi->scr); 521 u32 scr_val = read_ssi(&ssi->scr);
502 int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) + 522 int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
503 !!(scr_val & CCSR_SSI_SCR_RE); 523 !!(scr_val & CCSR_SSI_SCR_RE);
524 int keep_active;
525
526 if (nr_active_streams - 1 > 0)
527 keep_active = 1;
528 else
529 keep_active = 0;
504 530
505 /* Find the other direction values rx or tx which we do not want to 531 /* Find the other direction values rx or tx which we do not want to
506 * modify */ 532 * modify */
@@ -511,7 +537,8 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
511 537
512 /* If vals should be disabled, start with disabling the unit */ 538 /* If vals should be disabled, start with disabling the unit */
513 if (!enable) { 539 if (!enable) {
514 u32 scr = vals->scr & (vals->scr ^ avals->scr); 540 u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
541 keep_active);
515 write_ssi_mask(&ssi->scr, scr, 0); 542 write_ssi_mask(&ssi->scr, scr, 0);
516 } 543 }
517 544
@@ -522,7 +549,7 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
522 */ 549 */
523 if (ssi_private->offline_config) { 550 if (ssi_private->offline_config) {
524 if ((enable && !nr_active_streams) || 551 if ((enable && !nr_active_streams) ||
525 (!enable && nr_active_streams == 1)) 552 (!enable && !keep_active))
526 fsl_ssi_rxtx_config(ssi_private, enable); 553 fsl_ssi_rxtx_config(ssi_private, enable);
527 554
528 goto config_done; 555 goto config_done;
@@ -551,9 +578,12 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
551 */ 578 */
552 579
553 /* These assignments are simply vals without bits set in avals*/ 580 /* These assignments are simply vals without bits set in avals*/
554 sier = vals->sier & (vals->sier ^ avals->sier); 581 sier = fsl_ssi_disable_val(vals->sier, avals->sier,
555 srcr = vals->srcr & (vals->srcr ^ avals->srcr); 582 keep_active);
556 stcr = vals->stcr & (vals->stcr ^ avals->stcr); 583 srcr = fsl_ssi_disable_val(vals->srcr, avals->srcr,
584 keep_active);
585 stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
586 keep_active);
557 587
558 write_ssi_mask(&ssi->srcr, srcr, 0); 588 write_ssi_mask(&ssi->srcr, srcr, 0);
559 write_ssi_mask(&ssi->stcr, stcr, 0); 589 write_ssi_mask(&ssi->stcr, stcr, 0);