diff --git a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts index dbf2f3cacc2e6b..a36fa85a61f7ea 100644 --- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts +++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts @@ -13,6 +13,26 @@ }; fragment@1 { + target = <&soc>; + __overlay__ { + reg_digital: reg_digital@0 { + compatible = "regulator-fixed"; + regulator-name = "cs42448_dig_supply"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + reg_analogue: reg_analogue@0 { + compatible = "regulator-fixed"; + regulator-name = "cs42448_ana_supply"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + }; + }; + + fragment@2 { target = <&i2c1>; __overlay__ { #address-cells = <1>; @@ -25,6 +45,10 @@ reg = <0x48>; clocks = <&cs42448_mclk>; clock-names = "mclk"; + VA-supply = <®_analogue>; + VD-supply = <®_digital>; + VLS-supply = <®_digital>; + VLC-supply = <®_digital>; status = "okay"; }; @@ -36,12 +60,13 @@ }; }; - fragment@2 { + fragment@3 { target = <&sound>; __overlay__ { compatible = "ai,audioinjector-octo-soundcard"; mult-gpios = <&gpio 27 0>, <&gpio 22 0>, <&gpio 23 0>, <&gpio 24 0>; + reset-gpios = <&gpio 5 0>; i2s-controller = <&i2s>; codec = <&cs42448>; status = "okay"; diff --git a/sound/soc/bcm/audioinjector-octo-soundcard.c b/sound/soc/bcm/audioinjector-octo-soundcard.c index 9effea72579864..1198c36c4563b8 100644 --- a/sound/soc/bcm/audioinjector-octo-soundcard.c +++ b/sound/soc/bcm/audioinjector-octo-soundcard.c @@ -27,8 +27,18 @@ #include static struct gpio_descs *mult_gpios; +static struct gpio_desc *codec_rst_gpio; static unsigned int audioinjector_octo_rate; +static const unsigned int audioinjector_octo_rates[] = { + 96000, 48000, 88200, 44100, +}; + +static struct snd_pcm_hw_constraint_list audioinjector_octo_constraints = { + .list = audioinjector_octo_rates, + .count = ARRAY_SIZE(audioinjector_octo_rates), +}; + static int audioinjector_octo_dai_init(struct snd_soc_pcm_runtime *rtd) { return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, 64); @@ -42,6 +52,11 @@ static int audioinjector_octo_startup(struct snd_pcm_substream *substream) rtd->cpu_dai->driver->capture.channels_min = 8; rtd->cpu_dai->driver->capture.channels_max = 8; rtd->codec_dai->driver->capture.channels_max = 8; + + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &audioinjector_octo_constraints); + return 0; } @@ -76,7 +91,21 @@ static int audioinjector_octo_hw_params(struct snd_pcm_substream *substream, audioinjector_octo_rate = params_rate(params); - return 0; + // Set the correct sysclock for the codec + switch (audioinjector_octo_rate) { + case 96000: + case 48000: + return snd_soc_dai_set_sysclk(rtd->codec_dai, 0, 49152000, + 0); + break; + case 88200: + case 44100: + return snd_soc_dai_set_sysclk(rtd->codec_dai, 0, 45185400, + 0); + break; + default: + return -EINVAL; + } } static int audioinjector_octo_trigger(struct snd_pcm_substream *substream, @@ -92,49 +121,17 @@ static int audioinjector_octo_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: switch (audioinjector_octo_rate) { - case 192000: - mult[3] = 1; - case 176640: - mult[0] = 1; - mult[1] = 1; - mult[2] = 1; - break; case 96000: mult[3] = 1; case 88200: mult[1] = 1; mult[2] = 1; break; - case 64000: - mult[3] = 1; - case 58800: - mult[0] = 1; - mult[2] = 1; - break; case 48000: mult[3] = 1; case 44100: mult[2] = 1; break; - case 32000: - mult[3] = 1; - case 29400: - mult[0] = 1; - mult[1] = 1; - break; - case 24000: - mult[3] = 1; - case 22050: - mult[1] = 1; - break; - case 16000: - mult[3] = 1; - case 14700: - mult[0] = 1; - break; - case 8000: - mult[3] = 1; - break; default: return -EINVAL; } @@ -231,6 +228,18 @@ static int audioinjector_octo_probe(struct platform_device *pdev) if (IS_ERR(mult_gpios)) return PTR_ERR(mult_gpios); + codec_rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(codec_rst_gpio)) + return PTR_ERR(codec_rst_gpio); + + if (codec_rst_gpio) + gpiod_set_value(codec_rst_gpio, 0); + msleep(5); + if (codec_rst_gpio) + gpiod_set_value(codec_rst_gpio, 1); + msleep(50); + if (i2s_node && codec_node) { dai->cpu_dai_name = NULL; dai->cpu_of_node = i2s_node;