|
@@ -774,8 +774,107 @@ int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+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,
|