On Wed, Nov 22, 2017 at 12:54:26AM +0100, Maciej S. Szmigiero wrote: > We need to make sure that only proper channel slots (in SACCST register) > are enabled at playback start time since some AC'97 CODECs (like VT1613 on > UDOO board) were observed requesting via SLOTREQ spurious ones just after > an AC'97 link is started but before the CODEC is configured by its driver. > When a bit for some channel slot is set in a SLOTREQ request then SSI sets > the relevant bit in SACCST automatically, which then 'sticks' until it is > manually unset. > The SACCST register is not writable directly, we have to use SACCDIS and > SACCEN registers to configure it instead (these aren't normal registers: > writing a '1' bit at some position in SACCEN sets the relevant bit in > SACCST; SACCDIS operates in a similar way but allows unsetting bits in > SACCST). > > Theoretically, this should be necessary only for the very first playback > but since some CODECs are so untrustworthy and extra channel slots enabled > mean ruined playback let's play safe here and make sure that no extra > slots are enabled in SACCST every time a playback is started. > > Signed-off-by: Maciej S. Szmigiero <mail@xxxxxxxxxxxxxxxxxxxxx> The inline comments feel over descriptive but not critical. Anyway, I plan to do some clean up to this driver after all pending changes get finalized. So, Acked-by: Nicolin Chen <nicoleotsuka@xxxxxxxxx> > --- > Changes from v1: Split out this part from > "fsl_ssi: call _fsl_ssi_set_dai_fmt() just once in AC'97 mode" commit, > describe the problem and its solution better both in the commit message and > in the code, move the SACCST setup code into a separate function and call > it from TX config instead of doing it from trigger handler function. > > sound/soc/fsl/fsl_ssi.c | 52 +++++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 46 insertions(+), 6 deletions(-) > > diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c > index 48bb850a34d9..375aaaf6080d 100644 > --- a/sound/soc/fsl/fsl_ssi.c > +++ b/sound/soc/fsl/fsl_ssi.c > @@ -574,8 +574,54 @@ static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable) > fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx); > } > > +static void fsl_ssi_tx_ac97_saccst_setup(struct fsl_ssi_private *ssi_private) > +{ > + struct regmap *regs = ssi_private->regs; > + > + /* no SACC{ST,EN,DIS} regs on imx21-class SSI */ > + if (!ssi_private->soc->imx21regs) { > + /* > + * Note that these below aren't just normal registers. > + * They are a way to disable or enable bits in SACCST > + * register: > + * - writing a '1' bit at some position in SACCEN sets the > + * relevant bit in SACCST, > + * - writing a '1' bit at some position in SACCDIS unsets > + * the relevant bit in SACCST register. > + * > + * The two writes below first disable all channels slots, > + * then enable just slots 3 & 4 ("PCM Playback Left Channel" > + * and "PCM Playback Right Channel"). > + */ > + regmap_write(regs, CCSR_SSI_SACCDIS, 0xff); > + regmap_write(regs, CCSR_SSI_SACCEN, 0x300); > + } > +} > + > static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) > { > + /* > + * Why are we setting up SACCST everytime we are starting a > + * playback? > + * Some CODECs (like VT1613 CODEC on UDOO board) like to > + * (sometimes) set extra bits in their SLOTREQ requests. > + * When a bit is set in a SLOTREQ request then SSI sets the > + * relevant bit in SACCST automatically (it is enough if a bit was > + * set in a SLOTREQ just once, bits in SACCST are 'sticky'). > + * If an extra slot gets enabled that's a disaster for playback > + * because some of normal left or right channel samples are > + * redirected instead to this extra slot. > + * > + * A workaround implemented in fsl-asoc-card of setting an > + * appropriate CODEC register so that slots 3 & 4 (the normal > + * stereo playback slots) are used for S/PDIF seems to mostly fix > + * this issue on the UDOO board but since this CODEC is so > + * untrustworthy let's play safe here and make sure that no extra > + * slots are enabled every time a playback is started. > + */ > + if (enable && fsl_ssi_is_ac97(ssi_private)) > + fsl_ssi_tx_ac97_saccst_setup(ssi_private); > + > fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); > } > > @@ -630,12 +676,6 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) > regmap_write(regs, CCSR_SSI_SACNT, > CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV); > > - /* no SACC{ST,EN,DIS} regs on imx21-class SSI */ > - if (!ssi_private->soc->imx21regs) { > - regmap_write(regs, CCSR_SSI_SACCDIS, 0xff); > - regmap_write(regs, CCSR_SSI_SACCEN, 0x300); > - } > - > /* > * Enable SSI, Transmit and Receive. AC97 has to communicate with the > * codec before a stream is started. > > _______________________________________________ > Alsa-devel mailing list > Alsa-devel@xxxxxxxxxxxxxxxx > http://mailman.alsa-project.org/mailman/listinfo/alsa-devel _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel