Merge remote-tracking branch 'asoc/for-5.15' into asoc-linus
This commit is contained in:
commit
38b7673000
|
@ -6,6 +6,7 @@ Required properties:
|
|||
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
|
||||
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
|
||||
"ti,dra7-mcasp-audio" : for DRA7xx platforms
|
||||
"ti,omap4-mcasp-audio" : for OMAP4
|
||||
|
||||
- reg : Should contain reg specifiers for the entries in the reg-names property.
|
||||
- reg-names : Should contain:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Invensense ICS-43432 MEMS microphone with I2S output.
|
||||
Invensense ICS-43432-compatible MEMS microphone with I2S output.
|
||||
|
||||
There are no software configuration options for this device, indeed, the only
|
||||
host connection is the I2S interface. Apart from requirements on clock
|
||||
|
@ -8,7 +8,9 @@ contain audio data. A hardware pin determines if the device outputs data
|
|||
on the left or right channel of the I2S frame.
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "invensense,ics43432"
|
||||
- compatible: should be one of the following.
|
||||
"invensense,ics43432": For the Invensense ICS43432
|
||||
"cui,cmm-4030d-261": For the CUI CMM-4030D-261-I2S-TR
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mediatek AFE PCM controller for mt8195
|
||||
|
||||
maintainers:
|
||||
- Trevor Wu <trevor.wu@mediatek.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt8195-audio
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
mediatek,topckgen:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of the mediatek topckgen controller
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: 26M clock
|
||||
- description: audio pll1 clock
|
||||
- description: audio pll2 clock
|
||||
- description: clock divider for i2si1_mck
|
||||
- description: clock divider for i2si2_mck
|
||||
- description: clock divider for i2so1_mck
|
||||
- description: clock divider for i2so2_mck
|
||||
- description: clock divider for dptx_mck
|
||||
- description: a1sys hoping clock
|
||||
- description: audio intbus clock
|
||||
- description: audio hires clock
|
||||
- description: audio local bus clock
|
||||
- description: mux for dptx_mck
|
||||
- description: mux for i2so1_mck
|
||||
- description: mux for i2so2_mck
|
||||
- description: mux for i2si1_mck
|
||||
- description: mux for i2si2_mck
|
||||
- description: audio infra 26M clock
|
||||
- description: infra bus clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: clk26m
|
||||
- const: apll1_ck
|
||||
- const: apll2_ck
|
||||
- const: apll12_div0
|
||||
- const: apll12_div1
|
||||
- const: apll12_div2
|
||||
- const: apll12_div3
|
||||
- const: apll12_div9
|
||||
- const: a1sys_hp_sel
|
||||
- const: aud_intbus_sel
|
||||
- const: audio_h_sel
|
||||
- const: audio_local_bus_sel
|
||||
- const: dptx_m_sel
|
||||
- const: i2so1_m_sel
|
||||
- const: i2so2_m_sel
|
||||
- const: i2si1_m_sel
|
||||
- const: i2si2_m_sel
|
||||
- const: infra_ao_audio_26m_b
|
||||
- const: scp_adsp_audiodsp
|
||||
|
||||
mediatek,etdm-in1-chn-disabled:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
maxItems: 24
|
||||
description: Specify which input channel should be disabled.
|
||||
|
||||
mediatek,etdm-in2-chn-disabled:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
maxItems: 16
|
||||
description: Specify which input channel should be disabled.
|
||||
|
||||
patternProperties:
|
||||
"^mediatek,etdm-in[1-2]-mclk-always-on-rate-hz$":
|
||||
description: Specify etdm in mclk output rate for always on case.
|
||||
|
||||
"^mediatek,etdm-out[1-3]-mclk-always-on-rate-hz$":
|
||||
description: Specify etdm out mclk output rate for always on case.
|
||||
|
||||
"^mediatek,etdm-in[1-2]-multi-pin-mode$":
|
||||
type: boolean
|
||||
description: if present, the etdm data mode is I2S.
|
||||
|
||||
"^mediatek,etdm-out[1-3]-multi-pin-mode$":
|
||||
type: boolean
|
||||
description: if present, the etdm data mode is I2S.
|
||||
|
||||
"^mediatek,etdm-in[1-2]-cowork-source$":
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
etdm modules can share the same external clock pin. Specify
|
||||
which etdm clock source is required by this etdm in moudule.
|
||||
enum:
|
||||
- 0 # etdm1_in
|
||||
- 1 # etdm2_in
|
||||
- 2 # etdm1_out
|
||||
- 3 # etdm2_out
|
||||
|
||||
"^mediatek,etdm-out[1-2]-cowork-source$":
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
etdm modules can share the same external clock pin. Specify
|
||||
which etdm clock source is required by this etdm out moudule.
|
||||
enum:
|
||||
- 0 # etdm1_in
|
||||
- 1 # etdm2_in
|
||||
- 2 # etdm1_out
|
||||
- 3 # etdm2_out
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- mediatek,topckgen
|
||||
- power-domains
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8195-clk.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/power/mt8195-power.h>
|
||||
|
||||
afe: mt8195-afe-pcm@10890000 {
|
||||
compatible = "mediatek,mt8195-audio";
|
||||
reg = <0x10890000 0x10000>;
|
||||
interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
mediatek,topckgen = <&topckgen>;
|
||||
power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
|
||||
clocks = <&clk26m>,
|
||||
<&topckgen CLK_TOP_APLL1>,
|
||||
<&topckgen CLK_TOP_APLL2>,
|
||||
<&topckgen CLK_TOP_APLL12_DIV0>,
|
||||
<&topckgen CLK_TOP_APLL12_DIV1>,
|
||||
<&topckgen CLK_TOP_APLL12_DIV2>,
|
||||
<&topckgen CLK_TOP_APLL12_DIV3>,
|
||||
<&topckgen CLK_TOP_APLL12_DIV9>,
|
||||
<&topckgen CLK_TOP_A1SYS_HP_SEL>,
|
||||
<&topckgen CLK_TOP_AUD_INTBUS_SEL>,
|
||||
<&topckgen CLK_TOP_AUDIO_H_SEL>,
|
||||
<&topckgen CLK_TOP_AUDIO_LOCAL_BUS_SEL>,
|
||||
<&topckgen CLK_TOP_DPTX_M_SEL>,
|
||||
<&topckgen CLK_TOP_I2SO1_M_SEL>,
|
||||
<&topckgen CLK_TOP_I2SO2_M_SEL>,
|
||||
<&topckgen CLK_TOP_I2SI1_M_SEL>,
|
||||
<&topckgen CLK_TOP_I2SI2_M_SEL>,
|
||||
<&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>,
|
||||
<&scp_adsp CLK_SCP_ADSP_AUDIODSP>;
|
||||
clock-names = "clk26m",
|
||||
"apll1_ck",
|
||||
"apll2_ck",
|
||||
"apll12_div0",
|
||||
"apll12_div1",
|
||||
"apll12_div2",
|
||||
"apll12_div3",
|
||||
"apll12_div9",
|
||||
"a1sys_hp_sel",
|
||||
"aud_intbus_sel",
|
||||
"audio_h_sel",
|
||||
"audio_local_bus_sel",
|
||||
"dptx_m_sel",
|
||||
"i2so1_m_sel",
|
||||
"i2so2_m_sel",
|
||||
"i2si1_m_sel",
|
||||
"i2si2_m_sel",
|
||||
"infra_ao_audio_26m_b",
|
||||
"scp_adsp_audiodsp";
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,47 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1019-rt5682.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mediatek MT8195 with MT6359, RT1019 and RT5682 ASoC sound card driver
|
||||
|
||||
maintainers:
|
||||
- Trevor Wu <trevor.wu@mediatek.com>
|
||||
|
||||
description:
|
||||
This binding describes the MT8195 sound card.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt8195_mt6359_rt1019_rt5682
|
||||
|
||||
mediatek,platform:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of MT8195 ASoC platform.
|
||||
|
||||
mediatek,dptx-codec:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of MT8195 Display Port Tx codec node.
|
||||
|
||||
mediatek,hdmi-codec:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description: The phandle of MT8195 HDMI codec node.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mediatek,platform
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
sound: mt8195-sound {
|
||||
compatible = "mediatek,mt8195_mt6359_rt1019_rt5682";
|
||||
mediatek,platform = <&afe>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&aud_pins_default>;
|
||||
};
|
||||
|
||||
...
|
|
@ -15,7 +15,9 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: realtek,rt1015p
|
||||
enum:
|
||||
- realtek,rt1015p
|
||||
- realtek,rt1019p
|
||||
|
||||
sdb-gpios:
|
||||
description:
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/renesas,rz-ssi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/G2L ASoC Sound Serial Interface (SSIF-2)
|
||||
|
||||
maintainers:
|
||||
- Biju Das <biju.das.jz@bp.renesas.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a07g044-ssi # RZ/G2{L,LC}
|
||||
- const: renesas,rz-ssi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 4
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: int_req
|
||||
- const: dma_rx
|
||||
- const: dma_tx
|
||||
- const: dma_rt
|
||||
|
||||
clocks:
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ssi
|
||||
- const: ssi_sfr
|
||||
- const: audio_clk1
|
||||
- const: audio_clk2
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
description:
|
||||
The first cell represents a phandle to dmac
|
||||
The second cell specifies the encoded MID/RID values of the SSI port
|
||||
connected to the DMA client and the slave channel configuration
|
||||
parameters.
|
||||
bits[0:9] - Specifies MID/RID value of a SSI channel as below
|
||||
MID/RID value of SSI rx0 = 0x256
|
||||
MID/RID value of SSI tx0 = 0x255
|
||||
MID/RID value of SSI rx1 = 0x25a
|
||||
MID/RID value of SSI tx1 = 0x259
|
||||
MID/RID value of SSI rt2 = 0x25f
|
||||
MID/RID value of SSI rx3 = 0x262
|
||||
MID/RID value of SSI tx3 = 0x261
|
||||
bit[10] - HIEN = 1, Detects a request in response to the rising edge
|
||||
of the signal
|
||||
bit[11] - LVL = 0, Detects based on the edge
|
||||
bits[12:14] - AM = 2, Bus cycle mode
|
||||
bit[15] - TM = 0, Single transfer mode
|
||||
|
||||
dma-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: tx
|
||||
- const: rx
|
||||
- items:
|
||||
- const: rt
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- '#sound-dai-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/r9a07g044-cpg.h>
|
||||
|
||||
ssi0: ssi@10049c00 {
|
||||
compatible = "renesas,r9a07g044-ssi",
|
||||
"renesas,rz-ssi";
|
||||
reg = <0x10049c00 0x400>;
|
||||
interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
|
||||
clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
|
||||
<&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
|
||||
<&audio_clk1>,
|
||||
<&audio_clk2>;
|
||||
clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
|
||||
dmas = <&dmac 0x2655>,
|
||||
<&dmac 0x2656>;
|
||||
dma-names = "tx", "rx";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
|
@ -20,7 +20,9 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-i2s
|
||||
- rockchip,rk1808-i2s
|
||||
- rockchip,rk3036-i2s
|
||||
- rockchip,rk3128-i2s
|
||||
- rockchip,rk3188-i2s
|
||||
- rockchip,rk3228-i2s
|
||||
- rockchip,rk3288-i2s
|
||||
|
@ -29,6 +31,7 @@ properties:
|
|||
- rockchip,rk3366-i2s
|
||||
- rockchip,rk3368-i2s
|
||||
- rockchip,rk3399-i2s
|
||||
- rockchip,rv1126-i2s
|
||||
- const: rockchip,rk3066-i2s
|
||||
|
||||
reg:
|
||||
|
@ -61,6 +64,14 @@ properties:
|
|||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: reset-m
|
||||
- const: reset-h
|
||||
|
||||
resets:
|
||||
maxItems: 2
|
||||
|
||||
rockchip,capture-channels:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 2
|
||||
|
|
|
@ -23,6 +23,7 @@ properties:
|
|||
- const: rockchip,rk3366-spdif
|
||||
- const: rockchip,rk3368-spdif
|
||||
- const: rockchip,rk3399-spdif
|
||||
- const: rockchip,rk3568-spdif
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3188-spdif
|
||||
|
|
|
@ -271,6 +271,8 @@ patternProperties:
|
|||
description: Shenzen Chuangsiqi Technology Co.,Ltd.
|
||||
"^cubietech,.*":
|
||||
description: Cubietech, Ltd.
|
||||
"^cui,.*":
|
||||
description: CUI Devices
|
||||
"^cypress,.*":
|
||||
description: Cypress Semiconductor Corporation
|
||||
"^cznic,.*":
|
||||
|
|
|
@ -40,80 +40,6 @@ static int md_flags;
|
|||
module_param_named(sdw_md_flags, md_flags, int, 0444);
|
||||
MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
|
||||
|
||||
/* Intel SHIM Registers Definition */
|
||||
#define SDW_SHIM_LCAP 0x0
|
||||
#define SDW_SHIM_LCTL 0x4
|
||||
#define SDW_SHIM_IPPTR 0x8
|
||||
#define SDW_SHIM_SYNC 0xC
|
||||
|
||||
#define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
|
||||
#define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
|
||||
|
||||
#define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
|
||||
#define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
|
||||
#define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
|
||||
#define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
|
||||
#define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
|
||||
|
||||
#define SDW_SHIM_WAKEEN 0x190
|
||||
#define SDW_SHIM_WAKESTS 0x192
|
||||
|
||||
#define SDW_SHIM_LCTL_SPA BIT(0)
|
||||
#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
|
||||
#define SDW_SHIM_LCTL_CPA BIT(8)
|
||||
#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
|
||||
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
|
||||
#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
|
||||
#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
|
||||
#define SDW_SHIM_SYNC_CMDSYNC BIT(16)
|
||||
#define SDW_SHIM_SYNC_SYNCGO BIT(24)
|
||||
|
||||
#define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
|
||||
#define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
|
||||
#define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
|
||||
|
||||
#define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
|
||||
#define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
|
||||
#define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
|
||||
#define SDW_SHIM_PCMSYCM_DIR BIT(15)
|
||||
|
||||
#define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
|
||||
#define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
|
||||
#define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
|
||||
#define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
|
||||
|
||||
#define SDW_SHIM_IOCTL_MIF BIT(0)
|
||||
#define SDW_SHIM_IOCTL_CO BIT(1)
|
||||
#define SDW_SHIM_IOCTL_COE BIT(2)
|
||||
#define SDW_SHIM_IOCTL_DO BIT(3)
|
||||
#define SDW_SHIM_IOCTL_DOE BIT(4)
|
||||
#define SDW_SHIM_IOCTL_BKE BIT(5)
|
||||
#define SDW_SHIM_IOCTL_WPDD BIT(6)
|
||||
#define SDW_SHIM_IOCTL_CIBD BIT(8)
|
||||
#define SDW_SHIM_IOCTL_DIBD BIT(9)
|
||||
|
||||
#define SDW_SHIM_CTMCTL_DACTQE BIT(0)
|
||||
#define SDW_SHIM_CTMCTL_DODS BIT(1)
|
||||
#define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
|
||||
|
||||
#define SDW_SHIM_WAKEEN_ENABLE BIT(0)
|
||||
#define SDW_SHIM_WAKESTS_STATUS BIT(0)
|
||||
|
||||
/* Intel ALH Register definitions */
|
||||
#define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
|
||||
#define SDW_ALH_NUM_STREAMS 64
|
||||
|
||||
#define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
|
||||
#define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
|
||||
#define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
|
||||
|
||||
enum intel_pdi_type {
|
||||
INTEL_PDI_IN = 0,
|
||||
INTEL_PDI_OUT = 1,
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
#include "cadence_master.h"
|
||||
#include "intel.h"
|
||||
|
||||
#define SDW_SHIM_LCAP 0x0
|
||||
#define SDW_SHIM_BASE 0x2C000
|
||||
#define SDW_ALH_BASE 0x2C800
|
||||
#define SDW_LINK_BASE 0x30000
|
||||
#define SDW_LINK_SIZE 0x10000
|
||||
|
||||
static void intel_link_dev_release(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
|
||||
|
@ -69,8 +63,8 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *
|
|||
link->mmio_base = res->mmio_base;
|
||||
link->registers = res->mmio_base + SDW_LINK_BASE
|
||||
+ (SDW_LINK_SIZE * link_id);
|
||||
link->shim = res->mmio_base + SDW_SHIM_BASE;
|
||||
link->alh = res->mmio_base + SDW_ALH_BASE;
|
||||
link->shim = res->mmio_base + res->shim_base;
|
||||
link->alh = res->mmio_base + res->alh_base;
|
||||
|
||||
link->ops = res->ops;
|
||||
link->dev = res->dev;
|
||||
|
@ -220,6 +214,8 @@ static struct sdw_intel_ctx
|
|||
}
|
||||
|
||||
ctx->mmio_base = res->mmio_base;
|
||||
ctx->shim_base = res->shim_base;
|
||||
ctx->alh_base = res->alh_base;
|
||||
ctx->link_mask = res->link_mask;
|
||||
ctx->handle = res->handle;
|
||||
mutex_init(&ctx->shim_lock);
|
||||
|
@ -308,7 +304,7 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
|
|||
return -EINVAL;
|
||||
|
||||
/* Check SNDWLCAP.LCOUNT */
|
||||
caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
|
||||
caps = ioread32(ctx->mmio_base + ctx->shim_base + SDW_SHIM_LCAP);
|
||||
caps &= GENMASK(2, 0);
|
||||
|
||||
/* Check HW supported vs property value */
|
||||
|
|
|
@ -96,6 +96,7 @@ enum {
|
|||
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
|
||||
MCASP_VERSION_3, /* TI81xx/AM33xx */
|
||||
MCASP_VERSION_4, /* DRA7xxx */
|
||||
MCASP_VERSION_OMAP, /* OMAP4/5 */
|
||||
};
|
||||
|
||||
enum mcbsp_clk_input_pin {
|
||||
|
|
|
@ -7,6 +7,85 @@
|
|||
#include <linux/irqreturn.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
|
||||
#define SDW_SHIM_BASE 0x2C000
|
||||
#define SDW_ALH_BASE 0x2C800
|
||||
#define SDW_LINK_BASE 0x30000
|
||||
#define SDW_LINK_SIZE 0x10000
|
||||
|
||||
/* Intel SHIM Registers Definition */
|
||||
#define SDW_SHIM_LCAP 0x0
|
||||
#define SDW_SHIM_LCTL 0x4
|
||||
#define SDW_SHIM_IPPTR 0x8
|
||||
#define SDW_SHIM_SYNC 0xC
|
||||
|
||||
#define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
|
||||
#define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
|
||||
#define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
|
||||
|
||||
#define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
|
||||
#define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
|
||||
#define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
|
||||
#define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
|
||||
#define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
|
||||
|
||||
#define SDW_SHIM_WAKEEN 0x190
|
||||
#define SDW_SHIM_WAKESTS 0x192
|
||||
|
||||
#define SDW_SHIM_LCTL_SPA BIT(0)
|
||||
#define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
|
||||
#define SDW_SHIM_LCTL_CPA BIT(8)
|
||||
#define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
|
||||
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
|
||||
#define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
|
||||
#define SDW_SHIM_SYNC_SYNCCPU BIT(15)
|
||||
#define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
|
||||
#define SDW_SHIM_SYNC_CMDSYNC BIT(16)
|
||||
#define SDW_SHIM_SYNC_SYNCGO BIT(24)
|
||||
|
||||
#define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
|
||||
#define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
|
||||
#define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
|
||||
|
||||
#define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
|
||||
#define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
|
||||
#define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
|
||||
#define SDW_SHIM_PCMSYCM_DIR BIT(15)
|
||||
|
||||
#define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
|
||||
#define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
|
||||
#define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
|
||||
#define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
|
||||
|
||||
#define SDW_SHIM_IOCTL_MIF BIT(0)
|
||||
#define SDW_SHIM_IOCTL_CO BIT(1)
|
||||
#define SDW_SHIM_IOCTL_COE BIT(2)
|
||||
#define SDW_SHIM_IOCTL_DO BIT(3)
|
||||
#define SDW_SHIM_IOCTL_DOE BIT(4)
|
||||
#define SDW_SHIM_IOCTL_BKE BIT(5)
|
||||
#define SDW_SHIM_IOCTL_WPDD BIT(6)
|
||||
#define SDW_SHIM_IOCTL_CIBD BIT(8)
|
||||
#define SDW_SHIM_IOCTL_DIBD BIT(9)
|
||||
|
||||
#define SDW_SHIM_CTMCTL_DACTQE BIT(0)
|
||||
#define SDW_SHIM_CTMCTL_DODS BIT(1)
|
||||
#define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
|
||||
|
||||
#define SDW_SHIM_WAKEEN_ENABLE BIT(0)
|
||||
#define SDW_SHIM_WAKESTS_STATUS BIT(0)
|
||||
|
||||
/* Intel ALH Register definitions */
|
||||
#define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
|
||||
#define SDW_ALH_NUM_STREAMS 64
|
||||
|
||||
#define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
|
||||
#define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
|
||||
#define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
|
||||
|
||||
/**
|
||||
* struct sdw_intel_stream_params_data: configuration passed during
|
||||
* the @params_stream callback, e.g. for interaction with DSP
|
||||
|
@ -116,6 +195,8 @@ struct sdw_intel_slave_id {
|
|||
* @link_list: list to handle interrupts across all links
|
||||
* @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
|
||||
* @shim_mask: flags to track initialization of SHIM shared registers
|
||||
* @shim_base: sdw shim base.
|
||||
* @alh_base: sdw alh base.
|
||||
*/
|
||||
struct sdw_intel_ctx {
|
||||
int count;
|
||||
|
@ -128,6 +209,8 @@ struct sdw_intel_ctx {
|
|||
struct list_head link_list;
|
||||
struct mutex shim_lock; /* lock for access to shared SHIM registers */
|
||||
u32 shim_mask;
|
||||
u32 shim_base;
|
||||
u32 alh_base;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -146,6 +229,8 @@ struct sdw_intel_ctx {
|
|||
* machine-specific quirks are handled in the DSP driver.
|
||||
* @clock_stop_quirks: mask array of possible behaviors requested by the
|
||||
* DSP driver. The quirks are common for all links for now.
|
||||
* @shim_base: sdw shim base.
|
||||
* @alh_base: sdw alh base.
|
||||
*/
|
||||
struct sdw_intel_res {
|
||||
int count;
|
||||
|
@ -157,6 +242,8 @@ struct sdw_intel_res {
|
|||
struct device *dev;
|
||||
u32 link_mask;
|
||||
u32 clock_stop_quirks;
|
||||
u32 shim_base;
|
||||
u32 alh_base;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -101,5 +101,6 @@ struct sof_dev_desc {
|
|||
};
|
||||
|
||||
int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd);
|
||||
int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -233,6 +233,8 @@
|
|||
*
|
||||
* %SKL_TKN_U32_ASTATE_CLK_SRC: Clock source for A-State entry
|
||||
*
|
||||
* %SKL_TKN_U32_FMT_CFG_IDX: Format config index
|
||||
*
|
||||
* module_id and loadable flags dont have tokens as these values will be
|
||||
* read from the DSP FW manifest
|
||||
*
|
||||
|
@ -324,7 +326,9 @@ enum SKL_TKNS {
|
|||
SKL_TKN_U32_ASTATE_COUNT,
|
||||
SKL_TKN_U32_ASTATE_KCPS,
|
||||
SKL_TKN_U32_ASTATE_CLK_SRC,
|
||||
SKL_TKN_MAX = SKL_TKN_U32_ASTATE_CLK_SRC,
|
||||
|
||||
SKL_TKN_U32_FMT_CFG_IDX = 96,
|
||||
SKL_TKN_MAX = SKL_TKN_U32_FMT_CFG_IDX,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,3 +52,12 @@ config SND_SOC_AMD_RENOIR_MACH
|
|||
depends on SND_SOC_AMD_RENOIR
|
||||
help
|
||||
This option enables machine driver for DMIC
|
||||
|
||||
config SND_SOC_AMD_ACP5x
|
||||
tristate "AMD Audio Coprocessor-v5.x I2S support"
|
||||
depends on X86 && PCI
|
||||
help
|
||||
This option enables ACP v5.x support on AMD platform
|
||||
|
||||
By enabling this flag build will trigger for ACP PCI driver,
|
||||
ACP DMA driver, CPU DAI driver.
|
||||
|
|
|
@ -10,3 +10,4 @@ obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o
|
|||
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
|
||||
obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/
|
||||
|
|
|
@ -756,15 +756,9 @@ static int cz_probe(struct platform_device *pdev)
|
|||
snd_soc_card_set_drvdata(card, machine);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev,
|
||||
"devm_snd_soc_register_card(%s) failed: %d\n",
|
||||
card->name, ret);
|
||||
else
|
||||
dev_dbg(&pdev->dev,
|
||||
"devm_snd_soc_register_card(%s) probe deferred: %d\n",
|
||||
card->name, ret);
|
||||
return ret;
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"devm_snd_soc_register_card(%s) failed\n",
|
||||
card->name);
|
||||
}
|
||||
bt_uart_enable = !device_property_read_bool(&pdev->dev,
|
||||
"bt-pad-enable");
|
||||
|
|
|
@ -156,7 +156,7 @@ static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num,
|
|||
acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num);
|
||||
}
|
||||
|
||||
/* Initialize a dma descriptor in SRAM based on descritor information passed */
|
||||
/* Initialize a dma descriptor in SRAM based on descriptor information passed */
|
||||
static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
|
||||
u16 descr_idx,
|
||||
acp_dma_dscr_transfer_t *descr_info)
|
||||
|
@ -288,7 +288,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
|
|||
&dmadscr[i]);
|
||||
}
|
||||
pre_config_reset(acp_mmio, ch);
|
||||
/* Configure the DMA channel with the above descriptore */
|
||||
/* Configure the DMA channel with the above descriptor */
|
||||
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
|
||||
NUM_DSCRS_PER_CHANNEL,
|
||||
ACP_DMA_PRIORITY_LEVEL_NORMAL);
|
||||
|
@ -322,7 +322,7 @@ static void acp_pte_config(void __iomem *acp_mmio, dma_addr_t addr,
|
|||
high |= BIT(31);
|
||||
acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
|
||||
|
||||
/* Move to next physically contiguos page */
|
||||
/* Move to next physically contiguous page */
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
@ -602,11 +602,11 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
|
|||
acp_reg_write(val, acp_mmio, mmACP_BT_UART_PAD_SEL);
|
||||
}
|
||||
|
||||
/* initiailize Onion control DAGB register */
|
||||
/* initialize Onion control DAGB register */
|
||||
acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio,
|
||||
mmACP_AXI2DAGB_ONION_CNTL);
|
||||
|
||||
/* initiailize Garlic control DAGB registers */
|
||||
/* initialize Garlic control DAGB registers */
|
||||
acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio,
|
||||
mmACP_AXI2DAGB_GARLIC_CNTL);
|
||||
|
||||
|
@ -621,7 +621,7 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type)
|
|||
acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio,
|
||||
mmACP_DMA_DESC_BASE_ADDR);
|
||||
|
||||
/* Num of descriptiors in SRAM 0x4, means 256 descriptors;(64 * 4) */
|
||||
/* Num of descriptors in SRAM 0x4, means 256 descriptors;(64 * 4) */
|
||||
acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR);
|
||||
acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK,
|
||||
acp_mmio, mmACP_EXTERNAL_INTR_CNTL);
|
||||
|
@ -1035,13 +1035,6 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
|
|||
return bytes_to_frames(runtime, pos);
|
||||
}
|
||||
|
||||
static int acp_dma_mmap(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return snd_pcm_lib_default_mmap(substream, vma);
|
||||
}
|
||||
|
||||
static int acp_dma_prepare(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -1205,7 +1198,6 @@ static const struct snd_soc_component_driver acp_asoc_platform = {
|
|||
.hw_params = acp_dma_hw_params,
|
||||
.trigger = acp_dma_trigger,
|
||||
.pointer = acp_dma_pointer,
|
||||
.mmap = acp_dma_mmap,
|
||||
.prepare = acp_dma_prepare,
|
||||
.pcm_construct = acp_dma_new,
|
||||
};
|
||||
|
|
|
@ -512,17 +512,11 @@ static int acp3x_probe(struct platform_device *pdev)
|
|||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev,
|
||||
"devm_snd_soc_register_card(%s) failed: %d\n",
|
||||
card->name, ret);
|
||||
else
|
||||
dev_dbg(&pdev->dev,
|
||||
"devm_snd_soc_register_card(%s) probe deferred: %d\n",
|
||||
card->name, ret);
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"devm_snd_soc_register_card(%s) failed\n",
|
||||
card->name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id acp3x_audio_acpi_match[] = {
|
||||
|
|
|
@ -147,7 +147,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
|
|||
high |= BIT(31);
|
||||
rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
|
||||
+ 4);
|
||||
/* Move to next physically contiguos page */
|
||||
/* Move to next physically contiguous page */
|
||||
val += 8;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
|
@ -320,13 +320,6 @@ static int acp3x_dma_new(struct snd_soc_component *component,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int acp3x_dma_mmap(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return snd_pcm_lib_default_mmap(substream, vma);
|
||||
}
|
||||
|
||||
static int acp3x_dma_close(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -370,7 +363,6 @@ static const struct snd_soc_component_driver acp3x_i2s_component = {
|
|||
.close = acp3x_dma_close,
|
||||
.hw_params = acp3x_dma_hw_params,
|
||||
.pointer = acp3x_dma_pointer,
|
||||
.mmap = acp3x_dma_mmap,
|
||||
.pcm_construct = acp3x_dma_new,
|
||||
};
|
||||
|
||||
|
|
|
@ -291,13 +291,6 @@ static int acp_pdm_dma_new(struct snd_soc_component *component,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int acp_pdm_dma_mmap(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return snd_pcm_lib_default_mmap(substream, vma);
|
||||
}
|
||||
|
||||
static int acp_pdm_dma_close(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -375,7 +368,6 @@ static const struct snd_soc_component_driver acp_pdm_component = {
|
|||
.close = acp_pdm_dma_close,
|
||||
.hw_params = acp_pdm_dma_hw_params,
|
||||
.pointer = acp_pdm_dma_pointer,
|
||||
.mmap = acp_pdm_dma_mmap,
|
||||
.pcm_construct = acp_pdm_dma_new,
|
||||
};
|
||||
|
||||
|
|
|
@ -54,10 +54,9 @@ static int acp_probe(struct platform_device *pdev)
|
|||
snd_soc_card_set_drvdata(card, machine);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"snd_soc_register_card(%s) failed: %d\n",
|
||||
acp_card.name, ret);
|
||||
return ret;
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"snd_soc_register_card(%s) failed\n",
|
||||
card->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Vangogh platform Support
|
||||
snd-pci-acp5x-objs := pci-acp5x.o
|
||||
snd-acp5x-i2s-objs := acp5x-i2s.o
|
||||
snd-acp5x-pcm-dma-objs := acp5x-pcm-dma.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-pci-acp5x.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-i2s.o
|
||||
obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-pcm-dma.o
|
|
@ -0,0 +1,427 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// AMD ALSA SoC PCM Driver
|
||||
//
|
||||
// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dai.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "acp5x.h"
|
||||
|
||||
#define DRV_NAME "acp5x_i2s_playcap"
|
||||
|
||||
static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct i2s_dev_data *adata;
|
||||
int mode;
|
||||
|
||||
adata = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
|
||||
switch (mode) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
adata->tdm_mode = TDM_DISABLE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
adata->tdm_mode = TDM_ENABLE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
|
||||
switch (mode) {
|
||||
case SND_SOC_DAIFMT_CBC_CFC:
|
||||
adata->master_mode = I2S_MASTER_MODE_ENABLE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBP_CFP:
|
||||
adata->master_mode = I2S_MASTER_MODE_DISABLE;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp5x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
|
||||
u32 tx_mask, u32 rx_mask,
|
||||
int slots, int slot_width)
|
||||
{
|
||||
struct i2s_dev_data *adata;
|
||||
u32 frm_len;
|
||||
u16 slot_len;
|
||||
|
||||
adata = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
/* These values are as per Hardware Spec */
|
||||
switch (slot_width) {
|
||||
case SLOT_WIDTH_8:
|
||||
slot_len = 8;
|
||||
break;
|
||||
case SLOT_WIDTH_16:
|
||||
slot_len = 16;
|
||||
break;
|
||||
case SLOT_WIDTH_24:
|
||||
slot_len = 24;
|
||||
break;
|
||||
case SLOT_WIDTH_32:
|
||||
slot_len = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
|
||||
adata->tdm_fmt = frm_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct i2s_stream_instance *rtd;
|
||||
struct snd_soc_pcm_runtime *prtd;
|
||||
struct snd_soc_card *card;
|
||||
struct acp5x_platform_info *pinfo;
|
||||
struct i2s_dev_data *adata;
|
||||
union acp_i2stdm_mstrclkgen mclkgen;
|
||||
|
||||
u32 val;
|
||||
u32 reg_val, frmt_reg, master_reg;
|
||||
u32 lrclk_div_val, bclk_div_val;
|
||||
|
||||
lrclk_div_val = 0;
|
||||
bclk_div_val = 0;
|
||||
prtd = asoc_substream_to_rtd(substream);
|
||||
rtd = substream->runtime->private_data;
|
||||
card = prtd->card;
|
||||
adata = snd_soc_dai_get_drvdata(dai);
|
||||
pinfo = snd_soc_card_get_drvdata(card);
|
||||
if (pinfo) {
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rtd->i2s_instance = pinfo->play_i2s_instance;
|
||||
else
|
||||
rtd->i2s_instance = pinfo->cap_i2s_instance;
|
||||
}
|
||||
|
||||
/* These values are as per Hardware Spec */
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_U8:
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
rtd->xfer_resolution = 0x0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
rtd->xfer_resolution = 0x02;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
rtd->xfer_resolution = 0x04;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
rtd->xfer_resolution = 0x05;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_val = ACP_HSTDM_ITER;
|
||||
frmt_reg = ACP_HSTDM_TXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = ACP_I2STDM_ITER;
|
||||
frmt_reg = ACP_I2STDM_TXFRMT;
|
||||
}
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_val = ACP_HSTDM_IRER;
|
||||
frmt_reg = ACP_HSTDM_RXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = ACP_I2STDM_IRER;
|
||||
frmt_reg = ACP_I2STDM_RXFRMT;
|
||||
}
|
||||
}
|
||||
if (adata->tdm_mode) {
|
||||
val = acp_readl(rtd->acp5x_base + reg_val);
|
||||
acp_writel(val | 0x2, rtd->acp5x_base + reg_val);
|
||||
acp_writel(adata->tdm_fmt, rtd->acp5x_base + frmt_reg);
|
||||
}
|
||||
val = acp_readl(rtd->acp5x_base + reg_val);
|
||||
val &= ~ACP5x_ITER_IRER_SAMP_LEN_MASK;
|
||||
val = val | (rtd->xfer_resolution << 3);
|
||||
acp_writel(val, rtd->acp5x_base + reg_val);
|
||||
|
||||
if (adata->master_mode) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
master_reg = ACP_I2STDM2_MSTRCLKGEN;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
master_reg = ACP_I2STDM0_MSTRCLKGEN;
|
||||
break;
|
||||
}
|
||||
mclkgen.bits.i2stdm_master_mode = 0x1;
|
||||
if (adata->tdm_mode)
|
||||
mclkgen.bits.i2stdm_format_mode = 0x01;
|
||||
else
|
||||
mclkgen.bits.i2stdm_format_mode = 0x0;
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
switch (params_rate(params)) {
|
||||
case 8000:
|
||||
bclk_div_val = 768;
|
||||
break;
|
||||
case 16000:
|
||||
bclk_div_val = 384;
|
||||
break;
|
||||
case 24000:
|
||||
bclk_div_val = 256;
|
||||
break;
|
||||
case 32000:
|
||||
bclk_div_val = 192;
|
||||
break;
|
||||
case 44100:
|
||||
case 48000:
|
||||
bclk_div_val = 128;
|
||||
break;
|
||||
case 88200:
|
||||
case 96000:
|
||||
bclk_div_val = 64;
|
||||
break;
|
||||
case 192000:
|
||||
bclk_div_val = 32;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
lrclk_div_val = 32;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
switch (params_rate(params)) {
|
||||
case 8000:
|
||||
bclk_div_val = 384;
|
||||
break;
|
||||
case 16000:
|
||||
bclk_div_val = 192;
|
||||
break;
|
||||
case 24000:
|
||||
bclk_div_val = 128;
|
||||
break;
|
||||
case 32000:
|
||||
bclk_div_val = 96;
|
||||
break;
|
||||
case 44100:
|
||||
case 48000:
|
||||
bclk_div_val = 64;
|
||||
break;
|
||||
case 88200:
|
||||
case 96000:
|
||||
bclk_div_val = 32;
|
||||
break;
|
||||
case 192000:
|
||||
bclk_div_val = 16;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
lrclk_div_val = 64;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
mclkgen.bits.i2stdm_bclk_div_val = bclk_div_val;
|
||||
mclkgen.bits.i2stdm_lrclk_div_val = lrclk_div_val;
|
||||
acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp5x_i2s_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct i2s_stream_instance *rtd;
|
||||
u32 ret, val, period_bytes, reg_val, ier_val, water_val;
|
||||
u32 buf_size, buf_reg;
|
||||
|
||||
rtd = substream->runtime->private_data;
|
||||
period_bytes = frames_to_bytes(substream->runtime,
|
||||
substream->runtime->period_size);
|
||||
buf_size = frames_to_bytes(substream->runtime,
|
||||
substream->runtime->buffer_size);
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
rtd->bytescount = acp_get_byte_count(rtd,
|
||||
substream->stream);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
water_val =
|
||||
ACP_HS_TX_INTR_WATERMARK_SIZE;
|
||||
reg_val = ACP_HSTDM_ITER;
|
||||
ier_val = ACP_HSTDM_IER;
|
||||
buf_reg = ACP_HS_TX_RINGBUFSIZE;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
water_val =
|
||||
ACP_I2S_TX_INTR_WATERMARK_SIZE;
|
||||
reg_val = ACP_I2STDM_ITER;
|
||||
ier_val = ACP_I2STDM_IER;
|
||||
buf_reg = ACP_I2S_TX_RINGBUFSIZE;
|
||||
}
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
water_val =
|
||||
ACP_HS_RX_INTR_WATERMARK_SIZE;
|
||||
reg_val = ACP_HSTDM_IRER;
|
||||
ier_val = ACP_HSTDM_IER;
|
||||
buf_reg = ACP_HS_RX_RINGBUFSIZE;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
water_val =
|
||||
ACP_I2S_RX_INTR_WATERMARK_SIZE;
|
||||
reg_val = ACP_I2STDM_IRER;
|
||||
ier_val = ACP_I2STDM_IER;
|
||||
buf_reg = ACP_I2S_RX_RINGBUFSIZE;
|
||||
}
|
||||
}
|
||||
acp_writel(period_bytes, rtd->acp5x_base + water_val);
|
||||
acp_writel(buf_size, rtd->acp5x_base + buf_reg);
|
||||
val = acp_readl(rtd->acp5x_base + reg_val);
|
||||
val = val | BIT(0);
|
||||
acp_writel(val, rtd->acp5x_base + reg_val);
|
||||
acp_writel(1, rtd->acp5x_base + ier_val);
|
||||
ret = 0;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_val = ACP_HSTDM_ITER;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = ACP_I2STDM_ITER;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_val = ACP_HSTDM_IRER;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = ACP_I2STDM_IRER;
|
||||
}
|
||||
}
|
||||
val = acp_readl(rtd->acp5x_base + reg_val);
|
||||
val = val & ~BIT(0);
|
||||
acp_writel(val, rtd->acp5x_base + reg_val);
|
||||
|
||||
if (!(acp_readl(rtd->acp5x_base + ACP_HSTDM_ITER) & BIT(0)) &&
|
||||
!(acp_readl(rtd->acp5x_base + ACP_HSTDM_IRER) & BIT(0)))
|
||||
acp_writel(0, rtd->acp5x_base + ACP_HSTDM_IER);
|
||||
if (!(acp_readl(rtd->acp5x_base + ACP_I2STDM_ITER) & BIT(0)) &&
|
||||
!(acp_readl(rtd->acp5x_base + ACP_I2STDM_IRER) & BIT(0)))
|
||||
acp_writel(0, rtd->acp5x_base + ACP_I2STDM_IER);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops acp5x_i2s_dai_ops = {
|
||||
.hw_params = acp5x_i2s_hwparams,
|
||||
.trigger = acp5x_i2s_trigger,
|
||||
.set_fmt = acp5x_i2s_set_fmt,
|
||||
.set_tdm_slot = acp5x_i2s_set_tdm_slot,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver acp5x_dai_component = {
|
||||
.name = "acp5x-i2s",
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver acp5x_i2s_dai = {
|
||||
.playback = {
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
|
||||
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 96000,
|
||||
},
|
||||
.capture = {
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
|
||||
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 96000,
|
||||
},
|
||||
.ops = &acp5x_i2s_dai_ops,
|
||||
};
|
||||
|
||||
static int acp5x_dai_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct i2s_dev_data *adata;
|
||||
int ret;
|
||||
|
||||
adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
|
||||
GFP_KERNEL);
|
||||
if (!adata)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!adata->acp5x_base)
|
||||
return -ENOMEM;
|
||||
|
||||
adata->master_mode = I2S_MASTER_MODE_ENABLE;
|
||||
dev_set_drvdata(&pdev->dev, adata);
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&acp5x_dai_component,
|
||||
&acp5x_i2s_dai, 1);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver acp5x_dai_driver = {
|
||||
.probe = acp5x_dai_probe,
|
||||
.driver = {
|
||||
.name = "acp5x_i2s_playcap",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(acp5x_dai_driver);
|
||||
|
||||
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
|
||||
MODULE_DESCRIPTION("AMD ACP5.x CPU DAI Driver");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,517 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// AMD ALSA SoC PCM Driver
|
||||
//
|
||||
// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dai.h>
|
||||
|
||||
#include "acp5x.h"
|
||||
|
||||
#define DRV_NAME "acp5x_i2s_dma"
|
||||
|
||||
static const struct snd_pcm_hardware acp5x_pcm_hardware_playback = {
|
||||
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
|
||||
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 96000,
|
||||
.buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
|
||||
.period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
|
||||
.period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
|
||||
.periods_min = PLAYBACK_MIN_NUM_PERIODS,
|
||||
.periods_max = PLAYBACK_MAX_NUM_PERIODS,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware acp5x_pcm_hardware_capture = {
|
||||
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
|
||||
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 96000,
|
||||
.buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
|
||||
.period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
|
||||
.period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
|
||||
.periods_min = CAPTURE_MIN_NUM_PERIODS,
|
||||
.periods_max = CAPTURE_MAX_NUM_PERIODS,
|
||||
};
|
||||
|
||||
static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct i2s_dev_data *vg_i2s_data;
|
||||
u16 irq_flag;
|
||||
u32 val;
|
||||
|
||||
vg_i2s_data = dev_id;
|
||||
if (!vg_i2s_data)
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_flag = 0;
|
||||
val = acp_readl(vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
|
||||
if ((val & BIT(HS_TX_THRESHOLD)) && vg_i2s_data->play_stream) {
|
||||
acp_writel(BIT(HS_TX_THRESHOLD), vg_i2s_data->acp5x_base +
|
||||
ACP_EXTERNAL_INTR_STAT);
|
||||
snd_pcm_period_elapsed(vg_i2s_data->play_stream);
|
||||
irq_flag = 1;
|
||||
}
|
||||
if ((val & BIT(I2S_TX_THRESHOLD)) && vg_i2s_data->i2ssp_play_stream) {
|
||||
acp_writel(BIT(I2S_TX_THRESHOLD),
|
||||
vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
|
||||
snd_pcm_period_elapsed(vg_i2s_data->i2ssp_play_stream);
|
||||
irq_flag = 1;
|
||||
}
|
||||
|
||||
if ((val & BIT(HS_RX_THRESHOLD)) && vg_i2s_data->capture_stream) {
|
||||
acp_writel(BIT(HS_RX_THRESHOLD), vg_i2s_data->acp5x_base +
|
||||
ACP_EXTERNAL_INTR_STAT);
|
||||
snd_pcm_period_elapsed(vg_i2s_data->capture_stream);
|
||||
irq_flag = 1;
|
||||
}
|
||||
if ((val & BIT(I2S_RX_THRESHOLD)) && vg_i2s_data->i2ssp_capture_stream) {
|
||||
acp_writel(BIT(I2S_RX_THRESHOLD),
|
||||
vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT);
|
||||
snd_pcm_period_elapsed(vg_i2s_data->i2ssp_capture_stream);
|
||||
irq_flag = 1;
|
||||
}
|
||||
|
||||
if (irq_flag)
|
||||
return IRQ_HANDLED;
|
||||
else
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static void config_acp5x_dma(struct i2s_stream_instance *rtd, int direction)
|
||||
{
|
||||
u16 page_idx;
|
||||
u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
|
||||
u32 reg_dma_size, reg_fifo_size;
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = rtd->dma_addr;
|
||||
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
val = ACP_SRAM_HS_PB_PTE_OFFSET;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
val = ACP_SRAM_SP_PB_PTE_OFFSET;
|
||||
}
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
val = ACP_SRAM_HS_CP_PTE_OFFSET;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
val = ACP_SRAM_SP_CP_PTE_OFFSET;
|
||||
}
|
||||
}
|
||||
/* Group Enable */
|
||||
acp_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp5x_base +
|
||||
ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
|
||||
acp_writel(PAGE_SIZE_4K_ENABLE, rtd->acp5x_base +
|
||||
ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
|
||||
|
||||
for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
|
||||
/* Load the low address of page int ACP SRAM through SRBM */
|
||||
low = lower_32_bits(addr);
|
||||
high = upper_32_bits(addr);
|
||||
|
||||
acp_writel(low, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val);
|
||||
high |= BIT(31);
|
||||
acp_writel(high, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val + 4);
|
||||
/* Move to next physically contiguous page */
|
||||
val += 8;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_dma_size = ACP_HS_TX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
HS_PB_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_HS_TX_FIFOADDR;
|
||||
reg_fifo_size = ACP_HS_TX_FIFOSIZE;
|
||||
acp_writel(I2S_HS_TX_MEM_WINDOW_START,
|
||||
rtd->acp5x_base + ACP_HS_TX_RINGBUFADDR);
|
||||
break;
|
||||
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_dma_size = ACP_I2S_TX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
SP_PB_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
|
||||
reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
|
||||
acp_writel(I2S_SP_TX_MEM_WINDOW_START,
|
||||
rtd->acp5x_base + ACP_I2S_TX_RINGBUFADDR);
|
||||
}
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_dma_size = ACP_HS_RX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
HS_CAPT_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_HS_RX_FIFOADDR;
|
||||
reg_fifo_size = ACP_HS_RX_FIFOSIZE;
|
||||
acp_writel(I2S_HS_RX_MEM_WINDOW_START,
|
||||
rtd->acp5x_base + ACP_HS_RX_RINGBUFADDR);
|
||||
break;
|
||||
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_dma_size = ACP_I2S_RX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
SP_CAPT_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
|
||||
reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
|
||||
acp_writel(I2S_SP_RX_MEM_WINDOW_START,
|
||||
rtd->acp5x_base + ACP_I2S_RX_RINGBUFADDR);
|
||||
}
|
||||
}
|
||||
acp_writel(DMA_SIZE, rtd->acp5x_base + reg_dma_size);
|
||||
acp_writel(acp_fifo_addr, rtd->acp5x_base + reg_fifo_addr);
|
||||
acp_writel(FIFO_SIZE, rtd->acp5x_base + reg_fifo_size);
|
||||
acp_writel(BIT(I2S_RX_THRESHOLD) | BIT(HS_RX_THRESHOLD)
|
||||
| BIT(I2S_TX_THRESHOLD) | BIT(HS_TX_THRESHOLD),
|
||||
rtd->acp5x_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
}
|
||||
|
||||
static int acp5x_dma_open(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct snd_soc_pcm_runtime *prtd;
|
||||
struct i2s_dev_data *adata;
|
||||
struct i2s_stream_instance *i2s_data;
|
||||
int ret;
|
||||
|
||||
runtime = substream->runtime;
|
||||
prtd = asoc_substream_to_rtd(substream);
|
||||
component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
|
||||
adata = dev_get_drvdata(component->dev);
|
||||
|
||||
i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL);
|
||||
if (!i2s_data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
runtime->hw = acp5x_pcm_hardware_playback;
|
||||
else
|
||||
runtime->hw = acp5x_pcm_hardware_capture;
|
||||
|
||||
ret = snd_pcm_hw_constraint_integer(runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev, "set integer constraint failed\n");
|
||||
kfree(i2s_data);
|
||||
return ret;
|
||||
}
|
||||
i2s_data->acp5x_base = adata->acp5x_base;
|
||||
runtime->private_data = i2s_data;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acp5x_dma_hw_params(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct i2s_stream_instance *rtd;
|
||||
struct snd_soc_pcm_runtime *prtd;
|
||||
struct snd_soc_card *card;
|
||||
struct acp5x_platform_info *pinfo;
|
||||
struct i2s_dev_data *adata;
|
||||
u64 size;
|
||||
|
||||
prtd = asoc_substream_to_rtd(substream);
|
||||
card = prtd->card;
|
||||
pinfo = snd_soc_card_get_drvdata(card);
|
||||
adata = dev_get_drvdata(component->dev);
|
||||
rtd = substream->runtime->private_data;
|
||||
|
||||
if (!rtd)
|
||||
return -EINVAL;
|
||||
|
||||
if (pinfo) {
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
rtd->i2s_instance = pinfo->play_i2s_instance;
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
adata->play_stream = substream;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
adata->i2ssp_play_stream = substream;
|
||||
}
|
||||
} else {
|
||||
rtd->i2s_instance = pinfo->cap_i2s_instance;
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
adata->capture_stream = substream;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
adata->i2ssp_capture_stream = substream;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dev_err(component->dev, "pinfo failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
size = params_buffer_bytes(params);
|
||||
rtd->dma_addr = substream->dma_buffer.addr;
|
||||
rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
|
||||
config_acp5x_dma(rtd, substream->stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t acp5x_dma_pointer(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct i2s_stream_instance *rtd;
|
||||
u32 pos;
|
||||
u32 buffersize;
|
||||
u64 bytescount;
|
||||
|
||||
rtd = substream->runtime->private_data;
|
||||
buffersize = frames_to_bytes(substream->runtime,
|
||||
substream->runtime->buffer_size);
|
||||
bytescount = acp_get_byte_count(rtd, substream->stream);
|
||||
if (bytescount > rtd->bytescount)
|
||||
bytescount -= rtd->bytescount;
|
||||
pos = do_div(bytescount, buffersize);
|
||||
return bytes_to_frames(substream->runtime, pos);
|
||||
}
|
||||
|
||||
static int acp5x_dma_new(struct snd_soc_component *component,
|
||||
struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct device *parent = component->dev->parent;
|
||||
|
||||
snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
|
||||
parent, MIN_BUFFER, MAX_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp5x_dma_close(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *prtd;
|
||||
struct i2s_dev_data *adata;
|
||||
struct i2s_stream_instance *ins;
|
||||
|
||||
prtd = asoc_substream_to_rtd(substream);
|
||||
component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
|
||||
adata = dev_get_drvdata(component->dev);
|
||||
ins = substream->runtime->private_data;
|
||||
if (!ins)
|
||||
return -EINVAL;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (ins->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
adata->play_stream = NULL;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
adata->i2ssp_play_stream = NULL;
|
||||
}
|
||||
} else {
|
||||
switch (ins->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
adata->capture_stream = NULL;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
adata->i2ssp_capture_stream = NULL;
|
||||
}
|
||||
}
|
||||
kfree(ins);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver acp5x_i2s_component = {
|
||||
.name = DRV_NAME,
|
||||
.open = acp5x_dma_open,
|
||||
.close = acp5x_dma_close,
|
||||
.hw_params = acp5x_dma_hw_params,
|
||||
.pointer = acp5x_dma_pointer,
|
||||
.pcm_construct = acp5x_dma_new,
|
||||
};
|
||||
|
||||
static int acp5x_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct i2s_dev_data *adata;
|
||||
unsigned int irqflags;
|
||||
int status;
|
||||
|
||||
if (!pdev->dev.platform_data) {
|
||||
dev_err(&pdev->dev, "platform_data not retrieved\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
irqflags = *((unsigned int *)(pdev->dev.platform_data));
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
|
||||
if (!adata)
|
||||
return -ENOMEM;
|
||||
|
||||
adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!adata->acp5x_base)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
adata->i2s_irq = res->start;
|
||||
dev_set_drvdata(&pdev->dev, adata);
|
||||
status = devm_snd_soc_register_component(&pdev->dev,
|
||||
&acp5x_i2s_component,
|
||||
NULL, 0);
|
||||
if (status) {
|
||||
dev_err(&pdev->dev, "Fail to register acp i2s component\n");
|
||||
return status;
|
||||
}
|
||||
status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
|
||||
irqflags, "ACP5x_I2S_IRQ", adata);
|
||||
if (status) {
|
||||
dev_err(&pdev->dev, "ACP5x I2S IRQ request failed\n");
|
||||
return status;
|
||||
}
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_allow(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp5x_audio_remove(struct platform_device *pdev)
|
||||
{
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused acp5x_pcm_resume(struct device *dev)
|
||||
{
|
||||
struct i2s_dev_data *adata;
|
||||
u32 val, reg_val, frmt_val;
|
||||
|
||||
reg_val = 0;
|
||||
frmt_val = 0;
|
||||
adata = dev_get_drvdata(dev);
|
||||
|
||||
if (adata->play_stream && adata->play_stream->runtime) {
|
||||
struct i2s_stream_instance *rtd =
|
||||
adata->play_stream->runtime->private_data;
|
||||
config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_val = ACP_HSTDM_ITER;
|
||||
frmt_val = ACP_HSTDM_TXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = ACP_I2STDM_ITER;
|
||||
frmt_val = ACP_I2STDM_TXFRMT;
|
||||
}
|
||||
acp_writel((rtd->xfer_resolution << 3),
|
||||
rtd->acp5x_base + reg_val);
|
||||
}
|
||||
|
||||
if (adata->capture_stream && adata->capture_stream->runtime) {
|
||||
struct i2s_stream_instance *rtd =
|
||||
adata->capture_stream->runtime->private_data;
|
||||
config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
reg_val = ACP_HSTDM_IRER;
|
||||
frmt_val = ACP_HSTDM_RXFRMT;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = ACP_I2STDM_IRER;
|
||||
frmt_val = ACP_I2STDM_RXFRMT;
|
||||
}
|
||||
acp_writel((rtd->xfer_resolution << 3),
|
||||
rtd->acp5x_base + reg_val);
|
||||
}
|
||||
if (adata->tdm_mode == TDM_ENABLE) {
|
||||
acp_writel(adata->tdm_fmt, adata->acp5x_base + frmt_val);
|
||||
val = acp_readl(adata->acp5x_base + reg_val);
|
||||
acp_writel(val | 0x2, adata->acp5x_base + reg_val);
|
||||
}
|
||||
acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused acp5x_pcm_suspend(struct device *dev)
|
||||
{
|
||||
struct i2s_dev_data *adata;
|
||||
|
||||
adata = dev_get_drvdata(dev);
|
||||
acp_writel(0, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused acp5x_pcm_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct i2s_dev_data *adata;
|
||||
|
||||
adata = dev_get_drvdata(dev);
|
||||
acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops acp5x_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(acp5x_pcm_suspend,
|
||||
acp5x_pcm_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver acp5x_dma_driver = {
|
||||
.probe = acp5x_audio_probe,
|
||||
.remove = acp5x_audio_remove,
|
||||
.driver = {
|
||||
.name = "acp5x_i2s_dma",
|
||||
.pm = &acp5x_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(acp5x_dma_driver);
|
||||
|
||||
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
|
||||
MODULE_DESCRIPTION("AMD ACP 5.x PCM Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
|
@ -0,0 +1,193 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* AMD ALSA SoC PCM Driver
|
||||
*
|
||||
* Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "vg_chip_offset_byte.h"
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#define ACP5x_PHY_BASE_ADDRESS 0x1240000
|
||||
#define ACP_DEVICE_ID 0x15E2
|
||||
#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
|
||||
|
||||
#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01
|
||||
#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00
|
||||
#define ACP_PGFSM_STATUS_MASK 0x03
|
||||
#define ACP_POWERED_ON 0x00
|
||||
#define ACP_POWER_ON_IN_PROGRESS 0x01
|
||||
#define ACP_POWERED_OFF 0x02
|
||||
#define ACP_POWER_OFF_IN_PROGRESS 0x03
|
||||
|
||||
#define ACP_ERR_INTR_MASK 0x20000000
|
||||
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
|
||||
|
||||
#define ACP5x_DEVS 3
|
||||
#define ACP5x_REG_START 0x1240000
|
||||
#define ACP5x_REG_END 0x1250200
|
||||
#define ACP5x_I2STDM_REG_START 0x1242400
|
||||
#define ACP5x_I2STDM_REG_END 0x1242410
|
||||
#define ACP5x_HS_TDM_REG_START 0x1242814
|
||||
#define ACP5x_HS_TDM_REG_END 0x1242824
|
||||
#define I2S_MODE 0
|
||||
#define ACP5x_I2S_MODE 1
|
||||
#define ACP5x_RES 4
|
||||
#define I2S_RX_THRESHOLD 27
|
||||
#define I2S_TX_THRESHOLD 28
|
||||
#define HS_TX_THRESHOLD 24
|
||||
#define HS_RX_THRESHOLD 23
|
||||
|
||||
#define I2S_SP_INSTANCE 1
|
||||
#define I2S_HS_INSTANCE 2
|
||||
|
||||
#define ACP_SRAM_PTE_OFFSET 0x02050000
|
||||
#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0
|
||||
#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100
|
||||
#define ACP_SRAM_HS_PB_PTE_OFFSET 0x200
|
||||
#define ACP_SRAM_HS_CP_PTE_OFFSET 0x300
|
||||
#define PAGE_SIZE_4K_ENABLE 0x2
|
||||
#define I2S_SP_TX_MEM_WINDOW_START 0x4000000
|
||||
#define I2S_SP_RX_MEM_WINDOW_START 0x4020000
|
||||
#define I2S_HS_TX_MEM_WINDOW_START 0x4040000
|
||||
#define I2S_HS_RX_MEM_WINDOW_START 0x4060000
|
||||
|
||||
#define SP_PB_FIFO_ADDR_OFFSET 0x500
|
||||
#define SP_CAPT_FIFO_ADDR_OFFSET 0x700
|
||||
#define HS_PB_FIFO_ADDR_OFFSET 0x900
|
||||
#define HS_CAPT_FIFO_ADDR_OFFSET 0xB00
|
||||
#define PLAYBACK_MIN_NUM_PERIODS 2
|
||||
#define PLAYBACK_MAX_NUM_PERIODS 8
|
||||
#define PLAYBACK_MAX_PERIOD_SIZE 8192
|
||||
#define PLAYBACK_MIN_PERIOD_SIZE 1024
|
||||
#define CAPTURE_MIN_NUM_PERIODS 2
|
||||
#define CAPTURE_MAX_NUM_PERIODS 8
|
||||
#define CAPTURE_MAX_PERIOD_SIZE 8192
|
||||
#define CAPTURE_MIN_PERIOD_SIZE 1024
|
||||
|
||||
#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
|
||||
#define MIN_BUFFER MAX_BUFFER
|
||||
#define FIFO_SIZE 0x100
|
||||
#define DMA_SIZE 0x40
|
||||
#define FRM_LEN 0x100
|
||||
|
||||
#define I2S_MASTER_MODE_ENABLE 1
|
||||
#define I2S_MASTER_MODE_DISABLE 0
|
||||
|
||||
#define SLOT_WIDTH_8 8
|
||||
#define SLOT_WIDTH_16 16
|
||||
#define SLOT_WIDTH_24 24
|
||||
#define SLOT_WIDTH_32 32
|
||||
#define TDM_ENABLE 1
|
||||
#define TDM_DISABLE 0
|
||||
#define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x38
|
||||
|
||||
struct i2s_dev_data {
|
||||
bool tdm_mode;
|
||||
bool master_mode;
|
||||
unsigned int i2s_irq;
|
||||
u16 i2s_instance;
|
||||
u32 tdm_fmt;
|
||||
void __iomem *acp5x_base;
|
||||
struct snd_pcm_substream *play_stream;
|
||||
struct snd_pcm_substream *capture_stream;
|
||||
struct snd_pcm_substream *i2ssp_play_stream;
|
||||
struct snd_pcm_substream *i2ssp_capture_stream;
|
||||
};
|
||||
|
||||
struct i2s_stream_instance {
|
||||
u16 num_pages;
|
||||
u16 i2s_instance;
|
||||
u16 direction;
|
||||
u16 channels;
|
||||
u32 xfer_resolution;
|
||||
u32 val;
|
||||
dma_addr_t dma_addr;
|
||||
u64 bytescount;
|
||||
void __iomem *acp5x_base;
|
||||
};
|
||||
|
||||
union acp_dma_count {
|
||||
struct {
|
||||
u32 low;
|
||||
u32 high;
|
||||
} bcount;
|
||||
u64 bytescount;
|
||||
};
|
||||
|
||||
struct acp5x_platform_info {
|
||||
u16 play_i2s_instance;
|
||||
u16 cap_i2s_instance;
|
||||
};
|
||||
|
||||
union acp_i2stdm_mstrclkgen {
|
||||
struct {
|
||||
u32 i2stdm_master_mode : 1;
|
||||
u32 i2stdm_format_mode : 1;
|
||||
u32 i2stdm_lrclk_div_val : 9;
|
||||
u32 i2stdm_bclk_div_val : 11;
|
||||
u32:10;
|
||||
} bitfields, bits;
|
||||
u32 u32_all;
|
||||
};
|
||||
|
||||
/* common header file uses exact offset rather than relative
|
||||
* offset which requires subtraction logic from base_addr
|
||||
* for accessing ACP5x MMIO space registers
|
||||
*/
|
||||
static inline u32 acp_readl(void __iomem *base_addr)
|
||||
{
|
||||
return readl(base_addr - ACP5x_PHY_BASE_ADDRESS);
|
||||
}
|
||||
|
||||
static inline void acp_writel(u32 val, void __iomem *base_addr)
|
||||
{
|
||||
writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS);
|
||||
}
|
||||
|
||||
static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
|
||||
int direction)
|
||||
{
|
||||
union acp_dma_count byte_count;
|
||||
|
||||
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
byte_count.bcount.high =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_HS_TX_LINEARPOSCNTR_HIGH);
|
||||
byte_count.bcount.low =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_HS_TX_LINEARPOSCNTR_LOW);
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
byte_count.bcount.high =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_I2S_TX_LINEARPOSCNTR_HIGH);
|
||||
byte_count.bcount.low =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_I2S_TX_LINEARPOSCNTR_LOW);
|
||||
}
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_HS_INSTANCE:
|
||||
byte_count.bcount.high =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_HS_RX_LINEARPOSCNTR_HIGH);
|
||||
byte_count.bcount.low =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_HS_RX_LINEARPOSCNTR_LOW);
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
byte_count.bcount.high =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_I2S_RX_LINEARPOSCNTR_HIGH);
|
||||
byte_count.bcount.low =
|
||||
acp_readl(rtd->acp5x_base +
|
||||
ACP_I2S_RX_LINEARPOSCNTR_LOW);
|
||||
}
|
||||
}
|
||||
return byte_count.bytescount;
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// AMD Vangogh ACP PCI Driver
|
||||
//
|
||||
// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "acp5x.h"
|
||||
|
||||
struct acp5x_dev_data {
|
||||
void __iomem *acp5x_base;
|
||||
bool acp5x_audio_mode;
|
||||
struct resource *res;
|
||||
struct platform_device *pdev[ACP5x_DEVS];
|
||||
};
|
||||
|
||||
static int acp5x_power_on(void __iomem *acp5x_base)
|
||||
{
|
||||
u32 val;
|
||||
int timeout;
|
||||
|
||||
val = acp_readl(acp5x_base + ACP_PGFSM_STATUS);
|
||||
|
||||
if (val == 0)
|
||||
return val;
|
||||
|
||||
if ((val & ACP_PGFSM_STATUS_MASK) !=
|
||||
ACP_POWER_ON_IN_PROGRESS)
|
||||
acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
|
||||
acp5x_base + ACP_PGFSM_CONTROL);
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = acp_readl(acp5x_base + ACP_PGFSM_STATUS);
|
||||
if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_ON)
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int acp5x_reset(void __iomem *acp5x_base)
|
||||
{
|
||||
u32 val;
|
||||
int timeout;
|
||||
|
||||
acp_writel(1, acp5x_base + ACP_SOFT_RESET);
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = acp_readl(acp5x_base + ACP_SOFT_RESET);
|
||||
if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
acp_writel(0, acp5x_base + ACP_SOFT_RESET);
|
||||
timeout = 0;
|
||||
while (++timeout < 500) {
|
||||
val = acp_readl(acp5x_base + ACP_SOFT_RESET);
|
||||
if (!val)
|
||||
return 0;
|
||||
cpu_relax();
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void acp5x_enable_interrupts(void __iomem *acp5x_base)
|
||||
{
|
||||
acp_writel(0x01, acp5x_base + ACP_EXTERNAL_INTR_ENB);
|
||||
}
|
||||
|
||||
static void acp5x_disable_interrupts(void __iomem *acp5x_base)
|
||||
{
|
||||
acp_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp5x_base +
|
||||
ACP_EXTERNAL_INTR_STAT);
|
||||
acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_ENB);
|
||||
}
|
||||
|
||||
static int acp5x_init(void __iomem *acp5x_base)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* power on */
|
||||
ret = acp5x_power_on(acp5x_base);
|
||||
if (ret) {
|
||||
pr_err("ACP5x power on failed\n");
|
||||
return ret;
|
||||
}
|
||||
/* Reset */
|
||||
ret = acp5x_reset(acp5x_base);
|
||||
if (ret) {
|
||||
pr_err("ACP5x reset failed\n");
|
||||
return ret;
|
||||
}
|
||||
acp5x_enable_interrupts(acp5x_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp5x_deinit(void __iomem *acp5x_base)
|
||||
{
|
||||
int ret;
|
||||
|
||||
acp5x_disable_interrupts(acp5x_base);
|
||||
/* Reset */
|
||||
ret = acp5x_reset(acp5x_base);
|
||||
if (ret) {
|
||||
pr_err("ACP5x reset failed\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_acp5x_probe(struct pci_dev *pci,
|
||||
const struct pci_device_id *pci_id)
|
||||
{
|
||||
struct acp5x_dev_data *adata;
|
||||
struct platform_device_info pdevinfo[ACP5x_DEVS];
|
||||
unsigned int irqflags;
|
||||
int ret, i;
|
||||
u32 addr, val;
|
||||
|
||||
irqflags = IRQF_SHARED;
|
||||
if (pci->revision != 0x50)
|
||||
return -ENODEV;
|
||||
|
||||
if (pci_enable_device(pci)) {
|
||||
dev_err(&pci->dev, "pci_enable_device failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = pci_request_regions(pci, "AMD ACP5x audio");
|
||||
if (ret < 0) {
|
||||
dev_err(&pci->dev, "pci_request_regions failed\n");
|
||||
goto disable_pci;
|
||||
}
|
||||
|
||||
adata = devm_kzalloc(&pci->dev, sizeof(struct acp5x_dev_data),
|
||||
GFP_KERNEL);
|
||||
if (!adata) {
|
||||
ret = -ENOMEM;
|
||||
goto release_regions;
|
||||
}
|
||||
addr = pci_resource_start(pci, 0);
|
||||
adata->acp5x_base = devm_ioremap(&pci->dev, addr,
|
||||
pci_resource_len(pci, 0));
|
||||
if (!adata->acp5x_base) {
|
||||
ret = -ENOMEM;
|
||||
goto release_regions;
|
||||
}
|
||||
pci_set_master(pci);
|
||||
pci_set_drvdata(pci, adata);
|
||||
ret = acp5x_init(adata->acp5x_base);
|
||||
if (ret)
|
||||
goto release_regions;
|
||||
|
||||
val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG);
|
||||
switch (val) {
|
||||
case I2S_MODE:
|
||||
adata->res = devm_kzalloc(&pci->dev,
|
||||
sizeof(struct resource) * ACP5x_RES,
|
||||
GFP_KERNEL);
|
||||
if (!adata->res) {
|
||||
ret = -ENOMEM;
|
||||
goto de_init;
|
||||
}
|
||||
|
||||
adata->res[0].name = "acp5x_i2s_iomem";
|
||||
adata->res[0].flags = IORESOURCE_MEM;
|
||||
adata->res[0].start = addr;
|
||||
adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START);
|
||||
|
||||
adata->res[1].name = "acp5x_i2s_sp";
|
||||
adata->res[1].flags = IORESOURCE_MEM;
|
||||
adata->res[1].start = addr + ACP5x_I2STDM_REG_START;
|
||||
adata->res[1].end = addr + ACP5x_I2STDM_REG_END;
|
||||
|
||||
adata->res[2].name = "acp5x_i2s_hs";
|
||||
adata->res[2].flags = IORESOURCE_MEM;
|
||||
adata->res[2].start = addr + ACP5x_HS_TDM_REG_START;
|
||||
adata->res[2].end = addr + ACP5x_HS_TDM_REG_END;
|
||||
|
||||
adata->res[3].name = "acp5x_i2s_irq";
|
||||
adata->res[3].flags = IORESOURCE_IRQ;
|
||||
adata->res[3].start = pci->irq;
|
||||
adata->res[3].end = adata->res[3].start;
|
||||
|
||||
adata->acp5x_audio_mode = ACP5x_I2S_MODE;
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo[0].name = "acp5x_i2s_dma";
|
||||
pdevinfo[0].id = 0;
|
||||
pdevinfo[0].parent = &pci->dev;
|
||||
pdevinfo[0].num_res = 4;
|
||||
pdevinfo[0].res = &adata->res[0];
|
||||
pdevinfo[0].data = &irqflags;
|
||||
pdevinfo[0].size_data = sizeof(irqflags);
|
||||
|
||||
pdevinfo[1].name = "acp5x_i2s_playcap";
|
||||
pdevinfo[1].id = 0;
|
||||
pdevinfo[1].parent = &pci->dev;
|
||||
pdevinfo[1].num_res = 1;
|
||||
pdevinfo[1].res = &adata->res[1];
|
||||
|
||||
pdevinfo[2].name = "acp5x_i2s_playcap";
|
||||
pdevinfo[2].id = 1;
|
||||
pdevinfo[2].parent = &pci->dev;
|
||||
pdevinfo[2].num_res = 1;
|
||||
pdevinfo[2].res = &adata->res[2];
|
||||
|
||||
for (i = 0; i < ACP5x_DEVS; i++) {
|
||||
adata->pdev[i] =
|
||||
platform_device_register_full(&pdevinfo[i]);
|
||||
if (IS_ERR(adata->pdev[i])) {
|
||||
dev_err(&pci->dev, "cannot register %s device\n",
|
||||
pdevinfo[i].name);
|
||||
ret = PTR_ERR(adata->pdev[i]);
|
||||
goto unregister_devs;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_info(&pci->dev, "ACP audio mode : %d\n", val);
|
||||
}
|
||||
pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
|
||||
pm_runtime_use_autosuspend(&pci->dev);
|
||||
pm_runtime_put_noidle(&pci->dev);
|
||||
pm_runtime_allow(&pci->dev);
|
||||
return 0;
|
||||
|
||||
unregister_devs:
|
||||
for (--i; i >= 0; i--)
|
||||
platform_device_unregister(adata->pdev[i]);
|
||||
de_init:
|
||||
if (acp5x_deinit(adata->acp5x_base))
|
||||
dev_err(&pci->dev, "ACP de-init failed\n");
|
||||
release_regions:
|
||||
pci_release_regions(pci);
|
||||
disable_pci:
|
||||
pci_disable_device(pci);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused snd_acp5x_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct acp5x_dev_data *adata;
|
||||
|
||||
adata = dev_get_drvdata(dev);
|
||||
ret = acp5x_deinit(adata->acp5x_base);
|
||||
if (ret)
|
||||
dev_err(dev, "ACP de-init failed\n");
|
||||
else
|
||||
dev_dbg(dev, "ACP de-initialized\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused snd_acp5x_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct acp5x_dev_data *adata;
|
||||
|
||||
adata = dev_get_drvdata(dev);
|
||||
ret = acp5x_init(adata->acp5x_base);
|
||||
if (ret) {
|
||||
dev_err(dev, "ACP init failed\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops acp5x_pm = {
|
||||
SET_RUNTIME_PM_OPS(snd_acp5x_suspend,
|
||||
snd_acp5x_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(snd_acp5x_suspend, snd_acp5x_resume)
|
||||
};
|
||||
|
||||
static void snd_acp5x_remove(struct pci_dev *pci)
|
||||
{
|
||||
struct acp5x_dev_data *adata;
|
||||
int i, ret;
|
||||
|
||||
adata = pci_get_drvdata(pci);
|
||||
if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) {
|
||||
for (i = 0; i < ACP5x_DEVS; i++)
|
||||
platform_device_unregister(adata->pdev[i]);
|
||||
}
|
||||
ret = acp5x_deinit(adata->acp5x_base);
|
||||
if (ret)
|
||||
dev_err(&pci->dev, "ACP de-init failed\n");
|
||||
pm_runtime_forbid(&pci->dev);
|
||||
pm_runtime_get_noresume(&pci->dev);
|
||||
pci_release_regions(pci);
|
||||
pci_disable_device(pci);
|
||||
}
|
||||
|
||||
static const struct pci_device_id snd_acp5x_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
|
||||
.class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
|
||||
.class_mask = 0xffffff },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, snd_acp5x_ids);
|
||||
|
||||
static struct pci_driver acp5x_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = snd_acp5x_ids,
|
||||
.probe = snd_acp5x_probe,
|
||||
.remove = snd_acp5x_remove,
|
||||
.driver = {
|
||||
.pm = &acp5x_pm,
|
||||
}
|
||||
};
|
||||
|
||||
module_pci_driver(acp5x_driver);
|
||||
|
||||
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
|
||||
MODULE_DESCRIPTION("AMD Vangogh ACP PCI driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,337 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* AMD ACP 5.x Register Documentation
|
||||
*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _acp_ip_OFFSET_HEADER
|
||||
#define _acp_ip_OFFSET_HEADER
|
||||
|
||||
/* Registers from ACP_DMA block */
|
||||
#define ACP_DMA_CNTL_0 0x1240000
|
||||
#define ACP_DMA_CNTL_1 0x1240004
|
||||
#define ACP_DMA_CNTL_2 0x1240008
|
||||
#define ACP_DMA_CNTL_3 0x124000C
|
||||
#define ACP_DMA_CNTL_4 0x1240010
|
||||
#define ACP_DMA_CNTL_5 0x1240014
|
||||
#define ACP_DMA_CNTL_6 0x1240018
|
||||
#define ACP_DMA_CNTL_7 0x124001C
|
||||
#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020
|
||||
#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024
|
||||
#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028
|
||||
#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C
|
||||
#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030
|
||||
#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034
|
||||
#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038
|
||||
#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C
|
||||
#define ACP_DMA_DSCR_CNT_0 0x1240040
|
||||
#define ACP_DMA_DSCR_CNT_1 0x1240044
|
||||
#define ACP_DMA_DSCR_CNT_2 0x1240048
|
||||
#define ACP_DMA_DSCR_CNT_3 0x124004C
|
||||
#define ACP_DMA_DSCR_CNT_4 0x1240050
|
||||
#define ACP_DMA_DSCR_CNT_5 0x1240054
|
||||
#define ACP_DMA_DSCR_CNT_6 0x1240058
|
||||
#define ACP_DMA_DSCR_CNT_7 0x124005C
|
||||
#define ACP_DMA_PRIO_0 0x1240060
|
||||
#define ACP_DMA_PRIO_1 0x1240064
|
||||
#define ACP_DMA_PRIO_2 0x1240068
|
||||
#define ACP_DMA_PRIO_3 0x124006C
|
||||
#define ACP_DMA_PRIO_4 0x1240070
|
||||
#define ACP_DMA_PRIO_5 0x1240074
|
||||
#define ACP_DMA_PRIO_6 0x1240078
|
||||
#define ACP_DMA_PRIO_7 0x124007C
|
||||
#define ACP_DMA_CUR_DSCR_0 0x1240080
|
||||
#define ACP_DMA_CUR_DSCR_1 0x1240084
|
||||
#define ACP_DMA_CUR_DSCR_2 0x1240088
|
||||
#define ACP_DMA_CUR_DSCR_3 0x124008C
|
||||
#define ACP_DMA_CUR_DSCR_4 0x1240090
|
||||
#define ACP_DMA_CUR_DSCR_5 0x1240094
|
||||
#define ACP_DMA_CUR_DSCR_6 0x1240098
|
||||
#define ACP_DMA_CUR_DSCR_7 0x124009C
|
||||
#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0
|
||||
#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4
|
||||
#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8
|
||||
#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC
|
||||
#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0
|
||||
#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4
|
||||
#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8
|
||||
#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC
|
||||
#define ACP_DMA_ERR_STS_0 0x12400C0
|
||||
#define ACP_DMA_ERR_STS_1 0x12400C4
|
||||
#define ACP_DMA_ERR_STS_2 0x12400C8
|
||||
#define ACP_DMA_ERR_STS_3 0x12400CC
|
||||
#define ACP_DMA_ERR_STS_4 0x12400D0
|
||||
#define ACP_DMA_ERR_STS_5 0x12400D4
|
||||
#define ACP_DMA_ERR_STS_6 0x12400D8
|
||||
#define ACP_DMA_ERR_STS_7 0x12400DC
|
||||
#define ACP_DMA_DESC_BASE_ADDR 0x12400E0
|
||||
#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4
|
||||
#define ACP_DMA_CH_STS 0x12400E8
|
||||
#define ACP_DMA_CH_GROUP 0x12400EC
|
||||
#define ACP_DMA_CH_RST_STS 0x12400F0
|
||||
|
||||
/* Registers from ACP_AXI2AXIATU block */
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34
|
||||
#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38
|
||||
#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C
|
||||
#define ACPAXI2AXI_ATU_CTRL 0x1240C40
|
||||
|
||||
/* Registers from ACP_CLKRST block */
|
||||
#define ACP_SOFT_RESET 0x1241000
|
||||
#define ACP_CONTROL 0x1241004
|
||||
#define ACP_STATUS 0x1241008
|
||||
#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010
|
||||
|
||||
/* Registers from ACP_MISC block */
|
||||
#define ACP_EXTERNAL_INTR_ENB 0x1241800
|
||||
#define ACP_EXTERNAL_INTR_CNTL 0x1241804
|
||||
#define ACP_EXTERNAL_INTR_STAT 0x1241808
|
||||
#define ACP_ERROR_STATUS 0x12418C4
|
||||
#define ACP_SW_I2S_ERROR_REASON 0x12418C8
|
||||
#define ACP_MEM_PG_STS 0x12418CC
|
||||
#define ACP_PGMEM_DEEP_SLEEP_CTRL 0x12418D0
|
||||
#define ACP_PGMEM_SHUT_DOWN_CTRL 0x12418D4
|
||||
|
||||
/* Registers from ACP_PGFSM block */
|
||||
#define ACP_PIN_CONFIG 0x1241400
|
||||
#define ACP_PAD_PULLUP_CTRL 0x1241404
|
||||
#define ACP_PAD_PULLDOWN_CTRL 0x1241408
|
||||
#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x124140C
|
||||
#define ACP_PAD_SCHMEN_CTRL 0x1241410
|
||||
#define ACP_SW_PAD_KEEPER_EN 0x1241414
|
||||
#define ACP_SW_WAKE_EN 0x1241418
|
||||
#define ACP_I2S_WAKE_EN 0x124141C
|
||||
#define ACP_PME_EN 0x1241420
|
||||
#define ACP_PGFSM_CONTROL 0x1241424
|
||||
#define ACP_PGFSM_STATUS 0x1241428
|
||||
#define ACP_CLKMUX_SEL 0x124142C
|
||||
#define ACP_DEVICE_STATE 0x1241430
|
||||
#define AZ_DEVICE_STATE 0x1241434
|
||||
#define ACP_INTR_URGENCY_TIMER 0x1241438
|
||||
#define AZ_INTR_URGENCY_TIMER 0x124143C
|
||||
#define ACP_AON_SW_INTR_TRIG 0x1241440
|
||||
|
||||
/* Registers from ACP_SCRATCH block */
|
||||
#define ACP_SCRATCH_REG_0 0x1250000
|
||||
#define ACP_SCRATCH_REG_1 0x1250004
|
||||
#define ACP_SCRATCH_REG_2 0x1250008
|
||||
#define ACP_SCRATCH_REG_3 0x125000C
|
||||
#define ACP_SCRATCH_REG_4 0x1250010
|
||||
#define ACP_SCRATCH_REG_5 0x1250014
|
||||
#define ACP_SCRATCH_REG_6 0x1250018
|
||||
#define ACP_SCRATCH_REG_7 0x125001C
|
||||
#define ACP_SCRATCH_REG_8 0x1250020
|
||||
#define ACP_SCRATCH_REG_9 0x1250024
|
||||
#define ACP_SCRATCH_REG_10 0x1250028
|
||||
#define ACP_SCRATCH_REG_11 0x125002C
|
||||
#define ACP_SCRATCH_REG_12 0x1250030
|
||||
#define ACP_SCRATCH_REG_13 0x1250034
|
||||
#define ACP_SCRATCH_REG_14 0x1250038
|
||||
#define ACP_SCRATCH_REG_15 0x125003C
|
||||
#define ACP_SCRATCH_REG_16 0x1250040
|
||||
#define ACP_SCRATCH_REG_17 0x1250044
|
||||
#define ACP_SCRATCH_REG_18 0x1250048
|
||||
#define ACP_SCRATCH_REG_19 0x125004C
|
||||
#define ACP_SCRATCH_REG_20 0x1250050
|
||||
#define ACP_SCRATCH_REG_21 0x1250054
|
||||
#define ACP_SCRATCH_REG_22 0x1250058
|
||||
#define ACP_SCRATCH_REG_23 0x125005C
|
||||
#define ACP_SCRATCH_REG_24 0x1250060
|
||||
#define ACP_SCRATCH_REG_25 0x1250064
|
||||
#define ACP_SCRATCH_REG_26 0x1250068
|
||||
#define ACP_SCRATCH_REG_27 0x125006C
|
||||
#define ACP_SCRATCH_REG_28 0x1250070
|
||||
#define ACP_SCRATCH_REG_29 0x1250074
|
||||
#define ACP_SCRATCH_REG_30 0x1250078
|
||||
#define ACP_SCRATCH_REG_31 0x125007C
|
||||
#define ACP_SCRATCH_REG_32 0x1250080
|
||||
#define ACP_SCRATCH_REG_33 0x1250084
|
||||
#define ACP_SCRATCH_REG_34 0x1250088
|
||||
#define ACP_SCRATCH_REG_35 0x125008C
|
||||
#define ACP_SCRATCH_REG_36 0x1250090
|
||||
#define ACP_SCRATCH_REG_37 0x1250094
|
||||
#define ACP_SCRATCH_REG_38 0x1250098
|
||||
#define ACP_SCRATCH_REG_39 0x125009C
|
||||
#define ACP_SCRATCH_REG_40 0x12500A0
|
||||
#define ACP_SCRATCH_REG_41 0x12500A4
|
||||
#define ACP_SCRATCH_REG_42 0x12500A8
|
||||
#define ACP_SCRATCH_REG_43 0x12500AC
|
||||
#define ACP_SCRATCH_REG_44 0x12500B0
|
||||
#define ACP_SCRATCH_REG_45 0x12500B4
|
||||
#define ACP_SCRATCH_REG_46 0x12500B8
|
||||
#define ACP_SCRATCH_REG_47 0x12500BC
|
||||
#define ACP_SCRATCH_REG_48 0x12500C0
|
||||
#define ACP_SCRATCH_REG_49 0x12500C4
|
||||
#define ACP_SCRATCH_REG_50 0x12500C8
|
||||
#define ACP_SCRATCH_REG_51 0x12500CC
|
||||
#define ACP_SCRATCH_REG_52 0x12500D0
|
||||
#define ACP_SCRATCH_REG_53 0x12500D4
|
||||
#define ACP_SCRATCH_REG_54 0x12500D8
|
||||
#define ACP_SCRATCH_REG_55 0x12500DC
|
||||
#define ACP_SCRATCH_REG_56 0x12500E0
|
||||
#define ACP_SCRATCH_REG_57 0x12500E4
|
||||
#define ACP_SCRATCH_REG_58 0x12500E8
|
||||
#define ACP_SCRATCH_REG_59 0x12500EC
|
||||
#define ACP_SCRATCH_REG_60 0x12500F0
|
||||
#define ACP_SCRATCH_REG_61 0x12500F4
|
||||
#define ACP_SCRATCH_REG_62 0x12500F8
|
||||
#define ACP_SCRATCH_REG_63 0x12500FC
|
||||
#define ACP_SCRATCH_REG_64 0x1250100
|
||||
#define ACP_SCRATCH_REG_65 0x1250104
|
||||
#define ACP_SCRATCH_REG_66 0x1250108
|
||||
#define ACP_SCRATCH_REG_67 0x125010C
|
||||
#define ACP_SCRATCH_REG_68 0x1250110
|
||||
#define ACP_SCRATCH_REG_69 0x1250114
|
||||
#define ACP_SCRATCH_REG_70 0x1250118
|
||||
#define ACP_SCRATCH_REG_71 0x125011C
|
||||
#define ACP_SCRATCH_REG_72 0x1250120
|
||||
#define ACP_SCRATCH_REG_73 0x1250124
|
||||
#define ACP_SCRATCH_REG_74 0x1250128
|
||||
#define ACP_SCRATCH_REG_75 0x125012C
|
||||
#define ACP_SCRATCH_REG_76 0x1250130
|
||||
#define ACP_SCRATCH_REG_77 0x1250134
|
||||
#define ACP_SCRATCH_REG_78 0x1250138
|
||||
#define ACP_SCRATCH_REG_79 0x125013C
|
||||
#define ACP_SCRATCH_REG_80 0x1250140
|
||||
#define ACP_SCRATCH_REG_81 0x1250144
|
||||
#define ACP_SCRATCH_REG_82 0x1250148
|
||||
#define ACP_SCRATCH_REG_83 0x125014C
|
||||
#define ACP_SCRATCH_REG_84 0x1250150
|
||||
#define ACP_SCRATCH_REG_85 0x1250154
|
||||
#define ACP_SCRATCH_REG_86 0x1250158
|
||||
#define ACP_SCRATCH_REG_87 0x125015C
|
||||
#define ACP_SCRATCH_REG_88 0x1250160
|
||||
#define ACP_SCRATCH_REG_89 0x1250164
|
||||
#define ACP_SCRATCH_REG_90 0x1250168
|
||||
#define ACP_SCRATCH_REG_91 0x125016C
|
||||
#define ACP_SCRATCH_REG_92 0x1250170
|
||||
#define ACP_SCRATCH_REG_93 0x1250174
|
||||
#define ACP_SCRATCH_REG_94 0x1250178
|
||||
#define ACP_SCRATCH_REG_95 0x125017C
|
||||
#define ACP_SCRATCH_REG_96 0x1250180
|
||||
#define ACP_SCRATCH_REG_97 0x1250184
|
||||
#define ACP_SCRATCH_REG_98 0x1250188
|
||||
#define ACP_SCRATCH_REG_99 0x125018C
|
||||
#define ACP_SCRATCH_REG_100 0x1250190
|
||||
#define ACP_SCRATCH_REG_101 0x1250194
|
||||
#define ACP_SCRATCH_REG_102 0x1250198
|
||||
#define ACP_SCRATCH_REG_103 0x125019C
|
||||
#define ACP_SCRATCH_REG_104 0x12501A0
|
||||
#define ACP_SCRATCH_REG_105 0x12501A4
|
||||
#define ACP_SCRATCH_REG_106 0x12501A8
|
||||
#define ACP_SCRATCH_REG_107 0x12501AC
|
||||
#define ACP_SCRATCH_REG_108 0x12501B0
|
||||
#define ACP_SCRATCH_REG_109 0x12501B4
|
||||
#define ACP_SCRATCH_REG_110 0x12501B8
|
||||
#define ACP_SCRATCH_REG_111 0x12501BC
|
||||
#define ACP_SCRATCH_REG_112 0x12501C0
|
||||
#define ACP_SCRATCH_REG_113 0x12501C4
|
||||
#define ACP_SCRATCH_REG_114 0x12501C8
|
||||
#define ACP_SCRATCH_REG_115 0x12501CC
|
||||
#define ACP_SCRATCH_REG_116 0x12501D0
|
||||
#define ACP_SCRATCH_REG_117 0x12501D4
|
||||
#define ACP_SCRATCH_REG_118 0x12501D8
|
||||
#define ACP_SCRATCH_REG_119 0x12501DC
|
||||
#define ACP_SCRATCH_REG_120 0x12501E0
|
||||
#define ACP_SCRATCH_REG_121 0x12501E4
|
||||
#define ACP_SCRATCH_REG_122 0x12501E8
|
||||
#define ACP_SCRATCH_REG_123 0x12501EC
|
||||
#define ACP_SCRATCH_REG_124 0x12501F0
|
||||
#define ACP_SCRATCH_REG_125 0x12501F4
|
||||
#define ACP_SCRATCH_REG_126 0x12501F8
|
||||
#define ACP_SCRATCH_REG_127 0x12501FC
|
||||
#define ACP_SCRATCH_REG_128 0x1250200
|
||||
|
||||
/* Registers from ACP_AUDIO_BUFFERS block */
|
||||
#define ACP_I2S_RX_RINGBUFADDR 0x1242000
|
||||
#define ACP_I2S_RX_RINGBUFSIZE 0x1242004
|
||||
#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008
|
||||
#define ACP_I2S_RX_FIFOADDR 0x124200C
|
||||
#define ACP_I2S_RX_FIFOSIZE 0x1242010
|
||||
#define ACP_I2S_RX_DMA_SIZE 0x1242014
|
||||
#define ACP_I2S_RX_LINEARPOSCNTR_HIGH 0x1242018
|
||||
#define ACP_I2S_RX_LINEARPOSCNTR_LOW 0x124201C
|
||||
#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020
|
||||
#define ACP_I2S_TX_RINGBUFADDR 0x1242024
|
||||
#define ACP_I2S_TX_RINGBUFSIZE 0x1242028
|
||||
#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C
|
||||
#define ACP_I2S_TX_FIFOADDR 0x1242030
|
||||
#define ACP_I2S_TX_FIFOSIZE 0x1242034
|
||||
#define ACP_I2S_TX_DMA_SIZE 0x1242038
|
||||
#define ACP_I2S_TX_LINEARPOSCNTR_HIGH 0x124203C
|
||||
#define ACP_I2S_TX_LINEARPOSCNTR_LOW 0x1242040
|
||||
#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044
|
||||
#define ACP_BT_RX_RINGBUFADDR 0x1242048
|
||||
#define ACP_BT_RX_RINGBUFSIZE 0x124204C
|
||||
#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050
|
||||
#define ACP_BT_RX_FIFOADDR 0x1242054
|
||||
#define ACP_BT_RX_FIFOSIZE 0x1242058
|
||||
#define ACP_BT_RX_DMA_SIZE 0x124205C
|
||||
#define ACP_BT_RX_LINEARPOSCNTR_HIGH 0x1242060
|
||||
#define ACP_BT_RX_LINEARPOSCNTR_LOW 0x1242064
|
||||
#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068
|
||||
#define ACP_BT_TX_RINGBUFADDR 0x124206C
|
||||
#define ACP_BT_TX_RINGBUFSIZE 0x1242070
|
||||
#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074
|
||||
#define ACP_BT_TX_FIFOADDR 0x1242078
|
||||
#define ACP_BT_TX_FIFOSIZE 0x124207C
|
||||
#define ACP_BT_TX_DMA_SIZE 0x1242080
|
||||
#define ACP_BT_TX_LINEARPOSCNTR_HIGH 0x1242084
|
||||
#define ACP_BT_TX_LINEARPOSCNTR_LOW 0x1242088
|
||||
#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C
|
||||
#define ACP_HS_RX_RINGBUFADDR 0x1242090
|
||||
#define ACP_HS_RX_RINGBUFSIZE 0x1242094
|
||||
#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098
|
||||
#define ACP_HS_RX_FIFOADDR 0x124209C
|
||||
#define ACP_HS_RX_FIFOSIZE 0x12420A0
|
||||
#define ACP_HS_RX_DMA_SIZE 0x12420A4
|
||||
#define ACP_HS_RX_LINEARPOSCNTR_HIGH 0x12420A8
|
||||
#define ACP_HS_RX_LINEARPOSCNTR_LOW 0x12420AC
|
||||
#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0
|
||||
#define ACP_HS_TX_RINGBUFADDR 0x12420B4
|
||||
#define ACP_HS_TX_RINGBUFSIZE 0x12420B8
|
||||
#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC
|
||||
#define ACP_HS_TX_FIFOADDR 0x12420C0
|
||||
#define ACP_HS_TX_FIFOSIZE 0x12420C4
|
||||
#define ACP_HS_TX_DMA_SIZE 0x12420C8
|
||||
#define ACP_HS_TX_LINEARPOSCNTR_HIGH 0x12420CC
|
||||
#define ACP_HS_TX_LINEARPOSCNTR_LOW 0x12420D0
|
||||
#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4
|
||||
|
||||
/* Registers from ACP_I2S_TDM block */
|
||||
#define ACP_I2STDM_IER 0x1242400
|
||||
#define ACP_I2STDM_IRER 0x1242404
|
||||
#define ACP_I2STDM_RXFRMT 0x1242408
|
||||
#define ACP_I2STDM_ITER 0x124240C
|
||||
#define ACP_I2STDM_TXFRMT 0x1242410
|
||||
#define ACP_I2STDM0_MSTRCLKGEN 0x1242414
|
||||
#define ACP_I2STDM1_MSTRCLKGEN 0x1242418
|
||||
#define ACP_I2STDM2_MSTRCLKGEN 0x124241C
|
||||
#define ACP_I2STDM_REFCLKGEN 0x1242420
|
||||
|
||||
/* Registers from ACP_BT_TDM block */
|
||||
#define ACP_BTTDM_IER 0x1242800
|
||||
#define ACP_BTTDM_IRER 0x1242804
|
||||
#define ACP_BTTDM_RXFRMT 0x1242808
|
||||
#define ACP_BTTDM_ITER 0x124280C
|
||||
#define ACP_BTTDM_TXFRMT 0x1242810
|
||||
#define ACP_HSTDM_IER 0x1242814
|
||||
#define ACP_HSTDM_IRER 0x1242818
|
||||
#define ACP_HSTDM_RXFRMT 0x124281C
|
||||
#define ACP_HSTDM_ITER 0x1242820
|
||||
#define ACP_HSTDM_TXFRMT 0x1242824
|
||||
#endif
|
|
@ -11,7 +11,6 @@ if SND_ATMEL_SOC
|
|||
|
||||
config SND_ATMEL_SOC_PDC
|
||||
bool
|
||||
depends on HAS_DMA
|
||||
|
||||
config SND_ATMEL_SOC_DMA
|
||||
bool
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
/* Validity Bit Mode */
|
||||
#define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1)
|
||||
#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
|
||||
(0 << 1) /* Load sample regardles of validity bit value */
|
||||
(0 << 1) /* Load sample regardless of validity bit value */
|
||||
#define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
|
||||
(1 << 1) /* Load sample only if validity bit is 0 */
|
||||
|
||||
|
@ -519,7 +519,7 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev,
|
|||
/* check for new data available */
|
||||
ret = wait_for_completion_interruptible_timeout(&ch_stat->done,
|
||||
msecs_to_jiffies(100));
|
||||
/* IP might not be started or valid stream might not be prezent */
|
||||
/* IP might not be started or valid stream might not be present */
|
||||
if (ret < 0) {
|
||||
dev_dbg(dev->dev, "channel status for channel %d timeout\n",
|
||||
channel);
|
||||
|
@ -571,7 +571,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,
|
|||
mchp_spdifrx_isr_blockend_en(dev);
|
||||
ret = wait_for_completion_interruptible_timeout(&user_data->done,
|
||||
msecs_to_jiffies(100));
|
||||
/* IP might not be started or valid stream might not be prezent */
|
||||
/* IP might not be started or valid stream might not be present */
|
||||
if (ret <= 0) {
|
||||
dev_dbg(dev->dev, "user data for channel %d timeout\n",
|
||||
channel);
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
#define SPDIFTX_MR_VALID1 BIT(24)
|
||||
#define SPDIFTX_MR_VALID2 BIT(25)
|
||||
|
||||
/* Disable Null Frame on underrrun */
|
||||
/* Disable Null Frame on underrun */
|
||||
#define SPDIFTX_MR_DNFR_MASK GENMASK(27, 27)
|
||||
#define SPDIFTX_MR_DNFR_INVALID (0 << 27)
|
||||
#define SPDIFTX_MR_DNFR_VALID (1 << 27)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
// IN2 +---o--+------------+--o---+ OUT2
|
||||
// loop2 relays
|
||||
//
|
||||
// The 'loop1' gpio pin controlls two relays, which are either in loop
|
||||
// The 'loop1' gpio pin controls two relays, which are either in loop
|
||||
// position, meaning that input and output are directly connected, or
|
||||
// they are in mixer position, meaning that the signal is passed through
|
||||
// the 'Sum' mixer. Similarly for 'loop2'.
|
||||
|
|
|
@ -729,7 +729,7 @@ static struct snd_soc_component_driver cygnus_soc_platform = {
|
|||
int cygnus_soc_platform_register(struct device *dev,
|
||||
struct cygnus_audio *cygaud)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
dev_dbg(dev, "%s Enter\n", __func__);
|
||||
|
||||
|
|
|
@ -187,6 +187,7 @@ config SND_SOC_ALL_CODECS
|
|||
imply SND_SOC_RT715_SDCA_SDW
|
||||
imply SND_SOC_RT1308_SDW
|
||||
imply SND_SOC_RT1316_SDW
|
||||
imply SND_SOC_SDW_MOCKUP
|
||||
imply SND_SOC_SGTL5000
|
||||
imply SND_SOC_SI476X
|
||||
imply SND_SOC_SIMPLE_AMPLIFIER
|
||||
|
@ -847,7 +848,7 @@ config SND_SOC_HDAC_HDA
|
|||
select SND_HDA
|
||||
|
||||
config SND_SOC_ICS43432
|
||||
tristate
|
||||
tristate "ICS43423 and compatible i2s microphones"
|
||||
|
||||
config SND_SOC_INNO_RK3036
|
||||
tristate "Inno codec driver for RK3036 SoC"
|
||||
|
@ -1287,6 +1288,23 @@ config SND_SOC_RT715_SDCA_SDW
|
|||
select REGMAP_SOUNDWIRE
|
||||
select REGMAP_SOUNDWIRE_MBQ
|
||||
|
||||
config SND_SOC_SDW_MOCKUP
|
||||
tristate "SoundWire mockup codec"
|
||||
depends on EXPERT
|
||||
depends on SOUNDWIRE
|
||||
help
|
||||
This option enables a SoundWire mockup codec that does not drive the
|
||||
bus, take part in the command/command protocol or generate data on a
|
||||
Source port.
|
||||
This option is only intended to be used for tests on a device
|
||||
with a connector, in combination with a bus analyzer, or to test new
|
||||
topologies that differ from the actual hardware layout.
|
||||
This mockup device could be totally virtual but could also be a
|
||||
real physical one with one key restriction: it is not allowed by the
|
||||
SoundWire specification to be configured via a sideband mechanism and
|
||||
generate audio data for capture. However, nothing prevents such a
|
||||
peripheral device from snooping the bus.
|
||||
|
||||
#Freescale sgtl5000 codec
|
||||
config SND_SOC_SGTL5000
|
||||
tristate "Freescale SGTL5000 CODEC"
|
||||
|
@ -1564,6 +1582,7 @@ config SND_SOC_WCD938X
|
|||
config SND_SOC_WCD938X_SDW
|
||||
tristate "WCD9380/WCD9385 Codec - SDW"
|
||||
select SND_SOC_WCD938X
|
||||
select SND_SOC_WCD_MBHC
|
||||
depends on SOUNDWIRE
|
||||
select REGMAP_SOUNDWIRE
|
||||
help
|
||||
|
|
|
@ -203,6 +203,7 @@ snd-soc-rt711-objs := rt711.o rt711-sdw.o
|
|||
snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o
|
||||
snd-soc-rt715-objs := rt715.o rt715-sdw.o
|
||||
snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o
|
||||
snd-soc-sdw-mockup-objs := sdw-mockup.o
|
||||
snd-soc-sgtl5000-objs := sgtl5000.o
|
||||
snd-soc-alc5623-objs := alc5623.o
|
||||
snd-soc-alc5632-objs := alc5632.o
|
||||
|
@ -530,6 +531,7 @@ obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o
|
|||
obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o
|
||||
obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o
|
||||
obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o
|
||||
obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o
|
||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
||||
obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
|
||||
|
|
|
@ -316,6 +316,13 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
|
|||
int word_len = 0, master_rate = 0;
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
|
||||
bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
u8 dacc0;
|
||||
|
||||
dev_dbg(dai->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
|
||||
__func__, params_rate(params), params_format(params),
|
||||
params_width(params), params_channels(params));
|
||||
|
||||
|
||||
/* bit size */
|
||||
switch (params_width(params)) {
|
||||
|
@ -346,6 +353,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
|
|||
break;
|
||||
}
|
||||
|
||||
if (is_playback) {
|
||||
switch (params_rate(params)) {
|
||||
case 48000:
|
||||
dacc0 = AD193X_DAC_SR_48;
|
||||
break;
|
||||
case 96000:
|
||||
dacc0 = AD193X_DAC_SR_96;
|
||||
break;
|
||||
case 192000:
|
||||
dacc0 = AD193X_DAC_SR_192;
|
||||
break;
|
||||
default:
|
||||
dev_err(dai->dev, "invalid sampling rate: %d\n", params_rate(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0, AD193X_DAC_SR_MASK, dacc0);
|
||||
}
|
||||
|
||||
regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
|
||||
AD193X_PLL_INPUT_MASK, master_rate);
|
||||
|
||||
|
@ -385,7 +411,7 @@ static struct snd_soc_dai_driver ad193x_dai = {
|
|||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
|
||||
},
|
||||
|
@ -407,7 +433,7 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = {
|
|||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
|
||||
},
|
||||
|
|
|
@ -37,6 +37,10 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
|
|||
#define AD193X_PLL_CLK_SRC_MCLK (1 << 1)
|
||||
#define AD193X_DAC_CTRL0 0x02
|
||||
#define AD193X_DAC_POWERDOWN 0x01
|
||||
#define AD193X_DAC_SR_MASK 0x06
|
||||
#define AD193X_DAC_SR_48 (0 << 1)
|
||||
#define AD193X_DAC_SR_96 (1 << 1)
|
||||
#define AD193X_DAC_SR_192 (2 << 1)
|
||||
#define AD193X_DAC_SERFMT_MASK 0xC0
|
||||
#define AD193X_DAC_SERFMT_STEREO (0 << 6)
|
||||
#define AD193X_DAC_SERFMT_TDM (1 << 6)
|
||||
|
|
|
@ -586,6 +586,7 @@ struct cs42l42_pll_params {
|
|||
* Table 4-5 from the Datasheet
|
||||
*/
|
||||
static const struct cs42l42_pll_params pll_ratio_table[] = {
|
||||
{ 1411200, 0, 1, 0x00, 0x80, 0x000000, 0x03, 0x10, 11289600, 128, 2},
|
||||
{ 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2},
|
||||
{ 2304000, 0, 1, 0x00, 0x55, 0xC00000, 0x02, 0x10, 12288000, 85, 2},
|
||||
{ 2400000, 0, 1, 0x00, 0x50, 0x000000, 0x03, 0x10, 12000000, 80, 2},
|
||||
|
@ -843,6 +844,13 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
if (channels == 1)
|
||||
cs42l42->bclk *= 2;
|
||||
|
||||
/*
|
||||
* Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
|
||||
* more than assumed (which would result in overclocking).
|
||||
*/
|
||||
if (params_width(params) == 24)
|
||||
cs42l42->bclk = (cs42l42->bclk / 3) * 4;
|
||||
|
||||
switch(substream->stream) {
|
||||
case SNDRV_PCM_STREAM_CAPTURE:
|
||||
if (channels == 2) {
|
||||
|
@ -890,10 +898,23 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
|
|||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
|
||||
int i;
|
||||
|
||||
cs42l42->sclk = freq;
|
||||
if (freq == 0) {
|
||||
cs42l42->sclk = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
|
||||
if (pll_ratio_table[i].sclk == freq) {
|
||||
cs42l42->sclk = freq;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dev_err(component->dev, "SCLK %u not supported\n", freq);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
||||
|
@ -2106,4 +2127,7 @@ MODULE_DESCRIPTION("ASoC CS42L42 driver");
|
|||
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
|
||||
MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
|
||||
MODULE_AUTHOR("Michael White, Cirrus Logic Inc, <michael.white@cirrus.com>");
|
||||
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_AUTHOR("Vitaly Rodionov <vitalyr@opensource.cirrus.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -206,7 +206,7 @@ static int cx20442_write(struct snd_soc_component *component, unsigned int reg,
|
|||
*/
|
||||
|
||||
/* Modem init: echo off, digital speaker off, quiet off, voice mode */
|
||||
static const char *v253_init = "ate0m0q0+fclass=8\r";
|
||||
static const char v253_init[] = "ate0m0q0+fclass=8\r";
|
||||
|
||||
/* Line discipline .open() */
|
||||
static int v253_open(struct tty_struct *tty)
|
||||
|
@ -279,11 +279,6 @@ static void v253_receive(struct tty_struct *tty, const unsigned char *cp,
|
|||
}
|
||||
}
|
||||
|
||||
/* Line discipline .write_wakeup() */
|
||||
static void v253_wakeup(struct tty_struct *tty)
|
||||
{
|
||||
}
|
||||
|
||||
struct tty_ldisc_ops v253_ops = {
|
||||
.name = "cx20442",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -291,7 +286,6 @@ struct tty_ldisc_ops v253_ops = {
|
|||
.close = v253_close,
|
||||
.hangup = v253_hangup,
|
||||
.receive_buf = v253_receive,
|
||||
.write_wakeup = v253_wakeup,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(v253_ops);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* I2S MEMS microphone driver for InvenSense ICS-43432
|
||||
* I2S MEMS microphone driver for InvenSense ICS-43432 and similar
|
||||
* MEMS-based microphones.
|
||||
*
|
||||
* - Non configurable.
|
||||
* - I2S interface, 64 BCLs per frame, 32 bits per channel, 24 bit data
|
||||
|
@ -53,6 +54,7 @@ static int ics43432_probe(struct platform_device *pdev)
|
|||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id ics43432_ids[] = {
|
||||
{ .compatible = "invensense,ics43432", },
|
||||
{ .compatible = "cui,cmm-4030d-261", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ics43432_ids);
|
||||
|
|
|
@ -1722,42 +1722,43 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
|
|||
case RX_MACRO_AIF2_PB:
|
||||
case RX_MACRO_AIF3_PB:
|
||||
case RX_MACRO_AIF4_PB:
|
||||
for (j = 0; j < INTERP_MAX; j++) {
|
||||
reg = CDC_RX_RXn_RX_PATH_CTL(j);
|
||||
mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
|
||||
dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
|
||||
for (j = 0; j < INTERP_MAX; j++) {
|
||||
reg = CDC_RX_RXn_RX_PATH_CTL(j);
|
||||
mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j);
|
||||
dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j);
|
||||
|
||||
if (mute) {
|
||||
snd_soc_component_update_bits(component, reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK,
|
||||
CDC_RX_PATH_PGA_MUTE_ENABLE);
|
||||
snd_soc_component_update_bits(component, mix_reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK,
|
||||
CDC_RX_PATH_PGA_MUTE_ENABLE);
|
||||
} else {
|
||||
snd_soc_component_update_bits(component, reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
|
||||
snd_soc_component_update_bits(component, mix_reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
|
||||
}
|
||||
if (mute) {
|
||||
snd_soc_component_update_bits(component, reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK,
|
||||
CDC_RX_PATH_PGA_MUTE_ENABLE);
|
||||
snd_soc_component_update_bits(component, mix_reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK,
|
||||
CDC_RX_PATH_PGA_MUTE_ENABLE);
|
||||
} else {
|
||||
snd_soc_component_update_bits(component, reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
|
||||
snd_soc_component_update_bits(component, mix_reg,
|
||||
CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
|
||||
}
|
||||
|
||||
if (j == INTERP_AUX)
|
||||
dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
|
||||
if (j == INTERP_AUX)
|
||||
dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL;
|
||||
|
||||
int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
|
||||
int_mux_cfg1 = int_mux_cfg0 + 4;
|
||||
int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
|
||||
int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
|
||||
int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
|
||||
int_mux_cfg1 = int_mux_cfg0 + 4;
|
||||
int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
|
||||
int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1);
|
||||
|
||||
if (snd_soc_component_read(component, dsm_reg) & 0x01) {
|
||||
if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
|
||||
snd_soc_component_update_bits(component, reg, 0x20, 0x20);
|
||||
if (int_mux_cfg1_val & 0x0F) {
|
||||
snd_soc_component_update_bits(component, reg, 0x20, 0x20);
|
||||
snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20);
|
||||
if (snd_soc_component_read(component, dsm_reg) & 0x01) {
|
||||
if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0))
|
||||
snd_soc_component_update_bits(component, reg, 0x20, 0x20);
|
||||
if (int_mux_cfg1_val & 0x0F) {
|
||||
snd_soc_component_update_bits(component, reg, 0x20, 0x20);
|
||||
snd_soc_component_update_bits(component, mix_reg, 0x20,
|
||||
0x20);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -2158,13 +2158,11 @@ static void max98090_jack_work(struct work_struct *work)
|
|||
|
||||
msleep(50);
|
||||
|
||||
reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
|
||||
snd_soc_component_read(component, M98090_REG_JACK_STATUS);
|
||||
|
||||
/* Weak pull up allows only insertion detection */
|
||||
snd_soc_component_update_bits(component, M98090_REG_JACK_DETECT,
|
||||
M98090_JDWK_MASK, M98090_JDWK_MASK);
|
||||
} else {
|
||||
reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
|
||||
}
|
||||
|
||||
reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS);
|
||||
|
|
|
@ -765,17 +765,26 @@ static int max98390_dsm_init(struct snd_soc_component *component)
|
|||
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
|
||||
product = dmi_get_system_info(DMI_PRODUCT_NAME);
|
||||
|
||||
if (vendor && product) {
|
||||
snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin",
|
||||
vendor, product);
|
||||
if (!strcmp(max98390->dsm_param_name, "default")) {
|
||||
if (vendor && product) {
|
||||
snprintf(filename, sizeof(filename),
|
||||
"dsm_param_%s_%s.bin", vendor, product);
|
||||
} else {
|
||||
sprintf(filename, "dsm_param.bin");
|
||||
}
|
||||
} else {
|
||||
sprintf(filename, "dsm_param.bin");
|
||||
snprintf(filename, sizeof(filename), "%s",
|
||||
max98390->dsm_param_name);
|
||||
}
|
||||
ret = request_firmware(&fw, filename, component->dev);
|
||||
if (ret) {
|
||||
ret = request_firmware(&fw, "dsm_param.bin", component->dev);
|
||||
if (ret)
|
||||
goto err;
|
||||
if (ret) {
|
||||
ret = request_firmware(&fw, "dsmparam.bin",
|
||||
component->dev);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(component->dev,
|
||||
|
@ -1047,6 +1056,11 @@ static int max98390_i2c_probe(struct i2c_client *i2c,
|
|||
__func__, max98390->ref_rdc_value,
|
||||
max98390->ambient_temp_value);
|
||||
|
||||
ret = device_property_read_string(&i2c->dev, "maxim,dsm_param_name",
|
||||
&max98390->dsm_param_name);
|
||||
if (ret)
|
||||
max98390->dsm_param_name = "default";
|
||||
|
||||
/* voltage/current slot configuration */
|
||||
max98390_slot_config(i2c, max98390);
|
||||
|
||||
|
|
|
@ -662,5 +662,6 @@ struct max98390_priv {
|
|||
unsigned int i_l_slot;
|
||||
unsigned int ref_rdc_value;
|
||||
unsigned int ambient_temp_value;
|
||||
const char *dsm_param_name;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -234,7 +234,7 @@ static void recover_eint_setting(struct mt6359_accdet *priv)
|
|||
|
||||
static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
unsigned int value = 0;
|
||||
|
||||
regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
|
||||
|
@ -461,7 +461,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
|
|||
{
|
||||
struct mt6359_accdet *priv = data;
|
||||
unsigned int irq_val = 0, val = 0, value = 0;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->res_lock);
|
||||
regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val);
|
||||
|
@ -551,7 +551,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data)
|
|||
|
||||
static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct device *dev = priv->dev;
|
||||
struct device_node *node = NULL;
|
||||
int pwm_deb[15] = {0};
|
||||
|
@ -926,7 +926,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct mt6359_accdet *priv;
|
||||
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s(), dev name %s\n",
|
||||
__func__, dev_name(&pdev->dev));
|
||||
|
@ -1057,22 +1057,7 @@ static struct platform_driver mt6359_accdet_driver = {
|
|||
.probe = mt6359_accdet_probe,
|
||||
};
|
||||
|
||||
static int __init mt6359_accdet_driver_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = platform_driver_register(&mt6359_accdet_driver);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit mt6359_accdet_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mt6359_accdet_driver);
|
||||
}
|
||||
module_init(mt6359_accdet_driver_init);
|
||||
module_exit(mt6359_accdet_driver_exit);
|
||||
module_platform_driver(mt6359_accdet_driver)
|
||||
|
||||
/* Module information */
|
||||
MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver");
|
||||
|
|
|
@ -547,31 +547,6 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rt1015_flush_work(struct work_struct *work)
|
||||
{
|
||||
struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
|
||||
flush_work.work);
|
||||
struct snd_soc_component *component = rt1015->component;
|
||||
unsigned int val, i;
|
||||
|
||||
for (i = 0; i < 200; ++i) {
|
||||
usleep_range(1000, 1500);
|
||||
dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i);
|
||||
regmap_read(rt1015->regmap, RT1015_CLK_DET, &val);
|
||||
if (val & 0x800)
|
||||
break;
|
||||
}
|
||||
|
||||
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
|
||||
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7);
|
||||
regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028);
|
||||
|
||||
if (val & 0x800)
|
||||
dev_dbg(component->dev, "Flush DAC completed.\n");
|
||||
else
|
||||
dev_warn(component->dev, "Fail to flush DAC data.\n");
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new rt1015_snd_controls[] = {
|
||||
SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT,
|
||||
127, 0, dac_vol_tlv),
|
||||
|
@ -630,10 +605,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
|
|||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8);
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
if (rt1015->bypass_boost == RT1015_Enable_Boost) {
|
||||
snd_soc_component_write(component,
|
||||
|
@ -653,8 +624,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
|
|||
RT1015_SYS_RST2, 0x0b9a);
|
||||
}
|
||||
rt1015->dac_is_used = 0;
|
||||
|
||||
cancel_delayed_work_sync(&rt1015->flush_work);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -687,8 +656,6 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w,
|
|||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
if (rt1015->hw_config == RT1015_HW_28)
|
||||
schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10));
|
||||
msleep(rt1015->pdata.power_up_delay_ms);
|
||||
break;
|
||||
default:
|
||||
|
@ -702,7 +669,7 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = {
|
|||
NULL, 0),
|
||||
SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
|
||||
r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
||||
r1015_dac_event, SND_SOC_DAPM_PRE_PMU |
|
||||
SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0,
|
||||
rt1015_amp_drv_event, SND_SOC_DAPM_PRE_PMU |
|
||||
|
@ -722,7 +689,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
|
||||
int pre_div, bclk_ms, frame_size, lrck;
|
||||
int pre_div, frame_size, lrck;
|
||||
unsigned int val_len = 0;
|
||||
|
||||
lrck = params_rate(params);
|
||||
|
@ -739,10 +706,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bclk_ms = frame_size > 32;
|
||||
|
||||
dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
|
||||
bclk_ms, pre_div, dai->id);
|
||||
dev_dbg(component->dev, "pre_div is %d for iis %d\n", pre_div, dai->id);
|
||||
|
||||
dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
|
||||
lrck, pre_div, dai->id);
|
||||
|
@ -1028,7 +992,6 @@ static int rt1015_probe(struct snd_soc_component *component)
|
|||
snd_soc_component_get_drvdata(component);
|
||||
|
||||
rt1015->component = component;
|
||||
INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1037,7 +1000,6 @@ static void rt1015_remove(struct snd_soc_component *component)
|
|||
{
|
||||
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
cancel_delayed_work_sync(&rt1015->flush_work);
|
||||
regmap_write(rt1015->regmap, RT1015_RESET, 0);
|
||||
}
|
||||
|
||||
|
@ -1180,8 +1142,6 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
|
|||
return ret;
|
||||
}
|
||||
|
||||
rt1015->hw_config = (i2c->addr == 0x29) ? RT1015_HW_29 : RT1015_HW_28;
|
||||
|
||||
ret = regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev,
|
||||
|
|
|
@ -444,8 +444,6 @@ struct rt1015_priv {
|
|||
int bypass_boost;
|
||||
int dac_is_used;
|
||||
int cali_done;
|
||||
int hw_config;
|
||||
struct delayed_work flush_work;
|
||||
};
|
||||
|
||||
#endif /* __RT1015_H__ */
|
||||
|
|
|
@ -127,6 +127,7 @@ static int rt1015p_platform_probe(struct platform_device *pdev)
|
|||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id rt1015p_device_id[] = {
|
||||
{ .compatible = "realtek,rt1015p" },
|
||||
{ .compatible = "realtek,rt1019p" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rt1015p_device_id);
|
||||
|
@ -135,6 +136,7 @@ MODULE_DEVICE_TABLE(of, rt1015p_device_id);
|
|||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id rt1015p_acpi_match[] = {
|
||||
{ "RTL1015", 0},
|
||||
{ "RTL1019", 0},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, rt1015p_acpi_match);
|
||||
|
|
|
@ -494,7 +494,7 @@ static const struct snd_kcontrol_new rt5514_sto2_dmic_mux =
|
|||
*/
|
||||
static int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate)
|
||||
{
|
||||
int div[] = {2, 3, 4, 8, 12, 16, 24, 32};
|
||||
static const int div[] = {2, 3, 4, 8, 12, 16, 24, 32};
|
||||
int i;
|
||||
|
||||
if (rate < 1000000 * div[0]) {
|
||||
|
|
|
@ -2093,7 +2093,7 @@ int rt5640_sel_asrc_clk_src(struct snd_soc_component *component,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src);
|
||||
|
||||
static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
|
||||
void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
|
||||
|
||||
|
@ -2105,8 +2105,9 @@ static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component)
|
|||
snd_soc_dapm_sync_unlocked(dapm);
|
||||
snd_soc_dapm_mutex_unlock(dapm);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_enable_micbias1_for_ovcd);
|
||||
|
||||
static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component)
|
||||
void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
|
||||
|
||||
|
@ -2117,6 +2118,7 @@ static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component
|
|||
snd_soc_dapm_sync_unlocked(dapm);
|
||||
snd_soc_dapm_mutex_unlock(dapm);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_disable_micbias1_for_ovcd);
|
||||
|
||||
static void rt5640_enable_micbias1_ovcd_irq(struct snd_soc_component *component)
|
||||
{
|
||||
|
@ -2241,7 +2243,7 @@ static void rt5640_button_press_work(struct work_struct *work)
|
|||
schedule_delayed_work(&rt5640->bp_work, msecs_to_jiffies(BP_POLL_TIME));
|
||||
}
|
||||
|
||||
static int rt5640_detect_headset(struct snd_soc_component *component)
|
||||
int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio)
|
||||
{
|
||||
int i, headset_count = 0, headphone_count = 0;
|
||||
|
||||
|
@ -2259,8 +2261,13 @@ static int rt5640_detect_headset(struct snd_soc_component *component)
|
|||
msleep(JACK_SETTLE_TIME);
|
||||
|
||||
/* Check the jack is still connected before checking ovcd */
|
||||
if (!rt5640_jack_inserted(component))
|
||||
return 0;
|
||||
if (hp_det_gpio) {
|
||||
if (gpiod_get_value_cansleep(hp_det_gpio))
|
||||
return 0;
|
||||
} else {
|
||||
if (!rt5640_jack_inserted(component))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rt5640_micbias1_ovcd(component)) {
|
||||
/*
|
||||
|
@ -2285,6 +2292,7 @@ static int rt5640_detect_headset(struct snd_soc_component *component)
|
|||
dev_err(component->dev, "Error detecting headset vs headphones, bad contact?, assuming headphones\n");
|
||||
return SND_JACK_HEADPHONE;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_detect_headset);
|
||||
|
||||
static void rt5640_jack_work(struct work_struct *work)
|
||||
{
|
||||
|
@ -2309,7 +2317,7 @@ static void rt5640_jack_work(struct work_struct *work)
|
|||
/* Jack inserted */
|
||||
WARN_ON(rt5640->ovcd_irq_enabled);
|
||||
rt5640_enable_micbias1_for_ovcd(component);
|
||||
status = rt5640_detect_headset(component);
|
||||
status = rt5640_detect_headset(component, NULL);
|
||||
if (status == SND_JACK_HEADSET) {
|
||||
/* Enable ovcd IRQ for button press detect. */
|
||||
rt5640_enable_micbias1_ovcd_irq(component);
|
||||
|
@ -2362,29 +2370,10 @@ static void rt5640_cancel_work(void *data)
|
|||
cancel_delayed_work_sync(&rt5640->bp_work);
|
||||
}
|
||||
|
||||
static void rt5640_enable_jack_detect(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *jack)
|
||||
void rt5640_set_ovcd_params(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
/* Select JD-source */
|
||||
snd_soc_component_update_bits(component, RT5640_JD_CTRL,
|
||||
RT5640_JD_MASK, rt5640->jd_src);
|
||||
|
||||
/* Selecting GPIO01 as an interrupt */
|
||||
snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1,
|
||||
RT5640_GP1_PIN_MASK, RT5640_GP1_PIN_IRQ);
|
||||
|
||||
/* Set GPIO1 output */
|
||||
snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3,
|
||||
RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT);
|
||||
|
||||
/* Enabling jd2 in general control 1 */
|
||||
snd_soc_component_write(component, RT5640_DUMMY1, 0x3f41);
|
||||
|
||||
/* Enabling jd2 in general control 2 */
|
||||
snd_soc_component_write(component, RT5640_DUMMY2, 0x4001);
|
||||
|
||||
snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4,
|
||||
0xa800 | rt5640->ovcd_sf);
|
||||
|
||||
|
@ -2403,6 +2392,57 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
|
|||
*/
|
||||
snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2,
|
||||
RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5640_set_ovcd_params);
|
||||
|
||||
static void rt5640_disable_jack_detect(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
/*
|
||||
* soc_remove_component() force-disables jack and thus rt5640->jack
|
||||
* could be NULL at the time of driver's module unloading.
|
||||
*/
|
||||
if (!rt5640->jack)
|
||||
return;
|
||||
|
||||
free_irq(rt5640->irq, rt5640);
|
||||
rt5640_cancel_work(rt5640);
|
||||
|
||||
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
|
||||
rt5640_disable_micbias1_ovcd_irq(component);
|
||||
rt5640_disable_micbias1_for_ovcd(component);
|
||||
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
|
||||
}
|
||||
|
||||
rt5640->jack = NULL;
|
||||
}
|
||||
|
||||
static void rt5640_enable_jack_detect(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *jack)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
/* Select JD-source */
|
||||
snd_soc_component_update_bits(component, RT5640_JD_CTRL,
|
||||
RT5640_JD_MASK, rt5640->jd_src);
|
||||
|
||||
/* Selecting GPIO01 as an interrupt */
|
||||
snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1,
|
||||
RT5640_GP1_PIN_MASK, RT5640_GP1_PIN_IRQ);
|
||||
|
||||
/* Set GPIO1 output */
|
||||
snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3,
|
||||
RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT);
|
||||
|
||||
/* Enabling jd2 in general control 1 */
|
||||
snd_soc_component_write(component, RT5640_DUMMY1, 0x3f41);
|
||||
|
||||
/* Enabling jd2 in general control 2 */
|
||||
snd_soc_component_write(component, RT5640_DUMMY2, 0x4001);
|
||||
|
||||
rt5640_set_ovcd_params(component);
|
||||
|
||||
/*
|
||||
* All IRQs get or-ed together, so we need the jack IRQ to report 0
|
||||
|
@ -2423,32 +2463,19 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
|
|||
rt5640_enable_micbias1_ovcd_irq(component);
|
||||
}
|
||||
|
||||
enable_irq(rt5640->irq);
|
||||
/* sync initial jack state */
|
||||
queue_work(system_long_wq, &rt5640->jack_work);
|
||||
}
|
||||
|
||||
static void rt5640_disable_jack_detect(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
/*
|
||||
* soc_remove_component() force-disables jack and thus rt5640->jack
|
||||
* could be NULL at the time of driver's module unloading.
|
||||
*/
|
||||
if (!rt5640->jack)
|
||||
ret = request_irq(rt5640->irq, rt5640_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"rt5640", rt5640);
|
||||
if (ret) {
|
||||
dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
|
||||
rt5640->irq = -ENXIO;
|
||||
/* Undo above settings */
|
||||
rt5640_disable_jack_detect(component);
|
||||
return;
|
||||
|
||||
disable_irq(rt5640->irq);
|
||||
rt5640_cancel_work(rt5640);
|
||||
|
||||
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
|
||||
rt5640_disable_micbias1_ovcd_irq(component);
|
||||
rt5640_disable_micbias1_for_ovcd(component);
|
||||
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
|
||||
}
|
||||
|
||||
rt5640->jack = NULL;
|
||||
/* sync initial jack state */
|
||||
queue_work(system_long_wq, &rt5640->jack_work);
|
||||
}
|
||||
|
||||
static int rt5640_set_jack(struct snd_soc_component *component,
|
||||
|
@ -2836,18 +2863,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_request_irq(&i2c->dev, rt5640->irq, rt5640_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
|
||||
| IRQF_ONESHOT, "rt5640", rt5640);
|
||||
if (ret == 0) {
|
||||
/* Gets re-enabled by rt5640_set_jack() */
|
||||
disable_irq(rt5640->irq);
|
||||
} else {
|
||||
dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n",
|
||||
rt5640->irq, ret);
|
||||
rt5640->irq = -ENXIO;
|
||||
}
|
||||
|
||||
return devm_snd_soc_register_component(&i2c->dev,
|
||||
&soc_component_dev_rt5640,
|
||||
rt5640_dai, ARRAY_SIZE(rt5640_dai));
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define _RT5640_H
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <dt-bindings/sound/rt5640.h>
|
||||
|
||||
|
@ -2157,4 +2158,9 @@ int rt5640_dmic_enable(struct snd_soc_component *component,
|
|||
int rt5640_sel_asrc_clk_src(struct snd_soc_component *component,
|
||||
unsigned int filter_mask, unsigned int clk_src);
|
||||
|
||||
void rt5640_set_ovcd_params(struct snd_soc_component *component);
|
||||
void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component);
|
||||
void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component);
|
||||
int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -117,6 +117,13 @@ static struct snd_soc_dai_driver rt5682_dai[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void rt5682_i2c_disable_regulators(void *data)
|
||||
{
|
||||
struct rt5682_priv *rt5682 = data;
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
|
||||
}
|
||||
|
||||
static int rt5682_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -157,6 +164,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators,
|
||||
rt5682);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies),
|
||||
rt5682->supplies);
|
||||
if (ret) {
|
||||
|
@ -282,10 +294,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
|
|||
|
||||
static int rt5682_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
|
||||
|
||||
rt5682_i2c_shutdown(client);
|
||||
regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,9 @@ static const struct reg_sequence patch_list[] = {
|
|||
{RT5682_DAC_ADC_DIG_VOL1, 0xa020},
|
||||
{RT5682_I2C_CTRL, 0x000f},
|
||||
{RT5682_PLL2_INTERNAL, 0x8266},
|
||||
{RT5682_SAR_IL_CMD_3, 0x8365},
|
||||
{RT5682_SAR_IL_CMD_1, 0x22b7},
|
||||
{RT5682_SAR_IL_CMD_3, 0x0365},
|
||||
{RT5682_SAR_IL_CMD_6, 0x0110},
|
||||
};
|
||||
|
||||
void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
|
||||
|
@ -1726,8 +1728,6 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", RT5682_STO1_ADC_DIG_VOL,
|
||||
RT5682_R_MUTE_SFT, 1, rt5682_sto1_adc_r_mix,
|
||||
ARRAY_SIZE(rt5682_sto1_adc_r_mix)),
|
||||
SND_SOC_DAPM_SUPPLY("BTN Detection Mode", RT5682_SAR_IL_CMD_1,
|
||||
14, 1, NULL, 0),
|
||||
|
||||
/* ADC PGA */
|
||||
SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
@ -1898,8 +1898,6 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
|
|||
{"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"},
|
||||
{"Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter"},
|
||||
|
||||
{"ADC Stereo1 Filter", NULL, "BTN Detection Mode"},
|
||||
|
||||
{"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL"},
|
||||
{"Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR"},
|
||||
|
||||
|
@ -2915,10 +2913,47 @@ static void rt5682_remove(struct snd_soc_component *component)
|
|||
static int rt5682_suspend(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val;
|
||||
|
||||
if (rt5682->is_sdw)
|
||||
return 0;
|
||||
|
||||
cancel_delayed_work_sync(&rt5682->jack_detect_work);
|
||||
cancel_delayed_work_sync(&rt5682->jd_check_work);
|
||||
if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
|
||||
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
|
||||
RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
|
||||
RT5682_CTRL_MB1_REG | RT5682_CTRL_MB2_REG);
|
||||
val = snd_soc_component_read(component,
|
||||
RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK;
|
||||
|
||||
switch (val) {
|
||||
case 0x1:
|
||||
snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
|
||||
RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
|
||||
RT5682_SAR_SEL_MB1_NOSEL | RT5682_SAR_SEL_MB2_SEL);
|
||||
break;
|
||||
case 0x2:
|
||||
snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
|
||||
RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK,
|
||||
RT5682_SAR_SEL_MB1_SEL | RT5682_SAR_SEL_MB2_NOSEL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
|
||||
RT5682_PWR_CBJ, 0);
|
||||
|
||||
/* enter SAR ADC power saving mode */
|
||||
snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
|
||||
RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK |
|
||||
RT5682_SAR_BUTDET_RST_MASK | RT5682_SAR_SEL_MB1_MB2_MASK, 0);
|
||||
snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
|
||||
RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK,
|
||||
RT5682_SAR_BUTT_DET_EN | RT5682_SAR_BUTDET_POW_SAV | RT5682_SAR_BUTDET_RST_NORMAL);
|
||||
}
|
||||
|
||||
regcache_cache_only(rt5682->regmap, true);
|
||||
regcache_mark_dirty(rt5682->regmap);
|
||||
return 0;
|
||||
|
@ -2934,6 +2969,17 @@ static int rt5682_resume(struct snd_soc_component *component)
|
|||
regcache_cache_only(rt5682->regmap, false);
|
||||
regcache_sync(rt5682->regmap);
|
||||
|
||||
if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) {
|
||||
snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1,
|
||||
RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_SEL_MB1_MB2_MASK,
|
||||
RT5682_SAR_BUTDET_POW_NORM | RT5682_SAR_SEL_MB1_MB2_AUTO);
|
||||
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
|
||||
RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK,
|
||||
RT5682_CTRL_MB1_FSM | RT5682_CTRL_MB2_FSM);
|
||||
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
|
||||
RT5682_PWR_CBJ, RT5682_PWR_CBJ);
|
||||
}
|
||||
|
||||
mod_delayed_work(system_power_efficient_wq,
|
||||
&rt5682->jack_detect_work, msecs_to_jiffies(250));
|
||||
|
||||
|
|
|
@ -0,0 +1,310 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// sdw-mockup.c -- a mockup SoundWire codec for tests where only the host
|
||||
// drives the bus.
|
||||
//
|
||||
// Copyright(c) 2021 Intel Corporation
|
||||
//
|
||||
//
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
struct sdw_mockup_priv {
|
||||
struct sdw_slave *slave;
|
||||
};
|
||||
|
||||
struct sdw_stream_data {
|
||||
struct sdw_stream_runtime *sdw_stream;
|
||||
};
|
||||
|
||||
static int sdw_mockup_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sdw_mockup_component_remove(struct snd_soc_component *component)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = {
|
||||
.probe = sdw_mockup_component_probe,
|
||||
.remove = sdw_mockup_component_remove,
|
||||
};
|
||||
|
||||
static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
|
||||
int direction)
|
||||
{
|
||||
struct sdw_stream_data *stream;
|
||||
|
||||
if (!sdw_stream)
|
||||
return 0;
|
||||
|
||||
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
|
||||
if (!stream)
|
||||
return -ENOMEM;
|
||||
|
||||
stream->sdw_stream = sdw_stream;
|
||||
|
||||
/* Use tx_mask or rx_mask to configure stream tag and set dma_data */
|
||||
if (direction == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dai->playback_dma_data = stream;
|
||||
else
|
||||
dai->capture_dma_data = stream;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sdw_mockup_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sdw_stream_data *stream;
|
||||
|
||||
stream = snd_soc_dai_get_dma_data(dai, substream);
|
||||
snd_soc_dai_set_dma_data(dai, substream, NULL);
|
||||
kfree(stream);
|
||||
}
|
||||
|
||||
static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
|
||||
struct sdw_stream_config stream_config;
|
||||
struct sdw_port_config port_config;
|
||||
enum sdw_data_direction direction;
|
||||
struct sdw_stream_data *stream;
|
||||
int num_channels;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
stream = snd_soc_dai_get_dma_data(dai, substream);
|
||||
if (!stream)
|
||||
return -EINVAL;
|
||||
|
||||
if (!sdw_mockup->slave)
|
||||
return -EINVAL;
|
||||
|
||||
/* SoundWire specific configuration */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
direction = SDW_DATA_DIR_RX;
|
||||
port = 1;
|
||||
} else {
|
||||
direction = SDW_DATA_DIR_TX;
|
||||
port = 8;
|
||||
}
|
||||
|
||||
stream_config.frame_rate = params_rate(params);
|
||||
stream_config.ch_count = params_channels(params);
|
||||
stream_config.bps = snd_pcm_format_width(params_format(params));
|
||||
stream_config.direction = direction;
|
||||
|
||||
num_channels = params_channels(params);
|
||||
port_config.ch_mask = (1 << num_channels) - 1;
|
||||
port_config.num = port;
|
||||
|
||||
ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config,
|
||||
&port_config, 1, stream->sdw_stream);
|
||||
if (ret)
|
||||
dev_err(dai->dev, "Unable to configure port\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component);
|
||||
struct sdw_stream_data *stream =
|
||||
snd_soc_dai_get_dma_data(dai, substream);
|
||||
|
||||
if (!sdw_mockup->slave)
|
||||
return -EINVAL;
|
||||
|
||||
sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops sdw_mockup_ops = {
|
||||
.hw_params = sdw_mockup_pcm_hw_params,
|
||||
.hw_free = sdw_mockup_pcm_hw_free,
|
||||
.set_sdw_stream = sdw_mockup_set_sdw_stream,
|
||||
.shutdown = sdw_mockup_shutdown,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver sdw_mockup_dai[] = {
|
||||
{
|
||||
.name = "sdw-mockup-aif1",
|
||||
.id = 1,
|
||||
.playback = {
|
||||
.stream_name = "DP1 Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "DP8 Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
},
|
||||
.ops = &sdw_mockup_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int sdw_mockup_update_status(struct sdw_slave *slave,
|
||||
enum sdw_slave_status status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdw_mockup_read_prop(struct sdw_slave *slave)
|
||||
{
|
||||
struct sdw_slave_prop *prop = &slave->prop;
|
||||
int nval;
|
||||
int i, j;
|
||||
u32 bit;
|
||||
unsigned long addr;
|
||||
struct sdw_dpn_prop *dpn;
|
||||
|
||||
prop->paging_support = false;
|
||||
|
||||
/*
|
||||
* first we need to allocate memory for set bits in port lists
|
||||
* the port allocation is completely arbitrary:
|
||||
* DP0 is not supported
|
||||
* DP1 is sink
|
||||
* DP8 is source
|
||||
*/
|
||||
prop->source_ports = BIT(8);
|
||||
prop->sink_ports = BIT(1);
|
||||
|
||||
nval = hweight32(prop->source_ports);
|
||||
prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
|
||||
sizeof(*prop->src_dpn_prop),
|
||||
GFP_KERNEL);
|
||||
if (!prop->src_dpn_prop)
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
dpn = prop->src_dpn_prop;
|
||||
addr = prop->source_ports;
|
||||
for_each_set_bit(bit, &addr, 32) {
|
||||
dpn[i].num = bit;
|
||||
dpn[i].type = SDW_DPN_FULL;
|
||||
dpn[i].simple_ch_prep_sm = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* do this again for sink now */
|
||||
nval = hweight32(prop->sink_ports);
|
||||
prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
|
||||
sizeof(*prop->sink_dpn_prop),
|
||||
GFP_KERNEL);
|
||||
if (!prop->sink_dpn_prop)
|
||||
return -ENOMEM;
|
||||
|
||||
j = 0;
|
||||
dpn = prop->sink_dpn_prop;
|
||||
addr = prop->sink_ports;
|
||||
for_each_set_bit(bit, &addr, 32) {
|
||||
dpn[j].num = bit;
|
||||
dpn[j].type = SDW_DPN_FULL;
|
||||
dpn[j].simple_ch_prep_sm = true;
|
||||
j++;
|
||||
}
|
||||
|
||||
prop->simple_clk_stop_capable = true;
|
||||
|
||||
/* wake-up event */
|
||||
prop->wake_capable = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdw_mockup_bus_config(struct sdw_slave *slave,
|
||||
struct sdw_bus_params *params)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdw_mockup_interrupt_callback(struct sdw_slave *slave,
|
||||
struct sdw_slave_intr_status *status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sdw_slave_ops sdw_mockup_slave_ops = {
|
||||
.read_prop = sdw_mockup_read_prop,
|
||||
.interrupt_callback = sdw_mockup_interrupt_callback,
|
||||
.update_status = sdw_mockup_update_status,
|
||||
.bus_config = sdw_mockup_bus_config,
|
||||
};
|
||||
|
||||
static int sdw_mockup_sdw_probe(struct sdw_slave *slave,
|
||||
const struct sdw_device_id *id)
|
||||
{
|
||||
struct device *dev = &slave->dev;
|
||||
struct sdw_mockup_priv *sdw_mockup;
|
||||
int ret;
|
||||
|
||||
sdw_mockup = devm_kzalloc(dev, sizeof(*sdw_mockup), GFP_KERNEL);
|
||||
if (!sdw_mockup)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, sdw_mockup);
|
||||
sdw_mockup->slave = slave;
|
||||
|
||||
ret = devm_snd_soc_register_component(dev,
|
||||
&snd_soc_sdw_mockup_component,
|
||||
sdw_mockup_dai,
|
||||
ARRAY_SIZE(sdw_mockup_dai));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sdw_mockup_sdw_remove(struct sdw_slave *slave)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Intel reserved parts ID with the following mapping expected:
|
||||
* 0xAAAA: generic full-duplex codec
|
||||
* 0xAA55: headset codec (mock-up of RT711/RT5682) - full-duplex
|
||||
* 0x55AA: amplifier (mock-up of RT1308/Maxim 98373) - playback only with
|
||||
* IV feedback
|
||||
* 0x5555: mic codec (mock-up of RT715) - capture-only
|
||||
*/
|
||||
static const struct sdw_device_id sdw_mockup_id[] = {
|
||||
SDW_SLAVE_ENTRY_EXT(0x0105, 0xAAAA, 0x0, 0, 0),
|
||||
SDW_SLAVE_ENTRY_EXT(0x0105, 0xAA55, 0x0, 0, 0),
|
||||
SDW_SLAVE_ENTRY_EXT(0x0105, 0x55AA, 0x0, 0, 0),
|
||||
SDW_SLAVE_ENTRY_EXT(0x0105, 0x5555, 0x0, 0, 0),
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, sdw_mockup_id);
|
||||
|
||||
static struct sdw_driver sdw_mockup_sdw_driver = {
|
||||
.driver = {
|
||||
.name = "sdw-mockup",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = sdw_mockup_sdw_probe,
|
||||
.remove = sdw_mockup_sdw_remove,
|
||||
.ops = &sdw_mockup_slave_ops,
|
||||
.id_table = sdw_mockup_id,
|
||||
};
|
||||
module_sdw_driver(sdw_mockup_sdw_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC SDW mockup codec driver");
|
||||
MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -714,7 +714,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
|
|||
unsigned long adc_clock_rate, dac_clock_rate;
|
||||
int ret;
|
||||
|
||||
struct clk_bulk_data clocks[] = {
|
||||
static struct clk_bulk_data clocks[] = {
|
||||
{ .id = "pll" },
|
||||
{ .id = "nadc" },
|
||||
{ .id = "madc" },
|
||||
|
@ -878,7 +878,7 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
|
|||
{
|
||||
int ret;
|
||||
|
||||
struct clk_bulk_data clocks[] = {
|
||||
static struct clk_bulk_data clocks[] = {
|
||||
{ .id = "madc" },
|
||||
{ .id = "mdac" },
|
||||
{ .id = "bdiv" },
|
||||
|
@ -994,7 +994,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
|
|||
u32 tmp_reg;
|
||||
int ret;
|
||||
|
||||
struct clk_bulk_data clocks[] = {
|
||||
static struct clk_bulk_data clocks[] = {
|
||||
{ .id = "codec_clkin" },
|
||||
{ .id = "pll" },
|
||||
{ .id = "bdiv" },
|
||||
|
@ -1131,7 +1131,7 @@ static struct snd_soc_dai_driver aic32x4_tas2505_dai = {
|
|||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = AIC32X4_FORMATS,},
|
||||
.ops = &aic32x4_ops,
|
||||
|
@ -1144,7 +1144,7 @@ static int aic32x4_tas2505_component_probe(struct snd_soc_component *component)
|
|||
u32 tmp_reg;
|
||||
int ret;
|
||||
|
||||
struct clk_bulk_data clocks[] = {
|
||||
static struct clk_bulk_data clocks[] = {
|
||||
{ .id = "codec_clkin" },
|
||||
{ .id = "pll" },
|
||||
{ .id = "bdiv" },
|
||||
|
|
|
@ -4076,6 +4076,16 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void wcd9335_teardown_irqs(struct wcd9335_codec *wcd)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* disable interrupts on all slave ports */
|
||||
for (i = 0; i < WCD9335_SLIM_NUM_PORT_REG; i++)
|
||||
regmap_write(wcd->if_regmap, WCD9335_SLIM_PGD_PORT_INT_EN0 + i,
|
||||
0x00);
|
||||
}
|
||||
|
||||
static void wcd9335_cdc_sido_ccl_enable(struct wcd9335_codec *wcd,
|
||||
bool ccl_flag)
|
||||
{
|
||||
|
@ -4844,6 +4854,7 @@ static void wcd9335_codec_init(struct snd_soc_component *component)
|
|||
static int wcd9335_codec_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
snd_soc_component_init_regmap(component, wcd->regmap);
|
||||
|
@ -4861,7 +4872,15 @@ static int wcd9335_codec_probe(struct snd_soc_component *component)
|
|||
for (i = 0; i < NUM_CODEC_DAIS; i++)
|
||||
INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list);
|
||||
|
||||
return wcd9335_setup_irqs(wcd);
|
||||
ret = wcd9335_setup_irqs(wcd);
|
||||
if (ret)
|
||||
goto free_clsh_ctrl;
|
||||
|
||||
return 0;
|
||||
|
||||
free_clsh_ctrl:
|
||||
wcd_clsh_ctrl_free(wcd->clsh_ctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wcd9335_codec_remove(struct snd_soc_component *comp)
|
||||
|
@ -4869,7 +4888,7 @@ static void wcd9335_codec_remove(struct snd_soc_component *comp)
|
|||
struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
|
||||
|
||||
wcd_clsh_ctrl_free(wcd->clsh_ctrl);
|
||||
free_irq(regmap_irq_get_virq(wcd->irq_data, WCD9335_IRQ_SLIMBUS), wcd);
|
||||
wcd9335_teardown_irqs(wcd);
|
||||
}
|
||||
|
||||
static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -658,7 +658,6 @@ struct wcd938x_sdw_priv {
|
|||
struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
|
||||
struct wcd938x_sdw_ch_info *ch_info;
|
||||
bool port_enable[WCD938X_MAX_SWR_CH_IDS];
|
||||
int port_map[WCD938X_MAX_SWR_PORTS];
|
||||
int active_ports;
|
||||
int num_ports;
|
||||
bool is_tx;
|
||||
|
|
|
@ -2031,10 +2031,9 @@ static struct wm_coeff_ctl *wm_adsp_get_ctl(struct wm_adsp *dsp,
|
|||
if (!pos->subname)
|
||||
continue;
|
||||
if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
|
||||
strncmp(pos->fw_name, fw_txt,
|
||||
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0 &&
|
||||
pos->alg_region.alg == alg &&
|
||||
pos->alg_region.type == type) {
|
||||
pos->fw_name == fw_txt &&
|
||||
pos->alg_region.alg == alg &&
|
||||
pos->alg_region.type == type) {
|
||||
rslt = pos;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -642,7 +642,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|||
|
||||
dev->dev = &pdev->dev;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
irq = platform_get_irq_optional(pdev, 0);
|
||||
if (irq >= 0) {
|
||||
ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0,
|
||||
pdev->name, dev);
|
||||
|
|
|
@ -165,25 +165,25 @@ static int fsl_rpmsg_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Get the optional clocks */
|
||||
rpmsg->ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
rpmsg->ipg = devm_clk_get_optional(&pdev->dev, "ipg");
|
||||
if (IS_ERR(rpmsg->ipg))
|
||||
rpmsg->ipg = NULL;
|
||||
return PTR_ERR(rpmsg->ipg);
|
||||
|
||||
rpmsg->mclk = devm_clk_get(&pdev->dev, "mclk");
|
||||
rpmsg->mclk = devm_clk_get_optional(&pdev->dev, "mclk");
|
||||
if (IS_ERR(rpmsg->mclk))
|
||||
rpmsg->mclk = NULL;
|
||||
return PTR_ERR(rpmsg->mclk);
|
||||
|
||||
rpmsg->dma = devm_clk_get(&pdev->dev, "dma");
|
||||
rpmsg->dma = devm_clk_get_optional(&pdev->dev, "dma");
|
||||
if (IS_ERR(rpmsg->dma))
|
||||
rpmsg->dma = NULL;
|
||||
return PTR_ERR(rpmsg->dma);
|
||||
|
||||
rpmsg->pll8k = devm_clk_get(&pdev->dev, "pll8k");
|
||||
rpmsg->pll8k = devm_clk_get_optional(&pdev->dev, "pll8k");
|
||||
if (IS_ERR(rpmsg->pll8k))
|
||||
rpmsg->pll8k = NULL;
|
||||
return PTR_ERR(rpmsg->pll8k);
|
||||
|
||||
rpmsg->pll11k = devm_clk_get(&pdev->dev, "pll11k");
|
||||
rpmsg->pll11k = devm_clk_get_optional(&pdev->dev, "pll11k");
|
||||
if (IS_ERR(rpmsg->pll11k))
|
||||
rpmsg->pll11k = NULL;
|
||||
return PTR_ERR(rpmsg->pll11k);
|
||||
|
||||
platform_set_drvdata(pdev, rpmsg);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
|
|
@ -1189,10 +1189,8 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
|
|||
|
||||
/* get IRQs */
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "no irq[0]: %d\n", irq);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, irq, irq0_isr, 0, pdev->name, xcvr);
|
||||
if (ret) {
|
||||
|
|
|
@ -125,7 +125,7 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
|
|||
snd_soc_card_set_drvdata(&data->card, data);
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
|
||||
dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -640,8 +640,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
|
|||
cnf_num += li->num[i].codecs;
|
||||
}
|
||||
|
||||
dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
|
||||
dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL);
|
||||
dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
|
||||
dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL);
|
||||
if (!dais || !dlcs)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx,
|
|||
while (header.p.header_high.part.busy) {
|
||||
if (loop_count > 25) {
|
||||
dev_err(sst_drv_ctx->dev,
|
||||
"sst: Busy wait failed, cant send this msg\n");
|
||||
"sst: Busy wait failed, can't send this msg\n");
|
||||
retval = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -602,6 +602,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
|
|||
select SND_SOC_DMIC
|
||||
select SND_SOC_INTEL_HDA_DSP_COMMON
|
||||
select SND_SOC_INTEL_SOF_MAXIM_COMMON
|
||||
select SND_SOC_SDW_MOCKUP
|
||||
help
|
||||
Add support for Intel SoundWire-based platforms connected to
|
||||
MAX98373, RT700, RT711, RT1308 and RT715
|
||||
|
|
|
@ -37,6 +37,7 @@ struct byt_cht_es8316_private {
|
|||
struct clk *mclk;
|
||||
struct snd_soc_jack jack;
|
||||
struct gpio_desc *speaker_en_gpio;
|
||||
struct device *codec_dev;
|
||||
bool speaker_en;
|
||||
};
|
||||
|
||||
|
@ -461,6 +462,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
|
|||
const struct dmi_system_id *dmi_id;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct snd_soc_acpi_mach *mach;
|
||||
struct fwnode_handle *fwnode;
|
||||
const char *platform_name;
|
||||
struct acpi_device *adev;
|
||||
struct device *codec_dev;
|
||||
|
@ -491,6 +493,9 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
|
|||
"i2c-%s", acpi_dev_name(adev));
|
||||
put_device(&adev->dev);
|
||||
byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* override plaform name, if required */
|
||||
|
@ -535,15 +540,25 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* get speaker enable GPIO */
|
||||
codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
|
||||
codec_dev = acpi_get_first_physical_node(adev);
|
||||
if (!codec_dev)
|
||||
return -EPROBE_DEFER;
|
||||
priv->codec_dev = get_device(codec_dev);
|
||||
|
||||
if (quirk & BYT_CHT_ES8316_JD_INVERTED)
|
||||
props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
|
||||
|
||||
if (cnt) {
|
||||
ret = device_add_properties(codec_dev, props);
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode)) {
|
||||
put_device(codec_dev);
|
||||
return PTR_ERR(fwnode);
|
||||
}
|
||||
|
||||
ret = device_add_software_node(codec_dev, to_software_node(fwnode));
|
||||
|
||||
fwnode_handle_put(fwnode);
|
||||
|
||||
if (ret) {
|
||||
put_device(codec_dev);
|
||||
return ret;
|
||||
|
@ -555,7 +570,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
|
|||
gpiod_get_index(codec_dev, "speaker-enable", 0,
|
||||
/* see comment in byt_cht_es8316_resume */
|
||||
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
|
||||
put_device(codec_dev);
|
||||
|
||||
if (IS_ERR(priv->speaker_en_gpio)) {
|
||||
ret = PTR_ERR(priv->speaker_en_gpio);
|
||||
|
@ -567,7 +581,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
|
|||
dev_err(dev, "get speaker GPIO failed: %d\n", ret);
|
||||
fallthrough;
|
||||
case -EPROBE_DEFER:
|
||||
return ret;
|
||||
goto err_put_codec;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,10 +619,15 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
|
|||
if (ret) {
|
||||
gpiod_put(priv->speaker_en_gpio);
|
||||
dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
|
||||
return ret;
|
||||
goto err_put_codec;
|
||||
}
|
||||
platform_set_drvdata(pdev, &byt_cht_es8316_card);
|
||||
return 0;
|
||||
|
||||
err_put_codec:
|
||||
device_remove_software_node(priv->codec_dev);
|
||||
put_device(priv->codec_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
|
||||
|
@ -617,6 +636,8 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
|
|||
struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
|
||||
|
||||
gpiod_put(priv->speaker_en_gpio);
|
||||
device_remove_software_node(priv->codec_dev);
|
||||
put_device(priv->codec_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -73,6 +75,10 @@ enum {
|
|||
#define BYT_RT5640_MCLK_EN BIT(22)
|
||||
#define BYT_RT5640_MCLK_25MHZ BIT(23)
|
||||
#define BYT_RT5640_NO_SPEAKERS BIT(24)
|
||||
#define BYT_RT5640_LINEOUT BIT(25)
|
||||
#define BYT_RT5640_LINEOUT_AS_HP2 BIT(26)
|
||||
#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27)
|
||||
#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)
|
||||
|
||||
#define BYTCR_INPUT_DEFAULTS \
|
||||
(BYT_RT5640_IN3_MAP | \
|
||||
|
@ -86,7 +92,10 @@ enum {
|
|||
|
||||
struct byt_rt5640_private {
|
||||
struct snd_soc_jack jack;
|
||||
struct snd_soc_jack jack2;
|
||||
struct gpio_desc *hsmic_detect;
|
||||
struct clk *mclk;
|
||||
struct device *codec_dev;
|
||||
};
|
||||
static bool is_bytcr;
|
||||
|
||||
|
@ -125,6 +134,8 @@ static void log_quirks(struct device *dev)
|
|||
dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
|
||||
break;
|
||||
}
|
||||
if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)
|
||||
dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n");
|
||||
if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
|
||||
dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
|
||||
BYT_RT5640_JDSRC(byt_rt5640_quirk));
|
||||
|
@ -135,10 +146,16 @@ static void log_quirks(struct device *dev)
|
|||
}
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
|
||||
dev_info(dev, "quirk JD_NOT_INV enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
|
||||
dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
|
||||
dev_info(dev, "quirk MONO_SPEAKER enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
|
||||
dev_info(dev, "quirk NO_SPEAKERS enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT)
|
||||
dev_info(dev, "quirk LINEOUT enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
|
||||
dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
|
||||
dev_info(dev, "quirk DIFF_MIC enabled\n");
|
||||
if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
|
||||
|
@ -224,6 +241,20 @@ static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
|
|||
#define BYT_CODEC_DAI1 "rt5640-aif1"
|
||||
#define BYT_CODEC_DAI2 "rt5640-aif2"
|
||||
|
||||
static struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
|
||||
codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
|
||||
if (!codec_dai)
|
||||
codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
|
||||
if (!codec_dai)
|
||||
dev_err(card->dev, "Error codec dai not found\n");
|
||||
|
||||
return codec_dai;
|
||||
}
|
||||
|
||||
static int platform_clock_control(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *k, int event)
|
||||
{
|
||||
|
@ -233,15 +264,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
|
|||
struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
|
||||
int ret;
|
||||
|
||||
codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
|
||||
codec_dai = byt_rt5640_get_codec_dai(dapm);
|
||||
if (!codec_dai)
|
||||
codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
|
||||
|
||||
if (!codec_dai) {
|
||||
dev_err(card->dev,
|
||||
"Codec dai not found; Unable to set platform clock\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
|
||||
|
@ -276,23 +301,48 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *k, int event)
|
||||
{
|
||||
unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
|
||||
if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* On devices which use line-out as a second headphones output,
|
||||
* the codec's GPIO1 pin is used to enable an external HP-amp.
|
||||
*/
|
||||
|
||||
codec_dai = byt_rt5640_get_codec_dai(w->dapm);
|
||||
if (!codec_dai)
|
||||
return -EIO;
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
gpio_ctrl3_val |= RT5640_GP1_OUT_HI;
|
||||
|
||||
snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3,
|
||||
RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
|
||||
SND_SOC_DAPM_MIC("Internal Mic", NULL),
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout),
|
||||
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
|
||||
platform_clock_control, SND_SOC_DAPM_PRE_PMU |
|
||||
SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
|
||||
{"Headphone", NULL, "Platform Clock"},
|
||||
{"Headset Mic", NULL, "Platform Clock"},
|
||||
{"Internal Mic", NULL, "Platform Clock"},
|
||||
{"Speaker", NULL, "Platform Clock"},
|
||||
|
||||
{"Headset Mic", NULL, "MICBIAS1"},
|
||||
{"IN2P", NULL, "Headset Mic"},
|
||||
{"Headphone", NULL, "HPOL"},
|
||||
|
@ -300,23 +350,33 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
|
||||
{"Internal Mic", NULL, "Platform Clock"},
|
||||
{"DMIC1", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
|
||||
{"Internal Mic", NULL, "Platform Clock"},
|
||||
{"DMIC2", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
|
||||
{"Internal Mic", NULL, "Platform Clock"},
|
||||
{"Internal Mic", NULL, "MICBIAS1"},
|
||||
{"IN1P", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
|
||||
{"Internal Mic", NULL, "Platform Clock"},
|
||||
{"Internal Mic", NULL, "MICBIAS1"},
|
||||
{"IN3P", NULL, "Internal Mic"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = {
|
||||
{"Headset Mic 2", NULL, "Platform Clock"},
|
||||
{"Headset Mic 2", NULL, "MICBIAS1"},
|
||||
{"IN1P", NULL, "Headset Mic 2"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {
|
||||
{"ssp2 Tx", NULL, "codec_out0"},
|
||||
{"ssp2 Tx", NULL, "codec_out1"},
|
||||
|
@ -354,6 +414,7 @@ static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
|
||||
{"Speaker", NULL, "Platform Clock"},
|
||||
{"Speaker", NULL, "SPOLP"},
|
||||
{"Speaker", NULL, "SPOLN"},
|
||||
{"Speaker", NULL, "SPORP"},
|
||||
|
@ -361,15 +422,24 @@ static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
|
||||
{"Speaker", NULL, "Platform Clock"},
|
||||
{"Speaker", NULL, "SPOLP"},
|
||||
{"Speaker", NULL, "SPOLN"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = {
|
||||
{"Line Out", NULL, "Platform Clock"},
|
||||
{"Line Out", NULL, "LOUTR"},
|
||||
{"Line Out", NULL, "LOUTL"},
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new byt_rt5640_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Headphone"),
|
||||
SOC_DAPM_PIN_SWITCH("Headset Mic"),
|
||||
SOC_DAPM_PIN_SWITCH("Headset Mic 2"),
|
||||
SOC_DAPM_PIN_SWITCH("Internal Mic"),
|
||||
SOC_DAPM_PIN_SWITCH("Speaker"),
|
||||
SOC_DAPM_PIN_SWITCH("Line Out"),
|
||||
};
|
||||
|
||||
static struct snd_soc_jack_pin rt5640_pins[] = {
|
||||
|
@ -383,6 +453,75 @@ static struct snd_soc_jack_pin rt5640_pins[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_jack_pin rt5640_pins2[] = {
|
||||
{
|
||||
/* The 2nd headset jack uses lineout with an external HP-amp */
|
||||
.pin = "Line Out",
|
||||
.mask = SND_JACK_HEADPHONE,
|
||||
},
|
||||
{
|
||||
.pin = "Headset Mic 2",
|
||||
.mask = SND_JACK_MICROPHONE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_jack_gpio rt5640_jack_gpio = {
|
||||
.name = "hp-detect",
|
||||
.report = SND_JACK_HEADSET,
|
||||
.invert = true,
|
||||
.debounce_time = 200,
|
||||
};
|
||||
|
||||
static struct snd_soc_jack_gpio rt5640_jack2_gpio = {
|
||||
.name = "hp2-detect",
|
||||
.report = SND_JACK_HEADSET,
|
||||
.invert = true,
|
||||
.debounce_time = 200,
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false };
|
||||
static const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false };
|
||||
static const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false };
|
||||
|
||||
static const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = {
|
||||
{ "hp-detect-gpios", &acpi_gpio0, 1, },
|
||||
{ "headset-mic-detect-gpios", &acpi_gpio1, 1, },
|
||||
{ "hp2-detect-gpios", &acpi_gpio2, 1, },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data)
|
||||
{
|
||||
struct byt_rt5640_private *priv = data;
|
||||
int jack_status, mic_status;
|
||||
|
||||
jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc);
|
||||
if (jack_status)
|
||||
return 0;
|
||||
|
||||
mic_status = gpiod_get_value_cansleep(priv->hsmic_detect);
|
||||
if (mic_status)
|
||||
return SND_JACK_HEADPHONE;
|
||||
else
|
||||
return SND_JACK_HEADSET;
|
||||
}
|
||||
|
||||
static int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data)
|
||||
{
|
||||
struct snd_soc_component *component = data;
|
||||
int jack_status, report;
|
||||
|
||||
jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc);
|
||||
if (jack_status)
|
||||
return 0;
|
||||
|
||||
rt5640_enable_micbias1_for_ovcd(component);
|
||||
report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc);
|
||||
rt5640_disable_micbias1_for_ovcd(component);
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
|
@ -590,8 +729,12 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
|||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
|
||||
},
|
||||
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
|
||||
BYT_RT5640_MCLK_EN),
|
||||
.driver_data = (void *)(BYT_RT5640_DMIC2_MAP |
|
||||
BYT_RT5640_MCLK_EN |
|
||||
BYT_RT5640_LINEOUT |
|
||||
BYT_RT5640_LINEOUT_AS_HP2 |
|
||||
BYT_RT5640_HSMIC2_ON_IN1 |
|
||||
BYT_RT5640_JD_HP_ELITEP_1000G2),
|
||||
},
|
||||
{ /* HP Pavilion x2 10-k0XX, 10-n0XX */
|
||||
.matches = {
|
||||
|
@ -912,15 +1055,13 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
|||
* Note this MUST be called before snd_soc_register_card(), so that the props
|
||||
* are in place before the codec component driver's probe function parses them.
|
||||
*/
|
||||
static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
|
||||
static int byt_rt5640_add_codec_device_props(struct device *i2c_dev,
|
||||
struct byt_rt5640_private *priv)
|
||||
{
|
||||
struct property_entry props[MAX_NO_PROPS] = {};
|
||||
struct device *i2c_dev;
|
||||
int ret, cnt = 0;
|
||||
|
||||
i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
|
||||
if (!i2c_dev)
|
||||
return -EPROBE_DEFER;
|
||||
struct fwnode_handle *fwnode;
|
||||
int cnt = 0;
|
||||
int ret;
|
||||
|
||||
switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
|
||||
case BYT_RT5640_DMIC1_MAP:
|
||||
|
@ -960,8 +1101,15 @@ static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
|
|||
if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
|
||||
props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
|
||||
|
||||
ret = device_add_properties(i2c_dev, props);
|
||||
put_device(i2c_dev);
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode)) {
|
||||
/* put_device() is handled in caller */
|
||||
return PTR_ERR(fwnode);
|
||||
}
|
||||
|
||||
ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
|
||||
|
||||
fwnode_handle_put(fwnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1021,6 +1169,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) {
|
||||
ret = snd_soc_dapm_add_routes(&card->dapm,
|
||||
byt_rt5640_hsmic2_in1_map,
|
||||
ARRAY_SIZE(byt_rt5640_hsmic2_in1_map));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
|
||||
ret = snd_soc_dapm_add_routes(&card->dapm,
|
||||
byt_rt5640_ssp2_aif2_map,
|
||||
|
@ -1053,6 +1209,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {
|
||||
ret = snd_soc_dapm_add_routes(&card->dapm,
|
||||
byt_rt5640_lineout_map,
|
||||
ARRAY_SIZE(byt_rt5640_lineout_map));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
|
||||
/*
|
||||
* The firmware might enable the clock at
|
||||
|
@ -1093,9 +1257,53 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
|
|||
snd_soc_component_set_jack(component, &priv->jack, NULL);
|
||||
}
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
|
||||
ret = snd_soc_card_jack_new(card, "Headset",
|
||||
SND_JACK_HEADSET,
|
||||
&priv->jack, rt5640_pins,
|
||||
ARRAY_SIZE(rt5640_pins));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_card_jack_new(card, "Headset 2",
|
||||
SND_JACK_HEADSET,
|
||||
&priv->jack2, rt5640_pins2,
|
||||
ARRAY_SIZE(rt5640_pins2));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rt5640_jack_gpio.data = priv;
|
||||
rt5640_jack_gpio.gpiod_dev = priv->codec_dev;
|
||||
rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check;
|
||||
ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rt5640_set_ovcd_params(component);
|
||||
rt5640_jack2_gpio.data = component;
|
||||
rt5640_jack2_gpio.gpiod_dev = priv->codec_dev;
|
||||
rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check;
|
||||
ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);
|
||||
if (ret) {
|
||||
snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime)
|
||||
{
|
||||
struct snd_soc_card *card = runtime->card;
|
||||
struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
|
||||
snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);
|
||||
snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);
|
||||
}
|
||||
}
|
||||
|
||||
static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
|
@ -1208,6 +1416,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
|
|||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.init = byt_rt5640_init,
|
||||
.exit = byt_rt5640_exit,
|
||||
.ops = &byt_rt5640_be_ssp2_ops,
|
||||
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
|
||||
},
|
||||
|
@ -1218,7 +1427,7 @@ static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
|
|||
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
|
||||
static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */
|
||||
#endif
|
||||
static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */
|
||||
static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */
|
||||
|
||||
static int byt_rt5640_suspend(struct snd_soc_card *card)
|
||||
{
|
||||
|
@ -1288,10 +1497,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
|
||||
__maybe_unused const char *spk_type;
|
||||
const struct dmi_system_id *dmi_id;
|
||||
const char *headset2_string = "";
|
||||
const char *lineout_string = "";
|
||||
struct byt_rt5640_private *priv;
|
||||
struct snd_soc_acpi_mach *mach;
|
||||
const char *platform_name;
|
||||
struct acpi_device *adev;
|
||||
struct device *codec_dev;
|
||||
bool sof_parent;
|
||||
int ret_val = 0;
|
||||
int dai_index = 0;
|
||||
|
@ -1324,6 +1536,9 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
"i2c-%s", acpi_dev_name(adev));
|
||||
put_device(&adev->dev);
|
||||
byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1400,10 +1615,29 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
byt_rt5640_quirk = quirk_override;
|
||||
}
|
||||
|
||||
codec_dev = acpi_get_first_physical_node(adev);
|
||||
if (!codec_dev)
|
||||
return -EPROBE_DEFER;
|
||||
priv->codec_dev = get_device(codec_dev);
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
|
||||
acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),
|
||||
byt_rt5640_hp_elitepad_1000g2_gpios);
|
||||
|
||||
priv->hsmic_detect = devm_fwnode_gpiod_get(&pdev->dev, codec_dev->fwnode,
|
||||
"headset-mic-detect", GPIOD_IN,
|
||||
"headset-mic-detect");
|
||||
if (IS_ERR(priv->hsmic_detect)) {
|
||||
ret_val = PTR_ERR(priv->hsmic_detect);
|
||||
dev_err_probe(&pdev->dev, ret_val, "getting hsmic-detect GPIO\n");
|
||||
goto err_device;
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be called before register_card, also see declaration comment. */
|
||||
ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
|
||||
ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
goto err_remove_gpios;
|
||||
|
||||
log_quirks(&pdev->dev);
|
||||
|
||||
|
@ -1434,7 +1668,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
* for all other errors, including -EPROBE_DEFER
|
||||
*/
|
||||
if (ret_val != -ENOENT)
|
||||
return ret_val;
|
||||
goto err;
|
||||
byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
|
||||
}
|
||||
}
|
||||
|
@ -1450,9 +1684,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
spk_type = "stereo";
|
||||
}
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {
|
||||
if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)
|
||||
lineout_string = " cfg-hp2:lineout";
|
||||
else
|
||||
lineout_string = " cfg-lineout:2";
|
||||
}
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)
|
||||
headset2_string = " cfg-hs2:in1";
|
||||
|
||||
snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
|
||||
"cfg-spk:%d cfg-mic:%s aif:%d", cfg_spk,
|
||||
map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif);
|
||||
"cfg-spk:%d cfg-mic:%s aif:%d%s%s", cfg_spk,
|
||||
map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,
|
||||
lineout_string, headset2_string);
|
||||
byt_rt5640_card.components = byt_rt5640_components;
|
||||
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
|
||||
snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
|
||||
|
@ -1467,7 +1712,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
|
||||
platform_name);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
goto err;
|
||||
|
||||
sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
|
||||
|
||||
|
@ -1489,10 +1734,32 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|||
if (ret_val) {
|
||||
dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
|
||||
ret_val);
|
||||
return ret_val;
|
||||
goto err;
|
||||
}
|
||||
platform_set_drvdata(pdev, &byt_rt5640_card);
|
||||
return ret_val;
|
||||
|
||||
err:
|
||||
device_remove_software_node(priv->codec_dev);
|
||||
err_remove_gpios:
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
|
||||
acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));
|
||||
err_device:
|
||||
put_device(priv->codec_dev);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int snd_byt_rt5640_mc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)
|
||||
acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));
|
||||
|
||||
device_remove_software_node(priv->codec_dev);
|
||||
put_device(priv->codec_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver snd_byt_rt5640_mc_driver = {
|
||||
|
@ -1500,6 +1767,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = {
|
|||
.name = "bytcr_rt5640",
|
||||
},
|
||||
.probe = snd_byt_rt5640_mc_probe,
|
||||
.remove = snd_byt_rt5640_mc_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(snd_byt_rt5640_mc_driver);
|
||||
|
|
|
@ -85,6 +85,7 @@ struct byt_rt5651_private {
|
|||
struct gpio_desc *ext_amp_gpio;
|
||||
struct gpio_desc *hp_detect;
|
||||
struct snd_soc_jack jack;
|
||||
struct device *codec_dev;
|
||||
};
|
||||
|
||||
static const struct acpi_gpio_mapping *byt_rt5651_gpios;
|
||||
|
@ -527,10 +528,13 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
|
|||
* Note this MUST be called before snd_soc_register_card(), so that the props
|
||||
* are in place before the codec component driver's probe function parses them.
|
||||
*/
|
||||
static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
|
||||
static int byt_rt5651_add_codec_device_props(struct device *i2c_dev,
|
||||
struct byt_rt5651_private *priv)
|
||||
{
|
||||
struct property_entry props[MAX_NO_PROPS] = {};
|
||||
struct fwnode_handle *fwnode;
|
||||
int cnt = 0;
|
||||
int ret;
|
||||
|
||||
props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source",
|
||||
BYT_RT5651_JDSRC(byt_rt5651_quirk));
|
||||
|
@ -547,7 +551,17 @@ static int byt_rt5651_add_codec_device_props(struct device *i2c_dev)
|
|||
if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
|
||||
props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
|
||||
|
||||
return device_add_properties(i2c_dev, props);
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode)) {
|
||||
/* put_device(i2c_dev) is handled in caller */
|
||||
return PTR_ERR(fwnode);
|
||||
}
|
||||
|
||||
ret = device_add_software_node(i2c_dev, to_software_node(fwnode));
|
||||
|
||||
fwnode_handle_put(fwnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
|
||||
|
@ -920,13 +934,13 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
|
||||
return -ENODEV;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
|
||||
byt_rt5651_codec_name);
|
||||
codec_dev = acpi_get_first_physical_node(adev);
|
||||
if (!codec_dev)
|
||||
return -EPROBE_DEFER;
|
||||
priv->codec_dev = get_device(codec_dev);
|
||||
|
||||
/*
|
||||
* swap SSP0 if bytcr is detected
|
||||
|
@ -994,11 +1008,9 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Must be called before register_card, also see declaration comment. */
|
||||
ret_val = byt_rt5651_add_codec_device_props(codec_dev);
|
||||
if (ret_val) {
|
||||
put_device(codec_dev);
|
||||
return ret_val;
|
||||
}
|
||||
ret_val = byt_rt5651_add_codec_device_props(codec_dev, priv);
|
||||
if (ret_val)
|
||||
goto err_device;
|
||||
|
||||
/* Cherry Trail devices use an external amplifier enable gpio */
|
||||
if (soc_intel_is_cht() && !byt_rt5651_gpios)
|
||||
|
@ -1022,8 +1034,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
ret_val);
|
||||
fallthrough;
|
||||
case -EPROBE_DEFER:
|
||||
put_device(codec_dev);
|
||||
return ret_val;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev,
|
||||
|
@ -1042,14 +1053,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
ret_val);
|
||||
fallthrough;
|
||||
case -EPROBE_DEFER:
|
||||
put_device(codec_dev);
|
||||
return ret_val;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
put_device(codec_dev);
|
||||
|
||||
log_quirks(&pdev->dev);
|
||||
|
||||
if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
|
||||
|
@ -1073,7 +1081,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
* for all other errors, including -EPROBE_DEFER
|
||||
*/
|
||||
if (ret_val != -ENOENT)
|
||||
return ret_val;
|
||||
goto err;
|
||||
byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
|
||||
}
|
||||
}
|
||||
|
@ -1102,7 +1110,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card,
|
||||
platform_name);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
goto err;
|
||||
|
||||
sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
|
||||
|
||||
|
@ -1124,10 +1132,26 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
|
|||
if (ret_val) {
|
||||
dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
|
||||
ret_val);
|
||||
return ret_val;
|
||||
goto err;
|
||||
}
|
||||
platform_set_drvdata(pdev, &byt_rt5651_card);
|
||||
return ret_val;
|
||||
|
||||
err:
|
||||
device_remove_software_node(priv->codec_dev);
|
||||
err_device:
|
||||
put_device(priv->codec_dev);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int snd_byt_rt5651_mc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
|
||||
|
||||
device_remove_software_node(priv->codec_dev);
|
||||
put_device(priv->codec_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver snd_byt_rt5651_mc_driver = {
|
||||
|
@ -1135,6 +1159,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = {
|
|||
.name = "bytcr_rt5651",
|
||||
},
|
||||
.probe = snd_byt_rt5651_mc_probe,
|
||||
.remove = snd_byt_rt5651_mc_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(snd_byt_rt5651_mc_driver);
|
||||
|
|
|
@ -199,7 +199,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) {
|
||||
ret = snd_soc_dai_set_tdm_slot(codec_dai,
|
||||
0x03, 3, 8, 24);
|
||||
0x30, 3, 8, 16);
|
||||
if (ret < 0) {
|
||||
dev_err(runtime->dev,
|
||||
"DEV0 TDM slot err:%d\n", ret);
|
||||
|
@ -208,10 +208,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) {
|
||||
ret = snd_soc_dai_set_tdm_slot(codec_dai,
|
||||
0x0C, 3, 8, 24);
|
||||
0xC0, 3, 8, 16);
|
||||
if (ret < 0) {
|
||||
dev_err(runtime->dev,
|
||||
"DEV0 TDM slot err:%d\n", ret);
|
||||
"DEV1 TDM slot err:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -311,24 +311,6 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
* The above 2 loops are mutually exclusive based on the stream direction,
|
||||
* thus rtd_dpcm variable will never be overwritten
|
||||
*/
|
||||
/*
|
||||
* Topology for kblda7219m98373 & kblmax98373 supports only S24_LE,
|
||||
* where as kblda7219m98927 & kblmax98927 supports S16_LE by default.
|
||||
* Skipping the port wise FE and BE configuration for kblda7219m98373 &
|
||||
* kblmax98373 as the topology (FE & BE) supports S24_LE only.
|
||||
*/
|
||||
|
||||
if (!strcmp(rtd->card->name, "kblda7219m98373") ||
|
||||
!strcmp(rtd->card->name, "kblmax98373")) {
|
||||
/* The ADSP will convert the FE rate to 48k, stereo */
|
||||
rate->min = rate->max = 48000;
|
||||
chan->min = chan->max = DUAL_CHANNEL;
|
||||
|
||||
/* set SSP to 24 bit */
|
||||
snd_mask_none(fmt);
|
||||
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The ADSP will convert the FE rate to 48k, stereo, 24 bit
|
||||
|
@ -479,31 +461,20 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
|
|||
static int kbl_fe_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream);
|
||||
|
||||
/*
|
||||
* On this platform for PCM device we support,
|
||||
* 48Khz
|
||||
* stereo
|
||||
* 16 bit audio
|
||||
*/
|
||||
|
||||
runtime->hw.channels_max = DUAL_CHANNEL;
|
||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_channels);
|
||||
/*
|
||||
* Setup S24_LE (32 bit container and 24 bit valid data) for
|
||||
* kblda7219m98373 & kblmax98373. For kblda7219m98927 &
|
||||
* kblmax98927 keeping it as 16/16 due to topology FW dependency.
|
||||
*/
|
||||
if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
|
||||
!strcmp(soc_rt->card->name, "kblmax98373")) {
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
|
||||
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
|
||||
|
||||
} else {
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
|
||||
snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
|
||||
}
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
|
||||
snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
|
||||
|
||||
snd_pcm_hw_constraint_list(runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
|
||||
|
@ -536,23 +507,11 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream);
|
||||
|
||||
runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
|
||||
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
&constraints_channels_quad);
|
||||
|
||||
/*
|
||||
* Topology for kblda7219m98373 & kblmax98373 supports only S24_LE.
|
||||
* The DMIC also configured for S24_LE. Forcing the DMIC format to
|
||||
* S24_LE due to the topology FW dependency.
|
||||
*/
|
||||
if (!strcmp(soc_rt->card->name, "kblda7219m98373") ||
|
||||
!strcmp(soc_rt->card->name, "kblmax98373")) {
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE;
|
||||
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
|
||||
}
|
||||
|
||||
return snd_pcm_hw_constraint_list(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/sof.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <dt-bindings/sound/cs42l42.h>
|
||||
#include "../../codecs/hdac_hdmi.h"
|
||||
|
@ -36,7 +37,20 @@
|
|||
#define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7))
|
||||
#define SOF_CS42L42_NUM_HDMIDEV(quirk) \
|
||||
(((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK)
|
||||
#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(10)
|
||||
#define SOF_CS42L42_DAILINK_SHIFT 10
|
||||
#define SOF_CS42L42_DAILINK_MASK (GENMASK(24, 10))
|
||||
#define SOF_CS42L42_DAILINK(link1, link2, link3, link4, link5) \
|
||||
((((link1) | ((link2) << 3) | ((link3) << 6) | ((link4) << 9) | ((link5) << 12)) << SOF_CS42L42_DAILINK_SHIFT) & SOF_CS42L42_DAILINK_MASK)
|
||||
#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(25)
|
||||
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(26)
|
||||
|
||||
enum {
|
||||
LINK_NONE = 0,
|
||||
LINK_HP = 1,
|
||||
LINK_SPK = 2,
|
||||
LINK_DMIC = 3,
|
||||
LINK_HDMI = 4,
|
||||
};
|
||||
|
||||
/* Default: SSP2 */
|
||||
static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2);
|
||||
|
@ -122,7 +136,12 @@ static int sof_cs42l42_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
int clk_freq, ret;
|
||||
|
||||
clk_freq = 3072000; /* BCLK freq */
|
||||
clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */
|
||||
|
||||
if (clk_freq <= 0) {
|
||||
dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Configure sysclk for codec */
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0,
|
||||
|
@ -259,133 +278,168 @@ static struct snd_soc_dai_link_component dmic_component[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
||||
int ssp_codec,
|
||||
int ssp_amp,
|
||||
int dmic_be_num,
|
||||
int hdmi_num)
|
||||
static int create_spk_amp_dai_links(struct device *dev,
|
||||
struct snd_soc_dai_link *links,
|
||||
struct snd_soc_dai_link_component *cpus,
|
||||
int *id, int ssp_amp)
|
||||
{
|
||||
struct snd_soc_dai_link_component *idisp_components;
|
||||
struct snd_soc_dai_link_component *cpus;
|
||||
struct snd_soc_dai_link *links;
|
||||
int i, id = 0;
|
||||
|
||||
links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
|
||||
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
|
||||
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
|
||||
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
|
||||
if (!links || !cpus)
|
||||
goto devm_err;
|
||||
int ret = 0;
|
||||
|
||||
/* speaker amp */
|
||||
if (sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT) {
|
||||
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d-Codec", ssp_amp);
|
||||
if (!links[id].name)
|
||||
goto devm_err;
|
||||
if (!(sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT))
|
||||
return 0;
|
||||
|
||||
links[id].id = id;
|
||||
|
||||
if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
|
||||
max_98357a_dai_link(&links[id]);
|
||||
} else {
|
||||
dev_err(dev, "no amp defined\n");
|
||||
goto devm_err;
|
||||
}
|
||||
|
||||
links[id].platforms = platform_component;
|
||||
links[id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[id].dpcm_playback = 1;
|
||||
links[id].no_pcm = 1;
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].num_cpus = 1;
|
||||
|
||||
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d Pin",
|
||||
ssp_amp);
|
||||
if (!links[id].cpus->dai_name)
|
||||
goto devm_err;
|
||||
|
||||
id++;
|
||||
links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
|
||||
ssp_amp);
|
||||
if (!links[*id].name) {
|
||||
ret = -ENOMEM;
|
||||
goto devm_err;
|
||||
}
|
||||
|
||||
links[*id].id = *id;
|
||||
|
||||
if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) {
|
||||
max_98357a_dai_link(&links[*id]);
|
||||
} else if (sof_cs42l42_quirk & SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
|
||||
max_98360a_dai_link(&links[*id]);
|
||||
} else {
|
||||
dev_err(dev, "no amp defined\n");
|
||||
ret = -EINVAL;
|
||||
goto devm_err;
|
||||
}
|
||||
|
||||
links[*id].platforms = platform_component;
|
||||
links[*id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[*id].dpcm_playback = 1;
|
||||
links[*id].no_pcm = 1;
|
||||
links[*id].cpus = &cpus[*id];
|
||||
links[*id].num_cpus = 1;
|
||||
|
||||
links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d Pin", ssp_amp);
|
||||
if (!links[*id].cpus->dai_name) {
|
||||
ret = -ENOMEM;
|
||||
goto devm_err;
|
||||
}
|
||||
|
||||
(*id)++;
|
||||
|
||||
devm_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int create_hp_codec_dai_links(struct device *dev,
|
||||
struct snd_soc_dai_link *links,
|
||||
struct snd_soc_dai_link_component *cpus,
|
||||
int *id, int ssp_codec)
|
||||
{
|
||||
/* codec SSP */
|
||||
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d-Codec", ssp_codec);
|
||||
if (!links[id].name)
|
||||
links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec",
|
||||
ssp_codec);
|
||||
if (!links[*id].name)
|
||||
goto devm_err;
|
||||
|
||||
links[id].id = id;
|
||||
links[id].codecs = cs42l42_component;
|
||||
links[id].num_codecs = ARRAY_SIZE(cs42l42_component);
|
||||
links[id].platforms = platform_component;
|
||||
links[id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[id].init = sof_cs42l42_init;
|
||||
links[id].exit = sof_cs42l42_exit;
|
||||
links[id].ops = &sof_cs42l42_ops;
|
||||
links[id].dpcm_playback = 1;
|
||||
links[id].dpcm_capture = 1;
|
||||
links[id].no_pcm = 1;
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].num_cpus = 1;
|
||||
links[*id].id = *id;
|
||||
links[*id].codecs = cs42l42_component;
|
||||
links[*id].num_codecs = ARRAY_SIZE(cs42l42_component);
|
||||
links[*id].platforms = platform_component;
|
||||
links[*id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[*id].init = sof_cs42l42_init;
|
||||
links[*id].exit = sof_cs42l42_exit;
|
||||
links[*id].ops = &sof_cs42l42_ops;
|
||||
links[*id].dpcm_playback = 1;
|
||||
links[*id].dpcm_capture = 1;
|
||||
links[*id].no_pcm = 1;
|
||||
links[*id].cpus = &cpus[*id];
|
||||
links[*id].num_cpus = 1;
|
||||
|
||||
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d Pin",
|
||||
ssp_codec);
|
||||
if (!links[id].cpus->dai_name)
|
||||
links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"SSP%d Pin",
|
||||
ssp_codec);
|
||||
if (!links[*id].cpus->dai_name)
|
||||
goto devm_err;
|
||||
|
||||
id++;
|
||||
(*id)++;
|
||||
|
||||
return 0;
|
||||
|
||||
devm_err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int create_dmic_dai_links(struct device *dev,
|
||||
struct snd_soc_dai_link *links,
|
||||
struct snd_soc_dai_link_component *cpus,
|
||||
int *id, int dmic_be_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* dmic */
|
||||
if (dmic_be_num > 0) {
|
||||
/* at least we have dmic01 */
|
||||
links[id].name = "dmic01";
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].cpus->dai_name = "DMIC01 Pin";
|
||||
links[id].init = dmic_init;
|
||||
if (dmic_be_num > 1) {
|
||||
/* set up 2 BE links at most */
|
||||
links[id + 1].name = "dmic16k";
|
||||
links[id + 1].cpus = &cpus[id + 1];
|
||||
links[id + 1].cpus->dai_name = "DMIC16k Pin";
|
||||
dmic_be_num = 2;
|
||||
}
|
||||
if (dmic_be_num <= 0)
|
||||
return 0;
|
||||
|
||||
/* at least we have dmic01 */
|
||||
links[*id].name = "dmic01";
|
||||
links[*id].cpus = &cpus[*id];
|
||||
links[*id].cpus->dai_name = "DMIC01 Pin";
|
||||
links[*id].init = dmic_init;
|
||||
if (dmic_be_num > 1) {
|
||||
/* set up 2 BE links at most */
|
||||
links[*id + 1].name = "dmic16k";
|
||||
links[*id + 1].cpus = &cpus[*id + 1];
|
||||
links[*id + 1].cpus->dai_name = "DMIC16k Pin";
|
||||
dmic_be_num = 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < dmic_be_num; i++) {
|
||||
links[id].id = id;
|
||||
links[id].num_cpus = 1;
|
||||
links[id].codecs = dmic_component;
|
||||
links[id].num_codecs = ARRAY_SIZE(dmic_component);
|
||||
links[id].platforms = platform_component;
|
||||
links[id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[id].ignore_suspend = 1;
|
||||
links[id].dpcm_capture = 1;
|
||||
links[id].no_pcm = 1;
|
||||
id++;
|
||||
links[*id].id = *id;
|
||||
links[*id].num_cpus = 1;
|
||||
links[*id].codecs = dmic_component;
|
||||
links[*id].num_codecs = ARRAY_SIZE(dmic_component);
|
||||
links[*id].platforms = platform_component;
|
||||
links[*id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[*id].ignore_suspend = 1;
|
||||
links[*id].dpcm_capture = 1;
|
||||
links[*id].no_pcm = 1;
|
||||
|
||||
(*id)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_hdmi_dai_links(struct device *dev,
|
||||
struct snd_soc_dai_link *links,
|
||||
struct snd_soc_dai_link_component *cpus,
|
||||
int *id, int hdmi_num)
|
||||
{
|
||||
struct snd_soc_dai_link_component *idisp_components;
|
||||
int i;
|
||||
|
||||
/* HDMI */
|
||||
if (hdmi_num > 0) {
|
||||
idisp_components = devm_kzalloc(dev,
|
||||
sizeof(struct snd_soc_dai_link_component) *
|
||||
hdmi_num, GFP_KERNEL);
|
||||
if (!idisp_components)
|
||||
goto devm_err;
|
||||
}
|
||||
if (hdmi_num <= 0)
|
||||
return 0;
|
||||
|
||||
idisp_components = devm_kzalloc(dev,
|
||||
sizeof(struct snd_soc_dai_link_component) *
|
||||
hdmi_num, GFP_KERNEL);
|
||||
if (!idisp_components)
|
||||
goto devm_err;
|
||||
|
||||
for (i = 1; i <= hdmi_num; i++) {
|
||||
links[id].name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"iDisp%d", i);
|
||||
if (!links[id].name)
|
||||
links[*id].name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"iDisp%d", i);
|
||||
if (!links[*id].name)
|
||||
goto devm_err;
|
||||
|
||||
links[id].id = id;
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].num_cpus = 1;
|
||||
links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
|
||||
"iDisp%d Pin", i);
|
||||
if (!links[id].cpus->dai_name)
|
||||
links[*id].id = *id;
|
||||
links[*id].cpus = &cpus[*id];
|
||||
links[*id].num_cpus = 1;
|
||||
links[*id].cpus->dai_name = devm_kasprintf(dev,
|
||||
GFP_KERNEL,
|
||||
"iDisp%d Pin",
|
||||
i);
|
||||
if (!links[*id].cpus->dai_name)
|
||||
goto devm_err;
|
||||
|
||||
idisp_components[i - 1].name = "ehdaudio0D2";
|
||||
|
@ -396,14 +450,86 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
|||
if (!idisp_components[i - 1].dai_name)
|
||||
goto devm_err;
|
||||
|
||||
links[id].codecs = &idisp_components[i - 1];
|
||||
links[id].num_codecs = 1;
|
||||
links[id].platforms = platform_component;
|
||||
links[id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[id].init = sof_hdmi_init;
|
||||
links[id].dpcm_playback = 1;
|
||||
links[id].no_pcm = 1;
|
||||
id++;
|
||||
links[*id].codecs = &idisp_components[i - 1];
|
||||
links[*id].num_codecs = 1;
|
||||
links[*id].platforms = platform_component;
|
||||
links[*id].num_platforms = ARRAY_SIZE(platform_component);
|
||||
links[*id].init = sof_hdmi_init;
|
||||
links[*id].dpcm_playback = 1;
|
||||
links[*id].no_pcm = 1;
|
||||
|
||||
(*id)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
devm_err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
||||
int ssp_codec,
|
||||
int ssp_amp,
|
||||
int dmic_be_num,
|
||||
int hdmi_num)
|
||||
{
|
||||
struct snd_soc_dai_link_component *cpus;
|
||||
struct snd_soc_dai_link *links;
|
||||
int ret, id = 0, link_seq;
|
||||
|
||||
links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
|
||||
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
|
||||
cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
|
||||
sof_audio_card_cs42l42.num_links, GFP_KERNEL);
|
||||
if (!links || !cpus)
|
||||
goto devm_err;
|
||||
|
||||
link_seq = (sof_cs42l42_quirk & SOF_CS42L42_DAILINK_MASK) >> SOF_CS42L42_DAILINK_SHIFT;
|
||||
|
||||
while (link_seq) {
|
||||
int link_type = link_seq & 0x07;
|
||||
|
||||
switch (link_type) {
|
||||
case LINK_HP:
|
||||
ret = create_hp_codec_dai_links(dev, links, cpus, &id, ssp_codec);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "fail to create hp codec dai links, ret %d\n",
|
||||
ret);
|
||||
goto devm_err;
|
||||
}
|
||||
break;
|
||||
case LINK_SPK:
|
||||
ret = create_spk_amp_dai_links(dev, links, cpus, &id, ssp_amp);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "fail to create spk amp dai links, ret %d\n",
|
||||
ret);
|
||||
goto devm_err;
|
||||
}
|
||||
break;
|
||||
case LINK_DMIC:
|
||||
ret = create_dmic_dai_links(dev, links, cpus, &id, dmic_be_num);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "fail to create dmic dai links, ret %d\n",
|
||||
ret);
|
||||
goto devm_err;
|
||||
}
|
||||
break;
|
||||
case LINK_HDMI:
|
||||
ret = create_hdmi_dai_links(dev, links, cpus, &id, hdmi_num);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "fail to create hdmi dai links, ret %d\n",
|
||||
ret);
|
||||
goto devm_err;
|
||||
}
|
||||
break;
|
||||
case LINK_NONE:
|
||||
/* caught here if it's not used as terminator in macro */
|
||||
default:
|
||||
dev_err(dev, "invalid link type %d\n", link_type);
|
||||
goto devm_err;
|
||||
}
|
||||
|
||||
link_seq >>= 3;
|
||||
}
|
||||
|
||||
return links;
|
||||
|
@ -484,7 +610,16 @@ static const struct platform_device_id board_ids[] = {
|
|||
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_MAX98357A_SPEAKER_AMP_PRESENT |
|
||||
SOF_CS42L42_SSP_AMP(1)),
|
||||
SOF_CS42L42_SSP_AMP(1)) |
|
||||
SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE),
|
||||
},
|
||||
{
|
||||
.name = "jsl_cs4242_mx98360a",
|
||||
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_MAX98360A_SPEAKER_AMP_PRESENT |
|
||||
SOF_CS42L42_SSP_AMP(1)) |
|
||||
SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_NONE),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -134,7 +134,7 @@ void max_98373_set_codec_conf(struct snd_soc_card *card)
|
|||
EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
|
||||
|
||||
/*
|
||||
* Maxim MAX98357A
|
||||
* Maxim MAX98357A/MAX98360A
|
||||
*/
|
||||
static const struct snd_kcontrol_new max_98357a_kcontrols[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Spk"),
|
||||
|
@ -156,6 +156,13 @@ static struct snd_soc_dai_link_component max_98357a_components[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component max_98360a_components[] = {
|
||||
{
|
||||
.name = MAX_98360A_DEV0_NAME,
|
||||
.dai_name = MAX_98357A_CODEC_DAI,
|
||||
}
|
||||
};
|
||||
|
||||
static int max_98357a_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
|
@ -193,5 +200,13 @@ void max_98357a_dai_link(struct snd_soc_dai_link *link)
|
|||
}
|
||||
EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
|
||||
|
||||
void max_98360a_dai_link(struct snd_soc_dai_link *link)
|
||||
{
|
||||
link->codecs = max_98360a_components;
|
||||
link->num_codecs = ARRAY_SIZE(max_98360a_components);
|
||||
link->init = max_98357a_init;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -25,11 +25,13 @@ void max_98373_set_codec_conf(struct snd_soc_card *card);
|
|||
int max_98373_trigger(struct snd_pcm_substream *substream, int cmd);
|
||||
|
||||
/*
|
||||
* Maxim MAX98357A
|
||||
* Maxim MAX98357A/MAX98360A
|
||||
*/
|
||||
#define MAX_98357A_CODEC_DAI "HiFi"
|
||||
#define MAX_98357A_DEV0_NAME "MX98357A:00"
|
||||
#define MAX_98360A_DEV0_NAME "MX98360A:00"
|
||||
|
||||
void max_98357a_dai_link(struct snd_soc_dai_link *link);
|
||||
void max_98360a_dai_link(struct snd_soc_dai_link *link);
|
||||
|
||||
#endif /* __SOF_MAXIM_COMMON_H */
|
||||
|
|
|
@ -26,11 +26,16 @@
|
|||
|
||||
#define SOF_PCM512X_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0))
|
||||
#define SOF_PCM512X_SSP_CODEC_MASK (GENMASK(3, 0))
|
||||
#define SOF_PCM512X_ENABLE_SSP_CAPTURE BIT(4)
|
||||
#define SOF_PCM512X_ENABLE_DMIC BIT(5)
|
||||
|
||||
#define IDISP_CODEC_MASK 0x4
|
||||
|
||||
/* Default: SSP5 */
|
||||
static unsigned long sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(5);
|
||||
static unsigned long sof_pcm512x_quirk =
|
||||
SOF_PCM512X_SSP_CODEC(5) |
|
||||
SOF_PCM512X_ENABLE_SSP_CAPTURE |
|
||||
SOF_PCM512X_ENABLE_DMIC;
|
||||
|
||||
static bool is_legacy_cpu;
|
||||
|
||||
|
@ -244,8 +249,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
|||
links[id].dpcm_playback = 1;
|
||||
/*
|
||||
* capture only supported with specific versions of the Hifiberry DAC+
|
||||
* links[id].dpcm_capture = 1;
|
||||
*/
|
||||
if (sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE)
|
||||
links[id].dpcm_capture = 1;
|
||||
links[id].no_pcm = 1;
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].num_cpus = 1;
|
||||
|
@ -380,6 +386,9 @@ static int sof_audio_probe(struct platform_device *pdev)
|
|||
|
||||
ssp_codec = sof_pcm512x_quirk & SOF_PCM512X_SSP_CODEC_MASK;
|
||||
|
||||
if (!(sof_pcm512x_quirk & SOF_PCM512X_ENABLE_DMIC))
|
||||
dmic_be_num = 0;
|
||||
|
||||
/* compute number of dai links */
|
||||
sof_audio_card_pcm512x.num_links = 1 + dmic_be_num + hdmi_num;
|
||||
|
||||
|
|
|
@ -162,6 +162,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
|
|||
SOF_RT5682_SSP_AMP(2) |
|
||||
SOF_RT5682_NUM_HDMIDEV(4)),
|
||||
},
|
||||
{
|
||||
.callback = sof_rt5682_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
|
||||
DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
|
||||
SOF_RT5682_SSP_CODEC(0) |
|
||||
SOF_SPEAKER_AMP_PRESENT |
|
||||
SOF_MAX98373_SPEAKER_AMP_PRESENT |
|
||||
SOF_RT5682_SSP_AMP(2) |
|
||||
SOF_RT5682_NUM_HDMIDEV(4)),
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -456,10 +470,6 @@ static const struct snd_kcontrol_new sof_controls[] = {
|
|||
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new speaker_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Spk"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget sof_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
|
@ -467,10 +477,6 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
|
|||
SND_SOC_DAPM_SPK("Right Spk", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget speaker_widgets[] = {
|
||||
SND_SOC_DAPM_SPK("Spk", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget dmic_widgets[] = {
|
||||
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
|
||||
};
|
||||
|
@ -484,11 +490,6 @@ static const struct snd_soc_dapm_route sof_map[] = {
|
|||
{ "IN1P", NULL, "Headset Mic" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route speaker_map[] = {
|
||||
/* speaker */
|
||||
{ "Spk", NULL, "Speaker" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route speaker_map_lr[] = {
|
||||
{ "Left Spk", NULL, "Left SPO" },
|
||||
{ "Right Spk", NULL, "Right SPO" },
|
||||
|
@ -505,34 +506,6 @@ static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
|
|||
ARRAY_SIZE(speaker_map_lr));
|
||||
}
|
||||
|
||||
static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets,
|
||||
ARRAY_SIZE(speaker_widgets));
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
|
||||
/* Don't need to add routes if widget addition failed */
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_add_card_controls(card, speaker_controls,
|
||||
ARRAY_SIZE(speaker_controls));
|
||||
if (ret) {
|
||||
dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
|
||||
ARRAY_SIZE(speaker_map));
|
||||
|
||||
if (ret)
|
||||
dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dmic_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
|
@ -594,13 +567,6 @@ static struct snd_soc_dai_link_component dmic_component[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component max98360a_component[] = {
|
||||
{
|
||||
.name = "MX98360A:00",
|
||||
.dai_name = "HiFi",
|
||||
}
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component rt1015_components[] = {
|
||||
{
|
||||
.name = "i2c-10EC1015:00",
|
||||
|
@ -775,9 +741,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
|||
links[id].dpcm_capture = 1;
|
||||
} else if (sof_rt5682_quirk &
|
||||
SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
|
||||
links[id].codecs = max98360a_component;
|
||||
links[id].num_codecs = ARRAY_SIZE(max98360a_component);
|
||||
links[id].init = speaker_codec_init;
|
||||
max_98360a_dai_link(&links[id]);
|
||||
} else if (sof_rt5682_quirk &
|
||||
SOF_RT1011_SPEAKER_AMP_PRESENT) {
|
||||
sof_rt1011_dai_link(&links[id]);
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
#include <sound/soc.h>
|
||||
#include <sound/soc-acpi.h>
|
||||
#include "sof_sdw_common.h"
|
||||
#include "../../codecs/rt711.h"
|
||||
|
||||
unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1;
|
||||
unsigned long sof_sdw_quirk = RT711_JD1;
|
||||
static int quirk_override = -1;
|
||||
module_param_named(quirk, quirk_override, int, 0444);
|
||||
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
|
||||
|
@ -63,7 +64,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
|
||||
.driver_data = (void *)(RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX),
|
||||
},
|
||||
{
|
||||
|
@ -73,7 +74,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
|
||||
.driver_data = (void *)(RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX),
|
||||
},
|
||||
{
|
||||
|
@ -82,7 +83,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
|
||||
.driver_data = (void *)(RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
|
@ -92,7 +93,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
|
||||
.driver_data = (void *)(RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
|
@ -114,7 +115,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
"Tiger Lake Client Platform"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD1 |
|
||||
RT711_JD1 |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
SOF_SSP_PORT(SOF_I2S_SSP2)),
|
||||
},
|
||||
|
@ -125,9 +126,21 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX),
|
||||
},
|
||||
{
|
||||
/* Dell XPS 9710 */
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
|
@ -135,7 +148,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
|
@ -175,7 +188,18 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
SOF_RT711_JD_SRC_JD2),
|
||||
RT711_JD2),
|
||||
},
|
||||
{
|
||||
/* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
RT711_JD1),
|
||||
},
|
||||
/* TigerLake-SDCA devices */
|
||||
{
|
||||
|
@ -185,7 +209,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
RT711_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
|
@ -196,7 +220,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
|
||||
.driver_data = (void *)(RT711_JD2_100K |
|
||||
SOF_SDW_TGL_HDMI |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_BT_OFFLOAD_SSP(2) |
|
||||
|
@ -328,6 +352,20 @@ static const struct snd_soc_ops sdw_ops = {
|
|||
.shutdown = sdw_shutdown,
|
||||
};
|
||||
|
||||
static int sof_sdw_mic_codec_mockup_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
/*
|
||||
* force DAI link to use same ID as RT715 and DMIC
|
||||
* to reuse topologies
|
||||
*/
|
||||
dai_links->id = SDW_DMIC_DAI_ID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sof_sdw_codec_info codec_info_list[] = {
|
||||
{
|
||||
.part_id = 0x700,
|
||||
|
@ -410,6 +448,34 @@ static struct sof_sdw_codec_info codec_info_list[] = {
|
|||
.dai_name = "rt5682-sdw",
|
||||
.init = sof_sdw_rt5682_init,
|
||||
},
|
||||
{
|
||||
.part_id = 0xaaaa, /* generic codec mockup */
|
||||
.version_id = 0,
|
||||
.direction = {true, true},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.init = NULL,
|
||||
},
|
||||
{
|
||||
.part_id = 0xaa55, /* headset codec mockup */
|
||||
.version_id = 0,
|
||||
.direction = {true, true},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.init = NULL,
|
||||
},
|
||||
{
|
||||
.part_id = 0x55aa, /* amplifier mockup */
|
||||
.version_id = 0,
|
||||
.direction = {true, false},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.init = NULL,
|
||||
},
|
||||
{
|
||||
.part_id = 0x5555,
|
||||
.version_id = 0,
|
||||
.direction = {false, true},
|
||||
.dai_name = "sdw-mockup-aif1",
|
||||
.init = sof_sdw_mic_codec_mockup_init,
|
||||
},
|
||||
};
|
||||
|
||||
static inline int find_codec_info_part(u64 adr)
|
||||
|
@ -632,7 +698,8 @@ static int create_codec_dai_name(struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
|
||||
static int set_codec_init_func(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
bool playback, int group_id)
|
||||
{
|
||||
|
@ -655,7 +722,8 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
|
|||
if (link->adr_d[i].endpoints->group_id != group_id)
|
||||
continue;
|
||||
if (codec_info_list[codec_index].init)
|
||||
codec_info_list[codec_index].init(link,
|
||||
codec_info_list[codec_index].init(card,
|
||||
link,
|
||||
dai_links,
|
||||
&codec_info_list[codec_index],
|
||||
playback);
|
||||
|
@ -740,7 +808,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int create_sdw_dailink(struct device *dev, int *be_index,
|
||||
static int create_sdw_dailink(struct snd_soc_card *card,
|
||||
struct device *dev, int *be_index,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
int sdw_be_num, int sdw_cpu_dai_num,
|
||||
struct snd_soc_dai_link_component *cpus,
|
||||
|
@ -861,7 +930,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
|
|||
codecs, codec_num,
|
||||
NULL, &sdw_ops);
|
||||
|
||||
ret = set_codec_init_func(link, dai_links + (*be_index)++,
|
||||
ret = set_codec_init_func(card, link, dai_links + (*be_index)++,
|
||||
playback, group_id);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to init codec %d", codec_index);
|
||||
|
@ -1042,7 +1111,7 @@ static int sof_card_dai_links_create(struct device *dev,
|
|||
group_generated[endpoint->group_id])
|
||||
continue;
|
||||
|
||||
ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
|
||||
ret = create_sdw_dailink(card, dev, &be_id, links, sdw_be_num,
|
||||
sdw_cpu_dai_num, cpus, adr_link,
|
||||
&cpu_id, group_generated,
|
||||
codec_conf, codec_conf_count,
|
||||
|
@ -1105,7 +1174,7 @@ SSP:
|
|||
ssp_components, 1,
|
||||
NULL, info->ops);
|
||||
|
||||
ret = info->init(NULL, links + link_id, info, 0);
|
||||
ret = info->init(card, NULL, links + link_id, info, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1328,7 +1397,7 @@ static int mc_remove(struct platform_device *pdev)
|
|||
for_each_card_prelinks(card, j, link) {
|
||||
if (!strcmp(link->codecs[0].dai_name,
|
||||
codec_info_list[i].dai_name)) {
|
||||
ret = codec_info_list[i].exit(&pdev->dev, link);
|
||||
ret = codec_info_list[i].exit(card, link);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev,
|
||||
"codec exit failed %d\n",
|
||||
|
|
|
@ -22,11 +22,6 @@
|
|||
/* 8 combinations with 4 links + unused group 0 */
|
||||
#define SDW_MAX_GROUPS 9
|
||||
|
||||
enum {
|
||||
SOF_RT711_JD_SRC_JD1 = 1,
|
||||
SOF_RT711_JD_SRC_JD2 = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
SOF_PRE_TGL_HDMI_COUNT = 3,
|
||||
SOF_TGL_HDMI_COUNT = 4,
|
||||
|
@ -41,21 +36,21 @@ enum {
|
|||
SOF_I2S_SSP5 = BIT(5),
|
||||
};
|
||||
|
||||
#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(1, 0))
|
||||
#define SOF_SDW_FOUR_SPK BIT(2)
|
||||
#define SOF_SDW_TGL_HDMI BIT(3)
|
||||
#define SOF_SDW_PCH_DMIC BIT(4)
|
||||
#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 5)
|
||||
#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 5) & GENMASK(5, 0))
|
||||
#define SOF_RT715_DAI_ID_FIX BIT(11)
|
||||
#define SOF_SDW_NO_AGGREGATION BIT(12)
|
||||
#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
|
||||
#define SOF_SDW_FOUR_SPK BIT(4)
|
||||
#define SOF_SDW_TGL_HDMI BIT(5)
|
||||
#define SOF_SDW_PCH_DMIC BIT(6)
|
||||
#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7)
|
||||
#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0))
|
||||
#define SOF_RT715_DAI_ID_FIX BIT(13)
|
||||
#define SOF_SDW_NO_AGGREGATION BIT(14)
|
||||
|
||||
/* BT audio offload: reserve 3 bits for future */
|
||||
#define SOF_BT_OFFLOAD_SSP_SHIFT 13
|
||||
#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(15, 13))
|
||||
#define SOF_BT_OFFLOAD_SSP_SHIFT 15
|
||||
#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(17, 15))
|
||||
#define SOF_BT_OFFLOAD_SSP(quirk) \
|
||||
(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
|
||||
#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(16)
|
||||
#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(18)
|
||||
|
||||
struct sof_sdw_codec_info {
|
||||
const int part_id;
|
||||
|
@ -67,12 +62,13 @@ struct sof_sdw_codec_info {
|
|||
const char *dai_name;
|
||||
const struct snd_soc_ops *ops;
|
||||
|
||||
int (*init)(const struct snd_soc_acpi_link_adr *link,
|
||||
int (*init)(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
int (*exit)(struct device *dev, struct snd_soc_dai_link *dai_link);
|
||||
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
bool late_probe;
|
||||
int (*codec_card_late_probe)(struct snd_soc_card *card);
|
||||
};
|
||||
|
@ -81,6 +77,7 @@ struct mc_private {
|
|||
struct list_head hdmi_pcm_list;
|
||||
bool idisp_codec;
|
||||
struct snd_soc_jack sdw_headset;
|
||||
struct device *headset_codec_dev; /* only one headset per card */
|
||||
};
|
||||
|
||||
extern unsigned long sof_sdw_quirk;
|
||||
|
@ -100,21 +97,24 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card);
|
|||
int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
/* RT711 support */
|
||||
int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt711_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link);
|
||||
int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* RT711-SDCA support */
|
||||
int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link);
|
||||
int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
|
||||
|
||||
/* RT700 support */
|
||||
int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt700_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
@ -122,31 +122,36 @@ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
|
|||
/* RT1308 support */
|
||||
extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
|
||||
|
||||
int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt1308_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* RT1316 support */
|
||||
int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt1316_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* RT715 support */
|
||||
int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt715_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* RT715-SDCA support */
|
||||
int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
||||
/* MAX98373 support */
|
||||
int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_mx8373_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
@ -154,7 +159,8 @@ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
|
|||
int sof_sdw_mx8373_late_probe(struct snd_soc_card *card);
|
||||
|
||||
/* RT5682 support */
|
||||
int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt5682_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback);
|
||||
|
|
|
@ -90,7 +90,7 @@ static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enabl
|
|||
|
||||
static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
/* according to soc_pcm_prepare dai link prepare is called first */
|
||||
ret = sdw_prepare(substream);
|
||||
|
@ -102,7 +102,7 @@ static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
|
|||
|
||||
static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
/* according to soc_pcm_hw_free dai link free is called first */
|
||||
ret = sdw_hw_free(substream);
|
||||
|
@ -120,7 +120,8 @@ static const struct snd_soc_ops max_98373_sdw_ops = {
|
|||
.shutdown = sdw_shutdown,
|
||||
};
|
||||
|
||||
int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_mx8373_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -127,7 +127,8 @@ struct snd_soc_ops sof_sdw_rt1308_i2s_ops = {
|
|||
.hw_params = rt1308_i2s_hw_params,
|
||||
};
|
||||
|
||||
int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt1308_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -89,7 +89,8 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return second_spk_init(rtd);
|
||||
}
|
||||
|
||||
int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt1316_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -111,7 +111,8 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt5682_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -110,7 +110,8 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt700_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -21,23 +21,23 @@
|
|||
* Note this MUST be called before snd_soc_register_card(), so that the props
|
||||
* are in place before the codec component driver's probe function parses them.
|
||||
*/
|
||||
static int rt711_add_codec_device_props(const char *sdw_dev_name)
|
||||
static int rt711_add_codec_device_props(struct device *sdw_dev)
|
||||
{
|
||||
struct property_entry props[MAX_NO_PROPS] = {};
|
||||
struct device *sdw_dev;
|
||||
struct fwnode_handle *fwnode;
|
||||
int ret;
|
||||
|
||||
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name);
|
||||
if (!sdw_dev)
|
||||
return -EPROBE_DEFER;
|
||||
if (!SOF_RT711_JDSRC(sof_sdw_quirk))
|
||||
return 0;
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
|
||||
|
||||
if (SOF_RT711_JDSRC(sof_sdw_quirk)) {
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
|
||||
SOF_RT711_JDSRC(sof_sdw_quirk));
|
||||
}
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode))
|
||||
return PTR_ERR(fwnode);
|
||||
|
||||
ret = device_add_properties(sdw_dev, props);
|
||||
put_device(sdw_dev);
|
||||
ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
|
||||
|
||||
fwnode_handle_put(fwnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -135,26 +135,24 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link)
|
||||
int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
{
|
||||
struct device *sdw_dev;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
|
||||
dai_link->codecs[0].name);
|
||||
if (!sdw_dev)
|
||||
return -EINVAL;
|
||||
|
||||
device_remove_properties(sdw_dev);
|
||||
put_device(sdw_dev);
|
||||
device_remove_software_node(ctx->headset_codec_dev);
|
||||
put_device(ctx->headset_codec_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt711_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct device *sdw_dev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -164,9 +162,16 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link,
|
|||
if (!playback)
|
||||
return 0;
|
||||
|
||||
ret = rt711_add_codec_device_props(dai_links->codecs[0].name);
|
||||
if (ret < 0)
|
||||
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
|
||||
if (!sdw_dev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ret = rt711_add_codec_device_props(sdw_dev);
|
||||
if (ret < 0) {
|
||||
put_device(sdw_dev);
|
||||
return ret;
|
||||
}
|
||||
ctx->headset_codec_dev = sdw_dev;
|
||||
|
||||
dai_links->init = rt711_rtd_init;
|
||||
|
||||
|
|
|
@ -21,23 +21,24 @@
|
|||
* Note this MUST be called before snd_soc_register_card(), so that the props
|
||||
* are in place before the codec component driver's probe function parses them.
|
||||
*/
|
||||
static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name)
|
||||
static int rt711_sdca_add_codec_device_props(struct device *sdw_dev)
|
||||
{
|
||||
struct property_entry props[MAX_NO_PROPS] = {};
|
||||
struct device *sdw_dev;
|
||||
struct fwnode_handle *fwnode;
|
||||
int ret;
|
||||
|
||||
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name);
|
||||
if (!sdw_dev)
|
||||
return -EPROBE_DEFER;
|
||||
if (!SOF_RT711_JDSRC(sof_sdw_quirk))
|
||||
return 0;
|
||||
|
||||
if (SOF_RT711_JDSRC(sof_sdw_quirk)) {
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
|
||||
SOF_RT711_JDSRC(sof_sdw_quirk));
|
||||
}
|
||||
props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
|
||||
|
||||
ret = device_add_properties(sdw_dev, props);
|
||||
put_device(sdw_dev);
|
||||
fwnode = fwnode_create_software_node(props, NULL);
|
||||
if (IS_ERR(fwnode))
|
||||
return PTR_ERR(fwnode);
|
||||
|
||||
ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
|
||||
|
||||
fwnode_handle_put(fwnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -135,26 +136,24 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link)
|
||||
int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
|
||||
{
|
||||
struct device *sdw_dev;
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
|
||||
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
|
||||
dai_link->codecs[0].name);
|
||||
if (!sdw_dev)
|
||||
return -EINVAL;
|
||||
|
||||
device_remove_properties(sdw_dev);
|
||||
put_device(sdw_dev);
|
||||
device_remove_software_node(ctx->headset_codec_dev);
|
||||
put_device(ctx->headset_codec_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt711_sdca_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
{
|
||||
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
|
||||
struct device *sdw_dev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -164,9 +163,16 @@ int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link,
|
|||
if (!playback)
|
||||
return 0;
|
||||
|
||||
ret = rt711_sdca_add_codec_device_props(dai_links->codecs[0].name);
|
||||
if (ret < 0)
|
||||
sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
|
||||
if (!sdw_dev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ret = rt711_sdca_add_codec_device_props(sdw_dev);
|
||||
if (ret < 0) {
|
||||
put_device(sdw_dev);
|
||||
return ret;
|
||||
}
|
||||
ctx->headset_codec_dev = sdw_dev;
|
||||
|
||||
dai_links->init = rt711_sdca_rtd_init;
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt715_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -24,7 +24,8 @@ static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link,
|
||||
int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
|
||||
const struct snd_soc_acpi_link_adr *link,
|
||||
struct snd_soc_dai_link *dai_links,
|
||||
struct sof_sdw_codec_info *info,
|
||||
bool playback)
|
||||
|
|
|
@ -9,7 +9,8 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m
|
|||
soc-acpi-intel-cml-match.o soc-acpi-intel-icl-match.o \
|
||||
soc-acpi-intel-tgl-match.o soc-acpi-intel-ehl-match.o \
|
||||
soc-acpi-intel-jsl-match.o soc-acpi-intel-adl-match.o \
|
||||
soc-acpi-intel-hda-match.o
|
||||
soc-acpi-intel-hda-match.o \
|
||||
soc-acpi-intel-sdw-mockup-match.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
|
||||
obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-acpi-intel-match.h>
|
||||
#include "../skylake/skl.h"
|
||||
#include "soc-acpi-intel-sdw-mockup-match.h"
|
||||
|
||||
static struct skl_machine_pdata cnl_pdata = {
|
||||
.use_tplg_pcm = true,
|
||||
|
@ -60,6 +61,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = {
|
|||
.sof_fw_filename = "sof-cnl.ri",
|
||||
.sof_tplg_filename = "sof-cnl-rt5682-sdw2.tplg"
|
||||
},
|
||||
{
|
||||
.link_mask = GENMASK(3, 0),
|
||||
.links = sdw_mockup_headset_2amps_mic,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_fw_filename = "sof-cnl.ri",
|
||||
.sof_tplg_filename = "sof-cml-rt711-rt1308-rt715.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = BIT(0) | BIT(1) | BIT(3),
|
||||
.links = sdw_mockup_headset_1amp_mic,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_fw_filename = "sof-cnl.ri",
|
||||
.sof_tplg_filename = "sof-cml-rt711-rt1308-mono-rt715.tplg",
|
||||
},
|
||||
{}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines);
|
||||
|
|
|
@ -73,6 +73,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
|
|||
.quirk_data = &mx98360a_spk,
|
||||
.sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg",
|
||||
},
|
||||
{
|
||||
.id = "10134242",
|
||||
.drv_name = "jsl_cs4242_mx98360a",
|
||||
.sof_fw_filename = "sof-jsl.ri",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &mx98360a_spk,
|
||||
.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// soc-acpi-intel-sdw-mockup-match.c - tables and support for SoundWire
|
||||
// mockup device ACPI enumeration.
|
||||
//
|
||||
// Copyright (c) 2021, Intel Corporation.
|
||||
//
|
||||
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-acpi-intel-match.h>
|
||||
#include "soc-acpi-intel-sdw-mockup-match.h"
|
||||
|
||||
static const struct snd_soc_acpi_endpoint sdw_mockup_single_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 0,
|
||||
.group_position = 0,
|
||||
.group_id = 0,
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_endpoint sdw_mockup_l_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 1,
|
||||
.group_position = 0,
|
||||
.group_id = 1,
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_endpoint sdw_mockup_r_endpoint = {
|
||||
.num = 0,
|
||||
.aggregated = 1,
|
||||
.group_position = 1,
|
||||
.group_id = 1,
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_headset_0_adr[] = {
|
||||
{
|
||||
.adr = 0x0000000105AA5500ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_single_endpoint,
|
||||
.name_prefix = "sdw_mockup_headset0"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_headset_1_adr[] = {
|
||||
{
|
||||
.adr = 0x0001000105AA5500ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_single_endpoint,
|
||||
.name_prefix = "sdw_mockup_headset1"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_adr[] = {
|
||||
{
|
||||
.adr = 0x000100010555AA00ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_single_endpoint,
|
||||
.name_prefix = "sdw_mockup_amp1"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_adr[] = {
|
||||
{
|
||||
.adr = 0x000200010555AA00ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_single_endpoint,
|
||||
.name_prefix = "sdw_mockup_amp2"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_mic_0_adr[] = {
|
||||
{
|
||||
.adr = 0x0000000105555500ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_single_endpoint,
|
||||
.name_prefix = "sdw_mockup_mic0"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_mic_3_adr[] = {
|
||||
{
|
||||
.adr = 0x0003000105555500ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_single_endpoint,
|
||||
.name_prefix = "sdw_mockup_mic3"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000100010555AA00ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_l_endpoint,
|
||||
.name_prefix = "sdw_mockup_amp1_l"
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000200010555AA00ull,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &sdw_mockup_r_endpoint,
|
||||
.name_prefix = "sdw_mockup_amp2_r"
|
||||
}
|
||||
};
|
||||
|
||||
const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr),
|
||||
.adr_d = sdw_mockup_headset_0_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_amp_1_adr),
|
||||
.adr_d = sdw_mockup_amp_1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(3),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr),
|
||||
.adr_d = sdw_mockup_mic_3_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr),
|
||||
.adr_d = sdw_mockup_headset_0_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_amp_1_group1_adr),
|
||||
.adr_d = sdw_mockup_amp_1_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(2),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_amp_2_group1_adr),
|
||||
.adr_d = sdw_mockup_amp_2_group1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(3),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr),
|
||||
.adr_d = sdw_mockup_mic_3_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[] = {
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_headset_1_adr),
|
||||
.adr_d = sdw_mockup_headset_1_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(2),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_amp_2_adr),
|
||||
.adr_d = sdw_mockup_amp_2_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(sdw_mockup_mic_0_adr),
|
||||
.adr_d = sdw_mockup_mic_0_adr,
|
||||
},
|
||||
{}
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* soc-acpi-intel-sdw-mockup-match.h - tables and support for SoundWire
|
||||
* mockup device ACPI enumeration.
|
||||
*
|
||||
* Copyright (c) 2021, Intel Corporation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH
|
||||
#define _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH
|
||||
|
||||
extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[];
|
||||
extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[];
|
||||
extern const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[];
|
||||
|
||||
#endif
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <sound/soc-acpi.h>
|
||||
#include <sound/soc-acpi-intel-match.h>
|
||||
#include "soc-acpi-intel-sdw-mockup-match.h"
|
||||
|
||||
static const struct snd_soc_acpi_codecs tgl_codecs = {
|
||||
.num_codecs = 1,
|
||||
|
@ -196,6 +197,15 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr tgl_rvp_headset_only[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt711_0_adr),
|
||||
.adr_d = rt711_0_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr tgl_hp[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
|
@ -351,6 +361,28 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
|
|||
|
||||
/* this table is used when there is no I2S codec present */
|
||||
struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
|
||||
/* mockup tests need to be first */
|
||||
{
|
||||
.link_mask = GENMASK(3, 0),
|
||||
.links = sdw_mockup_headset_2amps_mic,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_fw_filename = "sof-tgl.ri",
|
||||
.sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = BIT(0) | BIT(1) | BIT(3),
|
||||
.links = sdw_mockup_headset_1amp_mic,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_fw_filename = "sof-tgl.ri",
|
||||
.sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = BIT(0) | BIT(1) | BIT(2),
|
||||
.links = sdw_mockup_mic_headset_1amp,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_fw_filename = "sof-tgl.ri",
|
||||
.sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x7,
|
||||
.links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0,
|
||||
|
@ -398,6 +430,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
|
|||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x1, /* rt711 on link 0 */
|
||||
.links = tgl_rvp_headset_only,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-tgl-rt711.tplg",
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines);
|
||||
|
|
|
@ -472,6 +472,75 @@ static void skl_set_base_module_format(struct skl_dev *skl,
|
|||
base_cfg->is_pages = res->is_pages;
|
||||
}
|
||||
|
||||
static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
|
||||
struct skl_module_fmt *format)
|
||||
{
|
||||
pin_fmt->number_of_channels = format->channels;
|
||||
pin_fmt->s_freq = format->s_freq;
|
||||
pin_fmt->bit_depth = format->bit_depth;
|
||||
pin_fmt->valid_bit_depth = format->valid_bit_depth;
|
||||
pin_fmt->ch_cfg = format->ch_cfg;
|
||||
pin_fmt->sample_type = format->sample_type;
|
||||
pin_fmt->channel_map = format->ch_map;
|
||||
pin_fmt->interleaving = format->interleaving_style;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any module configuration begins with a base module configuration but
|
||||
* can be followed by a generic extension containing audio format for all
|
||||
* module's pins that are in use.
|
||||
*/
|
||||
static void skl_set_base_ext_module_format(struct skl_dev *skl,
|
||||
struct skl_module_cfg *mconfig,
|
||||
struct skl_base_cfg_ext *base_cfg_ext)
|
||||
{
|
||||
struct skl_module *module = mconfig->module;
|
||||
struct skl_module_pin_resources *pin_res;
|
||||
struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
|
||||
struct skl_module_res *res = &module->resources[mconfig->res_idx];
|
||||
struct skl_module_fmt *format;
|
||||
struct skl_pin_format *pin_fmt;
|
||||
char *params;
|
||||
int i;
|
||||
|
||||
base_cfg_ext->nr_input_pins = res->nr_input_pins;
|
||||
base_cfg_ext->nr_output_pins = res->nr_output_pins;
|
||||
base_cfg_ext->priv_param_length =
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps_size;
|
||||
|
||||
for (i = 0; i < res->nr_input_pins; i++) {
|
||||
pin_res = &res->input[i];
|
||||
pin_fmt = &base_cfg_ext->pins_fmt[i];
|
||||
|
||||
pin_fmt->pin_idx = pin_res->pin_index;
|
||||
pin_fmt->buf_size = pin_res->buf_size;
|
||||
|
||||
format = &fmt->inputs[pin_res->pin_index].fmt;
|
||||
fill_pin_params(&pin_fmt->audio_fmt, format);
|
||||
}
|
||||
|
||||
for (i = 0; i < res->nr_output_pins; i++) {
|
||||
pin_res = &res->output[i];
|
||||
pin_fmt = &base_cfg_ext->pins_fmt[res->nr_input_pins + i];
|
||||
|
||||
pin_fmt->pin_idx = pin_res->pin_index;
|
||||
pin_fmt->buf_size = pin_res->buf_size;
|
||||
|
||||
format = &fmt->outputs[pin_res->pin_index].fmt;
|
||||
fill_pin_params(&pin_fmt->audio_fmt, format);
|
||||
}
|
||||
|
||||
if (!base_cfg_ext->priv_param_length)
|
||||
return;
|
||||
|
||||
params = (char *)base_cfg_ext + sizeof(struct skl_base_cfg_ext);
|
||||
params += (base_cfg_ext->nr_input_pins + base_cfg_ext->nr_output_pins) *
|
||||
sizeof(struct skl_pin_format);
|
||||
|
||||
memcpy(params, mconfig->formats_config[SKL_PARAM_INIT].caps,
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies copier capabilities into copier module and updates copier module
|
||||
* config size.
|
||||
|
@ -479,15 +548,15 @@ static void skl_set_base_module_format(struct skl_dev *skl,
|
|||
static void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
|
||||
struct skl_cpr_cfg *cpr_mconfig)
|
||||
{
|
||||
if (mconfig->formats_config.caps_size == 0)
|
||||
if (mconfig->formats_config[SKL_PARAM_INIT].caps_size == 0)
|
||||
return;
|
||||
|
||||
memcpy(cpr_mconfig->gtw_cfg.config_data,
|
||||
mconfig->formats_config.caps,
|
||||
mconfig->formats_config.caps_size);
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps,
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps_size);
|
||||
|
||||
cpr_mconfig->gtw_cfg.config_length =
|
||||
(mconfig->formats_config.caps_size) / 4;
|
||||
(mconfig->formats_config[SKL_PARAM_INIT].caps_size) / 4;
|
||||
}
|
||||
|
||||
#define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF
|
||||
|
@ -737,28 +806,6 @@ static void skl_set_copier_format(struct skl_dev *skl,
|
|||
skl_setup_cpr_gateway_cfg(skl, mconfig, cpr_mconfig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Algo module are DSP pre processing modules. Algo module take base module
|
||||
* configuration and params
|
||||
*/
|
||||
|
||||
static void skl_set_algo_format(struct skl_dev *skl,
|
||||
struct skl_module_cfg *mconfig,
|
||||
struct skl_algo_cfg *algo_mcfg)
|
||||
{
|
||||
struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg;
|
||||
|
||||
skl_set_base_module_format(skl, mconfig, base_cfg);
|
||||
|
||||
if (mconfig->formats_config.caps_size == 0)
|
||||
return;
|
||||
|
||||
memcpy(algo_mcfg->params,
|
||||
mconfig->formats_config.caps,
|
||||
mconfig->formats_config.caps_size);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Mic select module allows selecting one or many input channels, thus
|
||||
* acting as a demux.
|
||||
|
@ -781,12 +828,14 @@ static void skl_set_base_outfmt_format(struct skl_dev *skl,
|
|||
static u16 skl_get_module_param_size(struct skl_dev *skl,
|
||||
struct skl_module_cfg *mconfig)
|
||||
{
|
||||
struct skl_module_res *res;
|
||||
struct skl_module *module = mconfig->module;
|
||||
u16 param_size;
|
||||
|
||||
switch (mconfig->m_type) {
|
||||
case SKL_MODULE_TYPE_COPIER:
|
||||
param_size = sizeof(struct skl_cpr_cfg);
|
||||
param_size += mconfig->formats_config.caps_size;
|
||||
param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size;
|
||||
return param_size;
|
||||
|
||||
case SKL_MODULE_TYPE_SRCINT:
|
||||
|
@ -795,22 +844,24 @@ static u16 skl_get_module_param_size(struct skl_dev *skl,
|
|||
case SKL_MODULE_TYPE_UPDWMIX:
|
||||
return sizeof(struct skl_up_down_mixer_cfg);
|
||||
|
||||
case SKL_MODULE_TYPE_ALGO:
|
||||
param_size = sizeof(struct skl_base_cfg);
|
||||
param_size += mconfig->formats_config.caps_size;
|
||||
return param_size;
|
||||
|
||||
case SKL_MODULE_TYPE_BASE_OUTFMT:
|
||||
case SKL_MODULE_TYPE_MIC_SELECT:
|
||||
case SKL_MODULE_TYPE_KPB:
|
||||
return sizeof(struct skl_base_outfmt_cfg);
|
||||
|
||||
default:
|
||||
/*
|
||||
* return only base cfg when no specific module type is
|
||||
* specified
|
||||
*/
|
||||
case SKL_MODULE_TYPE_MIXER:
|
||||
case SKL_MODULE_TYPE_KPB:
|
||||
return sizeof(struct skl_base_cfg);
|
||||
|
||||
case SKL_MODULE_TYPE_ALGO:
|
||||
default:
|
||||
res = &module->resources[mconfig->res_idx];
|
||||
|
||||
param_size = sizeof(struct skl_base_cfg) + sizeof(struct skl_base_cfg_ext);
|
||||
param_size += (res->nr_input_pins + res->nr_output_pins) *
|
||||
sizeof(struct skl_pin_format);
|
||||
param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size;
|
||||
|
||||
return param_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -851,20 +902,23 @@ static int skl_set_module_format(struct skl_dev *skl,
|
|||
skl_set_updown_mixer_format(skl, module_config, *param_data);
|
||||
break;
|
||||
|
||||
case SKL_MODULE_TYPE_ALGO:
|
||||
skl_set_algo_format(skl, module_config, *param_data);
|
||||
break;
|
||||
|
||||
case SKL_MODULE_TYPE_BASE_OUTFMT:
|
||||
case SKL_MODULE_TYPE_MIC_SELECT:
|
||||
case SKL_MODULE_TYPE_KPB:
|
||||
skl_set_base_outfmt_format(skl, module_config, *param_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
case SKL_MODULE_TYPE_MIXER:
|
||||
case SKL_MODULE_TYPE_KPB:
|
||||
skl_set_base_module_format(skl, module_config, *param_data);
|
||||
break;
|
||||
|
||||
case SKL_MODULE_TYPE_ALGO:
|
||||
default:
|
||||
skl_set_base_module_format(skl, module_config, *param_data);
|
||||
skl_set_base_ext_module_format(skl, module_config,
|
||||
*param_data +
|
||||
sizeof(struct skl_base_cfg));
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n",
|
||||
|
@ -1085,19 +1139,6 @@ int skl_unbind_modules(struct skl_dev *skl,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void fill_pin_params(struct skl_audio_data_format *pin_fmt,
|
||||
struct skl_module_fmt *format)
|
||||
{
|
||||
pin_fmt->number_of_channels = format->channels;
|
||||
pin_fmt->s_freq = format->s_freq;
|
||||
pin_fmt->bit_depth = format->bit_depth;
|
||||
pin_fmt->valid_bit_depth = format->valid_bit_depth;
|
||||
pin_fmt->ch_cfg = format->ch_cfg;
|
||||
pin_fmt->sample_type = format->sample_type;
|
||||
pin_fmt->channel_map = format->ch_map;
|
||||
pin_fmt->interleaving = format->interleaving_style;
|
||||
}
|
||||
|
||||
#define CPR_SINK_FMT_PARAM_ID 2
|
||||
|
||||
/*
|
||||
|
|
|
@ -1214,13 +1214,6 @@ static snd_pcm_uframes_t skl_platform_soc_pointer(
|
|||
return bytes_to_frames(substream->runtime, pos);
|
||||
}
|
||||
|
||||
static int skl_platform_soc_mmap(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *area)
|
||||
{
|
||||
return snd_pcm_lib_default_mmap(substream, area);
|
||||
}
|
||||
|
||||
static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
|
||||
u64 nsec)
|
||||
{
|
||||
|
@ -1317,21 +1310,6 @@ static int skl_get_module_info(struct skl_dev *skl,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
list_for_each_entry(module, &skl->uuid_list, list) {
|
||||
if (guid_equal(uuid_mod, &module->uuid)) {
|
||||
mconfig->id.module_id = module->id;
|
||||
if (mconfig->module)
|
||||
mconfig->module->loadable = module->is_loadable;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
uuid_mod = &module->uuid;
|
||||
ret = -EIO;
|
||||
for (i = 0; i < skl->nr_modules; i++) {
|
||||
skl_module = skl->modules[i];
|
||||
uuid_tplg = &skl_module->uuid;
|
||||
|
@ -1341,10 +1319,18 @@ static int skl_get_module_info(struct skl_dev *skl,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skl->nr_modules && ret)
|
||||
return ret;
|
||||
|
||||
ret = -EIO;
|
||||
list_for_each_entry(module, &skl->uuid_list, list) {
|
||||
if (guid_equal(uuid_mod, &module->uuid)) {
|
||||
mconfig->id.module_id = module->id;
|
||||
mconfig->module->loadable = module->is_loadable;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_IN_QUEUE; i++) {
|
||||
pin_id = &mconfig->m_in_pin[i].id;
|
||||
if (guid_equal(&pin_id->mod_uuid, &module->uuid))
|
||||
|
@ -1358,7 +1344,7 @@ static int skl_get_module_info(struct skl_dev *skl,
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int skl_populate_modules(struct skl_dev *skl)
|
||||
|
@ -1460,7 +1446,6 @@ static const struct snd_soc_component_driver skl_component = {
|
|||
.trigger = skl_platform_soc_trigger,
|
||||
.pointer = skl_platform_soc_pointer,
|
||||
.get_time_info = skl_platform_soc_get_time_info,
|
||||
.mmap = skl_platform_soc_mmap,
|
||||
.pcm_construct = skl_platform_soc_new,
|
||||
.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
|
||||
};
|
||||
|
|
|
@ -113,7 +113,7 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w,
|
|||
|
||||
static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg)
|
||||
{
|
||||
struct skl_module_iface *iface = &mcfg->module->formats[0];
|
||||
struct skl_module_iface *iface = &mcfg->module->formats[mcfg->fmt_idx];
|
||||
|
||||
dev_dbg(skl->dev, "Dumping config\n");
|
||||
dev_dbg(skl->dev, "Input Format:\n");
|
||||
|
@ -195,8 +195,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
|
|||
struct skl_module_fmt *in_fmt, *out_fmt;
|
||||
|
||||
/* Fixups will be applied to pin 0 only */
|
||||
in_fmt = &m_cfg->module->formats[0].inputs[0].fmt;
|
||||
out_fmt = &m_cfg->module->formats[0].outputs[0].fmt;
|
||||
in_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].inputs[0].fmt;
|
||||
out_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].outputs[0].fmt;
|
||||
|
||||
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (is_fe) {
|
||||
|
@ -239,9 +239,9 @@ static void skl_tplg_update_buffer_size(struct skl_dev *skl,
|
|||
/* Since fixups is applied to pin 0 only, ibs, obs needs
|
||||
* change for pin 0 only
|
||||
*/
|
||||
res = &mcfg->module->resources[0];
|
||||
in_fmt = &mcfg->module->formats[0].inputs[0].fmt;
|
||||
out_fmt = &mcfg->module->formats[0].outputs[0].fmt;
|
||||
res = &mcfg->module->resources[mcfg->res_idx];
|
||||
in_fmt = &mcfg->module->formats[mcfg->fmt_idx].inputs[0].fmt;
|
||||
out_fmt = &mcfg->module->formats[mcfg->fmt_idx].outputs[0].fmt;
|
||||
|
||||
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
|
||||
multiplier = 5;
|
||||
|
@ -292,7 +292,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
|
|||
struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx];
|
||||
|
||||
/* check if we already have blob */
|
||||
if (m_cfg->formats_config.caps_size > 0)
|
||||
if (m_cfg->formats_config[SKL_PARAM_INIT].caps_size > 0)
|
||||
return 0;
|
||||
|
||||
dev_dbg(skl->dev, "Applying default cfg blob\n");
|
||||
|
@ -328,8 +328,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
|
|||
cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
|
||||
s_fmt, ch, s_freq, dir, dev_type);
|
||||
if (cfg) {
|
||||
m_cfg->formats_config.caps_size = cfg->size;
|
||||
m_cfg->formats_config.caps = (u32 *) &cfg->caps;
|
||||
m_cfg->formats_config[SKL_PARAM_INIT].caps_size = cfg->size;
|
||||
m_cfg->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps;
|
||||
} else {
|
||||
dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n",
|
||||
m_cfg->vbus_id, link_type, dir);
|
||||
|
@ -386,9 +386,9 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
|
|||
struct skl_algo_data *bc;
|
||||
struct skl_specific_cfg *sp_cfg;
|
||||
|
||||
if (mconfig->formats_config.caps_size > 0 &&
|
||||
mconfig->formats_config.set_params == SKL_PARAM_SET) {
|
||||
sp_cfg = &mconfig->formats_config;
|
||||
if (mconfig->formats_config[SKL_PARAM_SET].caps_size > 0 &&
|
||||
mconfig->formats_config[SKL_PARAM_SET].set_params == SKL_PARAM_SET) {
|
||||
sp_cfg = &mconfig->formats_config[SKL_PARAM_SET];
|
||||
ret = skl_set_module_params(skl, sp_cfg->caps,
|
||||
sp_cfg->caps_size,
|
||||
sp_cfg->param_id, mconfig);
|
||||
|
@ -438,8 +438,10 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
|
|||
if (bc->set_params != SKL_PARAM_INIT)
|
||||
continue;
|
||||
|
||||
mconfig->formats_config.caps = (u32 *)bc->params;
|
||||
mconfig->formats_config.caps_size = bc->size;
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps =
|
||||
(u32 *)bc->params;
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps_size =
|
||||
bc->size;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -498,8 +500,6 @@ skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe)
|
|||
mconfig->id.module_id, mconfig->guid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mconfig->m_state = SKL_MODULE_LOADED;
|
||||
}
|
||||
|
||||
/* prepare the DMA if the module is gateway cpr */
|
||||
|
@ -558,8 +558,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl,
|
|||
mconfig = w_module->w->priv;
|
||||
uuid_mod = (guid_t *)mconfig->guid;
|
||||
|
||||
if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod &&
|
||||
mconfig->m_state > SKL_MODULE_UNINIT) {
|
||||
if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod) {
|
||||
ret = skl->dsp->fw_ops.unload_mod(skl->dsp,
|
||||
mconfig->id.module_id);
|
||||
if (ret < 0)
|
||||
|
@ -641,8 +640,9 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
|
||||
dev_dbg(skl->dev, "No conn_type detected, take 0th config\n");
|
||||
if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) {
|
||||
dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n",
|
||||
pipe->ppl_id);
|
||||
pipe->cur_config_idx = 0;
|
||||
pipe->memory_pages = pconfig->mem_pages;
|
||||
|
||||
|
@ -801,9 +801,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (mconfig->formats_config.caps_size > 0 &&
|
||||
mconfig->formats_config.set_params == SKL_PARAM_BIND) {
|
||||
sp_cfg = &mconfig->formats_config;
|
||||
if (mconfig->formats_config[SKL_PARAM_BIND].caps_size > 0 &&
|
||||
mconfig->formats_config[SKL_PARAM_BIND].set_params ==
|
||||
SKL_PARAM_BIND) {
|
||||
sp_cfg = &mconfig->formats_config[SKL_PARAM_BIND];
|
||||
ret = skl_set_module_params(skl, sp_cfg->caps,
|
||||
sp_cfg->caps_size,
|
||||
sp_cfg->param_id, mconfig);
|
||||
|
@ -1463,12 +1464,6 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
|
|||
struct skl_dev *skl = get_skl_ctx(w->dapm->dev);
|
||||
|
||||
if (ac->params) {
|
||||
/*
|
||||
* Widget data is expected to be stripped of T and L
|
||||
*/
|
||||
size -= 2 * sizeof(unsigned int);
|
||||
data += 2;
|
||||
|
||||
if (size > ac->max)
|
||||
return -EINVAL;
|
||||
ac->size = size;
|
||||
|
@ -1505,7 +1500,8 @@ static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
|
|||
static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
|
||||
struct skl_mic_sel_config *mic_cfg, struct device *dev)
|
||||
{
|
||||
struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
|
||||
struct skl_specific_cfg *sp_cfg =
|
||||
&mconfig->formats_config[SKL_PARAM_INIT];
|
||||
|
||||
sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
|
||||
sp_cfg->set_params = SKL_PARAM_SET;
|
||||
|
@ -1637,11 +1633,12 @@ int skl_tplg_update_pipe_params(struct device *dev,
|
|||
struct skl_module_cfg *mconfig,
|
||||
struct skl_pipe_params *params)
|
||||
{
|
||||
struct skl_module_res *res = &mconfig->module->resources[0];
|
||||
struct skl_module_res *res;
|
||||
struct skl_dev *skl = get_skl_ctx(dev);
|
||||
struct skl_module_fmt *format = NULL;
|
||||
u8 cfg_idx = mconfig->pipe->cur_config_idx;
|
||||
|
||||
res = &mconfig->module->resources[mconfig->res_idx];
|
||||
skl_tplg_fill_dma_id(mconfig, params);
|
||||
mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
|
||||
mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
|
||||
|
@ -1650,9 +1647,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
|
|||
return 0;
|
||||
|
||||
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
format = &mconfig->module->formats[0].inputs[0].fmt;
|
||||
format = &mconfig->module->formats[mconfig->fmt_idx].inputs[0].fmt;
|
||||
else
|
||||
format = &mconfig->module->formats[0].outputs[0].fmt;
|
||||
format = &mconfig->module->formats[mconfig->fmt_idx].outputs[0].fmt;
|
||||
|
||||
/* set the hw_params */
|
||||
format->s_freq = params->s_freq;
|
||||
|
@ -1827,7 +1824,7 @@ static u8 skl_tplg_be_link_type(int dev_type)
|
|||
* Fill the BE gateway parameters
|
||||
* The BE gateway expects a blob of parameters which are kept in the ACPI
|
||||
* NHLT blob, so query the blob for interface type (i2s/pdm) and instance.
|
||||
* The port can have multiple settings so pick based on the PCM
|
||||
* The port can have multiple settings so pick based on the pipeline
|
||||
* parameters
|
||||
*/
|
||||
static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
|
||||
|
@ -1835,6 +1832,8 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
|
|||
struct skl_pipe_params *params)
|
||||
{
|
||||
struct nhlt_specific_cfg *cfg;
|
||||
struct skl_pipe *pipe = mconfig->pipe;
|
||||
struct skl_pipe_fmt *pipe_fmt;
|
||||
struct skl_dev *skl = get_skl_ctx(dai->dev);
|
||||
int link_type = skl_tplg_be_link_type(mconfig->dev_type);
|
||||
u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type);
|
||||
|
@ -1844,20 +1843,23 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
|
|||
if (link_type == NHLT_LINK_HDA)
|
||||
return 0;
|
||||
|
||||
if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
pipe_fmt = &pipe->configs[pipe->pipe_config_idx].out_fmt;
|
||||
else
|
||||
pipe_fmt = &pipe->configs[pipe->pipe_config_idx].in_fmt;
|
||||
|
||||
/* update the blob based on virtual bus_id*/
|
||||
cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
|
||||
params->s_fmt, params->ch,
|
||||
params->s_freq, params->stream,
|
||||
pipe_fmt->bps, pipe_fmt->channels,
|
||||
pipe_fmt->freq, pipe->direction,
|
||||
dev_type);
|
||||
if (cfg) {
|
||||
mconfig->formats_config.caps_size = cfg->size;
|
||||
mconfig->formats_config.caps = (u32 *) &cfg->caps;
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps_size = cfg->size;
|
||||
mconfig->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps;
|
||||
} else {
|
||||
dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n",
|
||||
mconfig->vbus_id, link_type,
|
||||
params->stream);
|
||||
dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n",
|
||||
params->ch, params->s_freq, params->s_fmt);
|
||||
dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n",
|
||||
mconfig->vbus_id, link_type, params->stream,
|
||||
params->ch, params->s_freq, params->s_fmt);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2570,19 +2572,26 @@ static int skl_tplg_get_token(struct device *dev,
|
|||
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_FMT_CFG_IDX:
|
||||
if (tkn_elem->value > SKL_MAX_PARAMS_TYPES)
|
||||
return -EINVAL;
|
||||
|
||||
mconfig->fmt_cfg_idx = tkn_elem->value;
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_CAPS_SIZE:
|
||||
mconfig->formats_config.caps_size =
|
||||
mconfig->formats_config[mconfig->fmt_cfg_idx].caps_size =
|
||||
tkn_elem->value;
|
||||
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_CAPS_SET_PARAMS:
|
||||
mconfig->formats_config.set_params =
|
||||
mconfig->formats_config[mconfig->fmt_cfg_idx].set_params =
|
||||
tkn_elem->value;
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_CAPS_PARAMS_ID:
|
||||
mconfig->formats_config.param_id =
|
||||
mconfig->formats_config[mconfig->fmt_cfg_idx].param_id =
|
||||
tkn_elem->value;
|
||||
break;
|
||||
|
||||
|
@ -2796,6 +2805,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
|
|||
struct skl_dfw_v4_module *dfw =
|
||||
(struct skl_dfw_v4_module *)tplg_w->priv.data;
|
||||
int ret;
|
||||
int idx = mconfig->fmt_cfg_idx;
|
||||
|
||||
dev_dbg(dev, "Parsing Skylake v4 widget topology data\n");
|
||||
|
||||
|
@ -2829,7 +2839,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
|
|||
mconfig->dev_type = dfw->dev_type;
|
||||
mconfig->hw_conn_type = dfw->hw_conn_type;
|
||||
mconfig->time_slot = dfw->time_slot;
|
||||
mconfig->formats_config.caps_size = dfw->caps.caps_size;
|
||||
mconfig->formats_config[idx].caps_size = dfw->caps.caps_size;
|
||||
|
||||
mconfig->m_in_pin = devm_kcalloc(dev,
|
||||
MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin),
|
||||
|
@ -2850,21 +2860,39 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
|
|||
dfw->is_dynamic_out_pin,
|
||||
mconfig->module->max_output_pins);
|
||||
|
||||
if (mconfig->formats_config.caps_size) {
|
||||
mconfig->formats_config.set_params = dfw->caps.set_params;
|
||||
mconfig->formats_config.param_id = dfw->caps.param_id;
|
||||
mconfig->formats_config.caps =
|
||||
devm_kzalloc(dev, mconfig->formats_config.caps_size,
|
||||
if (mconfig->formats_config[idx].caps_size) {
|
||||
mconfig->formats_config[idx].set_params = dfw->caps.set_params;
|
||||
mconfig->formats_config[idx].param_id = dfw->caps.param_id;
|
||||
mconfig->formats_config[idx].caps =
|
||||
devm_kzalloc(dev, mconfig->formats_config[idx].caps_size,
|
||||
GFP_KERNEL);
|
||||
if (!mconfig->formats_config.caps)
|
||||
if (!mconfig->formats_config[idx].caps)
|
||||
return -ENOMEM;
|
||||
memcpy(mconfig->formats_config.caps, dfw->caps.caps,
|
||||
memcpy(mconfig->formats_config[idx].caps, dfw->caps.caps,
|
||||
dfw->caps.caps_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_tplg_get_caps_data(struct device *dev, char *data,
|
||||
struct skl_module_cfg *mconfig)
|
||||
{
|
||||
int idx = mconfig->fmt_cfg_idx;
|
||||
|
||||
if (mconfig->formats_config[idx].caps_size > 0) {
|
||||
mconfig->formats_config[idx].caps =
|
||||
devm_kzalloc(dev, mconfig->formats_config[idx].caps_size,
|
||||
GFP_KERNEL);
|
||||
if (!mconfig->formats_config[idx].caps)
|
||||
return -ENOMEM;
|
||||
memcpy(mconfig->formats_config[idx].caps, data,
|
||||
mconfig->formats_config[idx].caps_size);
|
||||
}
|
||||
|
||||
return mconfig->formats_config[idx].caps_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the private data for the token and corresponding value.
|
||||
* The private data can have multiple data blocks. So, a data block
|
||||
|
@ -2925,18 +2953,14 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
|
|||
if (block_type == SKL_TYPE_TUPLE) {
|
||||
ret = skl_tplg_get_tokens(dev, data,
|
||||
skl, mconfig, block_size);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
--num_blocks;
|
||||
} else {
|
||||
if (mconfig->formats_config.caps_size > 0)
|
||||
memcpy(mconfig->formats_config.caps, data,
|
||||
mconfig->formats_config.caps_size);
|
||||
--num_blocks;
|
||||
ret = mconfig->formats_config.caps_size;
|
||||
ret = skl_tplg_get_caps_data(dev, data, mconfig);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
--num_blocks;
|
||||
off += ret;
|
||||
}
|
||||
|
||||
|
@ -3027,6 +3051,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index,
|
|||
*/
|
||||
mconfig->id.module_id = -1;
|
||||
|
||||
/* To provide backward compatibility, set default as SKL_PARAM_INIT */
|
||||
mconfig->fmt_cfg_idx = SKL_PARAM_INIT;
|
||||
|
||||
/* Parse private data for tuples */
|
||||
ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -81,6 +81,8 @@ enum skl_s_freq {
|
|||
SKL_FS_INVALID
|
||||
};
|
||||
|
||||
#define SKL_MAX_PARAMS_TYPES 4
|
||||
|
||||
enum skl_widget_type {
|
||||
SKL_WIDGET_VMIXER = 1,
|
||||
SKL_WIDGET_MIXER = 2,
|
||||
|
@ -150,6 +152,21 @@ struct skl_up_down_mixer_cfg {
|
|||
u32 ch_map;
|
||||
} __packed;
|
||||
|
||||
struct skl_pin_format {
|
||||
u32 pin_idx;
|
||||
u32 buf_size;
|
||||
struct skl_audio_data_format audio_fmt;
|
||||
} __packed;
|
||||
|
||||
struct skl_base_cfg_ext {
|
||||
u16 nr_input_pins;
|
||||
u16 nr_output_pins;
|
||||
u8 reserved[8];
|
||||
u32 priv_param_length;
|
||||
/* Input pin formats followed by output ones. */
|
||||
struct skl_pin_format pins_fmt[0];
|
||||
} __packed;
|
||||
|
||||
struct skl_algo_cfg {
|
||||
struct skl_base_cfg base_cfg;
|
||||
char params[];
|
||||
|
@ -311,10 +328,8 @@ struct skl_pipe {
|
|||
|
||||
enum skl_module_state {
|
||||
SKL_MODULE_UNINIT = 0,
|
||||
SKL_MODULE_LOADED = 1,
|
||||
SKL_MODULE_INIT_DONE = 2,
|
||||
SKL_MODULE_BIND_DONE = 3,
|
||||
SKL_MODULE_UNLOADED = 4,
|
||||
SKL_MODULE_INIT_DONE = 1,
|
||||
SKL_MODULE_BIND_DONE = 2,
|
||||
};
|
||||
|
||||
enum d0i3_capability {
|
||||
|
@ -373,6 +388,7 @@ struct skl_module_cfg {
|
|||
struct skl_module *module;
|
||||
int res_idx;
|
||||
int fmt_idx;
|
||||
int fmt_cfg_idx;
|
||||
u8 domain;
|
||||
bool homogenous_inputs;
|
||||
bool homogenous_outputs;
|
||||
|
@ -403,7 +419,7 @@ struct skl_module_cfg {
|
|||
enum skl_hw_conn_type hw_conn_type;
|
||||
enum skl_module_state m_state;
|
||||
struct skl_pipe *pipe;
|
||||
struct skl_specific_cfg formats_config;
|
||||
struct skl_specific_cfg formats_config[SKL_MAX_PARAMS_TYPES];
|
||||
struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE];
|
||||
};
|
||||
|
||||
|
|
|
@ -184,3 +184,27 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
|
|||
with the MT6359 RT1015 RT5682 audio codec.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8195
|
||||
tristate "ASoC support for Mediatek MT8195 chip"
|
||||
select SND_SOC_MEDIATEK
|
||||
help
|
||||
This adds ASoC platform driver support for Mediatek MT8195 chip
|
||||
that can be used with other codecs.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_MT8195_MT6359_RT1019_RT5682
|
||||
tristate "ASoC Audio driver for MT8195 with MT6359 RT1019 RT5682 codec"
|
||||
depends on I2C
|
||||
depends on SND_SOC_MT8195
|
||||
select SND_SOC_MT6359
|
||||
select SND_SOC_RT1015P
|
||||
select SND_SOC_RT5682_I2C
|
||||
select SND_SOC_DMIC
|
||||
select SND_SOC_HDMI_CODEC
|
||||
help
|
||||
This adds ASoC driver for Mediatek MT8195 boards
|
||||
with the MT6359 RT1019 RT5682 audio codec.
|
||||
Select Y if you have such device.
|
||||
If unsure select "N".
|
||||
|
|
|
@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
|
|||
obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
|
||||
obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
|
||||
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
|
||||
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
|
||||
|
|
|
@ -139,7 +139,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
|
|||
substream->runtime->dma_area,
|
||||
substream->runtime->dma_bytes);
|
||||
|
||||
memset_io(substream->runtime->dma_area, 0,
|
||||
memset_io((void __force __iomem *)substream->runtime->dma_area, 0,
|
||||
substream->runtime->dma_bytes);
|
||||
|
||||
/* set addr */
|
||||
|
@ -433,11 +433,20 @@ int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
|
|||
phys_buf_addr_upper_32);
|
||||
}
|
||||
|
||||
/* set MSB to 33-bit */
|
||||
if (memif->data->msb_reg >= 0)
|
||||
/*
|
||||
* set MSB to 33-bit, for memif address
|
||||
* only for memif base address, if msb_end_reg exists
|
||||
*/
|
||||
if (memif->data->msb_reg)
|
||||
mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
|
||||
1, msb_at_bit33, memif->data->msb_shift);
|
||||
|
||||
/* set MSB to 33-bit, for memif end address */
|
||||
if (memif->data->msb_end_reg)
|
||||
mtk_regmap_update_bits(afe->regmap, memif->data->msb_end_reg,
|
||||
1, msb_at_bit33,
|
||||
memif->data->msb_end_shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_memif_set_addr);
|
||||
|
@ -464,6 +473,13 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
|
|||
else
|
||||
mono = (channel == 1) ? 1 : 0;
|
||||
|
||||
/* for specific configuration of memif mono mode */
|
||||
if (memif->data->int_odd_flag_reg)
|
||||
mtk_regmap_update_bits(afe->regmap,
|
||||
memif->data->int_odd_flag_reg,
|
||||
1, mono,
|
||||
memif->data->int_odd_flag_shift);
|
||||
|
||||
return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
|
||||
1, mono, memif->data->mono_shift);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue