ASoC: atmel_ssc_dai: Match the CMR divider only in full duplex.
authorPeter Rosin <peda@axentia.se>
Fri, 24 Oct 2014 19:25:59 +0000 (21:25 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 3 Nov 2014 12:45:27 +0000 (12:45 +0000)
The CMR divider register is shared by playback and capture. The SSC driver
therefore tries to enforce rules so that the needed register content do
not conflict during simultaneous playback/capture. However, the
implementation also prevents changing the register content in
half-duplex scenarios, which is needed when using the OSS API.

Thus, only lock the divider if there is a stream in the other direction.

Fixes the below program to not fail with the atmel ssc dai in master mode.

int
main(void)
{
int fd;
int format;
int channels;
int speed;

if ((fd = open("/dev/dsp", O_WRONLY, 0)) == -1) {
perror("open");
return 1;
}
format = AFMT_S16_LE;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) == -1) {
perror("SNDCTL_DSP_SETFMT");
return 1;
}
channels = 2;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
perror("SNDCTL_DSP_CHANNELS");
return 1;
}
speed = 22025;
if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
perror("SNDCTL_DSP_SPEED");
return 1;
}
return 0;
}

Signed-off-by: Peter Rosin <peda@axentia.se>
Acked-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/atmel/atmel_ssc_dai.c

index f403f399808afc1431b6ad8a52a377329536707f..b1cc2a4a7fc0ec3c08a597e58ef5bc9e94d68d61 100644 (file)
@@ -310,7 +310,10 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
                 * transmit and receive, so if a value has already
                 * been set, it must match this value.
                 */
-               if (ssc_p->cmr_div == 0)
+               if (ssc_p->dir_mask !=
+                       (SSC_DIR_MASK_PLAYBACK | SSC_DIR_MASK_CAPTURE))
+                       ssc_p->cmr_div = div;
+               else if (ssc_p->cmr_div == 0)
                        ssc_p->cmr_div = div;
                else
                        if (div != ssc_p->cmr_div)