SDM660 sound card and internal MI2S support
Subsystems (5)
v5 cover SDM660 sound card and internal MI2S support
This adds support for the SDM660 (formerly "SDM660 internal") sound card and support for WCD codecs over internal MI2S (represented in APIs as LPI MI2S).
Like on MSM8916 and MSM8953, some SDM660 and SDM670 devices connect to a digital and analog codec. The connection to the digital codec is through special "internal" MI2S ports. The digital and analog codecs are used on the Xiaomi Redmi Note 7 for headset (playback + capture) and earpiece, and also on the Google Pixel 3a for the headset.
This series does not include devicetree patches.
Changes since v4 (https://lore.kernel.org/r/[email protected]):
- name internal MI2S ports as LPI for public API (2/15, 6/15, 7/15, 8/15, 9/15, 10/15, 11/15, 12/15)
- fix capture stream macro (11/15)
- fix is_rx in q6afe port map (7/15)
- use NULL pointer in place of "NULL" string (8/15)
- change fallback compatible for WCD analog codec to pm8953 (4/15)
- add ack tags (1/15, 3/15)
Changes since v3 (https://lore.kernel.org/r/[email protected]):
- rebase onto v7.1-rc1
Changes since v2 (https://lore.kernel.org/r/[email protected]):
- add missing sign-off (1/15)
- use definition of last dt-bindings dai cell for LPASS_MAX_PORT (6/15)
- move sdm660 support to existing sm8250 driver (11-12/15)
- import WCD codec patches for MSM8953 (3/15, 13-14/15)
Changes from original (https://lore.kernel.org/r/[email protected]):
- add back empty line in WCD dt-bindings patch (3/15)
- add Dmitry's review tags (13-14/15)
- rebase onto q6dsp fixes
- rebase onto q6dsp fixes
Changes since v1 (https://lore.kernel.org/r/[email protected]):
- rename sound card to drop "internal" (1/11, 10/11)
- use common headphone jack code (9/11, 10/11)
- remove no-op code in sound card driver (10/11)
- remove inaccurate comment about clock consumer/producer (10/11)
- add review tags (3/11, 4/11)
Adam Skladowski (2):
ASoC: dt-bindings: pm8916-wcd-analog-codec: Document pm8950/pm8953
ASoC: msm8916-wcd-analog: add pm8950 codec
Nickolay Goppen (1):
ASoC: dt-bindings: qcom,sm8250: add compatible for sdm660
Richard Acayan (11):
ASoC: dt-bindings: qcom: q6dsp: add support for lpi mi2s ports 5-6
ASoC: dt-bindings: pm8916-analog-codec: Add PM660L compatible
ASoC: dt-bindings: msm8916-digital-codec: Add SDM660 compatible
ASoC: qdsp6: q6dsp-lpass-ports: add support for lpi mi2s ports 5-6
ASoC: qdsp6: q6afe: add internal mi2s support
ASoC: qdsp6: q6afe-dai: add internal mi2s support
ASoC: qdsp6: q6routing: add lpi mi2s support
ASoC: qdsp6: common: support headphone jacks connected to lpi mi2s
ASoC: qcom: sm8250: add support for LPI_MI2S_RX_0 and LPI_MI2S_TX_3
ASoC: qcom: sm8250: add SDM660 compatible
ASoC: msm8916-wcd-analog: add quirk for cajon 2.0
Vladimir Lypak (1):
ASoC: msm8916-wcd-analog: add pm8953 codec
.../sound/qcom,msm8916-wcd-digital-codec.yaml | 8 +- .../sound/qcom,pm8916-wcd-analog-codec.yaml | 11 +- .../sound/qcom,q6dsp-lpass-ports.yaml | 4 +- .../bindings/sound/qcom,sm8250.yaml | 1 + .../sound/qcom,q6dsp-lpass-ports.h | 4 + sound/soc/codecs/msm8916-wcd-analog.c | 144 +++++++++++++++++- sound/soc/qcom/common.c | 1 + sound/soc/qcom/common.h | 2 +- sound/soc/qcom/qdsp6/q6afe-dai.c | 48 ++++++ sound/soc/qcom/qdsp6/q6afe.c | 56 +++++++ sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c | 5 + sound/soc/qcom/qdsp6/q6routing.c | 78 +++++++++- sound/soc/qcom/sm8250.c | 17 +++ 13 files changed, 367 insertions(+), 12 deletions(-)
Signature · 1 line
2.54.0
PATCH v5 1/15 ASoC: dt-bindings: qcom,sm8250: add compatible for sdm660
From: Nickolay Goppen <[email protected]>
Add compatibles for sdm660 based soundcards.
--- Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 + 1 file changed, 1 insertion(+)
Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +1 -0
@@ -44,6 +44,7 @@ properties: - qcom,qrb5165-rb5-sndcard - qcom,sc7180-qdsp6-sndcard - qcom,sc8280xp-sndcard + - qcom,sdm660-sndcard - qcom,sdm845-sndcard - qcom,sm8250-sndcard - qcom,sm8450-sndcard
Signature · 1 line
2.54.0
PATCH v5 2/15 ASoC: dt-bindings: qcom: q6dsp: add support for lpi mi2s ports 5-6
In reply to Richard AcayanThere are 7 internal MI2S ports per direction found on devices with the internal sound card for Snapdragon 660. This is similar to the LPI MI2S ports, and the LPI MI2S bindings can be reused for internal MI2S. Extend the bindings for LPI MI2S ports to accommodate the internal MI2S ports.
--- .../devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml | 4 ++-- include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml +2 -2
@@ -127,7 +127,7 @@ patternProperties: contains: # MI2S DAI ID range PRIMARY_MI2S_RX - QUATERNARY_MI2S_TX and # QUINARY_MI2S_RX - QUINARY_MI2S_TX and - # LPI_MI2S_RX_0 - SENARY_MI2S_TX + # LPI_MI2S_RX_0 - LPI_MI2S_TX_6 items: oneOf: - minimum: 16
@@ -135,7 +135,7 @@ patternProperties: - minimum: 127 maximum: 128 - minimum: 137 - maximum: 148 + maximum: 152 then: required: - qcom,sd-lines
include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h +4 -0
@@ -152,6 +152,10 @@#define LPI_MI2S_TX_4 146#define SENARY_MI2S_RX 147#define SENARY_MI2S_TX 148 +#define LPI_MI2S_RX_5 149 +#define LPI_MI2S_TX_5 150 +#define LPI_MI2S_RX_6 151 +#define LPI_MI2S_TX_6 152#define LPASS_CLK_ID_PRI_MI2S_IBIT 1#define LPASS_CLK_ID_PRI_MI2S_EBIT 2
Signature · 1 line
2.54.0
Re: [PATCH v5 02/15] ASoC: dt-bindings: qcom: q6dsp: add support for lpi mi2s ports 5-6
Quoted 10 lines · Richard Acayan
There are 7 internal MI2S ports per direction found on devices with the internal sound card for Snapdragon 660. This is similar to the LPI MI2S ports, and the LPI MI2S bindings can be reused for internal MI2S. Extend the bindings for LPI MI2S ports to accommodate the internal MI2S ports.
Signed-off-by Richard Acayan <[email protected]>--- .../devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml | 4 ++-- include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-)
Best regards,
Krzysztof
PATCH v5 3/15 ASoC: dt-bindings: pm8916-wcd-analog-codec: Document pm8950/pm8953
In reply to Richard AcayanFrom: Adam Skladowski <[email protected]>
Document pm8950 and pm8953 analog audio codecs.
--- .../bindings/sound/qcom,pm8916-wcd-analog-codec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml +4 -1
@@ -14,7 +14,10 @@ description: properties: compatible: - const: qcom,pm8916-wcd-analog-codec + enum: + - qcom,pm8916-wcd-analog-codec + - qcom,pm8950-wcd-analog-codec + - qcom,pm8953-wcd-analog-codec reg: maxItems: 1
Signature · 1 line
2.54.0
PATCH v5 4/15 ASoC: dt-bindings: pm8916-analog-codec: Add PM660L compatible
In reply to Richard AcayanThe PM8953 (cajon 2.0) revision of the PM8916 analog codec is also found on PM660L, typically connected to the SDM660 internal sound card via the digital codec. Provide a space for specific compatibles and add the compatible for PM660L.
--- .../sound/qcom,pm8916-wcd-analog-codec.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml +10 -4
@@ -14,10 +14,16 @@ description: properties: compatible: - enum: - - qcom,pm8916-wcd-analog-codec - - qcom,pm8950-wcd-analog-codec - - qcom,pm8953-wcd-analog-codec + oneOf: + - items: + - enum: + - qcom,pm660l-wcd-analog-codec + - const: qcom,pm8953-wcd-analog-codec + + - enum: + - qcom,pm8916-wcd-analog-codec + - qcom,pm8950-wcd-analog-codec + - qcom,pm8953-wcd-analog-codec reg: maxItems: 1
Signature · 1 line
2.54.0
PATCH v5 5/15 ASoC: dt-bindings: msm8916-digital-codec: Add SDM660 compatible
In reply to Richard AcayanThe MSM8916 digital codec is also found on SDM660, typically connected to the SDM660 internal sound card. Provide a space
for specific compatibles and add the compatible for SDM660.
--- .../bindings/sound/qcom,msm8916-wcd-digital-codec.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital-codec.yaml +7 -1
@@ -14,7 +14,13 @@ description: properties: compatible: - const: qcom,msm8916-wcd-digital-codec + oneOf: + - items: + - enum: + - qcom,sdm660-wcd-digital-codec + - const: qcom,msm8916-wcd-digital-codec + + - const: qcom,msm8916-wcd-digital-codec reg: maxItems: 1
Signature · 1 line
2.54.0
PATCH v5 6/15 ASoC: qdsp6: q6dsp-lpass-ports: add support for lpi mi2s ports 5-6
In reply to Richard AcayanAdd the extra LPI MI2S ports used for internal MI2S on SDM660.
--- sound/soc/qcom/common.h | 2 +- sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-)
sound/soc/qcom/common.h +1 -1
@@ -7,7 +7,7 @@#include <dt-bindings/sound/qcom,q6afe.h> #include <sound/soc.h> -#define LPASS_MAX_PORT (SENARY_MI2S_TX + 1) +#define LPASS_MAX_PORT (LPI_MI2S_TX_6 + 1)int qcom_snd_parse_of (struct snd_soc_card *card); int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c +5 -0
@@ -553,11 +553,15 @@ static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {Q6AFE_MI2S_RX_DAI ("LPI RX2" ,LPI_MI2S_RX_2 ),Q6AFE_MI2S_RX_DAI ("LPI RX3" ,LPI_MI2S_RX_3 ),Q6AFE_MI2S_RX_DAI ("LPI RX4" ,LPI_MI2S_RX_4 ), +Q6AFE_MI2S_RX_DAI ("LPI RX5" ,LPI_MI2S_RX_5 ), +Q6AFE_MI2S_RX_DAI ("LPI RX6" ,LPI_MI2S_RX_6 ),Q6AFE_MI2S_TX_DAI ("LPI TX0" ,LPI_MI2S_TX_0 ),Q6AFE_MI2S_TX_DAI ("LPI TX1" ,LPI_MI2S_TX_1 ),Q6AFE_MI2S_TX_DAI ("LPI TX2" ,LPI_MI2S_TX_2 ),Q6AFE_MI2S_TX_DAI ("LPI TX3" ,LPI_MI2S_TX_3 ),Q6AFE_MI2S_TX_DAI ("LPI TX4" ,LPI_MI2S_TX_4 ), +Q6AFE_MI2S_TX_DAI ("LPI TX5" ,LPI_MI2S_TX_5 ), +Q6AFE_MI2S_TX_DAI ("LPI TX6" ,LPI_MI2S_TX_6 ),Q6AFE_TDM_PB_DAI ("Primary" ,0 ,PRIMARY_TDM_RX_0 ),Q6AFE_TDM_PB_DAI ("Primary" ,1 ,PRIMARY_TDM_RX_1 ), Q6AFE_TDM_PB_DAI("Primary", 2, PRIMARY_TDM_RX_2),
@@ -712,6 +716,7 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev, case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: case LPI_MI2S_RX_0 ... LPI_MI2S_TX_4: + case LPI_MI2S_RX_5 ... LPI_MI2S_TX_6: q6dsp_audio_fe_dais[i].ops = cfg->q6i2s_ops;break ; case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v5 06/15] ASoC: qdsp6: q6dsp-lpass-ports: add support for lpi mi2s ports 5-6
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Global singleton DAI array q6dsp_audio_fe_dais is unsafely modified, leading to cross-driver type confusion if multiple front-ends probe. --
commit 4aa03981f3bbeea9a8f5b00fc98ab94eec2d0492
Author: Richard Acayan <[email protected]>
ASoC: qdsp6: q6dsp-lpass-ports: add support for lpi mi2s ports 5-6
Add the extra LPI MI2S ports used for internal MI2S on SDM660.
Quoted 4 lines
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c +0
-0
[ ... ]
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev, · line 720
Quoted 6 lines
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c +1
-0@@ -712,6 +716,7 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev, case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: case LPI_MI2S_RX_0 ... LPI_MI2S_TX_4: + case LPI_MI2S_RX_5 ... LPI_MI2S_TX_6: q6dsp_audio_fe_dais[i].ops = cfg->q6i2s_ops;
[Severity: High]
This is a pre-existing issue, but adding new ports to this switch block highlights a potential problem with how q6dsp_audio_fe_dais is handled.
Since q6dsp_audio_ports_set_config() modifies the ops pointers of the global static q6dsp_audio_fe_dais array in-place, does this create a risk if multiple audio components that use this shared library probe on the same system?
If a second component probes, wouldn't it overwrite the ops pointers for all DAIs globally? Because ALSA stores a direct pointer to elements of this array during component registration via devm_snd_soc_register_component(), it seems the DAI callbacks for the first component could end up being executed by the second component's driver.
Could this cause cross-driver type confusion where a callback casts dev_get_drvdata(dai->dev) to its own driver data struct, but actually operates on the other component's data (like expecting q6apm_lpass_dai_data but getting q6afe_dai_data), potentially leading to memory corruption?
Quoted 2 lines
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c +0
-0break ; case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
PATCH v5 7/15 ASoC: qdsp6: q6afe: add internal mi2s support
In reply to Richard AcayanThe bindings for LPI MI2S ports, originally exclusive to q6apm, can be used for internal MI2S ports on q6afe. Add the port mappings for internal MI2S, found on the Snapdragon 660 internal sound card.
--- sound/soc/qcom/qdsp6/q6afe.c | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
sound/soc/qcom/qdsp6/q6afe.c +56 -0
@@ -132,6 +132,20 @@#define AFE_PORT_ID_QUINARY_MI2S_TX 0x1017#define AFE_PORT_ID_SENARY_MI2S_RX 0x1018#define AFE_PORT_ID_SENARY_MI2S_TX 0x1019 +#define AFE_PORT_ID_INT0_MI2S_RX 0x102e +#define AFE_PORT_ID_INT0_MI2S_TX 0x102f +#define AFE_PORT_ID_INT1_MI2S_RX 0x1030 +#define AFE_PORT_ID_INT1_MI2S_TX 0x1031 +#define AFE_PORT_ID_INT2_MI2S_RX 0x1032 +#define AFE_PORT_ID_INT2_MI2S_TX 0x1033 +#define AFE_PORT_ID_INT3_MI2S_RX 0x1034 +#define AFE_PORT_ID_INT3_MI2S_TX 0x1035 +#define AFE_PORT_ID_INT4_MI2S_RX 0x1036 +#define AFE_PORT_ID_INT4_MI2S_TX 0x1037 +#define AFE_PORT_ID_INT5_MI2S_RX 0x1038 +#define AFE_PORT_ID_INT5_MI2S_TX 0x1039 +#define AFE_PORT_ID_INT6_MI2S_RX 0x103a +#define AFE_PORT_ID_INT6_MI2S_TX 0x103b/* Start of the range of port IDs for TDM devices. */ #define AFE_PORT_ID_TDM_PORT_RANGE_START 0x9000
@@ -931,6 +945,34 @@ static struct afe_port_map port_maps[AFE_PORT_MAX] = { [RX_CODEC_DMA_RX_7 ] = {AFE_PORT_ID_RX_CODEC_DMA_RX_7 , RX_CODEC_DMA_RX_7, 1, 1}, [USB_RX] = { AFE_PORT_ID_USB_RX, USB_RX, 1, 1}, + [LPI_MI2S_RX_0 ] = {AFE_PORT_ID_INT0_MI2S_RX , + LPI_MI2S_RX_0, 1, 1}, + [LPI_MI2S_TX_0 ] = {AFE_PORT_ID_INT0_MI2S_TX , + LPI_MI2S_TX_0, 0, 1}, + [LPI_MI2S_RX_1 ] = {AFE_PORT_ID_INT1_MI2S_RX , + LPI_MI2S_RX_1, 1, 1}, + [LPI_MI2S_TX_1 ] = {AFE_PORT_ID_INT1_MI2S_TX , + LPI_MI2S_TX_1, 0, 1}, + [LPI_MI2S_RX_2 ] = {AFE_PORT_ID_INT2_MI2S_RX , + LPI_MI2S_RX_2, 1, 1}, + [LPI_MI2S_TX_2 ] = {AFE_PORT_ID_INT2_MI2S_TX , + LPI_MI2S_TX_2, 0, 1}, + [LPI_MI2S_RX_3 ] = {AFE_PORT_ID_INT3_MI2S_RX , + LPI_MI2S_RX_3, 1, 1}, + [LPI_MI2S_TX_3 ] = {AFE_PORT_ID_INT3_MI2S_TX , + LPI_MI2S_TX_3, 0, 1}, + [LPI_MI2S_RX_4 ] = {AFE_PORT_ID_INT4_MI2S_RX , + LPI_MI2S_RX_4, 1, 1}, + [LPI_MI2S_TX_4 ] = {AFE_PORT_ID_INT4_MI2S_TX , + LPI_MI2S_TX_4, 0, 1}, + [LPI_MI2S_RX_5 ] = {AFE_PORT_ID_INT5_MI2S_RX , + LPI_MI2S_RX_5, 1, 1}, + [LPI_MI2S_TX_5 ] = {AFE_PORT_ID_INT5_MI2S_TX , + LPI_MI2S_TX_5, 0, 1}, + [LPI_MI2S_RX_6 ] = {AFE_PORT_ID_INT6_MI2S_RX , + LPI_MI2S_RX_6, 1, 1}, + [LPI_MI2S_TX_6 ] = {AFE_PORT_ID_INT6_MI2S_TX , + LPI_MI2S_TX_6, 0, 1}, };static void q6afe_port_free (struct kref *ref)
@@ -1785,6 +1827,20 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)case AFE_PORT_ID_QUINARY_MI2S_TX :case AFE_PORT_ID_SENARY_MI2S_RX :case AFE_PORT_ID_SENARY_MI2S_TX : +case AFE_PORT_ID_INT0_MI2S_RX : +case AFE_PORT_ID_INT0_MI2S_TX : +case AFE_PORT_ID_INT1_MI2S_RX : +case AFE_PORT_ID_INT1_MI2S_TX : +case AFE_PORT_ID_INT2_MI2S_RX : +case AFE_PORT_ID_INT2_MI2S_TX : +case AFE_PORT_ID_INT3_MI2S_RX : +case AFE_PORT_ID_INT3_MI2S_TX : +case AFE_PORT_ID_INT4_MI2S_RX : +case AFE_PORT_ID_INT4_MI2S_TX : +case AFE_PORT_ID_INT5_MI2S_RX : +case AFE_PORT_ID_INT5_MI2S_TX : +case AFE_PORT_ID_INT6_MI2S_RX : +case AFE_PORT_ID_INT6_MI2S_TX : cfg_type =AFE_PARAM_ID_I2S_CONFIG ;break ; case AFE_PORT_ID_PRIMARY_TDM_RX ... AFE_PORT_ID_QUINARY_TDM_TX_7:
Signature · 1 line
2.54.0
PATCH v5 8/15 ASoC: qdsp6: q6afe-dai: add internal mi2s support
In reply to Richard AcayanThe bindings for LPI MI2S ports, originally exclusive to q6apm, can be used for internal MI2S ports on q6afe. Add the internal MI2S ports found on the SDM660 internal sound card using the LPI MI2S bindings.
--- sound/soc/qcom/qdsp6/q6afe-dai.c | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
sound/soc/qcom/qdsp6/q6afe-dai.c +48 -0
@@ -412,6 +412,8 @@ static int q6afe_dai_prepare(struct snd_pcm_substream *substream, case SENARY_MI2S_RX ... SENARY_MI2S_TX: case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case LPI_MI2S_RX_0 ... LPI_MI2S_TX_4: + case LPI_MI2S_RX_5 ... LPI_MI2S_TX_6: rc =q6afe_i2s_port_prepare (dai_data->port[dai->id], &dai_data->port_config[dai->id].i2s_cfg);if (rc <0 ) {
@@ -665,6 +667,21 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {/* USB playback AFE port receives data for playback, hence use the RX port */ {"USB Playback", NULL, "USB_RX"}, + + {"LPI RX0 MI2S Playback", NULL, "LPI_MI2S_RX_0"}, + {"LPI_MI2S_TX_0", NULL, "LPI TX0 MI2S Capture"}, + {"LPI RX1 MI2S Playback", NULL, "LPI_MI2S_RX_1"}, + {"LPI_MI2S_TX_1", NULL, "LPI TX1 MI2S Capture"}, + {"LPI RX2 MI2S Playback", NULL, "LPI_MI2S_RX_2"}, + {"LPI_MI2S_TX_2", NULL, "LPI TX2 MI2S Capture"}, + {"LPI RX3 MI2S Playback", NULL, "LPI_MI2S_RX_3"}, + {"LPI_MI2S_TX_3", NULL, "LPI TX3 MI2S Capture"}, + {"LPI RX4 MI2S Playback", NULL, "LPI_MI2S_RX_4"}, + {"LPI_MI2S_TX_4", NULL, "LPI TX4 MI2S Capture"}, + {"LPI RX5 MI2S Playback", NULL, "LPI_MI2S_RX_5"}, + {"LPI_MI2S_TX_5", NULL, "LPI TX5 MI2S Capture"}, + {"LPI RX6 MI2S Playback", NULL, "LPI_MI2S_RX_6"}, + {"LPI_MI2S_TX_6", NULL, "LPI TX6 MI2S Capture"}, };static int msm_dai_q6_dai_probe (struct snd_soc_dai *dai)
@@ -1011,6 +1028,35 @@ static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { 0, SND_SOC_NOPM, 0, 0),SND_SOC_DAPM_AIF_IN ("USB_RX" ,NULL ,0 ,SND_SOC_NOPM ,0 ,0 ), + +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_0" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_0" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_1" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_1" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_2" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_2" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_3" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_3" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_4" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_4" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_5" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_5" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("LPI_MI2S_RX_6" ,NULL , +0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("LPI_MI2S_TX_6" ,NULL , + 0, SND_SOC_NOPM, 0, 0), }; static const struct snd_soc_component_driver q6afe_dai_component = {
@@ -1045,6 +1091,8 @@ static void of_q6afe_parse_dai_data(struct device *dev, case SENARY_MI2S_RX ... SENARY_MI2S_TX: case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case LPI_MI2S_RX_0 ... LPI_MI2S_TX_4: + case LPI_MI2S_RX_5 ... LPI_MI2S_TX_6: priv = &data->priv[id]; ret = of_property_read_variable_u32_array(node, "qcom,sd-lines",
Signature · 1 line
2.54.0
PATCH v5 9/15 ASoC: qdsp6: q6routing: add lpi mi2s support
In reply to Richard AcayanAdd the ASM-AFE routing for LPI MI2S ports which represent internal MI2S ports on SDM660.
--- sound/soc/qcom/qdsp6/q6routing.c | 78 +++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-)
sound/soc/qcom/qdsp6/q6routing.c +77 -1
@@ -127,7 +127,14 @@ { mix_name, "TX_CODEC_DMA_TX_2", "TX_CODEC_DMA_TX_2"}, \ { mix_name, "TX_CODEC_DMA_TX_3", "TX_CODEC_DMA_TX_3"}, \ { mix_name, "TX_CODEC_DMA_TX_4", "TX_CODEC_DMA_TX_4"}, \ - { mix_name, "TX_CODEC_DMA_TX_5", "TX_CODEC_DMA_TX_5"} + { mix_name, "TX_CODEC_DMA_TX_5", "TX_CODEC_DMA_TX_5"}, \ + { mix_name, "LPI_MI2S_TX_0", "LPI_MI2S_TX_0" }, \ + { mix_name, "LPI_MI2S_TX_1", "LPI_MI2S_TX_1" }, \ + { mix_name, "LPI_MI2S_TX_2", "LPI_MI2S_TX_2" }, \ + { mix_name, "LPI_MI2S_TX_3", "LPI_MI2S_TX_3" }, \ + { mix_name, "LPI_MI2S_TX_4", "LPI_MI2S_TX_4" }, \ + { mix_name, "LPI_MI2S_TX_5", "LPI_MI2S_TX_5" }, \ + { mix_name, "LPI_MI2S_TX_6", "LPI_MI2S_TX_6" } #define Q6ROUTING_TX_MIXERS(id) \ SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, \
@@ -320,6 +327,27 @@ id, 1, 0, msm_routing_get_audio_mixer, \ msm_routing_put_audio_mixer), \SOC_SINGLE_EXT ("TX_CODEC_DMA_TX_5" ,TX_CODEC_DMA_TX_5 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_0" ,LPI_MI2S_TX_0 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_1" ,LPI_MI2S_TX_1 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_2" ,LPI_MI2S_TX_2 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_3" ,LPI_MI2S_TX_3 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_4" ,LPI_MI2S_TX_4 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_5" ,LPI_MI2S_TX_5 , \ + id,1 ,0 , msm_routing_get_audio_mixer, \ + msm_routing_put_audio_mixer), \ +SOC_SINGLE_EXT ("LPI_MI2S_TX_6" ,LPI_MI2S_TX_6 , \ id,1 ,0 , msm_routing_get_audio_mixer, \ msm_routing_put_audio_mixer),
@@ -709,6 +737,26 @@ static const struct snd_kcontrol_new rxcodec_dma_rx_6_mixer_controls[] = {static const struct snd_kcontrol_new rx_codec_dma_rx_7_mixer_controls[] = {Q6ROUTING_RX_MIXERS (RX_CODEC_DMA_RX_7 ) }; +static const struct snd_kcontrol_new lpi_mi2s_rx_0_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_0 ) }; + +static const struct snd_kcontrol_new lpi_mi2s_rx_1_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_1 ) }; + +static const struct snd_kcontrol_new lpi_mi2s_rx_2_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_2 ) }; + +static const struct snd_kcontrol_new lpi_mi2s_rx_3_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_3 ) }; + +static const struct snd_kcontrol_new lpi_mi2s_rx_4_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_4 ) }; + +static const struct snd_kcontrol_new lpi_mi2s_rx_5_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_5 ) }; + +static const struct snd_kcontrol_new lpi_mi2s_rx_6_mixer_controls[] = { +Q6ROUTING_RX_MIXERS (LPI_MI2S_RX_6 ) };static const struct snd_kcontrol_new mmul1_mixer_controls[] = {Q6ROUTING_TX_MIXERS (MSM_FRONTEND_DAI_MULTIMEDIA1 ) };
@@ -938,6 +986,27 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {SND_SOC_DAPM_MIXER ("USB_RX Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , usb_rx_mixer_controls,ARRAY_SIZE (usb_rx_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_0 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_0_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_0_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_1 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_1_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_1_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_2 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_2_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_2_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_3 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_3_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_3_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_4 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_4_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_4_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_5 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_5_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_5_mixer_controls)), +SND_SOC_DAPM_MIXER ("LPI_MI2S_RX_6 Audio Mixer" ,SND_SOC_NOPM ,0 ,0 , + lpi_mi2s_rx_6_mixer_controls, +ARRAY_SIZE (lpi_mi2s_rx_6_mixer_controls)),SND_SOC_DAPM_MIXER ("MultiMedia1 Mixer" ,SND_SOC_NOPM ,0 ,0 , mmul1_mixer_controls,ARRAY_SIZE (mmul1_mixer_controls)), SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
@@ -1031,6 +1100,13 @@ static const struct snd_soc_dapm_route intercon[] = {Q6ROUTING_RX_DAPM_ROUTE ("RX_CODEC_DMA_RX_6 Audio Mixer" ,"RX_CODEC_DMA_RX_6" ),Q6ROUTING_RX_DAPM_ROUTE ("RX_CODEC_DMA_RX_7 Audio Mixer" ,"RX_CODEC_DMA_RX_7" ),Q6ROUTING_RX_DAPM_ROUTE ("USB_RX Audio Mixer" ,"USB_RX" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_0 Audio Mixer" ,"LPI_MI2S_RX_0" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_1 Audio Mixer" ,"LPI_MI2S_RX_1" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_2 Audio Mixer" ,"LPI_MI2S_RX_2" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_3 Audio Mixer" ,"LPI_MI2S_RX_3" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_4 Audio Mixer" ,"LPI_MI2S_RX_4" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_5 Audio Mixer" ,"LPI_MI2S_RX_5" ), +Q6ROUTING_RX_DAPM_ROUTE ("LPI_MI2S_RX_6 Audio Mixer" ,"LPI_MI2S_RX_6" ),Q6ROUTING_TX_DAPM_ROUTE ("MultiMedia1 Mixer" ),Q6ROUTING_TX_DAPM_ROUTE ("MultiMedia2 Mixer" ), Q6ROUTING_TX_DAPM_ROUTE("MultiMedia3 Mixer"),
Signature · 1 line
2.54.0
PATCH v5 10/15 ASoC: qdsp6: common: support headphone jacks connected to lpi mi2s
In reply to Richard AcayanOn SDM660, LPI MI2S ports can be connected to a WCD codec which may support headphones. Register the headphone jack on codecs connected to the playback port, LPI_MI2S_RX_0.
--- sound/soc/qcom/common.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/qcom/common.c +1 -0
@@ -232,6 +232,7 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, }switch (cpu_dai->id) { +case LPI_MI2S_RX_0 :case TX_CODEC_DMA_TX_0 :case TX_CODEC_DMA_TX_1 :case TX_CODEC_DMA_TX_2 :
Signature · 1 line
2.54.0
PATCH v5 11/15 ASoC: qcom: sm8250: add support for LPI_MI2S_RX_0 and LPI_MI2S_TX_3
In reply to Richard AcayanThe LPI_MI2S_RX_0 and LPI_MI2S_TX_3 ports on SDM660 can be connected to the digital and analog WCD codecs. They can be supported with the same logic for other ports, but just need to be explicitly stated. Add support for these ports.
--- sound/soc/qcom/sm8250.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
sound/soc/qcom/sm8250.c +16 -0
@@ -112,6 +112,22 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)snd_soc_dai_set_fmt (cpu_dai, fmt);snd_soc_dai_set_fmt (codec_dai, codec_dai_fmt);break ; +case LPI_MI2S_RX_0 : + codec_dai_fmt |=SND_SOC_DAIFMT_NB_NF |SND_SOC_DAIFMT_I2S ; +snd_soc_dai_set_sysclk (cpu_dai, +Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT , +MI2S_BCLK_RATE ,SNDRV_PCM_STREAM_PLAYBACK ); +snd_soc_dai_set_fmt (cpu_dai, fmt); +snd_soc_dai_set_fmt (codec_dai, codec_dai_fmt); +break ; +case LPI_MI2S_TX_3 : + codec_dai_fmt |=SND_SOC_DAIFMT_NB_NF |SND_SOC_DAIFMT_I2S ; +snd_soc_dai_set_sysclk (cpu_dai, +Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT , +MI2S_BCLK_RATE ,SNDRV_PCM_STREAM_CAPTURE ); +snd_soc_dai_set_fmt (cpu_dai, fmt); +snd_soc_dai_set_fmt (codec_dai, codec_dai_fmt); +break ;default :break ; }
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v5 11/15] ASoC: qcom: sm8250: add support for LPI_MI2S_RX_0 and LPI_MI2S_TX_3
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Hardware clock leak: MI2S sysclks are enabled on startup but never disabled on shutdown --
commit d56ecb81f1a498d069991569b37a6e2d484e4d23
Author: Richard Acayan <[email protected]>
ASoC: qcom: sm8250: add support for LPI_MI2S_RX_0 and LPI_MI2S_TX_3
This commit adds support for the LPI_MI2S_RX_0 and LPI_MI2S_TX_3 ports to the sm8250 machine driver. It configures the DAI formats and sets the sysclk for these new ports in the startup callback.
sound/soc/qcom/sm8250.c static int sm8250_snd_startup(struct snd_pcm_substream *substream) · line 119
Quoted 13 lines
sound/soc/qcom/sm8250.c +5
-0@@ -112,6 +112,22 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)snd_soc_dai_set_fmt (cpu_dai, fmt);snd_soc_dai_set_fmt (codec_dai, codec_dai_fmt);break ; +case LPI_MI2S_RX_0 : + codec_dai_fmt |=SND_SOC_DAIFMT_NB_NF |SND_SOC_DAIFMT_I2S ; +snd_soc_dai_set_sysclk (cpu_dai, +Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT , +MI2S_BCLK_RATE ,SNDRV_PCM_STREAM_PLAYBACK );
[Severity: High]
This is a pre-existing issue, but does this code leak the hardware clock?
The machine driver enables the DSP MI2S IBIT clocks via snd_soc_dai_set_sysclk() during stream startup, which sends an AFE_PARAM_ID_CLOCK_SET command to the DSP.
However, looking at the rest of the driver, the associated .shutdown callback (qcom_snd_sdw_shutdown) is specific to SoundWire and ignores MI2S DAIs.
Because there is no matching logic to call snd_soc_dai_set_sysclk() with a 0 frequency on stream close, will the DSP clock remain permanently enabled after the first playback and prevent the DSP and SoC from entering deep sleep states?
Quoted 3 lines
sound/soc/qcom/sm8250.c +3
-0+snd_soc_dai_set_fmt (cpu_dai, fmt); +snd_soc_dai_set_fmt (codec_dai, codec_dai_fmt); +break ;
[ ... ]
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=11
PATCH v5 12/15 ASoC: qcom: sm8250: add SDM660 compatible
In reply to Richard AcayanAdd the compatible for SDM660 and SDM670 devices, which can use the support for WCD codecs connected to internal MI2S.
--- sound/soc/qcom/sm8250.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/qcom/sm8250.c +1 -0
@@ -210,6 +210,7 @@ static const struct of_device_id snd_sm8250_dt_match[] = { { .compatible = "qcom,qrb2210-sndcard", .data = "qcm2290" }, { .compatible = "qcom,qrb4210-rb2-sndcard", .data = "sm4250" }, { .compatible = "qcom,qrb5165-rb5-sndcard", .data = "sm8250" }, + { .compatible = "qcom,sdm660-sndcard", .data = "sdm660" }, { .compatible = "qcom,sm8250-sndcard", .data = "sm8250" }, {} };
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v5 12/15] ASoC: qcom: sm8250: add SDM660 compatible
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] The commit message claims to add the compatible string for SDM670 devices, but it is completely…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The commit message claims to add the compatible string for SDM670 devices, but it is completely missing from the implementation. --
commit 075844a100dc2d901b8571b7631f5698eae8be05
Author: Richard Acayan <[email protected]>
ASoC: qcom: sm8250: add SDM660 compatible
This commit adds support for SDM660 devices to use WCD codecs connected to internal MI2S.
sound/soc/qcom/sm8250.c static const struct of_device_id snd_sm8250_dt_match[] = { · line 213
Quoted 12 lines
Add the compatible for SDM660 and SDM670 devices, which can use the support for WCD codecs connected to internal MI2S.
sound/soc/qcom/sm8250.c +1
-0@@ -210,6 +210,7 @@ static const struct of_device_id snd_sm8250_dt_match[] = { { .compatible = "qcom,qrb2210-sndcard", .data = "qcm2290" }, { .compatible = "qcom,qrb4210-rb2-sndcard", .data = "sm4250" }, { .compatible = "qcom,qrb5165-rb5-sndcard", .data = "sm8250" }, + { .compatible = "qcom,sdm660-sndcard", .data = "sdm660" },
[Severity: Medium]
The commit message indicates that this patch adds the compatible string for SDM670 devices, but only the SDM660 compatible is added here in snd_sm8250_dt_match.
Was the SDM670 compatible intentionally omitted from the array, or should the commit message be updated to match the code?
Quoted 2 lines
sound/soc/qcom/sm8250.c +0
-0{ .compatible = "qcom,sm8250-sndcard", .data = "sm8250" }, {}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=12
PATCH v5 13/15 ASoC: msm8916-wcd-analog: add pm8950 codec
In reply to Richard AcayanFrom: Adam Skladowski <[email protected]>
Add regs overrides for PM8950 codec and implement matching reg overrides via compatible.
--- sound/soc/codecs/msm8916-wcd-analog.c | 52 ++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-)
sound/soc/codecs/msm8916-wcd-analog.c +48 -4
@@ -232,6 +232,8 @@#define RX_EAR_CTL_PA_SEL_MASK BIT(7)#define RX_EAR_CTL_PA_SEL BIT(7) +#define CDC_A_RX_EAR_STATUS (0xf1A1) +#define CDC_A_SPKR_DAC_CTL (0xf1B0)#define SPKR_DAC_CTL_DAC_RESET_MASK BIT(4)#define SPKR_DAC_CTL_DAC_RESET_NORMAL 0
@@ -250,6 +252,7 @@ SPKR_DRV_CAL_EN | SPKR_DRV_SETTLE_EN | \ SPKR_DRV_FW_EN | SPKR_DRV_BOOST_SET | \ SPKR_DRV_CMFB_SET | SPKR_DRV_GAIN_SET) +#define CDC_A_SPKR_ANA_BIAS_SET (0xf1B3)#define CDC_A_SPKR_OCP_CTL (0xf1B4)#define CDC_A_SPKR_PWRSTG_CTL (0xf1B5)#define SPKR_PWRSTG_CTL_DAC_EN_MASK BIT(0)
@@ -264,6 +267,7 @@#define CDC_A_SPKR_DRV_DBG (0xf1B7)#define CDC_A_CURRENT_LIMIT (0xf1C0) +#define CDC_A_BYPASS_MODE (0xf1C2)#define CDC_A_BOOST_EN_CTL (0xf1C3)#define CDC_A_SLOPE_COMP_IP_ZERO (0xf1C4)#define CDC_A_SEC_ACCESS (0xf1D0)
@@ -286,6 +290,11 @@ static const char * const supply_names[] = {#define MBHC_MAX_BUTTONS (5) +struct wcd_reg_seq { +const struct reg_default *seq; +int seq_size; +}; +struct pm8916_wcd_analog_priv {u16 pmic_rev;u16 codec_version;
@@ -715,9 +724,41 @@ static const struct reg_default wcd_reg_defaults_2_0[] = { {CDC_A_MASTER_BIAS_CTL, 0x30}, }; +static const struct wcd_reg_seq pm8916_data = { + .seq = wcd_reg_defaults_2_0, + .seq_size =ARRAY_SIZE (wcd_reg_defaults_2_0), +}; + +static const struct reg_default wcd_reg_defaults_pm8950[] = { + {CDC_A_RX_COM_OCP_CTL ,0xd1 }, + {CDC_A_RX_COM_OCP_COUNT ,0xff }, + {CDC_D_SEC_ACCESS ,0xa5 }, + {CDC_D_PERPH_RESET_CTL3 ,0x0f }, + {CDC_A_TX_1_2_OPAMP_BIAS ,0x4c }, + {CDC_A_NCP_FBCTRL ,0xa8 }, + {CDC_A_NCP_VCTRL ,0xa4 }, + {CDC_A_SPKR_DRV_CTL ,0x69 }, + {CDC_A_SPKR_DRV_DBG ,0x01 }, + {CDC_A_SEC_ACCESS ,0xa5 }, + {CDC_A_PERPH_RESET_CTL3 ,0x0f }, + {CDC_A_CURRENT_LIMIT ,0x82 }, + {CDC_A_SPKR_ANA_BIAS_SET ,0x41 }, + {CDC_A_SPKR_DAC_CTL ,0x03 }, + {CDC_A_SPKR_OCP_CTL ,0xe1 }, + {CDC_A_RX_HPH_BIAS_PA ,0xfa }, + {CDC_A_MASTER_BIAS_CTL ,0x30 }, + {CDC_A_MICB_1_INT_RBIAS ,0x00 }, +}; + +static const struct wcd_reg_seq pm8950_data = { + .seq = wcd_reg_defaults_pm8950, + .seq_size =ARRAY_SIZE (wcd_reg_defaults_pm8950), +}; +static int pm8916_wcd_analog_probe (struct snd_soc_component *component) {struct pm8916_wcd_analog_priv *priv =dev_get_drvdata (component->dev); +const struct wcd_reg_seq *wcd_reg_init_data;int err, reg; err =regulator_bulk_enable (ARRAY_SIZE (priv->supplies), priv->supplies);
@@ -738,9 +779,11 @@ static int pm8916_wcd_analog_probe(struct snd_soc_component *component)snd_soc_component_write (component,CDC_D_PERPH_RESET_CTL4 ,0x01 );snd_soc_component_write (component,CDC_A_PERPH_RESET_CTL4 ,0x01 ); -for (reg =0 ; reg <ARRAY_SIZE (wcd_reg_defaults_2_0); reg++) -snd_soc_component_write (component, wcd_reg_defaults_2_0[reg].reg, - wcd_reg_defaults_2_0[reg].def); + wcd_reg_init_data =of_device_get_match_data (component->dev); + +for (reg =0 ; reg < wcd_reg_init_data->seq_size; reg++) +snd_soc_component_write (component, wcd_reg_init_data->seq[reg].reg, + wcd_reg_init_data->seq[reg].def); priv->component = component;
@@ -1259,7 +1302,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) }static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { - { .compatible ="qcom,pm8916-wcd-analog-codec" , }, + { .compatible ="qcom,pm8916-wcd-analog-codec" , .data = &pm8916_data }, + { .compatible ="qcom,pm8950-wcd-analog-codec" , .data = &pm8950_data }, { } };
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v5 13/15] ASoC: msm8916-wcd-analog: add pm8950 codec
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Interrupts are requested before their dependencies are initialized, leading to a NULL pointer dereference if an interrupt fires early. --
(Due to recitation restrictions, I cannot quote the patch directly. Here is a free-form summary of the review findings based on the provided commit.)
commit 6bdf31b5b0e7905983f34bd3546744e90b15273e
Author: Adam Skladowski <[email protected]>
ASoC: msm8916-wcd-analog: add pm8950 codec
This commit adds register overrides for the PM8950 codec. It also implements matching register overrides via the compatible string array.
[Severity: High]
This isn't a bug introduced by this patch, but could this pre-existing setup cause a NULL pointer dereference if an interrupt fires early?
In pm8916_wcd_analog_spmi_probe(), threaded IRQs (such as pm8916_mbhc_switch_irq_handler and mbhc_btn_press_irq_handler) are requested via devm_request_threaded_irq(). This enables the interrupts immediately. However, the ASoC component (priv->component) isn't initialized until much later in pm8916_wcd_analog_probe() during ASoC sound card binding.
If the interrupt fires before the component probe, the IRQ handler executes with a NULL priv->component:
pm8916_mbhc_switch_irq_handler()
struct snd_soc_component *component = priv->component;
if (snd_soc_component_read(component, CDC_A_MBHC_DET_CTL_1) ...Passing this NULL component pointer to snd_soc_component_read() looks like it would cause a crash. Should the IRQ registration be deferred to the component probe, or kept disabled until the component is fully initialized?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=13
PATCH v5 14/15 ASoC: msm8916-wcd-analog: add pm8953 codec
In reply to Richard AcayanFrom: Vladimir Lypak <[email protected]>
Add regs overrides for PM8953 codec.
--- sound/soc/codecs/msm8916-wcd-analog.c | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
sound/soc/codecs/msm8916-wcd-analog.c +29 -0
@@ -755,6 +755,34 @@ static const struct wcd_reg_seq pm8950_data = { .seq_size = ARRAY_SIZE(wcd_reg_defaults_pm8950), }; +static const struct reg_default wcd_reg_defaults_pm8953[] = { + {CDC_A_RX_COM_OCP_CTL ,0xd1 }, + {CDC_A_RX_COM_OCP_COUNT ,0xff }, + {CDC_D_SEC_ACCESS ,0xa5 }, + {CDC_D_PERPH_RESET_CTL3 ,0x0f }, + {CDC_A_TX_1_2_OPAMP_BIAS ,0x4c }, + {CDC_A_NCP_FBCTRL ,0xa8 }, + {CDC_A_NCP_VCTRL ,0xa4 }, + {CDC_A_SPKR_DRV_CTL ,0x69 }, + {CDC_A_SPKR_DRV_DBG ,0x01 }, + {CDC_A_SEC_ACCESS ,0xa5 }, + {CDC_A_PERPH_RESET_CTL3 ,0x0f }, + {CDC_A_CURRENT_LIMIT ,0xa2 }, + {CDC_A_BYPASS_MODE ,0x18 }, + {CDC_A_SPKR_ANA_BIAS_SET ,0x41 }, + {CDC_A_SPKR_DAC_CTL ,0x03 }, + {CDC_A_SPKR_OCP_CTL ,0xe1 }, + {CDC_A_RX_HPH_BIAS_PA ,0xfa }, + {CDC_A_RX_EAR_STATUS ,0x10 }, + {CDC_A_MASTER_BIAS_CTL ,0x30 }, + {CDC_A_MICB_1_INT_RBIAS ,0x00 }, +}; + +static const struct wcd_reg_seq pm8953_data = { + .seq = wcd_reg_defaults_pm8953, + .seq_size =ARRAY_SIZE (wcd_reg_defaults_pm8953), +}; +static int pm8916_wcd_analog_probe (struct snd_soc_component *component) {struct pm8916_wcd_analog_priv *priv =dev_get_drvdata (component->dev);
@@ -1304,6 +1332,7 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { { .compatible ="qcom,pm8916-wcd-analog-codec" , .data = &pm8916_data }, { .compatible ="qcom,pm8950-wcd-analog-codec" , .data = &pm8950_data }, + { .compatible ="qcom,pm8953-wcd-analog-codec" , .data = &pm8953_data }, { } };
Signature · 1 line
2.54.0
PATCH v5 15/15 ASoC: msm8916-wcd-analog: add quirk for cajon 2.0
In reply to Richard AcayanThe codec version CAJON_2_0 on the Snapdragon 670 requires touching the HPH test registers. Add the quirk so this driver can also support SDM670.
--- sound/soc/codecs/msm8916-wcd-analog.c | 63 ++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-)
sound/soc/codecs/msm8916-wcd-analog.c +61 -2
@@ -217,9 +217,11 @@#define CDC_A_RX_HPH_BIAS_LDO_OCP (0xf195)#define CDC_A_RX_HPH_BIAS_CNP (0xf196)#define CDC_A_RX_HPH_CNP_EN (0xf197) +#define CDC_A_RX_HPH_L_TEST (0xf19A)#define CDC_A_RX_HPH_L_PA_DAC_CTL (0xf19B)#define RX_HPA_L_PA_DAC_CTL_DATA_RESET_MASK BIT(1)#define RX_HPA_L_PA_DAC_CTL_DATA_RESET_RESET BIT(1) +#define CDC_A_RX_HPH_R_TEST (0xf19C)#define CDC_A_RX_HPH_R_PA_DAC_CTL (0xf19D)#define RX_HPH_R_PA_DAC_CTL_DATA_RESET BIT(1)#define RX_HPH_R_PA_DAC_CTL_DATA_RESET_MASK BIT(1)
@@ -705,6 +707,59 @@ static int pm8916_wcd_analog_enable_ear_pa(struct snd_soc_dapm_widget *w,return 0 ; } +static int pm8916_wcd_analog_enable_hphl_pa (struct snd_soc_dapm_widget *w, +struct snd_kcontrol *kcontrol, +int event) +{ +struct snd_soc_component *component =snd_soc_dapm_to_component (w->dapm); +struct pm8916_wcd_analog_priv *priv =dev_get_drvdata (component->dev); + +/* This quirk is not required for revisions prior to CAJON_2_0 */ +if (priv->codec_version <4 ) +return 0 ; + +switch (event) { +case SND_SOC_DAPM_POST_PMU : +usleep_range (7000 ,7100 ); +snd_soc_component_update_bits (component,CDC_A_RX_HPH_L_TEST , +0x04 ,0x04 ); +break ; +case SND_SOC_DAPM_POST_PMD : +/* wait 20 ms after the digital codec has powered down */ +msleep (20 ); +snd_soc_component_update_bits (component,CDC_A_RX_HPH_L_TEST , +0x04 ,0x00 ); +break ; + } +return 0 ; +} + +static int pm8916_wcd_analog_enable_hphr_pa (struct snd_soc_dapm_widget *w, +struct snd_kcontrol *kcontrol, +int event) +{ +struct snd_soc_component *component =snd_soc_dapm_to_component (w->dapm); +struct pm8916_wcd_analog_priv *priv =dev_get_drvdata (component->dev); + +/* This quirk is not required for revisions prior to CAJON_2_0 */ +if (priv->codec_version <4 ) +return 0 ; + +switch (event) { +case SND_SOC_DAPM_POST_PMU : +usleep_range (7000 ,7100 ); +snd_soc_component_update_bits (component,CDC_A_RX_HPH_R_TEST , +0x04 ,0x04 ); +break ; +case SND_SOC_DAPM_POST_PMD : +msleep (20 ); +snd_soc_component_update_bits (component,CDC_A_RX_HPH_R_TEST , +0x04 ,0x00 ); +break ; + } +return 0 ; +} +static const struct reg_default wcd_reg_defaults_2_0[] = { {CDC_A_RX_COM_OCP_CTL ,0xD1 }, {CDC_A_RX_COM_OCP_COUNT ,0xFF },
@@ -954,11 +1009,15 @@ static const struct snd_soc_dapm_widget pm8916_wcd_analog_dapm_widgets[] = {SND_SOC_DAPM_MUX ("EAR_S" ,SND_SOC_NOPM ,0 ,0 , &ear_mux),SND_SOC_DAPM_SUPPLY ("EAR CP" ,CDC_A_NCP_EN ,4 ,0 ,NULL ,0 ), -SND_SOC_DAPM_PGA ("HPHL PA" ,CDC_A_RX_HPH_CNP_EN ,5 ,0 ,NULL ,0 ), +SND_SOC_DAPM_PGA_E ("HPHL PA" ,CDC_A_RX_HPH_CNP_EN ,5 ,0 ,NULL ,0 , + pm8916_wcd_analog_enable_hphl_pa, +SND_SOC_DAPM_POST_PMU |SND_SOC_DAPM_POST_PMD ),SND_SOC_DAPM_MUX ("HPHL" ,SND_SOC_NOPM ,0 ,0 , &hphl_mux),SND_SOC_DAPM_MIXER ("HPHL DAC" ,CDC_A_RX_HPH_L_PA_DAC_CTL ,3 ,0 ,NULL ,0 ), -SND_SOC_DAPM_PGA ("HPHR PA" ,CDC_A_RX_HPH_CNP_EN ,4 ,0 ,NULL ,0 ), +SND_SOC_DAPM_PGA_E ("HPHR PA" ,CDC_A_RX_HPH_CNP_EN ,4 ,0 ,NULL ,0 , + pm8916_wcd_analog_enable_hphr_pa, +SND_SOC_DAPM_POST_PMU |SND_SOC_DAPM_POST_PMD ),SND_SOC_DAPM_MUX ("HPHR" ,SND_SOC_NOPM ,0 ,0 , &hphr_mux),SND_SOC_DAPM_MIXER ("HPHR DAC" ,CDC_A_RX_HPH_R_PA_DAC_CTL ,3 ,0 ,NULL , 0),
Signature · 1 line
2.54.0