@@ -21,6 +21,7 @@
#include <sound/soc-acpi.h>
#include "../../codecs/rt5670.h"
#include "../atom/sst-atom-controls.h"
+#include "../common/soc-intel-quirks.h"
/* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */
@@ -31,6 +32,7 @@ struct cht_mc_private {
struct snd_soc_jack headset;
char codec_name[SND_ACPI_I2C_ID_LEN];
struct clk *mclk;
+ bool use_ssp0;
};
/* Headset jack detection DAPM pins */
@@ -121,16 +123,26 @@ static const struct snd_soc_dapm_route cht_audio_map[] = {
{"Ext Spk", NULL, "SPOLN"},
{"Ext Spk", NULL, "SPORP"},
{"Ext Spk", NULL, "SPORN"},
+ {"Headphone", NULL, "Platform Clock"},
+ {"Headset Mic", NULL, "Platform Clock"},
+ {"Int Mic", NULL, "Platform Clock"},
+ {"Ext Spk", NULL, "Platform Clock"},
+};
+
+static const struct snd_soc_dapm_route cht_audio_ssp0_map[] = {
+ {"AIF1 Playback", NULL, "ssp0 Tx"},
+ {"ssp0 Tx", NULL, "modem_out"},
+ {"modem_in", NULL, "ssp0 Rx"},
+ {"ssp0 Rx", NULL, "AIF1 Capture"},
+};
+
+static const struct snd_soc_dapm_route cht_audio_ssp2_map[] = {
{"AIF1 Playback", NULL, "ssp2 Tx"},
{"ssp2 Tx", NULL, "codec_out0"},
{"ssp2 Tx", NULL, "codec_out1"},
{"codec_in0", NULL, "ssp2 Rx"},
{"codec_in1", NULL, "ssp2 Rx"},
{"ssp2 Rx", NULL, "AIF1 Capture"},
- {"Headphone", NULL, "Platform Clock"},
- {"Headset Mic", NULL, "Platform Clock"},
- {"Int Mic", NULL, "Platform Clock"},
- {"Ext Spk", NULL, "Platform Clock"},
};
static const struct snd_kcontrol_new cht_mc_controls[] = {
@@ -197,6 +209,18 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
| RT5670_AD_MONO_R_FILTER,
RT5670_CLK_SEL_I2S1_ASRC);
+ if (ctx->use_ssp0) {
+ ret = snd_soc_dapm_add_routes(&runtime->card->dapm,
+ cht_audio_ssp0_map,
+ ARRAY_SIZE(cht_audio_ssp0_map));
+ } else {
+ ret = snd_soc_dapm_add_routes(&runtime->card->dapm,
+ cht_audio_ssp2_map,
+ ARRAY_SIZE(cht_audio_ssp2_map));
+ }
+ if (ret)
+ return ret;
+
ret = snd_soc_card_jack_new(runtime->card, "Headset",
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2,
@@ -239,18 +263,26 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
+ struct cht_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
- int ret;
+ int ret, bits;
/* The DSP will covert the FE rate to 48k, stereo, 24bits */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
- /* set SSP2 to 24-bit */
- params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+ if (ctx->use_ssp0) {
+ /* set SSP0 to 16-bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
+ bits = 16;
+ } else {
+ /* set SSP2 to 24-bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+ bits = 24;
+ }
/*
* The default mode for the cpu-dai is TDM 4 slot. The default mode
@@ -274,6 +306,12 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
return ret;
}
+ ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
+ return ret;
+ }
+
return 0;
}
@@ -414,6 +452,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
const char *platform_name;
struct acpi_device *adev;
bool sof_parent;
+ int dai_index = 0;
int i;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
@@ -422,19 +461,27 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
strcpy(drv->codec_name, RT5672_I2C_DEFAULT);
+ /* find index of codec dai */
+ for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
+ if (!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) {
+ dai_index = i;
+ break;
+ }
+ }
+
/* fixup codec name based on HID */
adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
if (adev) {
snprintf(drv->codec_name, sizeof(drv->codec_name),
"i2c-%s", acpi_dev_name(adev));
put_device(&adev->dev);
- for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
- if (!strcmp(cht_dailink[i].codecs->name,
- RT5672_I2C_DEFAULT)) {
- cht_dailink[i].codecs->name = drv->codec_name;
- break;
- }
- }
+ cht_dailink[dai_index].codecs->name = drv->codec_name;
+ }
+
+ /* Use SSP0 on Bay Trail CR devices */
+ if (soc_intel_is_byt() && mach->mach_params.acpi_ipc_irq_index == 0) {
+ cht_dailink[dai_index].cpus->dai_name = "ssp0-port";
+ drv->use_ssp0 = true;
}
/* override plaform name, if required */
The rt5672 codec is used on some Bay Trail CR boards, on these SoCs SSP2 is not available and SSP0 should be used instead. At support for this. This has been tested on a Dell Venue 10 Pro 5055. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- sound/soc/intel/boards/cht_bsw_rt5672.c | 75 ++++++++++++++++++++----- 1 file changed, 61 insertions(+), 14 deletions(-)