diff options
author | Mark Brown <broonie@kernel.org> | 2015-06-22 12:24:19 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-06-22 12:24:19 +0300 |
commit | 208a128f6b19eedd1819cb1b19f29dc99ca1d27e (patch) | |
tree | 5d95c61efeb06ed6ec827267bc05e89498836bec /sound/soc/intel/atom/sst-atom-controls.c | |
parent | d21504d4c993838b31d970d392b1b78eb33cfd61 (diff) | |
parent | 11e688862c4c8162119a4ca51c3326555966c8bb (diff) | |
download | linux-208a128f6b19eedd1819cb1b19f29dc99ca1d27e.tar.xz |
Merge tag 'asoc-v4.2' into asoc-next
ASoC: Updates for v4.2
The big thing this release has been Liam's addition of topology support
to the core. We've also seen quite a bit of driver work and the
continuation of Lars' refactoring for component support.
- Support for loading ASoC topology maps from firmware, intended to be
used to allow self-describing DSP firmware images to be built which
can map controls added by the DSP to userspace without the kernel
needing to know about individual DSP firmwares.
- Lots of refactoring to avoid direct access to snd_soc_codec where
it's not needed supporting future refactoring.
- Big refactoring and cleanup serieses for the Wolfson ADSP and TI
TAS2552 drivers.
- Support for TI TAS571x power amplifiers.
- Support for Qualcomm APQ8016 and ZTE ZX296702 SoCs.
- Support for x86 systems with RT5650 and Qualcomm Storm.
# gpg: Signature made Mon 08 Jun 2015 18:48:37 BST using RSA key ID 5D5487D0
# gpg: Oops: keyid_from_fingerprint: no pubkey
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg: aka "Mark Brown <broonie@debian.org>"
# gpg: aka "Mark Brown <broonie@kernel.org>"
# gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg: aka "Mark Brown <broonie@linaro.org>"
# gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'sound/soc/intel/atom/sst-atom-controls.c')
-rw-r--r-- | sound/soc/intel/atom/sst-atom-controls.c | 167 |
1 files changed, 144 insertions, 23 deletions
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 90aa5c0476f3..61e240935451 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -774,8 +774,120 @@ int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable) return ret; } +int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); + + ctx->ssp_cmd.nb_slots = slots; + ctx->ssp_cmd.active_tx_slot_map = tx_mask; + ctx->ssp_cmd.active_rx_slot_map = rx_mask; + ctx->ssp_cmd.nb_bits_per_slots = slot_width; + + return 0; +} + +static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai, + unsigned int fmt) +{ + int format; + + format = fmt & SND_SOC_DAIFMT_INV_MASK; + dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); + + switch (format) { + case SND_SOC_DAIFMT_NB_NF: + return SSP_FS_ACTIVE_LOW; + case SND_SOC_DAIFMT_NB_IF: + return SSP_FS_ACTIVE_HIGH; + case SND_SOC_DAIFMT_IB_IF: + return SSP_FS_ACTIVE_LOW; + case SND_SOC_DAIFMT_IB_NF: + return SSP_FS_ACTIVE_HIGH; + default: + dev_err(dai->dev, "Invalid frame sync polarity %d\n", format); + } + + return -EINVAL; +} + +static int sst_get_ssp_mode(struct snd_soc_dai *dai, unsigned int fmt) +{ + int format; + + format = (fmt & SND_SOC_DAIFMT_MASTER_MASK); + dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); + + switch (format) { + case SND_SOC_DAIFMT_CBS_CFS: + return SSP_MODE_MASTER; + case SND_SOC_DAIFMT_CBM_CFM: + return SSP_MODE_SLAVE; + default: + dev_err(dai->dev, "Invalid ssp protocol: %d\n", format); + } + + return -EINVAL; +} + + +int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt) +{ + unsigned int mode; + int fs_polarity; + struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); + + mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + + switch (mode) { + case SND_SOC_DAIFMT_DSP_B: + ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM; + ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1); + ctx->ssp_cmd.start_delay = 0; + ctx->ssp_cmd.data_polarity = 1; + ctx->ssp_cmd.frame_sync_width = 1; + break; + + case SND_SOC_DAIFMT_DSP_A: + ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM; + ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1); + ctx->ssp_cmd.start_delay = 1; + ctx->ssp_cmd.data_polarity = 1; + ctx->ssp_cmd.frame_sync_width = 1; + break; + + case SND_SOC_DAIFMT_I2S: + ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S; + ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1); + ctx->ssp_cmd.start_delay = 1; + ctx->ssp_cmd.data_polarity = 0; + ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots; + break; + + case SND_SOC_DAIFMT_LEFT_J: + ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S; + ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1); + ctx->ssp_cmd.start_delay = 0; + ctx->ssp_cmd.data_polarity = 0; + ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots; + break; + + default: + dev_dbg(dai->dev, "using default ssp configs\n"); + } + + fs_polarity = sst_get_frame_sync_polarity(dai, fmt); + if (fs_polarity < 0) + return fs_polarity; + + ctx->ssp_cmd.frame_sync_polarity = fs_polarity; + + return 0; +} + /** * sst_ssp_config - contains SSP configuration for media UC + * this can be overwritten by set_dai_xxx APIs */ static const struct sst_ssp_config sst_ssp_configs = { .ssp_id = SSP_CODEC, @@ -789,47 +901,56 @@ static const struct sst_ssp_config sst_ssp_configs = { .fs_frequency = SSP_FS_48_KHZ, .active_slot_map = 0xF, .start_delay = 0, + .frame_sync_polarity = SSP_FS_ACTIVE_HIGH, + .data_polarity = 1, }; +void sst_fill_ssp_defaults(struct snd_soc_dai *dai) +{ + const struct sst_ssp_config *config; + struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); + + config = &sst_ssp_configs; + + ctx->ssp_cmd.selection = config->ssp_id; + ctx->ssp_cmd.nb_bits_per_slots = config->bits_per_slot; + ctx->ssp_cmd.nb_slots = config->slots; + ctx->ssp_cmd.mode = config->ssp_mode | (config->pcm_mode << 1); + ctx->ssp_cmd.duplex = config->duplex; + ctx->ssp_cmd.active_tx_slot_map = config->active_slot_map; + ctx->ssp_cmd.active_rx_slot_map = config->active_slot_map; + ctx->ssp_cmd.frame_sync_frequency = config->fs_frequency; + ctx->ssp_cmd.frame_sync_polarity = config->frame_sync_polarity; + ctx->ssp_cmd.data_polarity = config->data_polarity; + ctx->ssp_cmd.frame_sync_width = config->fs_width; + ctx->ssp_cmd.ssp_protocol = config->ssp_protocol; + ctx->ssp_cmd.start_delay = config->start_delay; + ctx->ssp_cmd.reserved1 = ctx->ssp_cmd.reserved2 = 0xFF; +} + int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable) { - struct sst_cmd_sba_hw_set_ssp cmd; struct sst_data *drv = snd_soc_dai_get_drvdata(dai); const struct sst_ssp_config *config; dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id); - SST_FILL_DEFAULT_DESTINATION(cmd.header.dst); - cmd.header.command_id = SBA_HW_SET_SSP; - cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp) + SST_FILL_DEFAULT_DESTINATION(drv->ssp_cmd.header.dst); + drv->ssp_cmd.header.command_id = SBA_HW_SET_SSP; + drv->ssp_cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp) - sizeof(struct sst_dsp_header); config = &sst_ssp_configs; dev_dbg(dai->dev, "ssp_id: %u\n", config->ssp_id); if (enable) - cmd.switch_state = SST_SWITCH_ON; + drv->ssp_cmd.switch_state = SST_SWITCH_ON; else - cmd.switch_state = SST_SWITCH_OFF; - - cmd.selection = config->ssp_id; - cmd.nb_bits_per_slots = config->bits_per_slot; - cmd.nb_slots = config->slots; - cmd.mode = config->ssp_mode | (config->pcm_mode << 1); - cmd.duplex = config->duplex; - cmd.active_tx_slot_map = config->active_slot_map; - cmd.active_rx_slot_map = config->active_slot_map; - cmd.frame_sync_frequency = config->fs_frequency; - cmd.frame_sync_polarity = SSP_FS_ACTIVE_HIGH; - cmd.data_polarity = 1; - cmd.frame_sync_width = config->fs_width; - cmd.ssp_protocol = config->ssp_protocol; - cmd.start_delay = config->start_delay; - cmd.reserved1 = cmd.reserved2 = 0xFF; + drv->ssp_cmd.switch_state = SST_SWITCH_OFF; return sst_fill_and_send_cmd(drv, SST_IPC_IA_CMD, SST_FLAG_BLOCKED, - SST_TASK_SBA, 0, &cmd, - sizeof(cmd.header) + cmd.header.length); + SST_TASK_SBA, 0, &drv->ssp_cmd, + sizeof(drv->ssp_cmd.header) + drv->ssp_cmd.header.length); } static int sst_set_be_modules(struct snd_soc_dapm_widget *w, |