diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 11:14:28 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 11:14:28 -0800 |
commit | ce38207f161513ee3d2bd3860489f07ebe65bc78 (patch) | |
tree | b3ad9e8a5e087b91d9f30a314c55df5fa70c142e /sound/soc/atmel/atmel_ssc_dai.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial (diff) | |
parent | ALSA: hiface: Fix M2Tech hiFace driver sampling rate change (diff) | |
download | linux-dev-ce38207f161513ee3d2bd3860489f07ebe65bc78.tar.xz linux-dev-ce38207f161513ee3d2bd3860489f07ebe65bc78.zip |
Merge tag 'sound-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"No dramatic changes are found in this development cycle, but as usual,
many commits are applied in a wide range of drivers.
Most of big changes are in ASoC, where a few bits of framework work
and quite a lot of cleanups and improvements to existing code have
been done. The rest are usual stuff, a few HD-audio and USB-audio
quirks and fixes, as well as the drop of kthread usages in the whole
subsystem.
Below are some highlights:
ASoC:
- support for stereo DAPM controls
- some initial work on the of-graph sound card
- regmap conversions of the remaining AC'97 drivers
- a new version of the topology ABI; this should be backward
compatible
- updates / cleanups of rsnd, sunxi, sti, nau8825, samsung, arizona,
Intel skylake, atom-sst
- new drivers for Cirrus Logic CS42L42, Qualcomm MSM8916-WCD, and
Realtek RT5665
USB-audio:
- yet another race fix at disconnection
- tolerated packet size calculation for some Android devices
- quirks for Axe-Fx II, QuickCam, TEAC 501/503
HD-audio:
- improvement of Dell pin fixup mapping
- quirks for HP Z1 Gen3, Alienware 15 R2 2016 and ALC622 headset mic
Misc:
- replace all kthread usages with simple works"
* tag 'sound-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (296 commits)
ALSA: hiface: Fix M2Tech hiFace driver sampling rate change
ALSA: usb-audio: Eliminate noise at the start of DSD playback.
ALSA: usb-audio: Add native DSD support for TEAC 501/503 DAC
ASoC: wm_adsp: wm_adsp_buf_alloc should use kfree in error path
ASoC: topology: avoid uninitialized kcontrol_type
ALSA: usb-audio: Add QuickCam Communicate Deluxe/S7500 to volume_control_quirks
ALSA: usb-audio: add implicit fb quirk for Axe-Fx II
ASoC: zte: spdif: correct ZX_SPDIF_CLK_RAT define
ASoC: zte: spdif and i2s drivers are not zx296702 specific
ASoC: rsnd: setup BRGCKR/BRRA/BRRB when starting
ASoC: rsnd: enable/disable ADG when suspend/resume timing
ASoC: rsnd: tidyup ssi->usrcnt counter check in hw_params
ALSA: cs46xx: add a new line
ASoC: Intel: update bxt_da7219_max98357a to support quad ch dmic capture
ASoC: nau8825: disable sinc filter for high THD of ADC
ALSA: usb-audio: more tolerant packetsize
ALSA: usb-audio: avoid setting of sample rate multiple times on bus
ASoC: cs35l34: Simplify the logic to set CS35L34_MCLK_CTL setting
ALSA: hda - Gate the mic jack on HP Z1 Gen3 AiO
ALSA: hda: when comparing pin configurations, ignore assoc in addition to seq
...
Diffstat (limited to 'sound/soc/atmel/atmel_ssc_dai.c')
-rw-r--r-- | sound/soc/atmel/atmel_ssc_dai.c | 83 |
1 files changed, 76 insertions, 7 deletions
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 16e459aedffe..a1e2c5682dcd 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -380,6 +380,7 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); /* Clear the SSC dividers */ ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; + ssc_p->forced_divider = 0; } spin_unlock_irq(&ssc_p->lock); @@ -426,14 +427,17 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, else if (div != ssc_p->cmr_div) return -EBUSY; + ssc_p->forced_divider |= BIT(ATMEL_SSC_CMR_DIV); break; case ATMEL_SSC_TCMR_PERIOD: ssc_p->tcmr_period = div; + ssc_p->forced_divider |= BIT(ATMEL_SSC_TCMR_PERIOD); break; case ATMEL_SSC_RCMR_PERIOD: ssc_p->rcmr_period = div; + ssc_p->forced_divider |= BIT(ATMEL_SSC_RCMR_PERIOD); break; default: @@ -443,6 +447,28 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, return 0; } +/* Is the cpu-dai master of the frame clock? */ +static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p) +{ + switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBS_CFS: + return 1; + } + return 0; +} + +/* Is the cpu-dai master of the bit clock? */ +static int atmel_ssc_cbs(struct atmel_ssc_info *ssc_p) +{ + switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBS_CFS: + return 1; + } + return 0; +} + /* * Configure the SSC. */ @@ -459,6 +485,9 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, u32 tfmr, rfmr, tcmr, rcmr; int ret; int fslen, fslen_ext; + u32 cmr_div; + u32 tcmr_period; + u32 rcmr_period; /* * Currently, there is only one set of dma params for @@ -470,6 +499,46 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, else dir = 1; + /* + * If the cpu dai should provide BCLK, but noone has provided the + * divider needed for that to work, fall back to something sensible. + */ + cmr_div = ssc_p->cmr_div; + if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_CMR_DIV)) && + atmel_ssc_cbs(ssc_p)) { + int bclk_rate = snd_soc_params_to_bclk(params); + + if (bclk_rate < 0) { + dev_err(dai->dev, "unable to calculate cmr_div: %d\n", + bclk_rate); + return bclk_rate; + } + + cmr_div = DIV_ROUND_CLOSEST(ssc_p->mck_rate, 2 * bclk_rate); + } + + /* + * If the cpu dai should provide LRCLK, but noone has provided the + * dividers needed for that to work, fall back to something sensible. + */ + tcmr_period = ssc_p->tcmr_period; + rcmr_period = ssc_p->rcmr_period; + if (atmel_ssc_cfs(ssc_p)) { + int frame_size = snd_soc_params_to_frame_size(params); + + if (frame_size < 0) { + dev_err(dai->dev, + "unable to calculate tx/rx cmr_period: %d\n", + frame_size); + return frame_size; + } + + if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_TCMR_PERIOD))) + tcmr_period = frame_size / 2 - 1; + if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_RCMR_PERIOD))) + rcmr_period = frame_size / 2 - 1; + } + dma_params = ssc_p->dma_params[dir]; channels = params_channels(params); @@ -524,7 +593,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, fslen_ext = (bits - 1) / 16; fslen = (bits - 1) % 16; - rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) + rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) @@ -540,7 +609,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); - tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) + tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) @@ -606,7 +675,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, fslen_ext = (bits - 1) / 16; fslen = (bits - 1) % 16; - rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) + rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | SSC_BF(RCMR_STTDLY, START_DELAY) | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) @@ -623,7 +692,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); - tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) + tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | SSC_BF(TCMR_STTDLY, START_DELAY) | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) @@ -650,7 +719,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, * MCK divider, and the BCLK signal is output * on the SSC TK line. */ - rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) + rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | SSC_BF(RCMR_STTDLY, 1) | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) @@ -665,7 +734,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RFMR_LOOP, 0) | SSC_BF(RFMR_DATLEN, (bits - 1)); - tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) + tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | SSC_BF(TCMR_STTDLY, 1) | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) @@ -760,7 +829,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, } /* set SSC clock mode register */ - ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); + ssc_writel(ssc_p->ssc->regs, CMR, cmr_div); /* set receive clock mode and format */ ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); |