diff --git a/sound/soc/codecs/ec25.c b/sound/soc/codecs/ec25.c index 7c96aa7a79d0..20687ec386ef 100644 --- a/sound/soc/codecs/ec25.c +++ b/sound/soc/codecs/ec25.c @@ -3,6 +3,50 @@ #include #include +u32 curr_sample_rate; + +static const char *const avail_sample_rates[] = {"8000", "16000", "48000"}; +static const struct soc_enum ec25_enum[] = { + SOC_ENUM_SINGLE_EXT(3, avail_sample_rates), +}; + +static int ec25_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_info("%s: Forced sample rate = %i\n", + __func__, curr_sample_rate); + ucontrol->value.integer.value[0] = curr_sample_rate; + return 0; +} + +static int ec25_sample_rate_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 0: + curr_sample_rate = 8000; + break; + case 1: + curr_sample_rate = 16000; + break; + case 2: + curr_sample_rate = 48000; + break; + default: + curr_sample_rate = 8000; + break; + } + pr_info("%s: Forced sample rate = %i\n", + __func__, curr_sample_rate); + return 0; +} + +static const struct snd_kcontrol_new ec25_controls[] = { + SOC_ENUM_EXT("EC25 Sample Rate", ec25_enum[0], + ec25_sample_rate_get, + ec25_sample_rate_set), +}; + static const struct snd_soc_dapm_widget ec25_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("AOUT"), SND_SOC_DAPM_INPUT("AIN"), @@ -22,23 +66,50 @@ static const struct snd_soc_component_driver ec25_component_driver = { .num_dapm_routes = ARRAY_SIZE(ec25_dapm_routes), .endianness = 1, .non_legacy_dai_naming = 1, + .controls = ec25_controls, + .num_controls = ARRAY_SIZE(ec25_controls), +}; + +static int ec25_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + /* HACK: This is a const pointer, but we know the underlying data is not const. */ + struct snd_soc_pcm_stream *params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; + struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, substream->stream); + + if (stream->rates & snd_pcm_rate_to_rate_bit(curr_sample_rate)) { + dev_info(dai->dev, "Setting sample rate to %u\n", curr_sample_rate); + params->rate_min = curr_sample_rate; + params->rate_max = curr_sample_rate; + } + + return 0; +} +static const struct snd_soc_dai_ops ec25_dai_ops = { + .startup = ec25_startup, }; static struct snd_soc_dai_driver ec25_dais[] = { { .name = "ec25", + .ops = &ec25_dai_ops, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .symmetric_rates = 1, @@ -69,6 +140,7 @@ static struct snd_soc_dai_driver ec25_dais[] = { static int ec25_codec_probe(struct platform_device *pdev) { + curr_sample_rate = 8000; return devm_snd_soc_register_component(&pdev->dev, &ec25_component_driver, ec25_dais, ARRAY_SIZE(ec25_dais)); }