ASoC: codecs: wcd9378: grow skeleton into TX/capture codec driver (WIP)
Replace the transport-test skeleton with a functional driver modeled on wcd937x: platform parent device (qcom,wcd9378-codec) as component master over the two SoundWire slaves, owning reset GPIO, supplies and micbias config; regmap (MAPLE cache, 32-bit paged SDCA addresses) on the TX slave; capture DAI (index 1) with sdw stream plumbing; DAPM TX path AMICn -> ADCn MUX -> TXn SEQUENCER -> ADCn_OUTPUT with the SDCA SmartMIC power sequence (ITxx_USAGE mode, PDE11 PS0 request, HPF init hold) and IT11_MICB-based refcounted micbias control; sys-usage profile auto-selection; SCP bus-clock indication (base clk, busclock scale, host-clk-div2) per the downstream capture-start sequence. Verified on FP6: probes and binds without any manual per-boot hacks (gpio162 reset, runtime PM force, l8b always-on all obsolete), sound card registers, full DPCM/SoundWire/CDC-DMA transport carries data. KNOWN ISSUE: the SmartMIC sequencer never leaves PWR_DN (PDE11_ACT_PS stays PS3, SEQ_TX0_STAT=PWR_DN_RDY) although every register the downstream driver writes has been replicated and verified on hardware by bypassed readback - capture records digital silence. Investigation notes in journal/mic.md. Assisted-by: Claude:claude-fable-5 Signed-off-by: Jorijn van der Graaf <jorijnvdgraaf@catcrafts.net>
This commit is contained in:
parent
5c9c899ba9
commit
9df8d66027
5 changed files with 1988 additions and 73 deletions
|
|
@ -2431,13 +2431,20 @@ config SND_SOC_WCD937X_SDW
|
|||
via soundwire.
|
||||
To compile this codec driver say Y or m.
|
||||
|
||||
config SND_SOC_WCD9378
|
||||
depends on SND_SOC_WCD9378_SDW
|
||||
tristate
|
||||
depends on SOUNDWIRE || !SOUNDWIRE
|
||||
select SND_SOC_WCD_COMMON
|
||||
|
||||
config SND_SOC_WCD9378_SDW
|
||||
tristate "WCD9378 Codec - SDW (bring-up skeleton)"
|
||||
tristate "WCD9378 Codec - SDW"
|
||||
select SND_SOC_WCD9378
|
||||
depends on SOUNDWIRE
|
||||
select REGMAP_SOUNDWIRE
|
||||
help
|
||||
Bring-up skeleton driver for the Qualcomm WCD9378 audio codec
|
||||
connected via SoundWire, as found on SM7635 phones.
|
||||
Driver for the Qualcomm WCD9378 audio codec connected via
|
||||
SoundWire, as found on SM7635 phones.
|
||||
To compile this codec driver say Y or m.
|
||||
|
||||
config SND_SOC_WCD938X
|
||||
|
|
|
|||
|
|
@ -356,6 +356,7 @@ snd-soc-wcd9335-y := wcd9335.o
|
|||
snd-soc-wcd934x-y := wcd934x.o
|
||||
snd-soc-wcd937x-y := wcd937x.o
|
||||
snd-soc-wcd937x-sdw-y := wcd937x-sdw.o
|
||||
snd-soc-wcd9378-y := wcd9378.o
|
||||
snd-soc-wcd9378-sdw-y := wcd9378-sdw.o
|
||||
snd-soc-wcd938x-y := wcd938x.o
|
||||
snd-soc-wcd938x-sdw-y := wcd938x-sdw.o
|
||||
|
|
@ -797,7 +798,11 @@ ifdef CONFIG_SND_SOC_WCD937X_SDW
|
|||
# avoid link failure by forcing sdw code built-in when needed
|
||||
obj-$(CONFIG_SND_SOC_WCD937X) += snd-soc-wcd937x-sdw.o
|
||||
endif
|
||||
obj-$(CONFIG_SND_SOC_WCD9378_SDW) += snd-soc-wcd9378-sdw.o
|
||||
obj-$(CONFIG_SND_SOC_WCD9378) += snd-soc-wcd9378.o
|
||||
ifdef CONFIG_SND_SOC_WCD9378_SDW
|
||||
# avoid link failure by forcing sdw code built-in when needed
|
||||
obj-$(CONFIG_SND_SOC_WCD9378) += snd-soc-wcd9378-sdw.o
|
||||
endif
|
||||
obj-$(CONFIG_SND_SOC_WCD938X) += snd-soc-wcd938x.o
|
||||
ifdef CONFIG_SND_SOC_WCD938X_SDW
|
||||
# avoid link failure by forcing sdw code built-in when needed
|
||||
|
|
|
|||
|
|
@ -4,85 +4,333 @@
|
|||
*
|
||||
* SoundWire slave driver for the Qualcomm WCD9378 audio codec.
|
||||
*
|
||||
* Bring-up skeleton: binds to the two WCD9378 SoundWire devices (TX and
|
||||
* RX), maps the SDCA control space through regmap and verifies the device
|
||||
* identity registers. No audio paths yet.
|
||||
* The codec presents two SoundWire slaves (RX and TX, mfg 0x0217 part
|
||||
* 0x0110); the SDCA control space is a 32-bit paged register map accessed
|
||||
* through the TX slave.
|
||||
*/
|
||||
|
||||
#include <linux/component.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include "wcd-common.h"
|
||||
#include "wcd9378.h"
|
||||
|
||||
struct wcd9378_sdw_priv {
|
||||
struct sdw_slave *sdev;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static const struct regmap_config wcd9378_sdw_regmap_config = {
|
||||
.name = "wcd9378_sdw",
|
||||
.reg_bits = 32,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.max_register = WCD9378_MAX_REGISTER,
|
||||
};
|
||||
|
||||
static void wcd9378_sdw_read_id(struct wcd9378_sdw_priv *wcd)
|
||||
{
|
||||
struct device *dev = &wcd->sdev->dev;
|
||||
static const struct {
|
||||
const char *name;
|
||||
unsigned int reg;
|
||||
} id_regs[] = {
|
||||
{ "DEV_MANU_ID_0", WCD9378_DEV_MANU_ID_0 },
|
||||
{ "DEV_MANU_ID_1", WCD9378_DEV_MANU_ID_1 },
|
||||
{ "DEV_PART_ID_0", WCD9378_DEV_PART_ID_0 },
|
||||
{ "DEV_PART_ID_1", WCD9378_DEV_PART_ID_1 },
|
||||
{ "DEV_VER", WCD9378_DEV_VER },
|
||||
{ "FUNC_EXT_ID_0", WCD9378_FUNC_EXT_ID_0 },
|
||||
{ "FUNC_EXT_ID_1", WCD9378_FUNC_EXT_ID_1 },
|
||||
{ "ANA_BIAS", WCD9378_ANA_BIAS },
|
||||
{ "ANA_TX_CH1", WCD9378_ANA_TX_CH1 },
|
||||
{ "ANA_MICB1", WCD9378_ANA_MICB1 },
|
||||
{ "SYS_USAGE_CTRL", WCD9378_SYS_USAGE_CTRL },
|
||||
};
|
||||
unsigned int val, packed, pval;
|
||||
int i, ret, pret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(id_regs); i++) {
|
||||
/* downstream WCD9378_REG() wire packing */
|
||||
packed = ((id_regs[i].reg & 0x0ff00000) >> 8) |
|
||||
(id_regs[i].reg & 0xfff);
|
||||
|
||||
ret = regmap_read(wcd->regmap, id_regs[i].reg, &val);
|
||||
pret = regmap_read(wcd->regmap, packed, &pval);
|
||||
dev_info(dev, "%s: virt %#010x = %#04x (ret %d), packed %#07x = %#04x (ret %d)\n",
|
||||
id_regs[i].name,
|
||||
id_regs[i].reg, ret ? 0xdead : val, ret,
|
||||
packed, pret ? 0xdead : pval, pret);
|
||||
#define WCD9378_SDW_CH(id, pn, cmask, mmask) \
|
||||
[id] = { \
|
||||
.port_num = pn, \
|
||||
.ch_mask = cmask, \
|
||||
.master_ch_mask = mmask, \
|
||||
}
|
||||
}
|
||||
|
||||
static int wcd9378_sdw_update_status(struct sdw_slave *slave,
|
||||
enum sdw_slave_status status)
|
||||
/*
|
||||
* Each ADC sits alone on its own TX device port (channel 1); by default
|
||||
* they land on channels 1/2/3 of the same master port (SWRM_TX1 on the
|
||||
* FP6). DMIC/MBHC masks per the downstream qcom,tx_swr_ch_map.
|
||||
*/
|
||||
static struct wcd_sdw_ch_info wcd9378_sdw_tx_ch_info[] = {
|
||||
WCD9378_SDW_CH(WCD9378_ADC1, WCD9378_ADC_1_PORT, BIT(0), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_ADC2, WCD9378_ADC_2_PORT, BIT(0), BIT(1)),
|
||||
WCD9378_SDW_CH(WCD9378_ADC3, WCD9378_ADC_3_PORT, BIT(0), BIT(2)),
|
||||
WCD9378_SDW_CH(WCD9378_DMIC0, WCD9378_DMIC_0_1_MBHC_PORT, BIT(2), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_DMIC1, WCD9378_DMIC_0_1_MBHC_PORT, BIT(3), BIT(1)),
|
||||
WCD9378_SDW_CH(WCD9378_MBHC, WCD9378_DMIC_0_1_MBHC_PORT, BIT(2), BIT(2)),
|
||||
WCD9378_SDW_CH(WCD9378_DMIC2, WCD9378_DMIC_2_5_PORT, BIT(0), BIT(2)),
|
||||
WCD9378_SDW_CH(WCD9378_DMIC3, WCD9378_DMIC_2_5_PORT, BIT(1), BIT(3)),
|
||||
WCD9378_SDW_CH(WCD9378_DMIC4, WCD9378_DMIC_2_5_PORT, BIT(2), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_DMIC5, WCD9378_DMIC_2_5_PORT, BIT(3), BIT(1)),
|
||||
};
|
||||
|
||||
static struct wcd_sdw_ch_info wcd9378_sdw_rx_ch_info[] = {
|
||||
WCD9378_SDW_CH(WCD9378_HPH_L, WCD9378_HPH_PORT, BIT(0), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_HPH_R, WCD9378_HPH_PORT, BIT(1), BIT(1)),
|
||||
WCD9378_SDW_CH(WCD9378_CLSH, WCD9378_CLSH_PORT, BIT(0), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_COMP_L, WCD9378_COMP_PORT, BIT(0), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_COMP_R, WCD9378_COMP_PORT, BIT(1), BIT(1)),
|
||||
WCD9378_SDW_CH(WCD9378_LO, WCD9378_LO_PORT, BIT(0), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_DSD_L, WCD9378_DSD_PORT, BIT(0), BIT(0)),
|
||||
WCD9378_SDW_CH(WCD9378_DSD_R, WCD9378_DSD_PORT, BIT(1), BIT(1)),
|
||||
};
|
||||
|
||||
static struct sdw_dpn_prop wcd9378_dpn_prop[WCD9378_MAX_SWR_PORTS] = {
|
||||
{
|
||||
.num = 1,
|
||||
.type = SDW_DPN_SIMPLE,
|
||||
.min_ch = 1,
|
||||
.max_ch = 8,
|
||||
.simple_ch_prep_sm = true,
|
||||
}, {
|
||||
.num = 2,
|
||||
.type = SDW_DPN_SIMPLE,
|
||||
.min_ch = 1,
|
||||
.max_ch = 4,
|
||||
.simple_ch_prep_sm = true,
|
||||
}, {
|
||||
.num = 3,
|
||||
.type = SDW_DPN_SIMPLE,
|
||||
.min_ch = 1,
|
||||
.max_ch = 4,
|
||||
.simple_ch_prep_sm = true,
|
||||
}, {
|
||||
.num = 4,
|
||||
.type = SDW_DPN_SIMPLE,
|
||||
.min_ch = 1,
|
||||
.max_ch = 4,
|
||||
.simple_ch_prep_sm = true,
|
||||
}, {
|
||||
.num = 5,
|
||||
.type = SDW_DPN_SIMPLE,
|
||||
.min_ch = 1,
|
||||
.max_ch = 4,
|
||||
.simple_ch_prep_sm = true,
|
||||
}
|
||||
};
|
||||
|
||||
int wcd9378_sdw_hw_params(struct wcd9378_sdw_priv *wcd,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct wcd9378_sdw_priv *wcd = dev_get_drvdata(&slave->dev);
|
||||
struct sdw_port_config port_config[WCD9378_MAX_SWR_PORTS];
|
||||
unsigned long ch_mask;
|
||||
int i, j;
|
||||
|
||||
dev_info(&slave->dev, "status %d (dev_num %d)\n", status,
|
||||
slave->dev_num);
|
||||
wcd->sconfig.ch_count = 1;
|
||||
wcd->active_ports = 0;
|
||||
for (i = 0; i < WCD9378_MAX_SWR_PORTS; i++) {
|
||||
ch_mask = wcd->port_config[i].ch_mask;
|
||||
if (!ch_mask)
|
||||
continue;
|
||||
|
||||
if (status == SDW_SLAVE_ATTACHED)
|
||||
wcd9378_sdw_read_id(wcd);
|
||||
for_each_set_bit(j, &ch_mask, 4)
|
||||
wcd->sconfig.ch_count++;
|
||||
|
||||
port_config[wcd->active_ports] = wcd->port_config[i];
|
||||
wcd->active_ports++;
|
||||
}
|
||||
|
||||
wcd->sconfig.bps = 1;
|
||||
wcd->sconfig.frame_rate = params_rate(params);
|
||||
wcd->sconfig.direction = wcd->is_tx ? SDW_DATA_DIR_TX : SDW_DATA_DIR_RX;
|
||||
wcd->sconfig.type = SDW_STREAM_PCM;
|
||||
|
||||
return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
|
||||
&port_config[0], wcd->active_ports,
|
||||
wcd->sruntime);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wcd9378_sdw_hw_params);
|
||||
|
||||
/*
|
||||
* Tell the codec the bus clock: base 19.2 MHz plus a scale (div) per bank.
|
||||
* The downstream driver writes these raw SCP registers on every capture
|
||||
* start; here the bus_config callback covers bank switches.
|
||||
*/
|
||||
static int wcd9378_bus_config(struct sdw_slave *slave,
|
||||
struct sdw_bus_params *params)
|
||||
{
|
||||
u8 scale;
|
||||
|
||||
switch (params->curr_dr_freq) {
|
||||
case 4800000:
|
||||
scale = WCD9378_SWRS_CLK_SCALE_DIV4;
|
||||
break;
|
||||
case 9600000:
|
||||
default:
|
||||
scale = WCD9378_SWRS_CLK_SCALE_DIV2;
|
||||
break;
|
||||
}
|
||||
|
||||
sdw_write(slave, WCD9378_SWRS_SCP_HOST_CLK_DIV2_CTL(params->next_bank),
|
||||
0x01);
|
||||
sdw_write(slave, WCD9378_SWRS_SCP_BASE_CLK,
|
||||
WCD9378_SWRS_BASE_CLK_19P2MHZ);
|
||||
sdw_write(slave, WCD9378_SWRS_SCP_BUSCLK_SCALE_BANK0, scale);
|
||||
sdw_write(slave, WCD9378_SWRS_SCP_BUSCLK_SCALE_BANK1, scale);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sdw_slave_ops wcd9378_sdw_ops = {
|
||||
.update_status = wcd9378_sdw_update_status,
|
||||
static const struct sdw_slave_ops wcd9378_slave_ops = {
|
||||
.update_status = wcd_update_status,
|
||||
.bus_config = wcd9378_bus_config,
|
||||
};
|
||||
|
||||
static const struct reg_default wcd9378_defaults[] = {
|
||||
{ WCD9378_ANA_BIAS, 0x00 },
|
||||
{ WCD9378_ANA_TX_CH1, 0x20 },
|
||||
{ WCD9378_ANA_TX_CH2, 0x00 },
|
||||
{ WCD9378_ANA_TX_CH3, 0x20 },
|
||||
{ WCD9378_ANA_TX_CH3_HPF, 0x00 },
|
||||
{ WCD9378_ANA_MICB2_RAMP, 0x00 },
|
||||
{ WCD9378_BIAS_VBG_FINE_ADJ, 0x55 },
|
||||
{ WCD9378_MBHC_CTL_SPARE_1, 0x02 },
|
||||
{ WCD9378_MICB1_TEST_CTL_2, 0x00 },
|
||||
{ WCD9378_MICB2_TEST_CTL_2, 0x00 },
|
||||
{ WCD9378_MICB3_TEST_CTL_2, 0x80 },
|
||||
{ WCD9378_TX_COM_TXFE_DIV_CTL, 0x22 },
|
||||
{ WCD9378_SLEEP_CTL, 0x16 },
|
||||
{ WCD9378_TX_NEW_CH12_MUX, 0x11 },
|
||||
{ WCD9378_TX_NEW_CH34_MUX, 0x23 },
|
||||
{ WCD9378_TOP_CLK_CFG, 0x00 },
|
||||
{ WCD9378_CDC_ANA_TX_CLK_CTL, 0x0e },
|
||||
{ WCD9378_CDC_AMIC_CTL, 0x07 },
|
||||
{ WCD9378_PDM_WD_CTL0, 0x0f },
|
||||
{ WCD9378_PDM_WD_CTL1, 0x0f },
|
||||
{ WCD9378_PLATFORM_CTL, 0x01 },
|
||||
{ WCD9378_SYS_USAGE_CTRL, 0x00 },
|
||||
{ WCD9378_HPH_UP_T0, 0x02 },
|
||||
{ WCD9378_HPH_UP_T9, 0x02 },
|
||||
{ WCD9378_HPH_DN_T0, 0x05 },
|
||||
{ WCD9378_MICB_REMAP_TABLE_VAL_3, 0x00 },
|
||||
{ WCD9378_MICB_REMAP_TABLE_VAL_4, 0x00 },
|
||||
{ WCD9378_MICB_REMAP_TABLE_VAL_5, 0x00 },
|
||||
{ WCD9378_SM0_MB_SEL, 0x00 },
|
||||
{ WCD9378_SM1_MB_SEL, 0x00 },
|
||||
{ WCD9378_SM2_MB_SEL, 0x00 },
|
||||
{ WCD9378_MB_PULLUP_EN, 0x00 },
|
||||
{ WCD9378_SMP_AMP_FUNC_ACT, 0x00 },
|
||||
{ WCD9378_CMT_GRP_MASK, 0x00 },
|
||||
{ WCD9378_SMP_JACK_IT31_MICB, 0x00 },
|
||||
{ WCD9378_SMP_JACK_IT31_USAGE, 0x03 },
|
||||
{ WCD9378_SMP_JACK_PDE34_REQ_PS, 0x03 },
|
||||
{ WCD9378_SMP_JACK_FUNC_ACT, 0x00 },
|
||||
{ WCD9378_SMP_MIC_IT11_MICB(0), 0x00 },
|
||||
{ WCD9378_SMP_MIC_IT11_USAGE(0), 0x03 },
|
||||
{ WCD9378_SMP_MIC_PDE11_REQ_PS(0), 0x03 },
|
||||
{ WCD9378_SMP_MIC_FUNC_ACT(0), 0x00 },
|
||||
{ WCD9378_SMP_MIC_IT11_MICB(1), 0x00 },
|
||||
{ WCD9378_SMP_MIC_IT11_USAGE(1), 0x03 },
|
||||
{ WCD9378_SMP_MIC_PDE11_REQ_PS(1), 0x03 },
|
||||
{ WCD9378_SMP_MIC_FUNC_ACT(1), 0x00 },
|
||||
{ WCD9378_SMP_MIC_IT11_MICB(2), 0x00 },
|
||||
{ WCD9378_SMP_MIC_IT11_USAGE(2), 0x03 },
|
||||
{ WCD9378_SMP_MIC_PDE11_REQ_PS(2), 0x03 },
|
||||
{ WCD9378_SMP_MIC_FUNC_ACT(2), 0x00 },
|
||||
};
|
||||
|
||||
static bool wcd9378_rdwr_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WCD9378_ANA_BIAS:
|
||||
case WCD9378_ANA_TX_CH1:
|
||||
case WCD9378_ANA_TX_CH2:
|
||||
case WCD9378_ANA_TX_CH3:
|
||||
case WCD9378_ANA_TX_CH3_HPF:
|
||||
case WCD9378_ANA_MICB2_RAMP:
|
||||
case WCD9378_BIAS_VBG_FINE_ADJ:
|
||||
case WCD9378_MBHC_CTL_SPARE_1:
|
||||
case WCD9378_MICB1_TEST_CTL_2:
|
||||
case WCD9378_MICB2_TEST_CTL_2:
|
||||
case WCD9378_MICB3_TEST_CTL_2:
|
||||
case WCD9378_TX_COM_TXFE_DIV_CTL:
|
||||
case WCD9378_SLEEP_CTL:
|
||||
case WCD9378_TX_NEW_CH12_MUX:
|
||||
case WCD9378_TX_NEW_CH34_MUX:
|
||||
case WCD9378_HPH_RDAC_GAIN_CTL:
|
||||
case WCD9378_HPH_RDAC_HD2_CTL_L:
|
||||
case WCD9378_HPH_RDAC_HD2_CTL_R:
|
||||
case WCD9378_TOP_CLK_CFG:
|
||||
case WCD9378_CDC_ANA_TX_CLK_CTL:
|
||||
case WCD9378_CDC_AMIC_CTL:
|
||||
case WCD9378_PDM_WD_CTL0:
|
||||
case WCD9378_PDM_WD_CTL1:
|
||||
case WCD9378_PLATFORM_CTL:
|
||||
case WCD9378_SYS_USAGE_CTRL:
|
||||
case WCD9378_HPH_UP_T0:
|
||||
case WCD9378_HPH_UP_T9:
|
||||
case WCD9378_HPH_DN_T0:
|
||||
case WCD9378_MICB_REMAP_TABLE_VAL_3:
|
||||
case WCD9378_MICB_REMAP_TABLE_VAL_4:
|
||||
case WCD9378_MICB_REMAP_TABLE_VAL_5:
|
||||
case WCD9378_SM0_MB_SEL:
|
||||
case WCD9378_SM1_MB_SEL:
|
||||
case WCD9378_SM2_MB_SEL:
|
||||
case WCD9378_MB_PULLUP_EN:
|
||||
case WCD9378_SMP_AMP_FUNC_STAT:
|
||||
case WCD9378_SMP_AMP_FUNC_ACT:
|
||||
case WCD9378_CMT_GRP_MASK:
|
||||
case WCD9378_SMP_JACK_IT31_MICB:
|
||||
case WCD9378_SMP_JACK_IT31_USAGE:
|
||||
case WCD9378_SMP_JACK_PDE34_REQ_PS:
|
||||
case WCD9378_SMP_JACK_FUNC_STAT:
|
||||
case WCD9378_SMP_JACK_FUNC_ACT:
|
||||
case WCD9378_SMP_MIC_IT11_MICB(0):
|
||||
case WCD9378_SMP_MIC_IT11_USAGE(0):
|
||||
case WCD9378_SMP_MIC_PDE11_REQ_PS(0):
|
||||
case WCD9378_SMP_MIC_FUNC_STAT(0):
|
||||
case WCD9378_SMP_MIC_FUNC_ACT(0):
|
||||
case WCD9378_SMP_MIC_IT11_MICB(1):
|
||||
case WCD9378_SMP_MIC_IT11_USAGE(1):
|
||||
case WCD9378_SMP_MIC_PDE11_REQ_PS(1):
|
||||
case WCD9378_SMP_MIC_FUNC_STAT(1):
|
||||
case WCD9378_SMP_MIC_FUNC_ACT(1):
|
||||
case WCD9378_SMP_MIC_IT11_MICB(2):
|
||||
case WCD9378_SMP_MIC_IT11_USAGE(2):
|
||||
case WCD9378_SMP_MIC_PDE11_REQ_PS(2):
|
||||
case WCD9378_SMP_MIC_FUNC_STAT(2):
|
||||
case WCD9378_SMP_MIC_FUNC_ACT(2):
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wcd9378_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WCD9378_FUNC_EXT_ID_0:
|
||||
case WCD9378_FUNC_EXT_ID_1:
|
||||
case WCD9378_FUNC_EXT_VER:
|
||||
case WCD9378_FUNC_STAT:
|
||||
case WCD9378_DEV_MANU_ID_0:
|
||||
case WCD9378_DEV_MANU_ID_1:
|
||||
case WCD9378_DEV_PART_ID_0:
|
||||
case WCD9378_DEV_PART_ID_1:
|
||||
case WCD9378_DEV_VER:
|
||||
case WCD9378_EFUSE_REG_16:
|
||||
case WCD9378_EFUSE_REG_29:
|
||||
case WCD9378_SEQ_TX0_STAT:
|
||||
case WCD9378_SEQ_TX1_STAT:
|
||||
case WCD9378_SEQ_TX2_STAT:
|
||||
case WCD9378_SMP_JACK_PDE34_ACT_PS:
|
||||
case WCD9378_SMP_MIC_OT10_USAGE(0):
|
||||
case WCD9378_SMP_MIC_PDE11_ACT_PS(0):
|
||||
case WCD9378_SMP_MIC_OT10_USAGE(1):
|
||||
case WCD9378_SMP_MIC_PDE11_ACT_PS(1):
|
||||
case WCD9378_SMP_MIC_OT10_USAGE(2):
|
||||
case WCD9378_SMP_MIC_PDE11_ACT_PS(2):
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wcd9378_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if (wcd9378_volatile_register(dev, reg))
|
||||
return true;
|
||||
|
||||
return wcd9378_rdwr_register(dev, reg);
|
||||
}
|
||||
|
||||
static const struct regmap_config wcd9378_regmap_config = {
|
||||
.name = "wcd9378_csr",
|
||||
.reg_bits = 32,
|
||||
.val_bits = 8,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults = wcd9378_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(wcd9378_defaults),
|
||||
.max_register = WCD9378_MAX_REGISTER,
|
||||
.readable_reg = wcd9378_readable_register,
|
||||
.writeable_reg = wcd9378_rdwr_register,
|
||||
.volatile_reg = wcd9378_volatile_register,
|
||||
};
|
||||
|
||||
static int wcd9378_sdw_probe(struct sdw_slave *pdev,
|
||||
|
|
@ -90,46 +338,150 @@ static int wcd9378_sdw_probe(struct sdw_slave *pdev,
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct wcd9378_sdw_priv *wcd;
|
||||
u8 master_ch_mask[WCD9378_MAX_SWR_CH_IDS];
|
||||
int master_ch_mask_size = 0;
|
||||
int ret, i;
|
||||
|
||||
wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL);
|
||||
if (!wcd)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Port map index starts at 0, however the data ports start at index 1 */
|
||||
if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) {
|
||||
wcd->is_tx = true;
|
||||
ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping",
|
||||
&pdev->m_port_map[1],
|
||||
WCD9378_MAX_TX_SWR_PORTS);
|
||||
} else {
|
||||
ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping",
|
||||
&pdev->m_port_map[1],
|
||||
WCD9378_MAX_SWR_PORTS);
|
||||
}
|
||||
if (ret < 0)
|
||||
dev_info(dev, "Error getting static port mapping for %s (%d)\n",
|
||||
wcd->is_tx ? "TX" : "RX", ret);
|
||||
|
||||
wcd->sdev = pdev;
|
||||
dev_set_drvdata(dev, wcd);
|
||||
|
||||
pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF |
|
||||
SDW_SCP_INT1_BUS_CLASH |
|
||||
SDW_SCP_INT1_PARITY;
|
||||
pdev->prop.lane_control_support = true;
|
||||
pdev->prop.simple_clk_stop_capable = true;
|
||||
/* The SDCA control space sits above the 16-bit address range */
|
||||
pdev->prop.paging_support = true;
|
||||
|
||||
wcd->regmap = devm_regmap_init_sdw(pdev, &wcd9378_sdw_regmap_config);
|
||||
if (IS_ERR(wcd->regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(wcd->regmap),
|
||||
"regmap init failed\n");
|
||||
memset(master_ch_mask, 0, WCD9378_MAX_SWR_CH_IDS);
|
||||
|
||||
dev_info(dev, "wcd9378 sdw slave probed\n");
|
||||
if (wcd->is_tx) {
|
||||
master_ch_mask_size = of_property_count_u8_elems(dev->of_node,
|
||||
"qcom,tx-channel-mapping");
|
||||
|
||||
if (master_ch_mask_size > 0)
|
||||
ret = of_property_read_u8_array(dev->of_node,
|
||||
"qcom,tx-channel-mapping",
|
||||
master_ch_mask,
|
||||
master_ch_mask_size);
|
||||
} else {
|
||||
master_ch_mask_size = of_property_count_u8_elems(dev->of_node,
|
||||
"qcom,rx-channel-mapping");
|
||||
|
||||
if (master_ch_mask_size > 0)
|
||||
ret = of_property_read_u8_array(dev->of_node,
|
||||
"qcom,rx-channel-mapping",
|
||||
master_ch_mask,
|
||||
master_ch_mask_size);
|
||||
}
|
||||
|
||||
if (wcd->is_tx) {
|
||||
pdev->prop.source_ports = GENMASK(WCD9378_MAX_TX_SWR_PORTS, 1);
|
||||
pdev->prop.src_dpn_prop = wcd9378_dpn_prop;
|
||||
wcd->ch_info = &wcd9378_sdw_tx_ch_info[0];
|
||||
|
||||
for (i = 0; i < master_ch_mask_size; i++)
|
||||
wcd->ch_info[i].master_ch_mask = WCD9378_SWRM_CH_MASK(master_ch_mask[i]);
|
||||
|
||||
pdev->prop.wake_capable = true;
|
||||
|
||||
wcd->regmap = devm_regmap_init_sdw(pdev, &wcd9378_regmap_config);
|
||||
if (IS_ERR(wcd->regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(wcd->regmap),
|
||||
"Regmap init failed\n");
|
||||
|
||||
/* Start in cache-only until device is enumerated */
|
||||
regcache_cache_only(wcd->regmap, true);
|
||||
} else {
|
||||
pdev->prop.sink_ports = GENMASK(WCD9378_MAX_SWR_PORTS, 1);
|
||||
pdev->prop.sink_dpn_prop = wcd9378_dpn_prop;
|
||||
wcd->ch_info = &wcd9378_sdw_rx_ch_info[0];
|
||||
|
||||
for (i = 0; i < master_ch_mask_size; i++)
|
||||
wcd->ch_info[i].master_ch_mask = WCD9378_SWRM_CH_MASK(master_ch_mask[i]);
|
||||
}
|
||||
|
||||
ret = component_add(dev, &wcd_sdw_component_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set suspended until aggregate device is bind */
|
||||
pm_runtime_set_suspended(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wcd9378_sdw_remove(struct sdw_slave *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
component_del(dev, &wcd_sdw_component_ops);
|
||||
}
|
||||
|
||||
static const struct sdw_device_id wcd9378_sdw_id[] = {
|
||||
SDW_SLAVE_ENTRY(0x0217, 0x0110, 0),
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, wcd9378_sdw_id);
|
||||
|
||||
static int wcd9378_sdw_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct wcd9378_sdw_priv *wcd = dev_get_drvdata(dev);
|
||||
|
||||
if (wcd->regmap) {
|
||||
regcache_cache_only(wcd->regmap, true);
|
||||
regcache_mark_dirty(wcd->regmap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9378_sdw_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct wcd9378_sdw_priv *wcd = dev_get_drvdata(dev);
|
||||
|
||||
if (wcd->regmap) {
|
||||
regcache_cache_only(wcd->regmap, false);
|
||||
regcache_sync(wcd->regmap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops wcd9378_sdw_pm_ops = {
|
||||
RUNTIME_PM_OPS(wcd9378_sdw_runtime_suspend, wcd9378_sdw_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct sdw_driver wcd9378_sdw_driver = {
|
||||
.probe = wcd9378_sdw_probe,
|
||||
.ops = &wcd9378_sdw_ops,
|
||||
.remove = wcd9378_sdw_remove,
|
||||
.ops = &wcd9378_slave_ops,
|
||||
.id_table = wcd9378_sdw_id,
|
||||
.driver = {
|
||||
.name = "wcd9378-sdw",
|
||||
},
|
||||
.pm = pm_ptr(&wcd9378_sdw_pm_ops),
|
||||
}
|
||||
};
|
||||
module_sdw_driver(wcd9378_sdw_driver);
|
||||
|
||||
MODULE_DESCRIPTION("WCD9378 SoundWire slave driver");
|
||||
MODULE_DESCRIPTION("WCD9378 SDW codec driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
1372
sound/soc/codecs/wcd9378.c
Normal file
1372
sound/soc/codecs/wcd9378.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -8,13 +8,17 @@
|
|||
* address space (bit 30 set, SDCA function number in bits 25:22), accessed
|
||||
* through the TX SoundWire slave. The analog core registers (function 0,
|
||||
* implementation-defined region at +0x180000) are layout-compatible with
|
||||
* the WCD937x family.
|
||||
* the WCD937x family; on top of that the chip adds SDCA-style functions
|
||||
* (SmartMIC0/1/2, SmartJACK, SmartAMP) whose sequencers drive the analog
|
||||
* power-up autonomously.
|
||||
*/
|
||||
|
||||
#ifndef __WCD9378_H__
|
||||
#define __WCD9378_H__
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
#include <linux/soundwire/sdw_type.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
/* SDCA function 0 (extension unit): device identity */
|
||||
|
|
@ -31,33 +35,208 @@
|
|||
/* Analog core (WCD937x-compatible layout), function 0 + 0x180000 */
|
||||
#define WCD9378_ANA_PAGE 0x40180000
|
||||
#define WCD9378_ANA_BIAS 0x40180001
|
||||
#define WCD9378_ANA_BIAS_ANALOG_BIAS_EN BIT(7)
|
||||
#define WCD9378_ANA_BIAS_PRECHRG_EN BIT(6)
|
||||
#define WCD9378_ANA_RX_SUPPLIES 0x40180008
|
||||
#define WCD9378_ANA_TX_CH1 0x4018000e
|
||||
#define WCD9378_ANA_TX_CH2 0x4018000f
|
||||
#define WCD9378_ANA_TX_CH2_HPF1_INIT BIT(6)
|
||||
#define WCD9378_ANA_TX_CH2_HPF2_INIT BIT(5)
|
||||
#define WCD9378_ANA_TX_CH3 0x40180010
|
||||
#define WCD9378_ANA_TX_CH3_HPF 0x40180011
|
||||
#define WCD9378_ANA_TX_CH3_HPF3_INIT BIT(6)
|
||||
#define WCD9378_ANA_TX_GAIN_MASK GENMASK(4, 0)
|
||||
#define WCD9378_ANA_MICB1 0x40180022
|
||||
#define WCD9378_ANA_MICB2 0x40180023
|
||||
#define WCD9378_ANA_MICB2_RAMP 0x40180024
|
||||
#define WCD9378_ANA_MICB2_RAMP_SHIFT_CTL_MASK GENMASK(4, 2)
|
||||
#define WCD9378_ANA_MICB2_RAMP_EN BIT(7)
|
||||
#define WCD9378_ANA_MICB3 0x40180025
|
||||
#define WCD9378_BIAS_VBG_FINE_ADJ 0x40180029
|
||||
#define WCD9378_MBHC_CTL_SPARE_1 0x40180058
|
||||
#define WCD9378_MICB1_TEST_CTL_2 0x4018006c
|
||||
#define WCD9378_MICB2_TEST_CTL_2 0x4018006f
|
||||
#define WCD9378_MICB3_TEST_CTL_2 0x40180072
|
||||
#define WCD9378_TX_COM_TXFE_DIV_CTL 0x4018007b
|
||||
#define WCD9378_TX_COM_TXFE_DIV_SEQ_BYPASS BIT(7)
|
||||
#define WCD9378_SLEEP_CTL 0x40180103
|
||||
#define WCD9378_SLEEP_CTL_BG_CTL_MASK GENMASK(3, 1)
|
||||
#define WCD9378_SLEEP_CTL_BG_EN BIT(7)
|
||||
#define WCD9378_SLEEP_CTL_LDOL_BG_SEL BIT(6)
|
||||
#define WCD9378_TX_NEW_CH12_MUX 0x4018012e
|
||||
#define WCD9378_TX_NEW_CH12_MUX_CH1_SEL_MASK GENMASK(2, 0)
|
||||
#define WCD9378_TX_NEW_CH12_MUX_CH2_SEL_MASK GENMASK(5, 3)
|
||||
#define WCD9378_TX_NEW_CH34_MUX 0x4018012f
|
||||
#define WCD9378_TX_NEW_CH34_MUX_CH3_SEL_MASK GENMASK(2, 0)
|
||||
#define WCD9378_HPH_RDAC_GAIN_CTL 0x40180132
|
||||
#define WCD9378_HPH_RDAC_HD2_CTL_L 0x40180133
|
||||
#define WCD9378_HPH_RDAC_HD2_CTL_R 0x40180136
|
||||
|
||||
/* Digital page */
|
||||
#define WCD9378_TOP_CLK_CFG 0x40180407
|
||||
#define WCD9378_CDC_ANA_TX_CLK_CTL 0x40180417
|
||||
#define WCD9378_CDC_ANA_TXSCBIAS_CLK_EN BIT(0)
|
||||
#define WCD9378_CDC_AMIC_CTL 0x4018045a
|
||||
#define WCD9378_PDM_WD_CTL0 0x40180465
|
||||
#define WCD9378_PDM_WD_CTL1 0x40180466
|
||||
#define WCD9378_EFUSE_REG_16 0x401804c0
|
||||
#define WCD9378_EFUSE_REG_29 0x401804cd
|
||||
#define WCD9378_PLATFORM_CTL 0x401804f0
|
||||
|
||||
/* Sequencer block (SEQR) */
|
||||
#define WCD9378_SYS_USAGE_CTRL 0x40180501
|
||||
#define WCD9378_SYS_USAGE_CTRL_MASK GENMASK(3, 0)
|
||||
#define WCD9378_HPH_UP_T0 0x40180510
|
||||
#define WCD9378_HPH_UP_T9 0x40180519
|
||||
#define WCD9378_HPH_DN_T0 0x4018051b
|
||||
#define WCD9378_SEQ_TX0_STAT 0x40180592
|
||||
#define WCD9378_SEQ_TX1_STAT 0x40180593
|
||||
#define WCD9378_SEQ_TX2_STAT 0x40180594
|
||||
#define WCD9378_MICB_REMAP_TABLE_VAL_3 0x401805a3
|
||||
#define WCD9378_MICB_REMAP_TABLE_VAL_4 0x401805a4
|
||||
#define WCD9378_MICB_REMAP_TABLE_VAL_5 0x401805a5
|
||||
#define WCD9378_SM0_MB_SEL 0x401805b0
|
||||
#define WCD9378_SM1_MB_SEL 0x401805b1
|
||||
#define WCD9378_SM2_MB_SEL 0x401805b2
|
||||
#define WCD9378_SM_MB_SEL_MASK GENMASK(1, 0)
|
||||
#define WCD9378_MB_PULLUP_EN 0x401805b3
|
||||
|
||||
/* SDCA function activation (one per function) */
|
||||
/* SmartAMP SDCA function */
|
||||
#define WCD9378_SMP_AMP_FUNC_STAT 0x40880000
|
||||
#define WCD9378_SMP_AMP_FUNC_ACT 0x40880008
|
||||
|
||||
/* SmartJACK SDCA function (hosts ADC2 when fed from AMIC2) */
|
||||
#define WCD9378_CMT_GRP_MASK 0x40c00008
|
||||
#define WCD9378_SMP_JACK_IT31_MICB 0x40c00798
|
||||
#define WCD9378_SMP_JACK_IT31_USAGE 0x40c007a0
|
||||
#define WCD9378_SMP_JACK_PDE34_REQ_PS 0x40c00808
|
||||
#define WCD9378_SMP_JACK_FUNC_STAT 0x40c80000
|
||||
#define WCD9378_SMP_JACK_FUNC_ACT 0x40c80008
|
||||
#define WCD9378_SMP_MIC_CTRL0_FUNC_STAT 0x41080000
|
||||
#define WCD9378_SMP_MIC_CTRL0_FUNC_ACT 0x41080008
|
||||
#define WCD9378_SMP_MIC_CTRL1_FUNC_STAT 0x41480000
|
||||
#define WCD9378_SMP_MIC_CTRL1_FUNC_ACT 0x41480008
|
||||
#define WCD9378_SMP_MIC_CTRL2_FUNC_STAT 0x41880000
|
||||
#define WCD9378_SMP_MIC_CTRL2_FUNC_ACT 0x41880008
|
||||
#define WCD9378_SMP_JACK_PDE34_ACT_PS 0x40c80800
|
||||
|
||||
/* SmartMIC0/1/2 SDCA functions (ADC1/ADC2/ADC3 sequencers) */
|
||||
#define WCD9378_SMP_MIC_BASE(n) (0x41000000 + (n) * 0x400000)
|
||||
#define WCD9378_SMP_MIC_IT11_MICB(n) (WCD9378_SMP_MIC_BASE(n) + 0x98)
|
||||
#define WCD9378_SMP_MIC_IT11_USAGE(n) (WCD9378_SMP_MIC_BASE(n) + 0xa0)
|
||||
#define WCD9378_SMP_MIC_PDE11_REQ_PS(n) (WCD9378_SMP_MIC_BASE(n) + 0x108)
|
||||
#define WCD9378_SMP_MIC_OT10_USAGE(n) (WCD9378_SMP_MIC_BASE(n) + 0x3a0)
|
||||
#define WCD9378_SMP_MIC_FUNC_STAT(n) (WCD9378_SMP_MIC_BASE(n) + 0x80000)
|
||||
#define WCD9378_SMP_MIC_FUNC_ACT(n) (WCD9378_SMP_MIC_BASE(n) + 0x80008)
|
||||
#define WCD9378_SMP_MIC_PDE11_ACT_PS(n) (WCD9378_SMP_MIC_BASE(n) + 0x80100)
|
||||
|
||||
#define WCD9378_MAX_REGISTER 0x41900070
|
||||
|
||||
/*
|
||||
* Raw (16-bit, non-paged) Qualcomm slave SCP registers, written with
|
||||
* sdw_write() directly. Bus clock indication towards the codec.
|
||||
*/
|
||||
#define WCD9378_SWRS_SCP_BASE_CLK 0x4d
|
||||
#define WCD9378_SWRS_SCP_BUSCLK_SCALE_BANK0 0x62
|
||||
#define WCD9378_SWRS_SCP_BUSCLK_SCALE_BANK1 0x72
|
||||
#define WCD9378_SWRS_SCP_HOST_CLK_DIV2_CTL(m) (0xe0 + 0x10 * (m))
|
||||
#define WCD9378_SWRS_BASE_CLK_19P2MHZ 0x01
|
||||
#define WCD9378_SWRS_CLK_SCALE_DIV2 0x02 /* 9.6 MHz */
|
||||
#define WCD9378_SWRS_CLK_SCALE_DIV4 0x03 /* 4.8 MHz */
|
||||
|
||||
/* ITxx_USAGE ADC mode values */
|
||||
#define WCD9378_ADC_USAGE_HIFI 0x01
|
||||
#define WCD9378_ADC_USAGE_LO_HIF 0x02
|
||||
#define WCD9378_ADC_USAGE_NORMAL 0x03
|
||||
#define WCD9378_ADC_USAGE_LP 0x05
|
||||
#define WCD9378_ADC_USAGE_OFF 0x00
|
||||
|
||||
/* ITxx_MICB usage values */
|
||||
#define WCD9378_MICB_USAGE_OFF 0x00
|
||||
#define WCD9378_MICB_USAGE_PULL_DOWN 0x01
|
||||
#define WCD9378_MICB_USAGE_1P2V 0x02
|
||||
#define WCD9378_MICB_USAGE_1P8V_OR_PULLUP 0x03
|
||||
#define WCD9378_MICB_USAGE_2P5V 0x04
|
||||
#define WCD9378_MICB_USAGE_2P75V 0x05
|
||||
#define WCD9378_MICB_USAGE_2P2V 0xf0
|
||||
#define WCD9378_MICB_USAGE_2P7V 0xf1
|
||||
#define WCD9378_MICB_USAGE_2P8V 0xf2
|
||||
#define WCD9378_MICB_USAGE_REMAP_TABLE_3 0xf3
|
||||
#define WCD9378_MICB_USAGE_REMAP_TABLE_4 0xf4
|
||||
#define WCD9378_MICB_USAGE_REMAP_TABLE_5 0xf5
|
||||
|
||||
/* PDExx_REQ_PS power states */
|
||||
#define WCD9378_PDE_PS0_ON 0x00
|
||||
#define WCD9378_PDE_PS3_OFF 0x03
|
||||
|
||||
#define WCD9378_MAX_MICBIAS 3
|
||||
#define WCD9378_MAX_SWR_CH_IDS 15
|
||||
#define WCD9378_SWRM_CH_MASK(ch_idx) BIT((ch_idx) - 1)
|
||||
|
||||
enum wcd9378_tx_sdw_ports {
|
||||
WCD9378_ADC_1_PORT = 1,
|
||||
WCD9378_ADC_2_PORT,
|
||||
WCD9378_ADC_3_PORT,
|
||||
WCD9378_DMIC_0_1_MBHC_PORT,
|
||||
WCD9378_DMIC_2_5_PORT,
|
||||
WCD9378_MAX_TX_SWR_PORTS = WCD9378_DMIC_2_5_PORT,
|
||||
};
|
||||
|
||||
enum wcd9378_rx_sdw_ports {
|
||||
WCD9378_HPH_PORT = 1,
|
||||
WCD9378_CLSH_PORT,
|
||||
WCD9378_COMP_PORT,
|
||||
WCD9378_LO_PORT,
|
||||
WCD9378_DSD_PORT,
|
||||
WCD9378_MAX_SWR_PORTS = WCD9378_DSD_PORT,
|
||||
};
|
||||
|
||||
enum wcd9378_tx_sdw_channels {
|
||||
WCD9378_ADC1,
|
||||
WCD9378_ADC2,
|
||||
WCD9378_ADC3,
|
||||
WCD9378_DMIC0,
|
||||
WCD9378_DMIC1,
|
||||
WCD9378_MBHC,
|
||||
WCD9378_DMIC2,
|
||||
WCD9378_DMIC3,
|
||||
WCD9378_DMIC4,
|
||||
WCD9378_DMIC5,
|
||||
};
|
||||
|
||||
enum wcd9378_rx_sdw_channels {
|
||||
WCD9378_HPH_L,
|
||||
WCD9378_HPH_R,
|
||||
WCD9378_CLSH,
|
||||
WCD9378_COMP_L,
|
||||
WCD9378_COMP_R,
|
||||
WCD9378_LO,
|
||||
WCD9378_DSD_L,
|
||||
WCD9378_DSD_R,
|
||||
};
|
||||
|
||||
struct wcd9378_priv;
|
||||
struct wcd9378_sdw_priv {
|
||||
struct sdw_slave *sdev;
|
||||
struct sdw_stream_config sconfig;
|
||||
struct sdw_stream_runtime *sruntime;
|
||||
struct sdw_port_config port_config[WCD9378_MAX_SWR_PORTS];
|
||||
struct wcd_sdw_ch_info *ch_info;
|
||||
bool port_enable[WCD9378_MAX_SWR_CH_IDS];
|
||||
unsigned int master_channel_map[SDW_MAX_PORTS];
|
||||
int active_ports;
|
||||
bool is_tx;
|
||||
struct wcd9378_priv *wcd9378;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_WCD9378_SDW)
|
||||
int wcd9378_sdw_hw_params(struct wcd9378_sdw_priv *wcd,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai);
|
||||
#else
|
||||
static inline int wcd9378_sdw_hw_params(struct wcd9378_sdw_priv *wcd,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __WCD9378_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue