Commit 4b73a4cd authored by Mark Brown's avatar Mark Brown

ASoC: Cleanup MediaTek soundcard machine drivers

Merge series from AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>:

Changes in v5:
 - Cleaned up MT8186 soundcard migration commit which erroneously
   had leftovers from development
 - Changed the mtk_pcm_constraints_data structure to hold pointers
   to snd_pcm_hw_constraint_list, as to really reuse the const data
 - Tested again on all of the listed MTK platforms.

Changes in v4:
 - Rebased over next-20240409
 - Dropped the first 4 patches from v3 as were already picked by Mark
 - Fixed W=1 build issue

Changes in v3:
 - Added audio-routing names in enum in all yaml files
 - Added mention of disallowing old and new properties together in
   commit message of bindings patches
 - Fixed validation errors with sound-card-common.yaml inclusion
   due to missing model property in examples
 - Removed `else` enforcing headset-codec/speaker-codecs requirement
   if xxx-dai-link not present to avoid future commit noise as the
   deprecated statement will disallow deprecated properties as required

Changes in v2:
 - Bindings: Changed link-name/codec/clk-provider to remove `items`
   and leave just the enum
 - Moved .*-dai-link pattern additionalProperties after `type: object`
 - Added ref to sound-card-common.yaml
 - Fixed dai-link-xxx -> xxx-dai-link typo in example comment

This series performs a cleanup of most of the MediaTek AFE drivers and
soundcard machine drivers, reducing code duplication and setting a base
to be consistent with their devicetree bindings, as many of those are
using different properties and nodes for no good reason.

Summarizing:
 - Commonizes functions and ops where possible
 - Adds a common probe mechanism, increasing maintainability of
   soundcard drivers for older MediaTek SoCs
 - Migrates all drivers to support the new bindings
   - Obviously retains compatibility with old device trees
 - Reduces machine-specific parameters hardcoding in drivers
   - Can now set machine-specific params in device tree
   - Uses the `audio-routing` and `dai-link` nodes like some
     other non-MediaTek SoC sound drivers
 - Imposes consistency between MediaTek ASoC machine soundcard
   drivers bindings
 - Reduces code size and greatly reduces the amount of code that
   will be required for newer drivers (retaining compatibility with
   the old bindings was costly in terms of code size, otherwise
   this series would've removed ~1000 more lines, or something
   along that line).

This series was (manually) tested on MT8173, MT8192, MT8195 and MT8186
Chromebooks.

AngeloGioacchino Del Regno (18):
  ASoC: mediatek: Add common machine soundcard driver probe mechanism
  ASoC: mediatek: common: Constify struct mtk_sof_priv
  ASoC: mediatek: mt8188: Migrate to mtk_soundcard_common_probe
  ASoC: mediatek: mt8195: Migrate to mtk_soundcard_common_probe
  ASoC: mediatek: mt8192: Migrate to mtk_soundcard_common_probe
  ASoC: mediatek: mt8186: Migrate to mtk_soundcard_common_probe
  ASoC: mediatek: Add common snd_soc_ops .startup() callback
  ASoC: mediatek: mt8195: Migrate to the common mtk_soundcard_startup
  ASoC: mediatek: mt8192: Migrate to the common mtk_soundcard_startup
  ASoC: mediatek: mt8186-rt1019: Migrate to the common
    mtk_soundcard_startup
  ASoC: mediatek: Add common mtk_afe_component_probe callback
  ASoC: mediatek: Use common mtk_afe_pcm_platform with common probe cb
  ASoC: mediatek: mt8186: Unify mt8186-mt6366 machine drivers
  ASoC: dt-bindings: mt8195: Document audio-routing and dai-link subnode
  ASoC: dt-bindings: mt8192: Document audio-routing and dai-link subnode
  ASoC: dt-bindings: mt8186: Document audio-routing and dai-link subnode
  arm64: dts: mediatek: mt8195-cherry: Specify sound DAI links and
    routing
  arm64: dts: mediatek: mt8186-corsola: Specify sound DAI links and
    routing

 .../sound/mt8186-mt6366-da7219-max98357.yaml  |  131 +-
 .../sound/mt8186-mt6366-rt1019-rt5682s.yaml   |  120 +-
 .../sound/mt8192-mt6359-rt1015-rt5682.yaml    |  139 +-
 .../bindings/sound/mt8195-mt6359.yaml         |  134 ++
 .../boot/dts/mediatek/mt8186-corsola.dtsi     |   42 +-
 .../boot/dts/mediatek/mt8195-cherry.dtsi      |   45 +
 sound/soc/mediatek/Kconfig                    |   24 +-
 .../mediatek/common/mtk-afe-platform-driver.c |   18 +
 .../soc/mediatek/common/mtk-dsp-sof-common.c  |   15 +-
 .../soc/mediatek/common/mtk-dsp-sof-common.h  |    1 -
 sound/soc/mediatek/common/mtk-soc-card.h      |    7 +-
 .../mediatek/common/mtk-soundcard-driver.c    |  199 +++
 .../mediatek/common/mtk-soundcard-driver.h    |   42 +
 sound/soc/mediatek/mt6797/mt6797-afe-pcm.c    |   14 +-
 sound/soc/mediatek/mt7986/mt7986-afe-pcm.c    |   14 +-
 sound/soc/mediatek/mt8183/mt8183-afe-pcm.c    |   14 +-
 sound/soc/mediatek/mt8186/Makefile            |    3 +-
 .../mt8186/mt8186-mt6366-da7219-max98357.c    | 1189 -----------------
 ...t6366-rt1019-rt5682s.c => mt8186-mt6366.c} |  578 ++++----
 sound/soc/mediatek/mt8188/mt8188-afe-pcm.c    |   21 +-
 sound/soc/mediatek/mt8188/mt8188-mt6359.c     |  203 +--
 sound/soc/mediatek/mt8192/mt8192-afe-pcm.c    |   25 +-
 .../mt8192/mt8192-mt6359-rt1015-rt5682.c      |  301 ++---
 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    |   21 +-
 sound/soc/mediatek/mt8195/mt8195-mt6359.c     |  487 +++----
 25 files changed, 1597 insertions(+), 2190 deletions(-)
 delete mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c
 rename sound/soc/mediatek/mt8186/{mt8186-mt6366-rt1019-rt5682s.c => mt8186-mt6366.c} (72%)

