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>"
This commit is contained in:
@@ -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,
|
||||
|
@@ -562,6 +562,8 @@ struct sst_ssp_config {
|
||||
u8 active_slot_map;
|
||||
u8 start_delay;
|
||||
u16 fs_width;
|
||||
u8 frame_sync_polarity;
|
||||
u8 data_polarity;
|
||||
};
|
||||
|
||||
struct sst_ssp_cfg {
|
||||
@@ -695,7 +697,7 @@ struct sst_gain_mixer_control {
|
||||
u16 module_id;
|
||||
u16 pipe_id;
|
||||
u16 task_id;
|
||||
char pname[44];
|
||||
char pname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
struct snd_soc_dapm_widget *w;
|
||||
};
|
||||
|
||||
@@ -867,4 +869,9 @@ struct sst_enum {
|
||||
SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
|
||||
SST_SSP_MUX_ENUM(xreg, xshift, xtexts))
|
||||
|
||||
int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
||||
unsigned int rx_mask, int slots, int slot_width);
|
||||
int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt);
|
||||
void sst_fill_ssp_defaults(struct snd_soc_dai *dai);
|
||||
|
||||
#endif
|
||||
|
@@ -434,13 +434,51 @@ static int sst_enable_ssp(struct snd_pcm_substream *substream,
|
||||
|
||||
if (!dai->active) {
|
||||
ret = sst_handle_vb_timer(dai, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = send_ssp_cmd(dai, dai->name, 1);
|
||||
sst_fill_ssp_defaults(dai);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sst_be_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dai->active == 1)
|
||||
ret = send_ssp_cmd(dai, dai->name, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!dai->active)
|
||||
return 0;
|
||||
|
||||
ret = sst_fill_ssp_config(dai, fmt);
|
||||
if (ret < 0)
|
||||
dev_err(dai->dev, "sst_set_format failed..\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sst_platform_set_ssp_slot(struct snd_soc_dai *dai,
|
||||
unsigned int tx_mask, unsigned int rx_mask,
|
||||
int slots, int slot_width) {
|
||||
int ret = 0;
|
||||
|
||||
if (!dai->active)
|
||||
return ret;
|
||||
|
||||
ret = sst_fill_ssp_slot(dai, tx_mask, rx_mask, slots, slot_width);
|
||||
if (ret < 0)
|
||||
dev_err(dai->dev, "sst_fill_ssp_slot failed..%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sst_disable_ssp(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
@@ -465,6 +503,9 @@ static struct snd_soc_dai_ops sst_compr_dai_ops = {
|
||||
|
||||
static struct snd_soc_dai_ops sst_be_dai_ops = {
|
||||
.startup = sst_enable_ssp,
|
||||
.hw_params = sst_be_hw_params,
|
||||
.set_fmt = sst_set_format,
|
||||
.set_tdm_slot = sst_platform_set_ssp_slot,
|
||||
.shutdown = sst_disable_ssp,
|
||||
};
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#define __SST_PLATFORMDRV_H__
|
||||
|
||||
#include "sst-mfld-dsp.h"
|
||||
#include "sst-atom-controls.h"
|
||||
|
||||
extern struct sst_device *sst;
|
||||
|
||||
@@ -175,6 +176,7 @@ struct sst_data {
|
||||
struct snd_sst_bytes_v2 *byte_stream;
|
||||
struct mutex lock;
|
||||
struct snd_soc_card *soc_card;
|
||||
struct sst_cmd_sba_hw_set_ssp ssp_cmd;
|
||||
};
|
||||
int sst_register_dsp(struct sst_device *sst);
|
||||
int sst_unregister_dsp(struct sst_device *sst);
|
||||
|
@@ -354,6 +354,10 @@ static struct sst_machines sst_acpi_chv[] = {
|
||||
&chv_platform_data },
|
||||
{"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
|
||||
&chv_platform_data },
|
||||
{"10EC5650", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
|
||||
&chv_platform_data },
|
||||
{"193C9890", "cht-bsw", "cht-bsw-max98090", NULL,
|
||||
"intel/fw_sst_22a8.bin", &chv_platform_data },
|
||||
{},
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user