I have a MAX9867 codec connected to LS connector.
The build is based on the Yocto project using the meta-qcom layer.
Using various guides posted here (thanks every one) I have a device tree overlay and kernel patch that integrate the codec.
This has the codec working through the Linaro qcom/release kernel through 5.4, 5.7 and 5.9.
meta-qcom has just bumped the kernel to 5.10. The build woks fine with the existing patch and overlay but the MAX9867 isn’t showing as a sound card.
Output from aplay -l with kernel 5.10
**** List of PLAYBACK Hardware Devices ****
card 0: DB410c [DB410c], device 0: ADV7533 i2s-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: DB410c [DB410c], device 1: WCD multicodec-1 []
Subdevices: 1/1
Subdevice #0: subdevice #0
output of aplay -l with kernel 5.9
card 0: DB410c [DB410c], device 0: MAX9867 max9867-aif1-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: DB410c [DB410c], device 1: WCD multicodec-1 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: DB410c [DB410c], device 3: ADV7533 i2s-hifi-3 []
Subdevices: 1/1
Subdevice #0: subdevice #0
The device is detected on the i2c bus at boot.
None of the drivers involved or files that are patch/overlaid have changed in the 5.9 - 5.10 merge.
Below is the patch and overlay, has anyone any idea what might have changed or how to resolve the issue?
The device tree overlay:
/dts-v1/;
#include <dt-bindings/input/input.h>
#include “apq8016-sbc.dtsi”
/ {
model = “Connexionz Ltd. Medius G2 based on Qualcomm Technologies, Inc. APQ 8016 SBC”;
compatible = “qcom,apq8016-sbc”, “qcom,apq8016”, “qcom,sbc”, “connexionz,medius-g2”;
};
// disable PM8916 RTC, can’t be written to and Medius has its own.
&pm8916_0 {
rtc@6000 {
status = “disabled”;
};
};
&soc {
dig_supply_3v3: fixedregulator@3 {
compatible = “regulator-fixed”;
regulator-name = “3v3-dig”;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
soc_supply_5v0: fixedregulator@4 {
compatible = "regulator-fixed";
regulator-name = "5v0-soc";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
clocks {
i2c6_osc: i2c6_osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <400000>;
};
};
sound {
// the apq8016 devicetree configures the soundcard to use the codec on the PM8916 PMC.
// We've added the pins for the external primary I2S interface, as described
// in https://www.96boards.org/blog/i2s-in-dragonboard410c/
// this interface is used for the external codec, max9867.
// The lines for the ext secondary interface are connected to the ADV7533 HDMI bridge,
// and are also enabled.
pinctrl-0 = <&ext_pri_tlmm_lines_act &ext_pri_ws_act &ext_sec_tlmm_lines_act>;
external-dai-link@0 {
link-name = "MAX9867";
cpu { /* PRIMARY */
sound-dai = <&lpass MI2S_PRIMARY>;
};
codec {
sound-dai = <&max9867_codec 0>;
};
};
external-dai-link@1 {
link-name = "ADV7533";
cpu { /* QUAT */
sound-dai = <&lpass MI2S_QUATERNARY>;
};
codec {
sound-dai = <&adv_bridge 0>;
};
};
internal-codec-playback-dai-link@0 {
status = "disabled";
};
internal-codec-capture-dai-link@0 {
status = "disabled";
};
};
};
&msmgpio {
/*
Lines for the external audio codec DAI. gpio115 has been removed because it’s
used for IO. gpio116 was removed because it’s NC on the DB410c
*/
ext-pri-tlmm-lines {
ext-pa-on {
pins = “gpio113”, “gpio114”;
};
ext-pa-off {
pins = “gpio113”, “gpio114”;
};
};
};
&blsp_i2c6 {
status =“okay”;
isl1219: rtc@6f {
compatible = “isil,isl1219”;
allow-set-time;
reg = <0x6f>;
status = “okay”;
};
max9867_codec: max9867@18 {
compatible = "maxim,max9867";
reg = <0x18>;
#sound-dai-cells = <1>;
status = "okay";
};
};
Kernel patch:
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index 575e2aefefe3…76420a3a603e 100644
— a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -30,7 +30,12 @@ struct apq8016_sbc_data {
#define MIC_CTRL_QUA_WS_SLAVE_SEL_10 BIT(17)
#define MIC_CTRL_TLMM_SCLK_EN BIT(1)
#define SPKR_CTL_PRI_WS_SLAVE_SEL_11 (BIT(17) | BIT(16))
-#define DEFAULT_MCLK_RATE 9600000
+
+#define SPKR_CTL_SCLK_EN BIT(2)
+#define SPKR_CTL_DATA1_EN BIT(3)
+#define SPKR_CTL_DATA0_EN BIT(4)
+#define DEFAULT_MCLK_RATE 12288000
+
static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
{
@@ -43,7 +48,7 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
switch (cpu_dai->id) {
case MI2S_PRIMARY:
-
writel(readl(pdata->spkr_iomux) | SPKR_CTL_PRI_WS_SLAVE_SEL_11,
-
writel(readl(pdata->spkr_iomux) | SPKR_CTL_PRI_WS_SLAVE_SEL_11 | SPKR_CTL_SCLK_EN | SPKR_CTL_DATA0_EN | SPKR_CTL_DATA1_EN, pdata->spkr_iomux); break;
@@ -94,13 +99,21 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
for_each_rtd_codec_dais(rtd, i, codec_dai) {
component = codec_dai->component;
-
/* Set default mclk for internal codec */
-
rval = snd_soc_component_set_sysclk(component, 0, 0, DEFAULT_MCLK_RATE,
-
SND_SOC_CLOCK_IN);
-
/* Set mclk for external codec */
-
rval = snd_soc_dai_set_sysclk(codec_dai, 0, DEFAULT_MCLK_RATE, SND_SOC_CLOCK_IN); if (rval != 0 && rval != -ENOTSUPP) { dev_warn(card->dev, "Failed to set mclk: %d\n", rval); return rval; }
-
/* Set fmt for external codec */
-
rval = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF);
-
if (rval != 0 && rval != -ENOTSUPP) {
-
dev_warn(card->dev, "Failed to set fmt: %d\n", rval);
-
return rval;
-
}
-
rval = snd_soc_component_set_jack(component, &pdata->jack, NULL); if (rval != 0 && rval != -ENOTSUPP) { dev_warn(card->dev, "Failed to set jack: %d\n", rval);