--
2.44.0
parents 58300f8d 787f190c
......@@ -12,17 +12,46 @@ maintainers:
description:
This binding describes the MT8186 sound card.
allOf:
- $ref: sound-card-common.yaml#
properties:
compatible:
enum:
- mediatek,mt8186-mt6366-da7219-max98357-sound
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source.
Valid names could be the input or output widgets of audio components,
power supplies, MicBias of codec and the software switch.
minItems: 2
items:
enum:
# Sinks
- HDMI1
- Headphones
- Line Out
- MIC
- Speakers
# Sources
- Headset Mic
- HPL
- HPR
- Speaker
- TX
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8186 ASoC platform.
headset-codec:
type: object
deprecated: true
additionalProperties: false
properties:
sound-dai:
......@@ -32,6 +61,7 @@ properties:
playback-codecs:
type: object
deprecated: true
additionalProperties: false
properties:
sound-dai:
......@@ -53,32 +83,115 @@ properties:
A list of the desired dai-links in the sound card. Each entry is a
name defined in the machine driver.
additionalProperties: false
patternProperties:
".*-dai-link$":
type: object
additionalProperties: false
description:
Container for dai-link level properties and CODEC sub-nodes.
properties:
link-name:
description: Indicates dai-link name and PCM stream name
items:
enum:
- I2S0
- I2S1
- I2S2
- I2S3
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
maxItems: 2
required:
- sound-dai
dai-format:
description: audio format
items:
enum:
- i2s
- right_j
- left_j
- dsp_a
- dsp_b
mediatek,clk-provider:
$ref: /schemas/types.yaml#/definitions/string
description: Indicates dai-link clock master.
items:
enum:
- cpu
- codec
required:
- link-name
unevaluatedProperties: false
required:
- compatible
- mediatek,platform
- headset-codec
- playback-codecs
# Disallow legacy properties if xxx-dai-link nodes are specified
if:
not:
patternProperties:
".*-dai-link$": false
then:
properties:
headset-codec: false
speaker-codecs: false
examples:
- |
sound: mt8186-sound {
compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound";
mediatek,platform = <&afe>;
model = "mt8186_da7219_m98357";
pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>;
pinctrl-1 = <&aud_clk_mosi_on>;
mediatek,platform = <&afe>;
headset-codec {
audio-routing =
"Headphones", "HPL",
"Headphones", "HPR",
"MIC", "Headset Mic",
"Speakers", "Speaker",
"HDMI1", "TX";
hs-playback-dai-link {
link-name = "I2S0";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&da7219>;
};
};
playback-codecs {
sound-dai = <&anx_bridge_dp>,
<&max98357a>;
hs-capture-dai-link {
link-name = "I2S1";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&da7219>;
};
};
spk-dp-playback-dai-link {
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&anx_bridge_dp>, <&max98357a>;
};
};
};
......
......@@ -12,6 +12,9 @@ maintainers:
description:
This binding describes the MT8186 sound card.
allOf:
- $ref: sound-card-common.yaml#
properties:
compatible:
enum:
......@@ -19,6 +22,34 @@ properties:
- mediatek,mt8186-mt6366-rt5682s-max98360-sound
- mediatek,mt8186-mt6366-rt5650-sound
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source.
Valid names could be the input or output widgets of audio components,
power supplies, MicBias of codec and the software switch.
minItems: 2
items:
enum:
# Sinks
- HDMI1
- Headphone
- IN1P
- IN1N
- Line Out
- Speakers
# Sources
- Headset Mic
- HPOL
- HPOR
- Speaker
- SPOL
- SPOR
- TX
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8186 ASoC platform.
......@@ -32,6 +63,7 @@ properties:
headset-codec:
type: object
deprecated: true
additionalProperties: false
properties:
sound-dai:
......@@ -41,6 +73,7 @@ properties:
playback-codecs:
type: object
deprecated: true
additionalProperties: false
properties:
sound-dai:
......@@ -62,13 +95,56 @@ properties:
A list of the desired dai-links in the sound card. Each entry is a
name defined in the machine driver.
additionalProperties: false
patternProperties:
".*-dai-link$":
type: object
additionalProperties: false
description:
Container for dai-link level properties and CODEC sub-nodes.
properties:
link-name:
description: Indicates dai-link name and PCM stream name
enum: [ I2S0, I2S1, I2S2, I2S3 ]
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
maxItems: 2
required:
- sound-dai
dai-format:
description: audio format
enum: [ i2s, right_j, left_j, dsp_a, dsp_b ]
mediatek,clk-provider:
$ref: /schemas/types.yaml#/definitions/string
description: Indicates dai-link clock master.
enum: [ cpu, codec ]
required:
- link-name
unevaluatedProperties: false
required:
- compatible
- mediatek,platform
- headset-codec
- playback-codecs
# Disallow legacy properties if xxx-dai-link nodes are specified
if:
not:
patternProperties:
".*-dai-link$": false
then:
properties:
headset-codec: false
speaker-codecs: false
examples:
- |
......@@ -76,23 +152,49 @@ examples:
sound: mt8186-sound {
compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound";
mediatek,platform = <&afe>;
model = "mt8186_rt1019_rt5682s";
pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on",
"aud_gpio_dmic_sec";
pinctrl-0 = <&aud_clk_mosi_off>;
pinctrl-1 = <&aud_clk_mosi_on>;
pinctrl-2 = <&aud_gpio_dmic_sec>;
mediatek,platform = <&afe>;
dmic-gpios = <&pio 23 GPIO_ACTIVE_HIGH>;
headset-codec {
sound-dai = <&rt5682s>;
audio-routing =
"Headphone", "HPOL",
"Headphone", "HPOR",
"IN1P", "Headset Mic",
"Speakers", "Speaker",
"HDMI1", "TX";
hs-playback-dai-link {
link-name = "I2S0";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682s 0>;
};
};
hs-capture-dai-link {
link-name = "I2S1";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682s 0>;
};
};
playback-codecs {
sound-dai = <&it6505dptx>,
<&rt1019p>;
spk-hdmi-playback-dai-link {
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&it6505dptx>, <&rt1019p>;
};
};
};
......
......@@ -13,6 +13,9 @@ maintainers:
description:
This binding describes the MT8192 sound card.
allOf:
- $ref: sound-card-common.yaml#
properties:
compatible:
enum:
......@@ -20,6 +23,31 @@ properties:
- mediatek,mt8192_mt6359_rt1015p_rt5682
- mediatek,mt8192_mt6359_rt1015p_rt5682s
audio-routing:
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source.
Valid names could be the input or output widgets of audio components,
power supplies, MicBias of codec and the software switch.
minItems: 2
items:
enum:
# Sinks
- Speakers
- Headphone Jack
- IN1P
- Left Spk
- Right Spk
# Sources
- Headset Mic
- HPOL
- HPOR
- Left SPO
- Right SPO
- Speaker
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8192 ASoC platform.
......@@ -27,10 +55,12 @@ properties:
mediatek,hdmi-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of HDMI codec.
deprecated: true
headset-codec:
type: object
additionalProperties: false
deprecated: true
properties:
sound-dai:
......@@ -41,6 +71,7 @@ properties:
speaker-codecs:
type: object
additionalProperties: false
deprecated: true
properties:
sound-dai:
......@@ -51,33 +82,121 @@ properties:
required:
- sound-dai
additionalProperties: false
patternProperties:
".*-dai-link$":
type: object
additionalProperties: false
description:
Container for dai-link level properties and CODEC sub-nodes.
properties:
link-name:
description: Indicates dai-link name and PCM stream name
enum:
- I2S0
- I2S1
- I2S2
- I2S3
- I2S4
- I2S5
- I2S6
- I2S7
- I2S8
- I2S9
- TDM
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
maxItems: 2
required:
- sound-dai
dai-format:
description: audio format
enum: [ i2s, right_j, left_j, dsp_a, dsp_b ]
mediatek,clk-provider:
$ref: /schemas/types.yaml#/definitions/string
description: Indicates dai-link clock master.
enum: [ cpu, codec ]
required:
- link-name
unevaluatedProperties: false
required:
- compatible
- mediatek,platform
- headset-codec
- speaker-codecs
# Disallow legacy properties if xxx-dai-link nodes are specified
if:
not:
patternProperties:
".*-dai-link$": false
then:
properties:
headset-codec: false
speaker-codecs: false
mediatek,hdmi-codec: false
examples:
- |
sound: mt8192-sound {
compatible = "mediatek,mt8192_mt6359_rt1015_rt5682";
mediatek,platform = <&afe>;
mediatek,hdmi-codec = <&anx_bridge_dp>;
model = "mt8192_mt6359_rt1015_rt5682";
pinctrl-names = "aud_clk_mosi_off",
"aud_clk_mosi_on";
pinctrl-0 = <&aud_clk_mosi_off>;
pinctrl-1 = <&aud_clk_mosi_on>;
mediatek,platform = <&afe>;
headset-codec {
sound-dai = <&rt5682>;
audio-routing =
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR",
"IN1P", "Headset Mic",
"Speakers", "Speaker";
spk-playback-dai-link {
link-name = "I2S3";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt1015p>;
};
};
hs-playback-dai-link {
link-name = "I2S8";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682 0>;
};
};
speaker-codecs {
sound-dai = <&rt1015_l>,
<&rt1015_r>;
hs-capture-dai-link {
link-name = "I2S9";
dai-format = "i2s";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&rt5682 0>;
};
};
displayport-dai-link {
link-name = "TDM";
dai-format = "dsp_a";
codec {
sound-dai = <&anx_bridge_dp>;
};
};
};
......
......@@ -12,6 +12,9 @@ maintainers:
description:
This binding describes the MT8195 sound card.
allOf:
- $ref: sound-card-common.yaml#
properties:
compatible:
enum:
......@@ -23,6 +26,33 @@ properties:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
audio-routing:
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source.
Valid names could be the input or output widgets of audio components,
power supplies, MicBias of codec and the software switch.
minItems: 2
items:
enum:
# Sinks
- Ext Spk
- Headphone
- IN1P
- Left Spk
- Right Spk
# Sources
- Headset Mic
- HPOL
- HPOR
- Left BE_OUT
- Left SPO
- Right BE_OUT
- Right SPO
- Speaker
mediatek,platform:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8195 ASoC platform.
......@@ -30,10 +60,12 @@ properties:
mediatek,dptx-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8195 Display Port Tx codec node.
deprecated: true
mediatek,hdmi-codec:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8195 HDMI codec node.
deprecated: true
mediatek,adsp:
$ref: /schemas/types.yaml#/definitions/phandle
......@@ -45,20 +77,122 @@ properties:
A list of the desired dai-links in the sound card. Each entry is a
name defined in the machine driver.
patternProperties:
".*-dai-link$":
type: object
additionalProperties: false
description:
Container for dai-link level properties and CODEC sub-nodes.
properties:
link-name:
description: Indicates dai-link name and PCM stream name
enum:
- DPTX_BE
- ETDM1_IN_BE
- ETDM2_IN_BE
- ETDM1_OUT_BE
- ETDM2_OUT_BE
- ETDM3_OUT_BE
- PCM1_BE
codec:
description: Holds subnode which indicates codec dai.
type: object
additionalProperties: false
properties:
sound-dai:
minItems: 1
maxItems: 2
required:
- sound-dai
dai-format:
description: audio format
enum: [ i2s, right_j, left_j, dsp_a, dsp_b ]
mediatek,clk-provider:
$ref: /schemas/types.yaml#/definitions/string
description: Indicates dai-link clock master.
enum: [ cpu, codec ]
required:
- link-name
additionalProperties: false
required:
- compatible
- mediatek,platform
# Disallow legacy properties if xxx-dai-link nodes are specified
if:
not:
patternProperties:
".*-dai-link$": false
then:
properties:
mediatek,dptx-codec: false
mediatek,hdmi-codec: false
examples:
- |
sound: mt8195-sound {
compatible = "mediatek,mt8195_mt6359_rt1019_rt5682";
model = "mt8195_r1019_5682";
mediatek,platform = <&afe>;
pinctrl-names = "default";
pinctrl-0 = <&aud_pins_default>;
audio-routing =
"Headphone", "HPOL",
"Headphone", "HPOR",
"IN1P", "Headset Mic",
"Ext Spk", "Speaker";
mm-dai-link {
link-name = "ETDM1_IN_BE";
mediatek,clk-provider = "cpu";
};
hs-playback-dai-link {
link-name = "ETDM1_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&headset_codec>;
};
};
hs-capture-dai-link {
link-name = "ETDM2_IN_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&headset_codec>;
};
};
spk-playback-dai-link {
link-name = "ETDM2_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
sound-dai = <&spk_amplifier>;
};
};
hdmi-dai-link {
link-name = "ETDM3_OUT_BE";
codec {
sound-dai = <&hdmi_tx>;
};
};
displayport-dai-link {
link-name = "DPTX_BE";
codec {
sound-dai = <&dp_tx>;
};
};
};
...
......@@ -185,27 +185,11 @@ config SND_SOC_MT8186
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8186_MT6366_DA7219_MAX98357
tristate "ASoC Audio driver for MT8186 with DA7219 MAX98357A codec"
config SND_SOC_MT8186_MT6366
tristate "ASoC Audio driver for MT8186 with MT6366 and I2S codecs"
depends on I2C && GPIOLIB
depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
select SND_SOC_MT6358
select SND_SOC_MAX98357A
select SND_SOC_DA7219
select SND_SOC_BT_SCO
select SND_SOC_DMIC
select SND_SOC_HDMI_CODEC
help
This adds ASoC driver for Mediatek MT8186 boards
with the MT6366(MT6358) DA7219 MAX98357A codecs.
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8186_MT6366_RT1019_RT5682S
tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S MAX98357A/MAX98360 codec"
depends on I2C && GPIOLIB
depends on SND_SOC_MT8186 && MTK_PMIC_WRAP
select SND_SOC_MAX98357A
select SND_SOC_MT6358
select SND_SOC_MAX98357A
select SND_SOC_RT1015P
......@@ -215,8 +199,8 @@ config SND_SOC_MT8186_MT6366_RT1019_RT5682S
select SND_SOC_DMIC
select SND_SOC_HDMI_CODEC
help
This adds ASoC driver for Mediatek MT8186 boards
with the MT6366(MT6358) RT1019 RT5682S codecs.
This adds the ASoC machine driver for Mediatek MT8186 boards
with the MT6366(MT6358) and other I2S audio codecs.
Select Y if you have such device.
If unsure select "N".
......
......@@ -126,10 +126,28 @@ int mtk_afe_pcm_new(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);
static int mtk_afe_component_probe(struct snd_soc_component *component)
{
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
int ret;
snd_soc_component_init_regmap(component, afe->regmap);
/* If the list was never initialized there are no sub-DAIs */
if (afe->sub_dais.next && afe->sub_dais.prev) {
ret = mtk_afe_add_sub_dai_control(component);
if (ret)
return ret;
}
return 0;
}
const struct snd_soc_component_driver mtk_afe_pcm_platform = {
.name = AFE_PCM_NAME,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
.probe = mtk_afe_component_probe,
};
EXPORT_SYMBOL_GPL(mtk_afe_pcm_platform);
......
......@@ -15,7 +15,7 @@ int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_card *card = rtd->card;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
int i, j, ret = 0;
for (i = 0; i < sof_priv->num_streams; i++) {
......@@ -55,7 +55,6 @@ int mtk_sof_card_probe(struct snd_soc_card *card)
int i;
struct snd_soc_dai_link *dai_link;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
/* Set stream_name to help sof bind widgets */
for_each_card_prelinks(card, i, dai_link) {
......@@ -63,7 +62,7 @@ int mtk_sof_card_probe(struct snd_soc_card *card)
dai_link->stream_name = dai_link->name;
}
INIT_LIST_HEAD(&sof_priv->dai_link_list);
INIT_LIST_HEAD(&soc_card_data->sof_dai_link_list);
return 0;
}
......@@ -73,7 +72,7 @@ static struct snd_soc_pcm_runtime *mtk_sof_find_tplg_be(struct snd_soc_pcm_runti
{
struct snd_soc_card *card = rtd->card;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
struct snd_soc_pcm_runtime *fe;
struct snd_soc_pcm_runtime *be;
struct snd_soc_dpcm *dpcm;
......@@ -113,7 +112,7 @@ static int mtk_sof_check_tplg_be_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_card *card = rtd->card;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
struct snd_soc_pcm_runtime *sof_be;
struct mtk_dai_link *dai_link;
int ret = 0;
......@@ -125,7 +124,7 @@ static int mtk_sof_check_tplg_be_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
else if (sof_be->dai_link->be_hw_params_fixup)
ret = sof_be->dai_link->be_hw_params_fixup(sof_be, params);
} else {
list_for_each_entry(dai_link, &sof_priv->dai_link_list, list) {
list_for_each_entry(dai_link, &soc_card_data->sof_dai_link_list, list) {
if (strcmp(dai_link->name, rtd->dai_link->name) == 0) {
if (dai_link->be_hw_params_fixup)
ret = dai_link->be_hw_params_fixup(rtd, params);
......@@ -144,7 +143,7 @@ int mtk_sof_card_late_probe(struct snd_soc_card *card)
struct snd_soc_component *sof_comp = NULL;
struct mtk_soc_card_data *soc_card_data =
snd_soc_card_get_drvdata(card);
struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv;
struct snd_soc_dai_link *dai_link;
struct mtk_dai_link *mtk_dai_link;
int i;
......@@ -173,7 +172,7 @@ int mtk_sof_card_late_probe(struct snd_soc_card *card)
mtk_dai_link->be_hw_params_fixup = dai_link->be_hw_params_fixup;
mtk_dai_link->name = dai_link->name;
list_add(&mtk_dai_link->list, &sof_priv->dai_link_list);
list_add(&mtk_dai_link->list, &soc_card_data->sof_dai_link_list);
}
if (dai_link->no_pcm)
......
......@@ -30,7 +30,6 @@ struct mtk_sof_priv {
int num_streams;
int (*sof_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
struct list_head dai_link_list;
};
int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
......
......@@ -9,9 +9,14 @@
#ifndef _MTK_SOC_CARD_H_
#define _MTK_SOC_CARD_H_
struct mtk_platform_card_data;
struct mtk_sof_priv;
struct mtk_soc_card_data {
const struct mtk_sof_priv *sof_priv;
struct list_head sof_dai_link_list;
struct mtk_platform_card_data *card_data;
void *mach_priv;
void *sof_priv;
};
#endif
......@@ -10,6 +10,8 @@
#include <linux/of.h>
#include <sound/soc.h>
#include "mtk-dsp-sof-common.h"
#include "mtk-soc-card.h"
#include "mtk-soundcard-driver.h"
static int set_card_codec_info(struct snd_soc_card *card,
......@@ -136,3 +138,200 @@ void clean_card_reference(struct snd_soc_card *card)
snd_soc_of_put_dai_link_codecs(dai_link);
}
EXPORT_SYMBOL_GPL(clean_card_reference);
int mtk_soundcard_startup(struct snd_pcm_substream *substream,
enum mtk_pcm_constraint_type ctype)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct mtk_soc_card_data *soc_card = snd_soc_card_get_drvdata(rtd->card);
const struct mtk_pcm_constraints_data *mpc = &soc_card->card_data->pcm_constraints[ctype];
int ret;
if (unlikely(!mpc))
return -EINVAL;
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
mpc->rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
mpc->channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(mtk_soundcard_startup);
static int mtk_soundcard_playback_startup(struct snd_pcm_substream *substream)
{
return mtk_soundcard_startup(substream, MTK_CONSTRAINT_PLAYBACK);
}
const struct snd_soc_ops mtk_soundcard_common_playback_ops = {
.startup = mtk_soundcard_playback_startup,
};
EXPORT_SYMBOL_GPL(mtk_soundcard_common_playback_ops);
static int mtk_soundcard_capture_startup(struct snd_pcm_substream *substream)
{
return mtk_soundcard_startup(substream, MTK_CONSTRAINT_CAPTURE);
}
const struct snd_soc_ops mtk_soundcard_common_capture_ops = {
.startup = mtk_soundcard_capture_startup,
};
EXPORT_SYMBOL_GPL(mtk_soundcard_common_capture_ops);
int mtk_soundcard_common_probe(struct platform_device *pdev)
{
struct device_node *platform_node, *adsp_node;
const struct mtk_soundcard_pdata *pdata;
struct mtk_soc_card_data *soc_card_data;
struct snd_soc_dai_link *orig_dai_link, *dai_link;
struct snd_soc_jack *jacks;
struct snd_soc_card *card;
int i, orig_num_links, ret;
bool needs_legacy_probe;
pdata = device_get_match_data(&pdev->dev);
if (!pdata)
return -EINVAL;
card = pdata->card_data->card;
card->dev = &pdev->dev;
orig_dai_link = card->dai_link;
orig_num_links = card->num_links;
ret = snd_soc_of_parse_card_name(card, "model");
if (ret)
return ret;
if (!card->name) {
if (!pdata->card_name)
return -EINVAL;
card->name = pdata->card_name;
}
needs_legacy_probe = !of_property_read_bool(pdev->dev.of_node, "audio-routing");
if (needs_legacy_probe) {
/*
* If we have no .soc_probe() callback there's no way of using
* any legacy probe mechanism, as that cannot not be generic.
*/
if (!pdata->soc_probe)
return -EINVAL;
dev_info_once(&pdev->dev, "audio-routing not found: using legacy probe\n");
} else {
ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
if (ret)
return ret;
}
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL);
if (!soc_card_data)
return -ENOMEM;
soc_card_data->card_data = pdata->card_data;
jacks = devm_kcalloc(card->dev, soc_card_data->card_data->num_jacks,
sizeof(*jacks), GFP_KERNEL);
if (!jacks)
return -ENOMEM;
soc_card_data->card_data->jacks = jacks;
platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
if (!platform_node)
return dev_err_probe(&pdev->dev, -EINVAL,
"Property mediatek,platform missing or invalid\n");
/* Check if this SoC has an Audio DSP */
if (pdata->sof_priv)
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
else
adsp_node = NULL;
if (adsp_node) {
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
"mediatek,dai-link",
card->dai_link, card->num_links);
if (ret) {
of_node_put(adsp_node);
of_node_put(platform_node);
return dev_err_probe(&pdev->dev, ret,
"Cannot parse mediatek,dai-link\n");
}
}
soc_card_data->sof_priv = pdata->sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
if (!card->topology_shortname_created) {
snprintf(card->topology_shortname, 32, "sof-%s", card->name);
card->topology_shortname_created = true;
}
card->name = card->topology_shortname;
}
/*
* Regardless of whether the ADSP is wanted and/or present in a machine
* specific device tree or not and regardless of whether any AFE_SOF
* link is present, we have to make sure that the platforms->of_node
* is not NULL, and set to either ADSP (adsp_node) or AFE (platform_node).
*/
for_each_card_prelinks(card, i, dai_link) {
if (adsp_node && !strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")))
dai_link->platforms->of_node = adsp_node;
else if (!dai_link->platforms->name && !dai_link->platforms->of_node)
dai_link->platforms->of_node = platform_node;
}
if (!needs_legacy_probe) {
ret = parse_dai_link_info(card);
if (ret)
goto err_restore_dais;
} else {
if (adsp_node)
of_node_put(adsp_node);
of_node_put(platform_node);
}
if (pdata->soc_probe) {
ret = pdata->soc_probe(soc_card_data, needs_legacy_probe);
if (ret) {
if (!needs_legacy_probe)
clean_card_reference(card);
goto err_restore_dais;
}
}
snd_soc_card_set_drvdata(card, soc_card_data);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (!needs_legacy_probe)
clean_card_reference(card);
if (ret) {
dev_err_probe(&pdev->dev, ret, "Cannot register card\n");
goto err_restore_dais;
}
return 0;
err_restore_dais:
card->dai_link = orig_dai_link;
card->num_links = orig_num_links;
return ret;
}
EXPORT_SYMBOL_GPL(mtk_soundcard_common_probe);
......@@ -9,6 +9,48 @@
#ifndef _MTK_SOUNDCARD_DRIVER_H_
#define _MTK_SOUNDCARD_DRIVER_H_
struct mtk_sof_priv;
struct mtk_soc_card_data;
struct snd_pcm_hw_constraint_list;
enum mtk_pcm_constraint_type {
MTK_CONSTRAINT_PLAYBACK,
MTK_CONSTRAINT_CAPTURE,
MTK_CONSTRAINT_HDMIDP,
MTK_CONSTRAINT_MAX
};
struct mtk_pcm_constraints_data {
const struct snd_pcm_hw_constraint_list *channels;
const struct snd_pcm_hw_constraint_list *rates;
};
struct mtk_platform_card_data {
struct snd_soc_card *card;
struct snd_soc_jack *jacks;
const struct mtk_pcm_constraints_data *pcm_constraints;
u8 num_jacks;
u8 num_pcm_constraints;
u8 flags;
};
struct mtk_soundcard_pdata {
const char *card_name;
struct mtk_platform_card_data *card_data;
const struct mtk_sof_priv *sof_priv;
int (*soc_probe)(struct mtk_soc_card_data *card_data, bool legacy);
};
/* Common playback/capture card startup ops */
extern const struct snd_soc_ops mtk_soundcard_common_playback_ops;
extern const struct snd_soc_ops mtk_soundcard_common_capture_ops;
/* Exported for custom/extended soundcard startup ops */
int mtk_soundcard_startup(struct snd_pcm_substream *substream,
enum mtk_pcm_constraint_type ctype);
int parse_dai_link_info(struct snd_soc_card *card);
void clean_card_reference(struct snd_soc_card *card);
int mtk_soundcard_common_probe(struct platform_device *pdev);
#endif
......@@ -704,18 +704,6 @@ static int mt6797_afe_runtime_resume(struct device *dev)
return 0;
}
static int mt6797_afe_component_probe(struct snd_soc_component *component)
{
return mtk_afe_add_sub_dai_control(component);
}
static const struct snd_soc_component_driver mt6797_afe_component = {
.name = AFE_PCM_NAME,
.probe = mt6797_afe_component_probe,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
};
static int mt6797_dai_memif_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
......@@ -852,7 +840,7 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev)
pm_runtime_get_sync(&pdev->dev);
/* register component */
ret = devm_snd_soc_register_component(dev, &mt6797_afe_component,
ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform,
NULL, 0);
if (ret) {
dev_warn(dev, "err_platform\n");
......
......@@ -429,18 +429,6 @@ static int mt7986_afe_runtime_resume(struct device *dev)
return 0;
}
static int mt7986_afe_component_probe(struct snd_soc_component *component)
{
return mtk_afe_add_sub_dai_control(component);
}
static const struct snd_soc_component_driver mt7986_afe_component = {
.name = AFE_PCM_NAME,
.probe = mt7986_afe_component_probe,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
};
static int mt7986_dai_memif_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
......@@ -573,7 +561,7 @@ static int mt7986_afe_pcm_dev_probe(struct platform_device *pdev)
/* register component */
ret = devm_snd_soc_register_component(&pdev->dev,
&mt7986_afe_component,
&mtk_afe_pcm_platform,
NULL, 0);
if (ret)
return dev_err_probe(dev, ret, "Cannot register AFE component\n");
......
......@@ -1042,18 +1042,6 @@ static int mt8183_afe_runtime_resume(struct device *dev)
return 0;
}
static int mt8183_afe_component_probe(struct snd_soc_component *component)
{
return mtk_afe_add_sub_dai_control(component);
}
static const struct snd_soc_component_driver mt8183_afe_component = {
.name = AFE_PCM_NAME,
.probe = mt8183_afe_component_probe,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
};
static int mt8183_dai_memif_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
......@@ -1232,7 +1220,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
/* register component */
ret = devm_snd_soc_register_component(&pdev->dev,
&mt8183_afe_component,
&mtk_afe_pcm_platform,
NULL, 0);
if (ret) {
dev_warn(dev, "err_platform\n");
......
......@@ -18,5 +18,4 @@ snd-soc-mt8186-afe-objs := \
mt8186-mt6366-common.o
obj-$(CONFIG_SND_SOC_MT8186) += snd-soc-mt8186-afe.o
obj-$(CONFIG_SND_SOC_MT8186_MT6366_DA7219_MAX98357) += mt8186-mt6366-da7219-max98357.o
obj-$(CONFIG_SND_SOC_MT8186_MT6366_RT1019_RT5682S) += mt8186-mt6366-rt1019-rt5682s.o
obj-$(CONFIG_SND_SOC_MT8186_MT6366) += mt8186-mt6366.o
// SPDX-License-Identifier: GPL-2.0
//
// mt8186-mt6366-da7219-max98357.c
// -- MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver
//
// Copyright (c) 2022 MediaTek Inc.
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
//
#include <linux/input.h>
#include <linux/module.h>
#include <linux/of.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "../../codecs/da7219.h"
#include "../../codecs/mt6358.h"
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-dsp-sof-common.h"
#include "../common/mtk-soc-card.h"
#include "mt8186-afe-common.h"
#include "mt8186-afe-clk.h"
#include "mt8186-afe-gpio.h"
#include "mt8186-mt6366-common.h"
#define DA7219_CODEC_DAI "da7219-hifi"
#define DA7219_DEV_NAME "da7219.5-001a"
#define SOF_DMA_DL1 "SOF_DMA_DL1"
#define SOF_DMA_DL2 "SOF_DMA_DL2"
#define SOF_DMA_UL1 "SOF_DMA_UL1"
#define SOF_DMA_UL2 "SOF_DMA_UL2"
struct mt8186_mt6366_da7219_max98357_priv {
struct snd_soc_jack headset_jack, hdmi_jack;
};
/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin mt8186_jack_pins[] = {
{
.pin = "Headphones",
.mask = SND_JACK_HEADPHONE,
},
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
{
.pin = "Line Out",
.mask = SND_JACK_LINEOUT,
},
};
static struct snd_soc_codec_conf mt8186_mt6366_da7219_max98357_codec_conf[] = {
{
.dlc = COMP_CODEC_CONF("mt6358-sound"),
.name_prefix = "Mt6366",
},
{
.dlc = COMP_CODEC_CONF("bt-sco"),
.name_prefix = "Mt8186 bt",
},
{
.dlc = COMP_CODEC_CONF("hdmi-audio-codec"),
.name_prefix = "Mt8186 hdmi",
},
};
static int mt8186_da7219_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
struct mtk_soc_card_data *soc_card_data =
snd_soc_card_get_drvdata(rtd->card);
struct mt8186_mt6366_da7219_max98357_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &priv->headset_jack;
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
int ret;
ret = mt8186_dai_i2s_set_share(afe, "I2S1", "I2S0");
if (ret) {
dev_err(rtd->dev, "Failed to set up shared clocks\n");
return ret;
}
/* Enable Headset and 4 Buttons Jack detection */
ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_BTN_0 |
SND_JACK_BTN_1 | SND_JACK_BTN_2 |
SND_JACK_BTN_3 | SND_JACK_LINEOUT,
jack, mt8186_jack_pins,
ARRAY_SIZE(mt8186_jack_pins));
if (ret) {
dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
return ret;
}
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
snd_soc_component_set_jack(cmpnt_codec, &priv->headset_jack, NULL);
return 0;
}
static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
unsigned int rate = params_rate(params);
unsigned int mclk_fs_ratio = 256;
unsigned int mclk_fs = rate * mclk_fs_ratio;
unsigned int freq;
int ret, j;
ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), 0,
mclk_fs, SND_SOC_CLOCK_OUT);
if (ret < 0) {
dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret);
return ret;
}
for_each_rtd_codec_dais(rtd, j, codec_dai) {
if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
ret = snd_soc_dai_set_sysclk(codec_dai,
DA7219_CLKSRC_MCLK,
mclk_fs,
SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "failed to set sysclk: %d\n",
ret);
return ret;
}
if ((rate % 8000) == 0)
freq = DA7219_PLL_FREQ_OUT_98304;
else
freq = DA7219_PLL_FREQ_OUT_90316;
ret = snd_soc_dai_set_pll(codec_dai, 0,
DA7219_SYSCLK_PLL_SRM,
0, freq);
if (ret) {
dev_err(rtd->dev, "failed to start PLL: %d\n",
ret);
return ret;
}
}
}
return 0;
}
static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
int ret = 0, j;
for_each_rtd_codec_dais(rtd, j, codec_dai) {
if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
ret = snd_soc_dai_set_pll(codec_dai,
0, DA7219_SYSCLK_MCLK, 0, 0);
if (ret < 0) {
dev_err(rtd->dev, "failed to stop PLL: %d\n",
ret);
return ret;
}
}
}
return 0;
}
static const struct snd_soc_ops mt8186_da7219_i2s_ops = {
.hw_params = mt8186_da7219_i2s_hw_params,
.hw_free = mt8186_da7219_i2s_hw_free,
};
static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
struct mtk_soc_card_data *soc_card_data =
snd_soc_card_get_drvdata(rtd->card);
struct mt8186_mt6366_da7219_max98357_priv *priv = soc_card_data->mach_priv;
int ret;
ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3");
if (ret) {
dev_err(rtd->dev, "Failed to set up shared clocks\n");
return ret;
}
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
if (ret) {
dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
return ret;
}
return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
}
static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params,
snd_pcm_format_t fmt)
{
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt);
/* fix BE i2s channel to 2 channel */
channels->min = 2;
channels->max = 2;
/* clean param mask first */
snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
params_set_format(params, fmt);
return 0;
}
static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
}
static int mt8186_anx7625_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
}
/* fixup the BE DAI link to match any values from topology */
static int mt8186_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
int ret;
ret = mtk_sof_dai_link_fixup(rtd, params);
if (!strcmp(rtd->dai_link->name, "I2S0") ||
!strcmp(rtd->dai_link->name, "I2S1") ||
!strcmp(rtd->dai_link->name, "I2S2"))
mt8186_i2s_hw_params_fixup(rtd, params);
else if (!strcmp(rtd->dai_link->name, "I2S3"))
mt8186_anx7625_i2s_hw_params_fixup(rtd, params);
return ret;
}
static int mt8186_mt6366_da7219_max98357_playback_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
2
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_playback_ops = {
.startup = mt8186_mt6366_da7219_max98357_playback_startup,
};
static int mt8186_mt6366_da7219_max98357_capture_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
1, 2
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_capture_ops = {
.startup = mt8186_mt6366_da7219_max98357_capture_startup,
};
/* FE */
SND_SOC_DAILINK_DEFS(playback1,
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback12,
DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback2,
DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback3,
DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback4,
DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback5,
DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback6,
DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback7,
DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(playback8,
DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture1,
DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture2,
DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture3,
DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture4,
DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture5,
DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture6,
DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(capture7,
DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
/* hostless */
SND_SOC_DAILINK_DEFS(hostless_lpbk,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_fm,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_src1,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_src_bargein,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
/* BE */
SND_SOC_DAILINK_DEFS(adda,
DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound",
"mt6358-snd-codec-aif1"),
COMP_CODEC("dmic-codec",
"dmic-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s0,
DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s1,
DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s2,
DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(i2s3,
DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hw_gain1,
DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hw_gain2,
DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hw_src1,
DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hw_src2,
DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(connsys_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(pcm1,
DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(tdm_in,
DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
/* hostless */
SND_SOC_DAILINK_DEFS(hostless_ul1,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_ul2,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_ul3,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_ul5,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_ul6,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(hostless_src_aaudio,
DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(AFE_SOF_DL1,
DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(AFE_SOF_DL2,
DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(AFE_SOF_UL1,
DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(AFE_SOF_UL2,
DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")),
DAILINK_COMP_ARRAY(COMP_DUMMY()),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static const struct sof_conn_stream g_sof_conn_streams[] = {
{ "I2S1", "AFE_SOF_DL1", SOF_DMA_DL1, SNDRV_PCM_STREAM_PLAYBACK},
{ "I2S3", "AFE_SOF_DL2", SOF_DMA_DL2, SNDRV_PCM_STREAM_PLAYBACK},
{ "Primary Codec", "AFE_SOF_UL1", SOF_DMA_UL1, SNDRV_PCM_STREAM_CAPTURE},
{ "I2S0", "AFE_SOF_UL2", SOF_DMA_UL2, SNDRV_PCM_STREAM_CAPTURE},
};
static struct snd_soc_dai_link mt8186_mt6366_da7219_max98357_dai_links[] = {
/* Front End DAI links */
{
.name = "Playback_1",
.stream_name = "Playback_1",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_da7219_max98357_playback_ops,
SND_SOC_DAILINK_REG(playback1),
},
{
.name = "Playback_12",
.stream_name = "Playback_12",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback12),
},
{
.name = "Playback_2",
.stream_name = "Playback_2",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(playback2),
},
{
.name = "Playback_3",
.stream_name = "Playback_3",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_da7219_max98357_playback_ops,
SND_SOC_DAILINK_REG(playback3),
},
{
.name = "Playback_4",
.stream_name = "Playback_4",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback4),
},
{
.name = "Playback_5",
.stream_name = "Playback_5",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback5),
},
{
.name = "Playback_6",
.stream_name = "Playback_6",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback6),
},
{
.name = "Playback_7",
.stream_name = "Playback_7",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback7),
},
{
.name = "Playback_8",
.stream_name = "Playback_8",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(playback8),
},
{
.name = "Capture_1",
.stream_name = "Capture_1",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture1),
},
{
.name = "Capture_2",
.stream_name = "Capture_2",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_da7219_max98357_capture_ops,
SND_SOC_DAILINK_REG(capture2),
},
{
.name = "Capture_3",
.stream_name = "Capture_3",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture3),
},
{
.name = "Capture_4",
.stream_name = "Capture_4",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_da7219_max98357_capture_ops,
SND_SOC_DAILINK_REG(capture4),
},
{
.name = "Capture_5",
.stream_name = "Capture_5",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture5),
},
{
.name = "Capture_6",
.stream_name = "Capture_6",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
SND_SOC_DAILINK_REG(capture6),
},
{
.name = "Capture_7",
.stream_name = "Capture_7",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(capture7),
},
{
.name = "Hostless_LPBK",
.stream_name = "Hostless_LPBK",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_lpbk),
},
{
.name = "Hostless_FM",
.stream_name = "Hostless_FM",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_fm),
},
{
.name = "Hostless_SRC_1",
.stream_name = "Hostless_SRC_1",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_src1),
},
{
.name = "Hostless_SRC_Bargein",
.stream_name = "Hostless_SRC_Bargein",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_src_bargein),
},
{
.name = "Hostless_HW_Gain_AAudio",
.stream_name = "Hostless_HW_Gain_AAudio",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
},
{
.name = "Hostless_SRC_AAudio",
.stream_name = "Hostless_SRC_AAudio",
.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_src_aaudio),
},
/* Back End DAI links */
{
.name = "Primary Codec",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.init = mt8186_mt6366_init,
SND_SOC_DAILINK_REG(adda),
},
{
.name = "I2S3",
.no_pcm = 1,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_IB_IF |
SND_SOC_DAIFMT_CBM_CFM,
.dpcm_playback = 1,
.ignore_suspend = 1,
.init = mt8186_mt6366_da7219_max98357_hdmi_init,
.be_hw_params_fixup = mt8186_anx7625_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s3),
},
{
.name = "I2S0",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
.ops = &mt8186_da7219_i2s_ops,
SND_SOC_DAILINK_REG(i2s0),
},
{
.name = "I2S1",
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
.init = mt8186_da7219_init,
.ops = &mt8186_da7219_i2s_ops,
SND_SOC_DAILINK_REG(i2s1),
},
{
.name = "I2S2",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s2),
},
{
.name = "HW Gain 1",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_gain1),
},
{
.name = "HW Gain 2",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_gain2),
},
{
.name = "HW_SRC_1",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_src1),
},
{
.name = "HW_SRC_2",
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hw_src2),
},
{
.name = "CONNSYS_I2S",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(connsys_i2s),
},
{
.name = "PCM 1",
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_IF,
.no_pcm = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(pcm1),
},
{
.name = "TDM IN",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(tdm_in),
},
/* dummy BE for ul memif to record from dl memif */
{
.name = "Hostless_UL1",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul1),
},
{
.name = "Hostless_UL2",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul2),
},
{
.name = "Hostless_UL3",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul3),
},
{
.name = "Hostless_UL5",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul5),
},
{
.name = "Hostless_UL6",
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
SND_SOC_DAILINK_REG(hostless_ul6),
},
/* SOF BE */
{
.name = "AFE_SOF_DL1",
.no_pcm = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(AFE_SOF_DL1),
},
{
.name = "AFE_SOF_DL2",
.no_pcm = 1,
.dpcm_playback = 1,
SND_SOC_DAILINK_REG(AFE_SOF_DL2),
},
{
.name = "AFE_SOF_UL1",
.no_pcm = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(AFE_SOF_UL1),
},
{
.name = "AFE_SOF_UL2",
.no_pcm = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(AFE_SOF_UL2),
},
};
static const struct snd_soc_dapm_widget
mt8186_mt6366_da7219_max98357_widgets[] = {
SND_SOC_DAPM_SPK("Speakers", NULL),
SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_LINE("Line Out", NULL),
SND_SOC_DAPM_OUTPUT("HDMI1"),
SND_SOC_DAPM_MIXER(SOF_DMA_DL1, SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER(SOF_DMA_UL1, SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER(SOF_DMA_UL2, SND_SOC_NOPM, 0, 0, NULL, 0),
};
static const struct snd_soc_dapm_route
mt8186_mt6366_da7219_max98357_routes[] = {
/* SPK */
{ "Speakers", NULL, "Speaker"},
/* Headset */
{ "Headphones", NULL, "HPL" },
{ "Headphones", NULL, "HPR" },
{ "MIC", NULL, "Headset Mic" },
/* HDMI */
{ "HDMI1", NULL, "TX"},
/* SOF Uplink */
{SOF_DMA_UL1, NULL, "UL1_CH1"},
{SOF_DMA_UL1, NULL, "UL1_CH2"},
{SOF_DMA_UL2, NULL, "UL2_CH1"},
{SOF_DMA_UL2, NULL, "UL2_CH2"},
/* SOF Downlink */
{"DSP_DL1_VIRT", NULL, SOF_DMA_DL1},
{"DSP_DL2_VIRT", NULL, SOF_DMA_DL2},
};
static const struct snd_kcontrol_new
mt8186_mt6366_da7219_max98357_controls[] = {
SOC_DAPM_PIN_SWITCH("Speakers"),
SOC_DAPM_PIN_SWITCH("Headphones"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Line Out"),
SOC_DAPM_PIN_SWITCH("HDMI1"),
};
static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = {
.name = "mt8186_da7219_max98357",
.owner = THIS_MODULE,
.dai_link = mt8186_mt6366_da7219_max98357_dai_links,
.num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links),
.controls = mt8186_mt6366_da7219_max98357_controls,
.num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls),
.dapm_widgets = mt8186_mt6366_da7219_max98357_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets),
.dapm_routes = mt8186_mt6366_da7219_max98357_routes,
.num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_routes),
.codec_conf = mt8186_mt6366_da7219_max98357_codec_conf,
.num_configs = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_codec_conf),
};
static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
struct snd_soc_dai_link *dai_link;
struct mtk_soc_card_data *soc_card_data;
struct mt8186_mt6366_da7219_max98357_priv *mach_priv;
struct device_node *platform_node, *headset_codec, *playback_codec, *adsp_node;
int sof_on = 0;
int ret, i;
card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
if (!card)
return -EINVAL;
card->dev = &pdev->dev;
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL);
if (!soc_card_data)
return -ENOMEM;
mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
soc_card_data->mach_priv = mach_priv;
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
if (adsp_node) {
struct mtk_sof_priv *sof_priv;
sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL);
if (!sof_priv) {
ret = -ENOMEM;
goto err_adsp_node;
}
sof_priv->conn_streams = g_sof_conn_streams;
sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams);
sof_priv->sof_dai_link_fixup = mt8186_sof_dai_link_fixup;
soc_card_data->sof_priv = sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
if (!card->topology_shortname_created) {
snprintf(card->topology_shortname, 32, "sof-%s", card->name);
card->topology_shortname_created = true;
}
card->name = card->topology_shortname;
sof_on = 1;
} else {
dev_dbg(&pdev->dev, "Probe without adsp\n");
}
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
"mediatek,dai-link",
mt8186_mt6366_da7219_max98357_dai_links,
ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links));
if (ret) {
dev_dbg(&pdev->dev, "Parse dai-link fail\n");
goto err_adsp_node;
}
} else {
if (!sof_on)
card->num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links)
- ARRAY_SIZE(g_sof_conn_streams);
}
platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
if (!platform_node) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
goto err_platform_node;
}
playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
if (!playback_codec) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
goto err_playback_codec;
}
headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
if (!headset_codec) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
goto err_headset_codec;
}
for_each_card_prelinks(card, i, dai_link) {
ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
dai_link->name);
goto err_probe;
}
ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
dai_link->name);
goto err_probe;
}
ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
dai_link->name);
goto err_probe;
}
if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && sof_on)
dai_link->platforms->of_node = adsp_node;
if (!dai_link->platforms->name && !dai_link->platforms->of_node)
dai_link->platforms->of_node = platform_node;
}
snd_soc_card_set_drvdata(card, soc_card_data);
ret = mt8186_afe_gpio_init(&pdev->dev);
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
goto err_probe;
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
err_probe:
of_node_put(headset_codec);
err_headset_codec:
of_node_put(playback_codec);
err_playback_codec:
of_node_put(platform_node);
err_platform_node:
err_adsp_node:
of_node_put(adsp_node);
return ret;
}
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id mt8186_mt6366_da7219_max98357_dt_match[] = {
{ .compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound",
.data = &mt8186_mt6366_da7219_max98357_soc_card,
},
{}
};
MODULE_DEVICE_TABLE(of, mt8186_mt6366_da7219_max98357_dt_match);
#endif
static struct platform_driver mt8186_mt6366_da7219_max98357_driver = {
.driver = {
.name = "mt8186_mt6366_da7219_max98357",
#if IS_ENABLED(CONFIG_OF)
.of_match_table = mt8186_mt6366_da7219_max98357_dt_match,
#endif
.pm = &snd_soc_pm_ops,
},
.probe = mt8186_mt6366_da7219_max98357_dev_probe,
};
module_platform_driver(mt8186_mt6366_da7219_max98357_driver);
/* Module information */
MODULE_DESCRIPTION("MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver");
MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("mt8186_mt6366_da7219_max98357 soc card");
// SPDX-License-Identifier: GPL-2.0
//
// mt8186-mt6366-rt1019-rt5682s.c
// -- MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver
// mt8186-mt6366.c
// -- MT8186-MT6366 ALSA SoC machine driver
//
// Copyright (c) 2022 MediaTek Inc.
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
//
// Copyright (c) 2024 Collabora Ltd.
// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
//
#include <linux/gpio/consumer.h>
#include <linux/input.h>
......@@ -16,11 +19,13 @@
#include <sound/rt5682.h>
#include <sound/soc.h>
#include "../../codecs/da7219.h"
#include "../../codecs/mt6358.h"
#include "../../codecs/rt5682.h"
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-dsp-sof-common.h"
#include "../common/mtk-soc-card.h"
#include "../common/mtk-soundcard-driver.h"
#include "mt8186-afe-common.h"
#include "mt8186-afe-clk.h"
#include "mt8186-afe-gpio.h"
......@@ -32,17 +37,27 @@
#define RT5682S_CODEC_DAI "rt5682s-aif1"
#define RT5682S_DEV0_NAME "rt5682s.5-001a"
#define DA7219_CODEC_DAI "da7219-hifi"
#define DA7219_DEV_NAME "da7219.5-001a"
#define SOF_DMA_DL1 "SOF_DMA_DL1"
#define SOF_DMA_DL2 "SOF_DMA_DL2"
#define SOF_DMA_UL1 "SOF_DMA_UL1"
#define SOF_DMA_UL2 "SOF_DMA_UL2"
#define DA7219_CODEC_PRESENT BIT(0)
struct mt8186_mt6366_rt1019_rt5682s_priv {
struct snd_soc_jack headset_jack, hdmi_jack;
struct gpio_desc *dmic_sel;
int dmic_switch;
};
enum mt8186_jacks {
MT8186_JACK_HEADSET,
MT8186_JACK_HDMI,
MT8186_JACK_MAX,
};
/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin mt8186_jack_pins[] = {
{
......@@ -158,17 +173,23 @@ static int primary_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
static int mt8186_headset_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
struct mtk_soc_card_data *soc_card_data =
snd_soc_card_get_drvdata(rtd->card);
struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &priv->headset_jack;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HEADSET];
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
const int hs_keys_rt5682[] = {
KEY_PLAYPAUSE, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_VOICECOMMAND
};
const int hs_keys_da7219[] = {
KEY_PLAYPAUSE, KEY_VOICECOMMAND, KEY_VOLUMEUP, KEY_VOLUMEDOWN
};
const int *hs_keys;
int ret;
int type;
......@@ -189,15 +210,90 @@ static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
if (soc_card_data->card_data->flags & DA7219_CODEC_PRESENT)
hs_keys = hs_keys_da7219;
else
hs_keys = hs_keys_rt5682;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, hs_keys[0]);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, hs_keys[1]);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, hs_keys[2]);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, hs_keys[3]);
type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3;
return snd_soc_component_set_jack(cmpnt_codec, jack, (void *)&type);
}
static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
unsigned int rate = params_rate(params);
unsigned int mclk_fs_ratio = 256;
unsigned int mclk_fs = rate * mclk_fs_ratio;
unsigned int freq;
int ret, j;
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
if (ret < 0) {
dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret);
return ret;
}
for_each_rtd_codec_dais(rtd, j, codec_dai) {
if (strcmp(codec_dai->component->name, DA7219_DEV_NAME))
continue;
ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK,
mclk_fs, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(rtd->dev, "failed to set sysclk: %d\n", ret);
return ret;
}
if ((rate % 8000) == 0)
freq = DA7219_PLL_FREQ_OUT_98304;
else
freq = DA7219_PLL_FREQ_OUT_90316;
ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM,
0, freq);
if (ret) {
dev_err(rtd->dev, "failed to start PLL: %d\n", ret);
return ret;
}
}
return 0;
}
static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
int j, ret;
for_each_rtd_codec_dais(rtd, j, codec_dai) {
if (strcmp(codec_dai->component->name, DA7219_DEV_NAME))
continue;
ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
if (ret < 0) {
dev_err(rtd->dev, "failed to stop PLL: %d\n", ret);
return ret;
}
}
return 0;
}
static const struct snd_soc_ops mt8186_da7219_i2s_ops = {
.hw_params = mt8186_da7219_i2s_hw_params,
.hw_free = mt8186_da7219_i2s_hw_free,
};
static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
......@@ -257,7 +353,7 @@ static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rt
snd_soc_rtd_to_codec(rtd, 0)->component;
struct mtk_soc_card_data *soc_card_data =
snd_soc_card_get_drvdata(rtd->card);
struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HDMI];
int ret;
ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3");
......@@ -266,13 +362,13 @@ static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rt
return ret;
}
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack);
if (ret) {
dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
return ret;
}
return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
}
static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
......@@ -297,13 +393,13 @@ static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int mt8186_i2s_hw_params_24le_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
}
static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int mt8186_i2s_hw_params_32le_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
......@@ -313,112 +409,28 @@ static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int mt8186_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
int ret;
ret = mtk_sof_dai_link_fixup(rtd, params);
if (!strcmp(rtd->dai_link->name, "I2S0") ||
!strcmp(rtd->dai_link->name, "I2S1") ||
!strcmp(rtd->dai_link->name, "I2S2"))
mt8186_i2s_hw_params_fixup(rtd, params);
else if (!strcmp(rtd->dai_link->name, "I2S3"))
mt8186_it6505_i2s_hw_params_fixup(rtd, params);
return ret;
}
static int mt8186_mt6366_rt1019_rt5682s_playback_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
2
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_playback_ops = {
.startup = mt8186_mt6366_rt1019_rt5682s_playback_startup,
};
static int mt8186_mt6366_rt1019_rt5682s_capture_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
1, 2
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
!strcmp(rtd->dai_link->name, "I2S2")) {
if (soc_card_data->card_data->flags & DA7219_CODEC_PRESENT)
mt8186_i2s_hw_params_32le_fixup(rtd, params);
else
mt8186_i2s_hw_params_24le_fixup(rtd, params);
} else if (!strcmp(rtd->dai_link->name, "I2S3")) {
if (soc_card_data->card_data->flags & DA7219_CODEC_PRESENT)
mt8186_i2s_hw_params_24le_fixup(rtd, params);
else
mt8186_i2s_hw_params_32le_fixup(rtd, params);
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_capture_ops = {
.startup = mt8186_mt6366_rt1019_rt5682s_capture_startup,
};
/* FE */
SND_SOC_DAILINK_DEFS(playback1,
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
......@@ -639,7 +651,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(playback1),
},
{
......@@ -673,7 +685,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(playback3),
},
{
......@@ -740,7 +752,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(capture2),
},
{
......@@ -762,7 +774,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dpcm_merged_format = 1,
.dpcm_merged_chan = 1,
.dpcm_merged_rate = 1,
.ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(capture4),
},
{
......@@ -879,7 +891,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.dpcm_playback = 1,
.ignore_suspend = 1,
.init = mt8186_mt6366_rt1019_rt5682s_hdmi_init,
.be_hw_params_fixup = mt8186_it6505_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s3),
},
{
......@@ -887,7 +898,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
.ops = &mt8186_rt5682s_i2s_ops,
SND_SOC_DAILINK_REG(i2s0),
},
......@@ -896,9 +906,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.no_pcm = 1,
.dpcm_playback = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
.init = mt8186_rt5682s_init,
.ops = &mt8186_rt5682s_i2s_ops,
.init = mt8186_headset_codec_init,
SND_SOC_DAILINK_REG(i2s1),
},
{
......@@ -906,7 +914,6 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
.no_pcm = 1,
.dpcm_capture = 1,
.ignore_suspend = 1,
.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
SND_SOC_DAILINK_REG(i2s2),
},
{
......@@ -1028,6 +1035,19 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = {
},
};
static const struct snd_soc_dapm_widget
mt8186_mt6366_da7219_max98357_widgets[] = {
SND_SOC_DAPM_SPK("Speakers", NULL),
SND_SOC_DAPM_HP("Headphones", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_LINE("Line Out", NULL),
SND_SOC_DAPM_LINE("HDMI1", NULL),
SND_SOC_DAPM_MIXER(SOF_DMA_DL1, SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER(SOF_DMA_UL1, SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER(SOF_DMA_UL2, SND_SOC_NOPM, 0, 0, NULL, 0),
};
static const struct snd_soc_dapm_widget
mt8186_mt6366_rt1019_rt5682s_widgets[] = {
SND_SOC_DAPM_SPK("Speakers", NULL),
......@@ -1081,6 +1101,14 @@ static const struct snd_soc_dapm_route mt8186_mt6366_rt5650_routes[] = {
{"DSP_DL2_VIRT", NULL, SOF_DMA_DL2},
};
static const struct snd_kcontrol_new mt8186_mt6366_da7219_max98357_controls[] = {
SOC_DAPM_PIN_SWITCH("Speakers"),
SOC_DAPM_PIN_SWITCH("Headphones"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Line Out"),
SOC_DAPM_PIN_SWITCH("HDMI1"),
};
static const struct snd_kcontrol_new
mt8186_mt6366_rt1019_rt5682s_controls[] = {
SOC_DAPM_PIN_SWITCH("Speakers"),
......@@ -1089,6 +1117,21 @@ mt8186_mt6366_rt1019_rt5682s_controls[] = {
SOC_DAPM_PIN_SWITCH("HDMI1"),
};
static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = {
.name = "mt8186_da7219_max98357",
.owner = THIS_MODULE,
.dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links,
.num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links),
.controls = mt8186_mt6366_da7219_max98357_controls,
.num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls),
.dapm_widgets = mt8186_mt6366_da7219_max98357_widgets,
.num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets),
.dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes,
.num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes),
.codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf,
.num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf),
};
static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = {
.name = "mt8186_rt1019_rt5682s",
.owner = THIS_MODULE,
......@@ -1134,187 +1177,222 @@ static struct snd_soc_card mt8186_mt6366_rt5650_soc_card = {
.num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf),
};
static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev)
static int mt8186_mt6366_legacy_probe(struct mtk_soc_card_data *soc_card_data)
{
struct snd_soc_card *card;
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
struct device *dev = card->dev;
struct snd_soc_dai_link *dai_link;
struct mtk_soc_card_data *soc_card_data;
struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv;
struct device_node *platform_node, *headset_codec, *playback_codec, *adsp_node;
int sof_on = 0;
struct device_node *headset_codec, *playback_codec;
int ret, i;
card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
if (!card)
return -EINVAL;
card->dev = &pdev->dev;
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL);
if (!soc_card_data)
return -ENOMEM;
mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
playback_codec = of_get_child_by_name(dev->of_node, "playback-codecs");
if (!playback_codec)
return dev_err_probe(dev, -EINVAL,
"Property 'playback-codecs' missing or invalid\n");
soc_card_data->mach_priv = mach_priv;
mach_priv->dmic_sel = devm_gpiod_get_optional(&pdev->dev,
"dmic", GPIOD_OUT_LOW);
if (IS_ERR(mach_priv->dmic_sel)) {
dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n",
PTR_ERR(mach_priv->dmic_sel));
return PTR_ERR(mach_priv->dmic_sel);
}
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
if (adsp_node) {
struct mtk_sof_priv *sof_priv;
sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL);
if (!sof_priv) {
ret = -ENOMEM;
goto err_adsp_node;
}
sof_priv->conn_streams = g_sof_conn_streams;
sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams);
sof_priv->sof_dai_link_fixup = mt8186_sof_dai_link_fixup;
soc_card_data->sof_priv = sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
if (!card->topology_shortname_created) {
snprintf(card->topology_shortname, 32, "sof-%s", card->name);
card->topology_shortname_created = true;
}
card->name = card->topology_shortname;
sof_on = 1;
} else {
dev_dbg(&pdev->dev, "Probe without adsp\n");
}
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
"mediatek,dai-link",
mt8186_mt6366_rt1019_rt5682s_dai_links,
ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links));
if (ret) {
dev_dbg(&pdev->dev, "Parse dai-link fail\n");
goto err_adsp_node;
}
} else {
if (!sof_on)
card->num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links)
- ARRAY_SIZE(g_sof_conn_streams);
}
platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
if (!platform_node) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
goto err_platform_node;
}
playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
if (!playback_codec) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'playback-codecs' missing or invalid\n");
goto err_playback_codec;
}
headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
headset_codec = of_get_child_by_name(dev->of_node, "headset-codec");
if (!headset_codec) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
goto err_headset_codec;
of_node_put(playback_codec);
return dev_err_probe(dev, -EINVAL,
"Property 'headset-codec' missing or invalid\n");
}
for_each_card_prelinks(card, i, dai_link) {
ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set playback_codec fail\n",
dev_err_probe(dev, ret, "%s set playback_codec fail\n",
dai_link->name);
goto err_probe;
break;
}
ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
dev_err_probe(dev, ret, "%s set headset_codec fail\n",
dai_link->name);
goto err_probe;
break;
}
ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
dev_err_probe(dev, ret, "%s set headset_codec fail\n",
dai_link->name);
goto err_probe;
break;
}
}
of_node_put(headset_codec);
of_node_put(playback_codec);
if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && sof_on)
dai_link->platforms->of_node = adsp_node;
return ret;
}
if (!dai_link->platforms->name && !dai_link->platforms->of_node)
dai_link->platforms->of_node = platform_node;
}
static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
{
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
struct snd_soc_dai_link *dai_link;
struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv;
int i, ret;
mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
soc_card_data->mach_priv = mach_priv;
snd_soc_card_set_drvdata(card, soc_card_data);
mach_priv->dmic_sel = devm_gpiod_get_optional(card->dev,
"dmic", GPIOD_OUT_LOW);
if (IS_ERR(mach_priv->dmic_sel))
return dev_err_probe(card->dev, PTR_ERR(mach_priv->dmic_sel),
"DMIC gpio failed\n");
ret = mt8186_afe_gpio_init(&pdev->dev);
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
goto err_probe;
for_each_card_prelinks(card, i, dai_link) {
if (strcmp(dai_link->name, "I2S0") == 0 ||
strcmp(dai_link->name, "I2S1") == 0 ||
strcmp(dai_link->name, "I2S2") == 0) {
if (card_data->flags & DA7219_CODEC_PRESENT) {
dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_32le_fixup;
dai_link->ops = &mt8186_da7219_i2s_ops;
} else {
dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_24le_fixup;
dai_link->ops = &mt8186_rt5682s_i2s_ops;
}
} else if (strcmp(dai_link->name, "I2S3") == 0) {
if (card_data->flags & DA7219_CODEC_PRESENT)
dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_24le_fixup;
else
dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_32le_fixup;
}
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (legacy) {
ret = mt8186_mt6366_legacy_probe(soc_card_data);
if (ret)
dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
return ret;
}
err_probe:
of_node_put(headset_codec);
err_headset_codec:
of_node_put(playback_codec);
err_playback_codec:
of_node_put(platform_node);
err_platform_node:
err_adsp_node:
of_node_put(adsp_node);
ret = mt8186_afe_gpio_init(card->dev);
if (ret)
return dev_err_probe(card->dev, ret, "init AFE gpio error\n");
return ret;
return 0;
}
static const unsigned int mt8186_pcm_playback_channels[] = { 2 };
static const unsigned int mt8186_pcm_capture_channels[] = { 1, 2 };
static const unsigned int mt8186_pcm_rates[] = { 48000 };
static const struct snd_pcm_hw_constraint_list mt8186_rate_constraint = {
.list = mt8186_pcm_rates,
.count = ARRAY_SIZE(mt8186_pcm_rates)
};
static const struct mtk_pcm_constraints_data mt8186_pcm_constraints[MTK_CONSTRAINT_CAPTURE + 1] = {
[MTK_CONSTRAINT_PLAYBACK] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8186_pcm_playback_channels,
.count = ARRAY_SIZE(mt8186_pcm_playback_channels)
},
.rates = &mt8186_rate_constraint,
},
[MTK_CONSTRAINT_CAPTURE] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8186_pcm_capture_channels,
.count = ARRAY_SIZE(mt8186_pcm_capture_channels)
},
.rates = &mt8186_rate_constraint,
}
};
static const struct mtk_sof_priv mt8186_sof_priv = {
.conn_streams = g_sof_conn_streams,
.num_streams = ARRAY_SIZE(g_sof_conn_streams),
.sof_dai_link_fixup = mt8186_sof_dai_link_fixup
};
static const struct mtk_soundcard_pdata mt8186_mt6366_da7219_max98357_pdata = {
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8186_mt6366_da7219_max98357_soc_card,
.num_jacks = MT8186_JACK_MAX,
.pcm_constraints = mt8186_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints),
.flags = DA7219_CODEC_PRESENT,
},
.sof_priv = &mt8186_sof_priv,
.soc_probe = mt8186_mt6366_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8186_mt6366_rt1019_rt5682s_pdata = {
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8186_mt6366_rt1019_rt5682s_soc_card,
.num_jacks = MT8186_JACK_MAX,
.pcm_constraints = mt8186_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints),
},
.sof_priv = &mt8186_sof_priv,
.soc_probe = mt8186_mt6366_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8186_mt6366_rt5682s_max98360_pdata = {
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8186_mt6366_rt5682s_max98360_soc_card,
.num_jacks = MT8186_JACK_MAX,
.pcm_constraints = mt8186_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints),
},
.sof_priv = &mt8186_sof_priv,
.soc_probe = mt8186_mt6366_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8186_mt6366_rt5650_pdata = {
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8186_mt6366_rt5650_soc_card,
.num_jacks = MT8186_JACK_MAX,
.pcm_constraints = mt8186_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints),
},
.sof_priv = &mt8186_sof_priv,
.soc_probe = mt8186_mt6366_soc_card_probe
};
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = {
static const struct of_device_id mt8186_mt6366_dt_match[] = {
{
.compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound",
.data = &mt8186_mt6366_rt1019_rt5682s_soc_card,
.data = &mt8186_mt6366_rt1019_rt5682s_pdata,
},
{
.compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound",
.data = &mt8186_mt6366_rt5682s_max98360_soc_card,
.data = &mt8186_mt6366_rt5682s_max98360_pdata,
},
{
.compatible = "mediatek,mt8186-mt6366-rt5650-sound",
.data = &mt8186_mt6366_rt5650_soc_card,
.data = &mt8186_mt6366_rt5650_pdata,
},
{
.compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound",
.data = &mt8186_mt6366_da7219_max98357_pdata,
},
{}
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mt8186_mt6366_rt1019_rt5682s_dt_match);
MODULE_DEVICE_TABLE(of, mt8186_mt6366_dt_match);
#endif
static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = {
static struct platform_driver mt8186_mt6366_driver = {
.driver = {
.name = "mt8186_mt6366_rt1019_rt5682s",
.name = "mt8186_mt6366",
#if IS_ENABLED(CONFIG_OF)
.of_match_table = mt8186_mt6366_rt1019_rt5682s_dt_match,
.of_match_table = mt8186_mt6366_dt_match,
#endif
.pm = &snd_soc_pm_ops,
},
.probe = mt8186_mt6366_rt1019_rt5682s_dev_probe,
.probe = mtk_soundcard_common_probe,
};
module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver);
module_platform_driver(mt8186_mt6366_driver);
/* Module information */
MODULE_DESCRIPTION("MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver");
MODULE_DESCRIPTION("MT8186-MT6366 ALSA SoC machine driver");
MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("mt8186_mt6366_rt1019_rt5682s soc card");
MODULE_ALIAS("mt8186_mt6366 soc card");
......@@ -3030,25 +3030,6 @@ static int mt8188_afe_runtime_resume(struct device *dev)
return 0;
}
static int mt8188_afe_component_probe(struct snd_soc_component *component)
{
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
int ret;
snd_soc_component_init_regmap(component, afe->regmap);
ret = mtk_afe_add_sub_dai_control(component);
return ret;
}
static const struct snd_soc_component_driver mt8188_afe_component = {
.name = AFE_PCM_NAME,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
.probe = mt8188_afe_component_probe,
};
static int init_memif_priv_data(struct mtk_base_afe *afe)
{
struct mt8188_afe_private *afe_priv = afe->platform_priv;
......@@ -3350,7 +3331,7 @@ static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev)
}
/* register component */
ret = devm_snd_soc_register_component(dev, &mt8188_afe_component,
ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform,
afe->dai_drivers, afe->num_dai_drivers);
if (ret) {
dev_warn(dev, "err_platform\n");
......
......@@ -236,11 +236,11 @@ static const struct sof_conn_stream g_sof_conn_streams[] = {
},
};
struct mt8188_mt6359_priv {
struct snd_soc_jack dp_jack;
struct snd_soc_jack hdmi_jack;
struct snd_soc_jack headset_jack;
void *private_data;
enum mt8188_jacks {
MT8188_JACK_HEADSET,
MT8188_JACK_DP,
MT8188_JACK_HDMI,
MT8188_JACK_MAX,
};
static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = {
......@@ -268,11 +268,6 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = {
},
};
struct mt8188_card_data {
const char *name;
unsigned long quirk;
};
static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = {
SOC_DAPM_PIN_SWITCH("Ext Spk"),
};
......@@ -590,12 +585,12 @@ static int mt8188_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HDMI];
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
int ret = 0;
ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack",
SND_JACK_LINEOUT, &priv->hdmi_jack,
SND_JACK_LINEOUT, jack,
mt8188_hdmi_jack_pins,
ARRAY_SIZE(mt8188_hdmi_jack_pins));
if (ret) {
......@@ -603,7 +598,7 @@ static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
ret = snd_soc_component_set_jack(component, &priv->hdmi_jack, NULL);
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret) {
dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
__func__, component->name, ret);
......@@ -616,19 +611,19 @@ static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_DP];
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
int ret = 0;
ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT,
&priv->dp_jack, mt8188_dp_jack_pins,
jack, mt8188_dp_jack_pins,
ARRAY_SIZE(mt8188_dp_jack_pins));
if (ret) {
dev_err(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
return ret;
}
ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL);
ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret) {
dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
__func__, component->name, ret);
......@@ -736,10 +731,9 @@ static int mt8188_max98390_codec_init(struct snd_soc_pcm_runtime *rtd)
static int mt8188_headset_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET];
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
struct snd_soc_jack *jack = &priv->headset_jack;
int ret;
ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_nau8825_widgets,
......@@ -1224,11 +1218,10 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
static void mt8188_fixup_controls(struct snd_soc_card *card)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv;
struct mt8188_card_data *card_data = (struct mt8188_card_data *)priv->private_data;
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_kcontrol *kctl;
if (card_data->quirk & (NAU8825_HS_PRESENT | RT5682S_HS_PRESENT | ES8326_HS_PRESENT)) {
if (card_data->flags & (NAU8825_HS_PRESENT | RT5682S_HS_PRESENT | ES8326_HS_PRESENT)) {
struct snd_soc_dapm_widget *w, *next_w;
for_each_card_widgets_safe(card, w, next_w) {
......@@ -1259,14 +1252,10 @@ static struct snd_soc_card mt8188_mt6359_soc_card = {
.fixup_controls = mt8188_fixup_controls,
};
static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
static int mt8188_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
{
struct snd_soc_card *card = &mt8188_mt6359_soc_card;
struct device_node *platform_node;
struct device_node *adsp_node;
struct mtk_soc_card_data *soc_card_data;
struct mt8188_mt6359_priv *priv;
struct mt8188_card_data *card_data;
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = soc_card_data->card_data->card;
struct snd_soc_dai_link *dai_link;
bool init_mt6359 = false;
bool init_es8326 = false;
......@@ -1274,91 +1263,12 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
bool init_rt5682s = false;
bool init_max98390 = false;
bool init_dumb = false;
int ret, i;
card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev);
card->dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(card, "model");
if (ret)
return dev_err_probe(&pdev->dev, ret, "%s new card name parsing error\n",
__func__);
if (!card->name)
card->name = card_data->name;
if (of_property_read_bool(pdev->dev.of_node, "audio-routing")) {
ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
if (ret)
return ret;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL);
if (!soc_card_data)
return -ENOMEM;
soc_card_data->mach_priv = priv;
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
if (adsp_node) {
struct mtk_sof_priv *sof_priv;
sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL);
if (!sof_priv) {
ret = -ENOMEM;
goto err_adsp_node;
}
sof_priv->conn_streams = g_sof_conn_streams;
sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams);
soc_card_data->sof_priv = sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
if (!card->topology_shortname_created) {
snprintf(card->topology_shortname, 32, "sof-%s", card->name);
card->topology_shortname_created = true;
}
card->name = card->topology_shortname;
}
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
"mediatek,dai-link",
mt8188_mt6359_dai_links,
ARRAY_SIZE(mt8188_mt6359_dai_links));
if (ret) {
dev_err_probe(&pdev->dev, ret, "Parse dai-link fail\n");
goto err_adsp_node;
}
} else {
if (!adsp_node)
card->num_links = DAI_LINK_REGULAR_NUM;
}
platform_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,platform", 0);
if (!platform_node) {
ret = dev_err_probe(&pdev->dev, -EINVAL,
"Property 'platform' missing or invalid\n");
goto err_adsp_node;
}
int i;
ret = parse_dai_link_info(card);
if (ret)
goto err;
if (legacy)
return -EINVAL;
for_each_card_prelinks(card, i, dai_link) {
if (!dai_link->platforms->name) {
if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && adsp_node)
dai_link->platforms->of_node = adsp_node;
else
dai_link->platforms->of_node = platform_node;
}
if (strcmp(dai_link->name, "DPTX_BE") == 0) {
if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8188_dptx_codec_init;
......@@ -1381,7 +1291,7 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
* mt8188_max98390_ops. Two amps is I2S mode,
* SOC and codec don't require TDM settings.
*/
if (!(card_data->quirk & MAX98390_TWO_AMP)) {
if (!(card_data->flags & MAX98390_TWO_AMP)) {
dai_link->ops = &mt8188_max98390_ops;
}
if (!init_max98390) {
......@@ -1420,40 +1330,55 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
}
}
priv->private_data = card_data;
snd_soc_card_set_drvdata(card, soc_card_data);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n",
__func__);
err:
of_node_put(platform_node);
clean_card_reference(card);
err_adsp_node:
of_node_put(adsp_node);
return ret;
return 0;
}
static struct mt8188_card_data mt8188_evb_card = {
.name = "mt8188_mt6359",
static const struct mtk_sof_priv mt8188_sof_priv = {
.conn_streams = g_sof_conn_streams,
.num_streams = ARRAY_SIZE(g_sof_conn_streams),
};
static struct mt8188_card_data mt8188_nau8825_card = {
.name = "mt8188_nau8825",
.quirk = NAU8825_HS_PRESENT,
static const struct mtk_soundcard_pdata mt8188_evb_card = {
.card_name = "mt8188_mt6359",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8188_mt6359_soc_card,
.num_jacks = MT8188_JACK_MAX,
},
.sof_priv = &mt8188_sof_priv,
.soc_probe = mt8188_mt6359_soc_card_probe,
};
static struct mt8188_card_data mt8188_rt5682s_card = {
.name = "mt8188_rt5682s",
.quirk = RT5682S_HS_PRESENT | MAX98390_TWO_AMP,
static const struct mtk_soundcard_pdata mt8188_nau8825_card = {
.card_name = "mt8188_nau8825",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8188_mt6359_soc_card,
.num_jacks = MT8188_JACK_MAX,
.flags = NAU8825_HS_PRESENT
},
.sof_priv = &mt8188_sof_priv,
.soc_probe = mt8188_mt6359_soc_card_probe,
};
static struct mt8188_card_data mt8188_es8326_card = {
.name = "mt8188_es8326",
.quirk = ES8326_HS_PRESENT | MAX98390_TWO_AMP,
static const struct mtk_soundcard_pdata mt8188_rt5682s_card = {
.card_name = "mt8188_rt5682s",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8188_mt6359_soc_card,
.num_jacks = MT8188_JACK_MAX,
.flags = RT5682S_HS_PRESENT | MAX98390_TWO_AMP
},
.sof_priv = &mt8188_sof_priv,
.soc_probe = mt8188_mt6359_soc_card_probe,
};
static const struct mtk_soundcard_pdata mt8188_es8326_card = {
.card_name = "mt8188_es8326",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8188_mt6359_soc_card,
.num_jacks = MT8188_JACK_MAX,
.flags = ES8326_HS_PRESENT | MAX98390_TWO_AMP
},
.sof_priv = &mt8188_sof_priv,
.soc_probe = mt8188_mt6359_soc_card_probe,
};
static const struct of_device_id mt8188_mt6359_dt_match[] = {
......@@ -1471,7 +1396,7 @@ static struct platform_driver mt8188_mt6359_driver = {
.of_match_table = mt8188_mt6359_dt_match,
.pm = &snd_soc_pm_ops,
},
.probe = mt8188_mt6359_dev_probe,
.probe = mtk_soundcard_common_probe,
};
module_platform_driver(mt8188_mt6359_driver);
......
......@@ -2125,22 +2125,6 @@ static int mt8192_afe_runtime_resume(struct device *dev)
return 0;
}
static int mt8192_afe_component_probe(struct snd_soc_component *component)
{
return mtk_afe_add_sub_dai_control(component);
}
static const struct snd_soc_component_driver mt8192_afe_component = {
.name = AFE_PCM_NAME,
.probe = mt8192_afe_component_probe,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
};
static const struct snd_soc_component_driver mt8192_afe_pcm_component = {
.name = "mt8192-afe-pcm-dai",
};
static int mt8192_dai_memif_register(struct mtk_base_afe *afe)
{
struct mtk_base_afe_dai *dai;
......@@ -2302,16 +2286,11 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
/* register platform */
ret = devm_snd_soc_register_component(&pdev->dev,
&mt8192_afe_component, NULL, 0);
if (ret)
return dev_err_probe(dev, ret, "Couldn't register AFE component\n");
ret = devm_snd_soc_register_component(&pdev->dev,
&mt8192_afe_pcm_component,
&mtk_afe_pcm_platform,
afe->dai_drivers,
afe->num_dai_drivers);
if (ret)
return dev_err_probe(dev, ret, "Couldn't register AFE-PCM component\n");
return dev_err_probe(dev, ret, "Couldn't register AFE component\n");
return 0;
}
......
......@@ -20,6 +20,8 @@
#include "../../codecs/rt1015.h"
#include "../../codecs/rt5682.h"
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-soc-card.h"
#include "../common/mtk-soundcard-driver.h"
#include "mt8192-afe-common.h"
#include "mt8192-afe-clk.h"
#include "mt8192-afe-gpio.h"
......@@ -38,9 +40,10 @@
#define RT1015P_RT5682_OF_NAME "mediatek,mt8192_mt6359_rt1015p_rt5682"
#define RT1015P_RT5682S_OF_NAME "mediatek,mt8192_mt6359_rt1015p_rt5682s"
struct mt8192_mt6359_priv {
struct snd_soc_jack headset_jack;
struct snd_soc_jack hdmi_jack;
enum mt8192_jacks {
MT8192_JACK_HEADSET,
MT8192_JACK_HDMI,
MT8192_JACK_MAX,
};
/* Headset jack detection DAPM pins */
......@@ -323,13 +326,13 @@ static int mt8192_mt6359_init(struct snd_soc_pcm_runtime *rtd)
static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8192_JACK_HEADSET];
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_jack *jack = &priv->headset_jack;
int ret;
ret = mt8192_dai_i2s_set_share(afe, "I2S8", "I2S9");
......@@ -359,19 +362,19 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd)
static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8192_JACK_HDMI];
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
int ret;
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
&priv->hdmi_jack);
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack);
if (ret) {
dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
return ret;
}
return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
}
static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
......@@ -386,100 +389,6 @@ static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
static int
mt8192_mt6359_cap1_startup(struct snd_pcm_substream *substream)
{
static const unsigned int channels[] = {
1, 2, 4
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
static const unsigned int rates[] = {
8000, 16000, 32000, 48000, 96000, 192000
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channels failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8192_mt6359_capture1_ops = {
.startup = mt8192_mt6359_cap1_startup,
};
static int
mt8192_mt6359_rt5682_startup(struct snd_pcm_substream *substream)
{
static const unsigned int channels[] = {
1, 2
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
static const unsigned int rates[] = {
48000
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channels failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8192_mt6359_rt5682_ops = {
.startup = mt8192_mt6359_rt5682_startup,
};
/* FE */
SND_SOC_DAILINK_DEFS(playback1,
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
......@@ -717,7 +626,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_playback = 1,
.ops = &mt8192_mt6359_rt5682_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(playback3),
},
{
......@@ -781,7 +690,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8192_mt6359_capture1_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(capture1),
},
{
......@@ -791,7 +700,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = {
SND_SOC_DPCM_TRIGGER_PRE},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8192_mt6359_rt5682_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(capture2),
},
{
......@@ -1136,71 +1045,53 @@ static int mt8192_mt6359_card_set_be_link(struct snd_soc_card *card,
return 0;
}
static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
static int mt8192_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data)
{
struct snd_soc_card *card;
struct device_node *platform_node, *hdmi_codec, *headset_codec, *speaker_codec;
int ret, i;
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
struct device *dev = card->dev;
struct device_node *hdmi_codec, *headset_codec, *speaker_codec;
struct snd_soc_dai_link *dai_link;
struct mt8192_mt6359_priv *priv;
card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
if (!card)
return -EINVAL;
card->dev = &pdev->dev;
if (of_device_is_compatible(pdev->dev.of_node, RT1015P_RT5682_OF_NAME))
card->name = RT1015P_RT5682_CARD_NAME;
else if (of_device_is_compatible(pdev->dev.of_node, RT1015P_RT5682S_OF_NAME))
card->name = RT1015P_RT5682S_CARD_NAME;
else
dev_dbg(&pdev->dev, "No need to set card name\n");
int i, ret = 0;
hdmi_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,hdmi-codec", 0);
hdmi_codec = of_parse_phandle(dev->of_node, "mediatek,hdmi-codec", 0);
if (!hdmi_codec)
dev_dbg(&pdev->dev, "The machine has no hdmi-codec\n");
dev_dbg(dev, "The machine has no hdmi-codec\n");
platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
if (!platform_node) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
goto err_platform_node;
}
speaker_codec = of_get_child_by_name(pdev->dev.of_node, "speaker-codecs");
speaker_codec = of_get_child_by_name(dev->of_node, "speaker-codecs");
if (!speaker_codec) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
dev_err_probe(dev, ret, "Property 'speaker-codecs' missing or invalid\n");
goto err_speaker_codec;
}
headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
headset_codec = of_get_child_by_name(dev->of_node, "headset-codec");
if (!headset_codec) {
ret = -EINVAL;
dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
dev_err_probe(dev, ret, "Property 'headset-codec' missing or invalid\n");
goto err_headset_codec;
}
for_each_card_prelinks(card, i, dai_link) {
ret = mt8192_mt6359_card_set_be_link(card, dai_link, speaker_codec, "I2S3");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
dev_err_probe(dev, ret, "%s set speaker_codec fail\n",
dai_link->name);
goto err_probe;
break;
}
ret = mt8192_mt6359_card_set_be_link(card, dai_link, headset_codec, "I2S8");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
dev_err_probe(dev, ret, "%s set headset_codec fail\n",
dai_link->name);
goto err_probe;
break;
}
ret = mt8192_mt6359_card_set_be_link(card, dai_link, headset_codec, "I2S9");
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
dev_err_probe(dev, ret, "%s set headset_codec fail\n",
dai_link->name);
goto err_probe;
break;
}
if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {
......@@ -1211,52 +1102,122 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev)
if (dai_link->num_codecs && dai_link->codecs[0].dai_name &&
strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0)
dai_link->ops = &mt8192_rt1015_i2s_ops;
if (!dai_link->platforms->name)
dai_link->platforms->of_node = platform_node;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto err_probe;
}
snd_soc_card_set_drvdata(card, priv);
ret = mt8192_afe_gpio_init(&pdev->dev);
if (ret) {
dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
goto err_probe;
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
err_probe:
of_node_put(headset_codec);
err_headset_codec:
of_node_put(speaker_codec);
err_speaker_codec:
of_node_put(platform_node);
err_platform_node:
if (hdmi_codec)
of_node_put(hdmi_codec);
return ret;
}
static int mt8192_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
{
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
int ret;
if (legacy) {
ret = mt8192_mt6359_legacy_probe(soc_card_data);
if (ret)
return ret;
} else {
struct snd_soc_dai_link *dai_link;
int i;
for_each_card_prelinks(card, i, dai_link)
if (dai_link->num_codecs && dai_link->codecs[0].dai_name &&
strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0)
dai_link->ops = &mt8192_rt1015_i2s_ops;
}
ret = mt8192_afe_gpio_init(card->dev);
if (ret)
return dev_err_probe(card->dev, ret, "%s init gpio error\n", __func__);
return 0;
}
static const unsigned int mt8192_pcm_playback_channels[] = { 1, 2 };
static const unsigned int mt8192_pcm_playback_rates[] = { 48000 };
static const unsigned int mt8192_pcm_capture_channels[] = { 1, 2, 4 };
static const unsigned int mt8192_pcm_capture_rates[] = {
8000, 16000, 32000, 48000, 96000, 192000
};
static const struct mtk_pcm_constraints_data mt8192_pcm_constraints[MTK_CONSTRAINT_CAPTURE + 1] = {
[MTK_CONSTRAINT_PLAYBACK] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8192_pcm_playback_channels,
.count = ARRAY_SIZE(mt8192_pcm_playback_channels)
},
.rates = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8192_pcm_playback_rates,
.count = ARRAY_SIZE(mt8192_pcm_playback_rates)
}
},
[MTK_CONSTRAINT_CAPTURE] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8192_pcm_capture_channels,
.count = ARRAY_SIZE(mt8192_pcm_capture_channels)
},
.rates = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8192_pcm_capture_rates,
.count = ARRAY_SIZE(mt8192_pcm_capture_rates)
}
}
};
static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015_rt5682_pdata = {
.card_name = RT1015_RT5682_CARD_NAME,
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8192_mt6359_rt1015_rt5682_card,
.num_jacks = MT8192_JACK_MAX,
.pcm_constraints = mt8192_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8192_pcm_constraints),
},
.soc_probe = mt8192_mt6359_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015p_rt5682_pdata = {
.card_name = RT1015P_RT5682_CARD_NAME,
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8192_mt6359_rt1015p_rt5682x_card,
.num_jacks = MT8192_JACK_MAX,
.pcm_constraints = mt8192_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8192_pcm_constraints),
},
.soc_probe = mt8192_mt6359_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015p_rt5682s_pdata = {
.card_name = RT1015P_RT5682S_CARD_NAME,
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8192_mt6359_rt1015p_rt5682x_card,
.num_jacks = MT8192_JACK_MAX,
.pcm_constraints = mt8192_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8192_pcm_constraints),
},
.soc_probe = mt8192_mt6359_soc_card_probe
};
#ifdef CONFIG_OF
static const struct of_device_id mt8192_mt6359_dt_match[] = {
{
.compatible = RT1015_RT5682_OF_NAME,
.data = &mt8192_mt6359_rt1015_rt5682_card,
.data = &mt8192_mt6359_rt1015_rt5682_pdata,
},
{
.compatible = RT1015P_RT5682_OF_NAME,
.data = &mt8192_mt6359_rt1015p_rt5682x_card,
.data = &mt8192_mt6359_rt1015p_rt5682_pdata,
},
{
.compatible = RT1015P_RT5682S_OF_NAME,
.data = &mt8192_mt6359_rt1015p_rt5682x_card,
.data = &mt8192_mt6359_rt1015p_rt5682s_pdata,
},
{}
};
......@@ -1276,7 +1237,7 @@ static struct platform_driver mt8192_mt6359_driver = {
#endif
.pm = &mt8192_mt6359_pm_ops,
},
.probe = mt8192_mt6359_dev_probe,
.probe = mtk_soundcard_common_probe,
};
module_platform_driver(mt8192_mt6359_driver);
......
......@@ -2944,25 +2944,6 @@ static int mt8195_afe_runtime_resume(struct device *dev)
return 0;
}
static int mt8195_afe_component_probe(struct snd_soc_component *component)
{
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
int ret = 0;
snd_soc_component_init_regmap(component, afe->regmap);
ret = mtk_afe_add_sub_dai_control(component);
return ret;
}
static const struct snd_soc_component_driver mt8195_afe_component = {
.name = AFE_PCM_NAME,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
.probe = mt8195_afe_component_probe,
};
static int init_memif_priv_data(struct mtk_base_afe *afe)
{
struct mt8195_afe_private *afe_priv = afe->platform_priv;
......@@ -3164,7 +3145,7 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev)
}
/* register component */
ret = devm_snd_soc_register_component(dev, &mt8195_afe_component,
ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform,
afe->dai_drivers, afe->num_dai_drivers);
if (ret) {
dev_warn(dev, "err_platform\n");
......
......@@ -22,6 +22,7 @@
#include "../common/mtk-afe-platform-driver.h"
#include "../common/mtk-dsp-sof-common.h"
#include "../common/mtk-soc-card.h"
#include "../common/mtk-soundcard-driver.h"
#include "mt8195-afe-clk.h"
#include "mt8195-afe-common.h"
......@@ -29,6 +30,13 @@
#define RT1019_SPEAKER_AMP_PRESENT BIT(1)
#define MAX98390_SPEAKER_AMP_PRESENT BIT(2)
#define DUMB_CODEC_INIT BIT(0)
#define MT6359_CODEC_INIT BIT(1)
#define RT1011_CODEC_INIT BIT(2)
#define RT1019_CODEC_INIT BIT(3)
#define MAX98390_CODEC_INIT BIT(4)
#define RT5682_CODEC_INIT BIT(5)
#define RT1011_CODEC_DAI "rt1011-aif"
#define RT1011_DEV0_NAME "rt1011.2-0038"
#define RT1011_DEV1_NAME "rt1011.2-0039"
......@@ -51,18 +59,17 @@
#define SOF_DMA_UL4 "SOF_DMA_UL4"
#define SOF_DMA_UL5 "SOF_DMA_UL5"
struct mt8195_card_data {
const char *name;
unsigned long quirk;
};
struct mt8195_mt6359_priv {
struct snd_soc_jack headset_jack;
struct snd_soc_jack dp_jack;
struct snd_soc_jack hdmi_jack;
struct clk *i2so1_mclk;
};
enum mt8195_jacks {
MT8195_JACK_HEADSET,
MT8195_JACK_DP,
MT8195_JACK_HDMI,
MT8195_JACK_MAX,
};
/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin mt8195_jack_pins[] = {
{
......@@ -321,44 +328,7 @@ static int mt8195_mt6359_init(struct snd_soc_pcm_runtime *rtd)
static int mt8195_hdmitx_dptx_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
2, 4, 6, 8
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
return mtk_soundcard_startup(substream, MTK_CONSTRAINT_HDMIDP);
}
static const struct snd_soc_ops mt8195_hdmitx_dptx_playback_ops = {
......@@ -382,33 +352,31 @@ static const struct snd_soc_ops mt8195_dptx_ops = {
static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8195_JACK_DP];
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
int ret;
ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT,
&priv->dp_jack);
ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT, jack);
if (ret)
return ret;
return snd_soc_component_set_jack(cmpnt_codec, &priv->dp_jack, NULL);
return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
}
static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8195_JACK_HDMI];
struct snd_soc_component *cmpnt_codec =
snd_soc_rtd_to_codec(rtd, 0)->component;
int ret;
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
&priv->hdmi_jack);
ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack);
if (ret)
return ret;
return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
return snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
}
static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
......@@ -423,98 +391,6 @@ static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
static int mt8195_playback_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
2
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8195_playback_ops = {
.startup = mt8195_playback_startup,
};
static int mt8195_capture_startup(struct snd_pcm_substream *substream)
{
static const unsigned int rates[] = {
48000
};
static const unsigned int channels[] = {
1, 2
};
static const struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
};
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list rate failed\n");
return ret;
}
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
if (ret < 0) {
dev_err(rtd->dev, "hw_constraint_list channel failed\n");
return ret;
}
return 0;
}
static const struct snd_soc_ops mt8195_capture_ops = {
.startup = mt8195_capture_startup,
};
static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
......@@ -566,7 +442,7 @@ static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_rtd_to_codec(rtd, 0)->component;
struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv;
struct snd_soc_jack *jack = &priv->headset_jack;
struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8195_JACK_HEADSET];
struct snd_soc_component *cmpnt_afe =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
......@@ -687,7 +563,7 @@ static int mt8195_rt1011_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
static int mt8195_rt1019_init(struct snd_soc_pcm_runtime *rtd)
static int mt8195_dumb_amp_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
......@@ -707,6 +583,18 @@ static int mt8195_rt1019_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
return 0;
}
static int mt8195_rt1019_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
ret = mt8195_dumb_amp_init(rtd);
if (ret)
return ret;
ret = snd_soc_dapm_add_routes(&card->dapm, mt8195_rt1019_routes,
ARRAY_SIZE(mt8195_rt1019_routes));
if (ret)
......@@ -1025,7 +913,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_playback = 1,
.ops = &mt8195_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL2_FE),
},
[DAI_LINK_DL3_FE] = {
......@@ -1037,7 +925,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_playback = 1,
.ops = &mt8195_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL3_FE),
},
[DAI_LINK_DL6_FE] = {
......@@ -1049,7 +937,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_playback = 1,
.ops = &mt8195_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL6_FE),
},
[DAI_LINK_DL7_FE] = {
......@@ -1072,7 +960,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_playback = 1,
.ops = &mt8195_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL8_FE),
},
[DAI_LINK_DL10_FE] = {
......@@ -1096,7 +984,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_playback = 1,
.ops = &mt8195_playback_ops,
.ops = &mtk_soundcard_common_playback_ops,
SND_SOC_DAILINK_REG(DL11_FE),
},
[DAI_LINK_UL1_FE] = {
......@@ -1119,7 +1007,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL2_FE),
},
[DAI_LINK_UL3_FE] = {
......@@ -1131,7 +1019,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL3_FE),
},
[DAI_LINK_UL4_FE] = {
......@@ -1143,7 +1031,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL4_FE),
},
[DAI_LINK_UL5_FE] = {
......@@ -1155,7 +1043,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL5_FE),
},
[DAI_LINK_UL6_FE] = {
......@@ -1178,7 +1066,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL8_FE),
},
[DAI_LINK_UL9_FE] = {
......@@ -1190,7 +1078,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL9_FE),
},
[DAI_LINK_UL10_FE] = {
......@@ -1202,7 +1090,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
},
.dynamic = 1,
.dpcm_capture = 1,
.ops = &mt8195_capture_ops,
.ops = &mtk_soundcard_common_capture_ops,
SND_SOC_DAILINK_REG(UL10_FE),
},
/* BE */
......@@ -1371,108 +1259,31 @@ static int mt8195_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
return ret;
}
static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
static int mt8195_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data)
{
struct snd_soc_card *card = &mt8195_mt6359_soc_card;
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
struct device_node *codec_node, *dp_node, *hdmi_node;
struct snd_soc_dai_link *dai_link;
struct mtk_soc_card_data *soc_card_data;
struct mt8195_mt6359_priv *mach_priv;
struct device_node *platform_node, *adsp_node, *codec_node, *dp_node, *hdmi_node;
struct mt8195_card_data *card_data;
int is5682s = 0;
int init6359 = 0;
int sof_on = 0;
int ret, i;
card_data = (struct mt8195_card_data *)of_device_get_match_data(&pdev->dev);
card->dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(card, "model");
if (ret) {
dev_err(&pdev->dev, "%s new card name parsing error %d\n",
__func__, ret);
return ret;
}
if (!card->name)
card->name = card_data->name;
struct device *dev = card->dev;
bool is5682s, init6359 = false;
int i;
if (strstr(card->name, "_5682s")) {
codec_node = of_find_compatible_node(NULL, NULL, "realtek,rt5682s");
is5682s = 1;
} else
codec_node = of_find_compatible_node(NULL, NULL, "realtek,rt5682i");
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL);
if (!soc_card_data)
return -ENOMEM;
mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
soc_card_data->mach_priv = mach_priv;
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
if (adsp_node) {
struct mtk_sof_priv *sof_priv;
sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL);
if (!sof_priv) {
ret = -ENOMEM;
goto err_kzalloc;
}
sof_priv->conn_streams = g_sof_conn_streams;
sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams);
sof_priv->sof_dai_link_fixup = mt8195_dai_link_fixup;
soc_card_data->sof_priv = sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
if (!card->topology_shortname_created) {
snprintf(card->topology_shortname, 32, "sof-%s", card->name);
card->topology_shortname_created = true;
}
card->name = card->topology_shortname;
sof_on = 1;
}
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
"mediatek,dai-link",
mt8195_mt6359_dai_links,
ARRAY_SIZE(mt8195_mt6359_dai_links));
if (ret) {
dev_dbg(&pdev->dev, "Parse dai-link fail\n");
goto err_parse_of;
}
is5682s = true;
} else {
if (!sof_on)
card->num_links = DAI_LINK_REGULAR_NUM;
}
platform_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,platform", 0);
if (!platform_node) {
dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n");
ret = -EINVAL;
goto err_platform_node;
codec_node = of_find_compatible_node(NULL, NULL, "realtek,rt5682i");
is5682s = false;
}
dp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,dptx-codec", 0);
hdmi_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,hdmi-codec", 0);
dp_node = of_parse_phandle(dev->of_node, "mediatek,dptx-codec", 0);
hdmi_node = of_parse_phandle(dev->of_node, "mediatek,hdmi-codec", 0);
for_each_card_prelinks(card, i, dai_link) {
if (!dai_link->platforms->name) {
if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && sof_on)
dai_link->platforms->of_node = adsp_node;
else
dai_link->platforms->of_node = platform_node;
}
if (strcmp(dai_link->name, "DPTX_BE") == 0) {
if (!dp_node) {
dev_dbg(&pdev->dev, "No property 'dptx-codec'\n");
dev_dbg(dev, "No property 'dptx-codec'\n");
} else {
dai_link->codecs->of_node = dp_node;
dai_link->codecs->name = NULL;
......@@ -1481,7 +1292,7 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
}
} else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
if (!hdmi_node) {
dev_dbg(&pdev->dev, "No property 'hdmi-codec'\n");
dev_dbg(dev, "No property 'hdmi-codec'\n");
} else {
dai_link->codecs->of_node = hdmi_node;
dai_link->codecs->name = NULL;
......@@ -1490,7 +1301,7 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
}
} else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0) {
if (!codec_node) {
dev_err(&pdev->dev, "Codec not found!\n");
dev_err(dev, "Codec not found!\n");
} else {
dai_link->codecs->of_node = codec_node;
dai_link->codecs->name = NULL;
......@@ -1501,7 +1312,7 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
}
} else if (strcmp(dai_link->name, "ETDM2_IN_BE") == 0) {
if (!codec_node) {
dev_err(&pdev->dev, "Codec not found!\n");
dev_err(dev, "Codec not found!\n");
} else {
dai_link->codecs->of_node = codec_node;
dai_link->codecs->name = NULL;
......@@ -1514,10 +1325,10 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
strcmp(dai_link->name, "UL_SRC2_BE") == 0) {
if (!init6359) {
dai_link->init = mt8195_mt6359_init;
init6359 = 1;
init6359 = true;
}
} else if (strcmp(dai_link->name, "ETDM2_OUT_BE") == 0) {
switch (card_data->quirk) {
switch (card_data->flags) {
case RT1011_SPEAKER_AMP_PRESENT:
dai_link->codecs = rt1011_comps;
dai_link->num_codecs = ARRAY_SIZE(rt1011_comps);
......@@ -1545,33 +1356,159 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev)
}
}
snd_soc_card_set_drvdata(card, soc_card_data);
return 0;
}
static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
{
struct mtk_platform_card_data *card_data = soc_card_data->card_data;
struct snd_soc_card *card = card_data->card;
struct mt8195_mt6359_priv *mach_priv;
struct snd_soc_dai_link *dai_link;
u8 codec_init = 0;
int i;
ret = devm_snd_soc_register_card(&pdev->dev, card);
mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
of_node_put(platform_node);
of_node_put(dp_node);
of_node_put(hdmi_node);
err_kzalloc:
err_parse_of:
err_platform_node:
of_node_put(adsp_node);
return ret;
soc_card_data->mach_priv = mach_priv;
if (legacy)
return mt8195_mt6359_legacy_probe(soc_card_data);
for_each_card_prelinks(card, i, dai_link) {
if (strcmp(dai_link->name, "DPTX_BE") == 0) {
if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8195_dptx_codec_init;
} else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8195_hdmi_codec_init;
} else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 ||
strcmp(dai_link->name, "UL_SRC1_BE") == 0 ||
strcmp(dai_link->name, "UL_SRC2_BE") == 0) {
if (!(codec_init & MT6359_CODEC_INIT)) {
dai_link->init = mt8195_mt6359_init;
codec_init |= MT6359_CODEC_INIT;
}
} else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0 ||
strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 ||
strcmp(dai_link->name, "ETDM1_IN_BE") == 0 ||
strcmp(dai_link->name, "ETDM2_IN_BE") == 0) {
if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) {
if (!(codec_init & MAX98390_CODEC_INIT)) {
dai_link->init = mt8195_max98390_init;
codec_init |= MAX98390_CODEC_INIT;
}
} else if (!strcmp(dai_link->codecs->dai_name, RT1011_CODEC_DAI)) {
dai_link->ops = &mt8195_rt1011_etdm_ops;
if (!(codec_init & RT1011_CODEC_INIT)) {
dai_link->init = mt8195_rt1011_init;
codec_init |= RT1011_CODEC_INIT;
}
} else if (!strcmp(dai_link->codecs->dai_name, RT1019_CODEC_DAI)) {
if (!(codec_init & RT1019_CODEC_INIT)) {
dai_link->init = mt8195_rt1019_init;
codec_init |= RT1019_CODEC_INIT;
}
} else if (!strcmp(dai_link->codecs->dai_name, RT5682_CODEC_DAI) ||
!strcmp(dai_link->codecs->dai_name, RT5682S_CODEC_DAI)) {
dai_link->ops = &mt8195_rt5682_etdm_ops;
if (!(codec_init & RT5682_CODEC_INIT)) {
dai_link->init = mt8195_rt5682_init;
codec_init |= RT5682_CODEC_INIT;
}
} else {
if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) {
if (!(codec_init & DUMB_CODEC_INIT)) {
dai_link->init = mt8195_dumb_amp_init;
codec_init |= DUMB_CODEC_INIT;
}
}
}
}
}
return 0;
}
static struct mt8195_card_data mt8195_mt6359_rt1019_rt5682_card = {
.name = "mt8195_r1019_5682",
.quirk = RT1019_SPEAKER_AMP_PRESENT,
static const unsigned int mt8195_pcm_playback_channels[] = { 2 };
static const unsigned int mt8195_pcm_capture_channels[] = { 1, 2 };
static const unsigned int mt8195_pcm_hdmidp_channels[] = { 2, 4, 6, 8 };
static const unsigned int mt8195_pcm_rates[] = { 48000 };
static const struct snd_pcm_hw_constraint_list mt8195_rate_constraint = {
.list = mt8195_pcm_rates,
.count = ARRAY_SIZE(mt8195_pcm_rates)
};
static struct mt8195_card_data mt8195_mt6359_rt1011_rt5682_card = {
.name = "mt8195_r1011_5682",
.quirk = RT1011_SPEAKER_AMP_PRESENT,
static const struct mtk_pcm_constraints_data mt8195_pcm_constraints[MTK_CONSTRAINT_HDMIDP + 1] = {
[MTK_CONSTRAINT_PLAYBACK] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8195_pcm_playback_channels,
.count = ARRAY_SIZE(mt8195_pcm_playback_channels)
},
.rates = &mt8195_rate_constraint,
},
[MTK_CONSTRAINT_CAPTURE] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8195_pcm_capture_channels,
.count = ARRAY_SIZE(mt8195_pcm_capture_channels)
},
.rates = &mt8195_rate_constraint,
},
[MTK_CONSTRAINT_HDMIDP] = {
.channels = &(const struct snd_pcm_hw_constraint_list) {
.list = mt8195_pcm_hdmidp_channels,
.count = ARRAY_SIZE(mt8195_pcm_hdmidp_channels)
},
.rates = &mt8195_rate_constraint,
},
};
static struct mt8195_card_data mt8195_mt6359_max98390_rt5682_card = {
.name = "mt8195_m98390_r5682",
.quirk = MAX98390_SPEAKER_AMP_PRESENT,
static const struct mtk_sof_priv mt8195_sof_priv = {
.conn_streams = g_sof_conn_streams,
.num_streams = ARRAY_SIZE(g_sof_conn_streams),
.sof_dai_link_fixup = mt8195_dai_link_fixup
};
static const struct mtk_soundcard_pdata mt8195_mt6359_rt1019_rt5682_card = {
.card_name = "mt8195_r1019_5682",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8195_mt6359_soc_card,
.num_jacks = MT8195_JACK_MAX,
.pcm_constraints = mt8195_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8195_pcm_constraints),
.flags = RT1019_SPEAKER_AMP_PRESENT
},
.sof_priv = &mt8195_sof_priv,
.soc_probe = mt8195_mt6359_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8195_mt6359_rt1011_rt5682_card = {
.card_name = "mt8195_r1011_5682",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8195_mt6359_soc_card,
.num_jacks = MT8195_JACK_MAX,
.pcm_constraints = mt8195_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8195_pcm_constraints),
.flags = RT1011_SPEAKER_AMP_PRESENT
},
.sof_priv = &mt8195_sof_priv,
.soc_probe = mt8195_mt6359_soc_card_probe
};
static const struct mtk_soundcard_pdata mt8195_mt6359_max98390_rt5682_card = {
.card_name = "mt8195_m98390_r5682",
.card_data = &(struct mtk_platform_card_data) {
.card = &mt8195_mt6359_soc_card,
.num_jacks = MT8195_JACK_MAX,
.pcm_constraints = mt8195_pcm_constraints,
.num_pcm_constraints = ARRAY_SIZE(mt8195_pcm_constraints),
.flags = MAX98390_SPEAKER_AMP_PRESENT
},
.sof_priv = &mt8195_sof_priv,
.soc_probe = mt8195_mt6359_soc_card_probe
};
static const struct of_device_id mt8195_mt6359_dt_match[] = {
......@@ -1597,7 +1534,7 @@ static struct platform_driver mt8195_mt6359_driver = {
.of_match_table = mt8195_mt6359_dt_match,
.pm = &snd_soc_pm_ops,
},
.probe = mt8195_mt6359_dev_probe,
.probe = mtk_soundcard_common_probe,
};
module_platform_driver(mt8195_mt6359_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment