forked from Minki/linux
Merge branch 'for-5.16' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-5.17 so we can apply new Tegra work
This commit is contained in:
commit
67140b64b6
@ -19,6 +19,9 @@ properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
|
@ -147,7 +147,7 @@ struct snd_soc_acpi_link_adr {
|
||||
*/
|
||||
/* Descriptor for SST ASoC machine driver */
|
||||
struct snd_soc_acpi_mach {
|
||||
const u8 id[ACPI_ID_LEN];
|
||||
u8 id[ACPI_ID_LEN];
|
||||
const struct snd_soc_acpi_codecs *comp_ids;
|
||||
const u32 link_mask;
|
||||
const struct snd_soc_acpi_link_adr *links;
|
||||
|
@ -146,10 +146,11 @@ static int snd_acp6x_probe(struct pci_dev *pci,
|
||||
{
|
||||
struct acp6x_dev_data *adata;
|
||||
struct platform_device_info pdevinfo[ACP6x_DEVS];
|
||||
int ret, index;
|
||||
int index = 0;
|
||||
int val = 0x00;
|
||||
u32 addr;
|
||||
unsigned int irqflags;
|
||||
int ret;
|
||||
|
||||
irqflags = IRQF_SHARED;
|
||||
/* Yellow Carp device check */
|
||||
|
@ -26,34 +26,6 @@ static const struct spi_device_id cs35l41_id_spi[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(spi, cs35l41_id_spi);
|
||||
|
||||
static void cs35l41_spi_otp_setup(struct cs35l41_private *cs35l41,
|
||||
bool is_pre_setup, unsigned int *freq)
|
||||
{
|
||||
struct spi_device *spi;
|
||||
u32 orig_spi_freq;
|
||||
|
||||
spi = to_spi_device(cs35l41->dev);
|
||||
|
||||
if (!spi) {
|
||||
dev_err(cs35l41->dev, "%s: No SPI device\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_pre_setup) {
|
||||
orig_spi_freq = spi->max_speed_hz;
|
||||
if (orig_spi_freq > CS35L41_SPI_MAX_FREQ_OTP) {
|
||||
spi->max_speed_hz = CS35L41_SPI_MAX_FREQ_OTP;
|
||||
spi_setup(spi);
|
||||
}
|
||||
*freq = orig_spi_freq;
|
||||
} else {
|
||||
if (spi->max_speed_hz != *freq) {
|
||||
spi->max_speed_hz = *freq;
|
||||
spi_setup(spi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int cs35l41_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct regmap_config *regmap_config = &cs35l41_regmap_spi;
|
||||
@ -65,6 +37,9 @@ static int cs35l41_spi_probe(struct spi_device *spi)
|
||||
if (!cs35l41)
|
||||
return -ENOMEM;
|
||||
|
||||
spi->max_speed_hz = CS35L41_SPI_MAX_FREQ;
|
||||
spi_setup(spi);
|
||||
|
||||
spi_set_drvdata(spi, cs35l41);
|
||||
cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config);
|
||||
if (IS_ERR(cs35l41->regmap)) {
|
||||
@ -75,7 +50,6 @@ static int cs35l41_spi_probe(struct spi_device *spi)
|
||||
|
||||
cs35l41->dev = &spi->dev;
|
||||
cs35l41->irq = spi->irq;
|
||||
cs35l41->otp_setup = cs35l41_spi_otp_setup;
|
||||
|
||||
return cs35l41_probe(cs35l41, pdata);
|
||||
}
|
||||
|
@ -438,7 +438,6 @@ static int cs35l41_otp_unpack(void *data)
|
||||
const struct cs35l41_otp_packed_element_t *otp_map;
|
||||
struct cs35l41_private *cs35l41 = data;
|
||||
int bit_offset, word_offset, ret, i;
|
||||
unsigned int orig_spi_freq;
|
||||
unsigned int bit_sum = 8;
|
||||
u32 otp_val, otp_id_reg;
|
||||
u32 *otp_mem;
|
||||
@ -462,9 +461,6 @@ static int cs35l41_otp_unpack(void *data)
|
||||
goto err_otp_unpack;
|
||||
}
|
||||
|
||||
if (cs35l41->otp_setup)
|
||||
cs35l41->otp_setup(cs35l41, true, &orig_spi_freq);
|
||||
|
||||
ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem,
|
||||
CS35L41_OTP_SIZE_WORDS);
|
||||
if (ret < 0) {
|
||||
@ -472,9 +468,6 @@ static int cs35l41_otp_unpack(void *data)
|
||||
goto err_otp_unpack;
|
||||
}
|
||||
|
||||
if (cs35l41->otp_setup)
|
||||
cs35l41->otp_setup(cs35l41, false, &orig_spi_freq);
|
||||
|
||||
otp_map = otp_map_match->map;
|
||||
|
||||
bit_offset = otp_map_match->bit_offset;
|
||||
|
@ -728,7 +728,7 @@
|
||||
#define CS35L41_FS2_WINDOW_MASK 0x00FFF800
|
||||
#define CS35L41_FS2_WINDOW_SHIFT 12
|
||||
|
||||
#define CS35L41_SPI_MAX_FREQ_OTP 4000000
|
||||
#define CS35L41_SPI_MAX_FREQ 4000000
|
||||
|
||||
#define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
|
||||
#define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
|
||||
@ -781,8 +781,6 @@ struct cs35l41_private {
|
||||
int irq;
|
||||
/* GPIO for /RST */
|
||||
struct gpio_desc *reset_gpio;
|
||||
void (*otp_setup)(struct cs35l41_private *cs35l41, bool is_pre_setup,
|
||||
unsigned int *freq);
|
||||
};
|
||||
|
||||
int cs35l41_probe(struct cs35l41_private *cs35l41,
|
||||
|
@ -2188,7 +2188,7 @@ static int rx_macro_config_classh(struct snd_soc_component *component,
|
||||
snd_soc_component_update_bits(component,
|
||||
CDC_RX_CLSH_DECAY_CTRL,
|
||||
CDC_RX_CLSH_DECAY_RATE_MASK, 0x0);
|
||||
snd_soc_component_update_bits(component,
|
||||
snd_soc_component_write_field(component,
|
||||
CDC_RX_RX1_RX_PATH_CFG0,
|
||||
CDC_RX_RXn_CLSH_EN_MASK, 0x1);
|
||||
break;
|
||||
|
@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver);
|
||||
MODULE_DESCRIPTION("ASoC RK817 codec driver");
|
||||
MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:rk817-codec");
|
||||
|
@ -2858,6 +2858,8 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682)
|
||||
|
||||
for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) {
|
||||
struct clk_init_data init = { };
|
||||
struct clk_parent_data parent_data;
|
||||
const struct clk_hw *parent;
|
||||
|
||||
dai_clk_hw = &rt5682->dai_clks_hw[i];
|
||||
|
||||
@ -2865,17 +2867,17 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682)
|
||||
case RT5682_DAI_WCLK_IDX:
|
||||
/* Make MCLK the parent of WCLK */
|
||||
if (rt5682->mclk) {
|
||||
init.parent_data = &(struct clk_parent_data){
|
||||
parent_data = (struct clk_parent_data){
|
||||
.fw_name = "mclk",
|
||||
};
|
||||
init.parent_data = &parent_data;
|
||||
init.num_parents = 1;
|
||||
}
|
||||
break;
|
||||
case RT5682_DAI_BCLK_IDX:
|
||||
/* Make WCLK the parent of BCLK */
|
||||
init.parent_hws = &(const struct clk_hw *){
|
||||
&rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]
|
||||
};
|
||||
parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX];
|
||||
init.parent_hws = &parent;
|
||||
init.num_parents = 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -2693,6 +2693,8 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component)
|
||||
|
||||
for (i = 0; i < RT5682S_DAI_NUM_CLKS; ++i) {
|
||||
struct clk_init_data init = { };
|
||||
struct clk_parent_data parent_data;
|
||||
const struct clk_hw *parent;
|
||||
|
||||
dai_clk_hw = &rt5682s->dai_clks_hw[i];
|
||||
|
||||
@ -2700,17 +2702,17 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component)
|
||||
case RT5682S_DAI_WCLK_IDX:
|
||||
/* Make MCLK the parent of WCLK */
|
||||
if (rt5682s->mclk) {
|
||||
init.parent_data = &(struct clk_parent_data){
|
||||
parent_data = (struct clk_parent_data){
|
||||
.fw_name = "mclk",
|
||||
};
|
||||
init.parent_data = &parent_data;
|
||||
init.num_parents = 1;
|
||||
}
|
||||
break;
|
||||
case RT5682S_DAI_BCLK_IDX:
|
||||
/* Make WCLK the parent of BCLK */
|
||||
init.parent_hws = &(const struct clk_hw *){
|
||||
&rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX]
|
||||
};
|
||||
parent = &rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX];
|
||||
init.parent_hws = &parent;
|
||||
init.num_parents = 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -1896,9 +1896,8 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
wcd->dai[dai->id].sconfig.rate = params_rate(params);
|
||||
wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream);
|
||||
|
||||
return 0;
|
||||
return wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream);
|
||||
}
|
||||
|
||||
static int wcd934x_hw_free(struct snd_pcm_substream *substream,
|
||||
|
@ -1174,6 +1174,9 @@ static bool wcd938x_readonly_register(struct device *dev, unsigned int reg)
|
||||
case WCD938X_DIGITAL_INTR_STATUS_0:
|
||||
case WCD938X_DIGITAL_INTR_STATUS_1:
|
||||
case WCD938X_DIGITAL_INTR_STATUS_2:
|
||||
case WCD938X_DIGITAL_INTR_CLEAR_0:
|
||||
case WCD938X_DIGITAL_INTR_CLEAR_1:
|
||||
case WCD938X_DIGITAL_INTR_CLEAR_2:
|
||||
case WCD938X_DIGITAL_SWR_HM_TEST_0:
|
||||
case WCD938X_DIGITAL_SWR_HM_TEST_1:
|
||||
case WCD938X_DIGITAL_EFUSE_T_DATA_0:
|
||||
|
@ -602,8 +602,9 @@ static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl)
|
||||
switch (cs_dsp->fw_ver) {
|
||||
case 0:
|
||||
case 1:
|
||||
snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x",
|
||||
cs_dsp->name, region_name, cs_ctl->alg_region.alg);
|
||||
ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
|
||||
"%s %s %x", cs_dsp->name, region_name,
|
||||
cs_ctl->alg_region.alg);
|
||||
break;
|
||||
case 2:
|
||||
ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
|
||||
|
@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
|
||||
.sof_fw_filename = "sof-cml.ri",
|
||||
.sof_tplg_filename = "sof-cml-da7219-max98390.tplg",
|
||||
},
|
||||
{
|
||||
.id = "ESSX8336",
|
||||
.drv_name = "sof-essx8336",
|
||||
.sof_fw_filename = "sof-cml.ri",
|
||||
.sof_tplg_filename = "sof-cml-es8336.tplg",
|
||||
},
|
||||
{},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
|
||||
|
@ -550,6 +550,10 @@ struct audio_hw_clk_cfg {
|
||||
uint32_t clock_root;
|
||||
} __packed;
|
||||
|
||||
struct audio_hw_clk_rel_cfg {
|
||||
uint32_t clock_id;
|
||||
} __packed;
|
||||
|
||||
#define PARAM_ID_HW_EP_POWER_MODE_CFG 0x8001176
|
||||
#define AR_HW_EP_POWER_MODE_0 0 /* default */
|
||||
#define AR_HW_EP_POWER_MODE_1 1 /* XO Shutdown allowed */
|
||||
|
@ -390,7 +390,7 @@ struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate,
|
||||
int ret = 0;
|
||||
|
||||
if (port_id < 0) {
|
||||
dev_err(dev, "Invalid port_id 0x%x\n", port_id);
|
||||
dev_err(dev, "Invalid port_id %d\n", port_id);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
@ -508,7 +508,7 @@ int q6adm_matrix_map(struct device *dev, int path,
|
||||
int port_idx = payload_map.port_id[i];
|
||||
|
||||
if (port_idx < 0) {
|
||||
dev_err(dev, "Invalid port_id 0x%x\n",
|
||||
dev_err(dev, "Invalid port_id %d\n",
|
||||
payload_map.port_id[i]);
|
||||
kfree(pkt);
|
||||
return -EINVAL;
|
||||
|
@ -269,9 +269,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: q6asm_open_write failed\n", __func__);
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
prtd->audio_client = NULL;
|
||||
return -ENOMEM;
|
||||
goto open_err;
|
||||
}
|
||||
|
||||
prtd->session_id = q6asm_get_session_id(prtd->audio_client);
|
||||
@ -279,7 +277,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
|
||||
prtd->session_id, substream->stream);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret);
|
||||
return ret;
|
||||
goto routing_err;
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
@ -301,10 +299,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
|
||||
}
|
||||
if (ret < 0)
|
||||
dev_info(dev, "%s: CMD Format block failed\n", __func__);
|
||||
else
|
||||
prtd->state = Q6ASM_STREAM_RUNNING;
|
||||
|
||||
prtd->state = Q6ASM_STREAM_RUNNING;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
routing_err:
|
||||
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
|
||||
open_err:
|
||||
q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
prtd->audio_client = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int q6asm_dai_trigger(struct snd_soc_component *component,
|
||||
|
@ -42,6 +42,12 @@ struct prm_cmd_request_rsc {
|
||||
struct audio_hw_clk_cfg clock_id;
|
||||
} __packed;
|
||||
|
||||
struct prm_cmd_release_rsc {
|
||||
struct apm_module_param_data param_data;
|
||||
uint32_t num_clk_id;
|
||||
struct audio_hw_clk_rel_cfg clock_id;
|
||||
} __packed;
|
||||
|
||||
static int q6prm_send_cmd_sync(struct q6prm *prm, struct gpr_pkt *pkt, uint32_t rsp_opcode)
|
||||
{
|
||||
return audioreach_send_cmd_sync(prm->dev, prm->gdev, &prm->result, &prm->lock,
|
||||
@ -102,8 +108,8 @@ int q6prm_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, uint32_
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6prm_unvote_lpass_core_hw);
|
||||
|
||||
int q6prm_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_root,
|
||||
unsigned int freq)
|
||||
static int q6prm_request_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_root,
|
||||
unsigned int freq)
|
||||
{
|
||||
struct q6prm *prm = dev_get_drvdata(dev->parent);
|
||||
struct apm_module_param_data *param_data;
|
||||
@ -138,6 +144,49 @@ int q6prm_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int q6prm_release_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_root,
|
||||
unsigned int freq)
|
||||
{
|
||||
struct q6prm *prm = dev_get_drvdata(dev->parent);
|
||||
struct apm_module_param_data *param_data;
|
||||
struct prm_cmd_release_rsc *rel;
|
||||
gpr_device_t *gdev = prm->gdev;
|
||||
struct gpr_pkt *pkt;
|
||||
int rc;
|
||||
|
||||
pkt = audioreach_alloc_cmd_pkt(sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id,
|
||||
GPR_PRM_MODULE_IID);
|
||||
if (IS_ERR(pkt))
|
||||
return PTR_ERR(pkt);
|
||||
|
||||
rel = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
|
||||
|
||||
param_data = &rel->param_data;
|
||||
|
||||
param_data->module_instance_id = GPR_PRM_MODULE_IID;
|
||||
param_data->error_code = 0;
|
||||
param_data->param_id = PARAM_ID_RSC_AUDIO_HW_CLK;
|
||||
param_data->param_size = sizeof(*rel) - APM_MODULE_PARAM_DATA_SIZE;
|
||||
|
||||
rel->num_clk_id = 1;
|
||||
rel->clock_id.clock_id = clk_id;
|
||||
|
||||
rc = q6prm_send_cmd_sync(prm, pkt, PRM_CMD_RSP_RELEASE_HW_RSC);
|
||||
|
||||
kfree(pkt);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int q6prm_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_root,
|
||||
unsigned int freq)
|
||||
{
|
||||
if (freq)
|
||||
return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq);
|
||||
|
||||
return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6prm_set_lpass_clock);
|
||||
|
||||
static int prm_callback(struct gpr_resp_pkt *data, void *priv, int op)
|
||||
|
@ -372,6 +372,12 @@ int q6routing_stream_open(int fedai_id, int perf_mode,
|
||||
}
|
||||
|
||||
session = &routing_data->sessions[stream_id - 1];
|
||||
if (session->port_id < 0) {
|
||||
dev_err(routing_data->dev, "Routing not setup for MultiMedia%d Session\n",
|
||||
session->fedai_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata = &routing_data->port_data[session->port_id];
|
||||
|
||||
mutex_lock(&routing_data->lock);
|
||||
@ -495,7 +501,11 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
|
||||
session->port_id = be_id;
|
||||
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update);
|
||||
} else {
|
||||
session->port_id = -1;
|
||||
if (session->port_id == be_id) {
|
||||
session->port_id = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update);
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev {
|
||||
spinlock_t lock; /* xfer lock */
|
||||
bool has_playback;
|
||||
bool has_capture;
|
||||
struct snd_soc_dai_driver *dai;
|
||||
};
|
||||
|
||||
static int to_ch_num(unsigned int val)
|
||||
@ -1310,19 +1311,14 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver i2s_tdm_dai = {
|
||||
static const struct snd_soc_dai_driver i2s_tdm_dai = {
|
||||
.probe = rockchip_i2s_tdm_dai_probe,
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
},
|
||||
.ops = &rockchip_i2s_tdm_dai_ops,
|
||||
};
|
||||
|
||||
static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
|
||||
static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
|
||||
{
|
||||
struct snd_soc_dai_driver *dai;
|
||||
struct property *dma_names;
|
||||
const char *dma_name;
|
||||
u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
|
||||
@ -1337,19 +1333,33 @@ static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
|
||||
i2s_tdm->has_capture = true;
|
||||
}
|
||||
|
||||
dai = devm_kmemdup(i2s_tdm->dev, &i2s_tdm_dai,
|
||||
sizeof(*dai), GFP_KERNEL);
|
||||
if (!dai)
|
||||
return -ENOMEM;
|
||||
|
||||
if (i2s_tdm->has_playback) {
|
||||
i2s_tdm_dai.playback.channels_min = 2;
|
||||
i2s_tdm_dai.playback.channels_max = 8;
|
||||
i2s_tdm_dai.playback.rates = SNDRV_PCM_RATE_8000_192000;
|
||||
i2s_tdm_dai.playback.formats = formats;
|
||||
dai->playback.stream_name = "Playback";
|
||||
dai->playback.channels_min = 2;
|
||||
dai->playback.channels_max = 8;
|
||||
dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
|
||||
dai->playback.formats = formats;
|
||||
}
|
||||
|
||||
if (i2s_tdm->has_capture) {
|
||||
i2s_tdm_dai.capture.channels_min = 2;
|
||||
i2s_tdm_dai.capture.channels_max = 8;
|
||||
i2s_tdm_dai.capture.rates = SNDRV_PCM_RATE_8000_192000;
|
||||
i2s_tdm_dai.capture.formats = formats;
|
||||
dai->capture.stream_name = "Capture";
|
||||
dai->capture.channels_min = 2;
|
||||
dai->capture.channels_max = 8;
|
||||
dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
|
||||
dai->capture.formats = formats;
|
||||
}
|
||||
|
||||
if (i2s_tdm->clk_trcm != TRCM_TXRX)
|
||||
dai->symmetric_rate = 1;
|
||||
|
||||
i2s_tdm->dai = dai;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm,
|
||||
@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&i2s_tdm->lock);
|
||||
i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data;
|
||||
|
||||
rockchip_i2s_tdm_init_dai(i2s_tdm);
|
||||
|
||||
i2s_tdm->frame_width = 64;
|
||||
|
||||
i2s_tdm->clk_trcm = TRCM_TXRX;
|
||||
@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
|
||||
}
|
||||
i2s_tdm->clk_trcm = TRCM_RX;
|
||||
}
|
||||
if (i2s_tdm->clk_trcm != TRCM_TXRX)
|
||||
i2s_tdm_dai.symmetric_rate = 1;
|
||||
|
||||
ret = rockchip_i2s_tdm_init_dai(i2s_tdm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
|
||||
if (IS_ERR(i2s_tdm->grf))
|
||||
@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&rockchip_i2s_tdm_component,
|
||||
&i2s_tdm_dai, 1);
|
||||
i2s_tdm->dai, 1);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Could not register DAI\n");
|
||||
|
@ -20,8 +20,10 @@ static bool snd_soc_acpi_id_present(struct snd_soc_acpi_mach *machine)
|
||||
|
||||
if (comp_ids) {
|
||||
for (i = 0; i < comp_ids->num_codecs; i++) {
|
||||
if (acpi_dev_present(comp_ids->codecs[i], NULL, -1))
|
||||
if (acpi_dev_present(comp_ids->codecs[i], NULL, -1)) {
|
||||
strscpy(machine->id, comp_ids->codecs[i], ACPI_ID_LEN);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2700,6 +2700,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
|
||||
/* remove dynamic controls from the component driver */
|
||||
int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
|
||||
{
|
||||
struct snd_card *card = comp->card->snd_card;
|
||||
struct snd_soc_dobj *dobj, *next_dobj;
|
||||
int pass = SOC_TPLG_PASS_END;
|
||||
|
||||
@ -2707,6 +2708,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
|
||||
while (pass >= SOC_TPLG_PASS_START) {
|
||||
|
||||
/* remove mixer controls */
|
||||
down_write(&card->controls_rwsem);
|
||||
list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,
|
||||
list) {
|
||||
|
||||
@ -2745,6 +2747,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_write(&card->controls_rwsem);
|
||||
pass--;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
|
||||
#define IDISP_VID_INTEL 0x80860000
|
||||
#define CODEC_PROBE_RETRIES 3
|
||||
|
||||
/* load the legacy HDA codec driver */
|
||||
static int request_codec_module(struct hda_codec *codec)
|
||||
@ -121,12 +122,15 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
|
||||
u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) |
|
||||
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
|
||||
u32 resp = -1;
|
||||
int ret;
|
||||
int ret, retry = 0;
|
||||
|
||||
do {
|
||||
mutex_lock(&hbus->core.cmd_mutex);
|
||||
snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
|
||||
snd_hdac_bus_get_response(&hbus->core, address, &resp);
|
||||
mutex_unlock(&hbus->core.cmd_mutex);
|
||||
} while (resp == -1 && retry++ < CODEC_PROBE_RETRIES);
|
||||
|
||||
mutex_lock(&hbus->core.cmd_mutex);
|
||||
snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
|
||||
snd_hdac_bus_get_response(&hbus->core, address, &resp);
|
||||
mutex_unlock(&hbus->core.cmd_mutex);
|
||||
if (resp == -1)
|
||||
return -EIO;
|
||||
dev_dbg(sdev->dev, "HDA codec #%d probed OK: response: %x\n",
|
||||
|
@ -701,7 +701,7 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1);
|
||||
nb_bits = frame_len * (FIELD_GET(I2S_CGFR_CHLEN, cgfr) + 1);
|
||||
ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate,
|
||||
(nb_bits * rate));
|
||||
if (ret)
|
||||
|
@ -26,51 +26,162 @@ static const struct reg_default tegra186_dspk_reg_defaults[] = {
|
||||
{ TEGRA186_DSPK_CODEC_CTRL, 0x03000000 },
|
||||
};
|
||||
|
||||
static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol,
|
||||
static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
if (strstr(kcontrol->id.name, "FIFO Threshold"))
|
||||
ucontrol->value.integer.value[0] = dspk->rx_fifo_th;
|
||||
else if (strstr(kcontrol->id.name, "OSR Value"))
|
||||
ucontrol->value.integer.value[0] = dspk->osr_val;
|
||||
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
|
||||
ucontrol->value.integer.value[0] = dspk->lrsel;
|
||||
else if (strstr(kcontrol->id.name, "Channel Select"))
|
||||
ucontrol->value.integer.value[0] = dspk->ch_sel;
|
||||
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
|
||||
ucontrol->value.integer.value[0] = dspk->mono_to_stereo;
|
||||
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
|
||||
ucontrol->value.integer.value[0] = dspk->stereo_to_mono;
|
||||
ucontrol->value.integer.value[0] = dspk->rx_fifo_th;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol,
|
||||
static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
int val = ucontrol->value.integer.value[0];
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (strstr(kcontrol->id.name, "FIFO Threshold"))
|
||||
dspk->rx_fifo_th = val;
|
||||
else if (strstr(kcontrol->id.name, "OSR Value"))
|
||||
dspk->osr_val = val;
|
||||
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
|
||||
dspk->lrsel = val;
|
||||
else if (strstr(kcontrol->id.name, "Channel Select"))
|
||||
dspk->ch_sel = val;
|
||||
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
|
||||
dspk->mono_to_stereo = val;
|
||||
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
|
||||
dspk->stereo_to_mono = val;
|
||||
if (value == dspk->rx_fifo_th)
|
||||
return 0;
|
||||
|
||||
dspk->rx_fifo_th = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dspk->osr_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dspk->osr_val)
|
||||
return 0;
|
||||
|
||||
dspk->osr_val = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dspk->lrsel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dspk->lrsel)
|
||||
return 0;
|
||||
|
||||
dspk->lrsel = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dspk->ch_sel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dspk->ch_sel)
|
||||
return 0;
|
||||
|
||||
dspk->ch_sel = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dspk->mono_to_stereo)
|
||||
return 0;
|
||||
|
||||
dspk->mono_to_stereo = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dspk->stereo_to_mono)
|
||||
return 0;
|
||||
|
||||
dspk->stereo_to_mono = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra186_dspk *dspk = dev_get_drvdata(dev);
|
||||
@ -279,17 +390,19 @@ static const struct soc_enum tegra186_dspk_lrsel_enum =
|
||||
static const struct snd_kcontrol_new tegrat186_dspk_controls[] = {
|
||||
SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0,
|
||||
TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0,
|
||||
tegra186_dspk_get_control, tegra186_dspk_put_control),
|
||||
tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th),
|
||||
SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum,
|
||||
tegra186_dspk_get_control, tegra186_dspk_put_control),
|
||||
tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val),
|
||||
SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum,
|
||||
tegra186_dspk_get_control, tegra186_dspk_put_control),
|
||||
tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel),
|
||||
SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum,
|
||||
tegra186_dspk_get_control, tegra186_dspk_put_control),
|
||||
tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel),
|
||||
SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum,
|
||||
tegra186_dspk_get_control, tegra186_dspk_put_control),
|
||||
tegra186_dspk_get_mono_to_stereo,
|
||||
tegra186_dspk_put_mono_to_stereo),
|
||||
SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum,
|
||||
tegra186_dspk_get_control, tegra186_dspk_put_control),
|
||||
tegra186_dspk_get_stereo_to_mono,
|
||||
tegra186_dspk_put_stereo_to_mono),
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver tegra186_dspk_cmpnt = {
|
||||
|
@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
|
||||
.trigger = tegra_admaif_trigger,
|
||||
};
|
||||
|
||||
static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
long *uctl_val = &ucontrol->value.integer.value[0];
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
|
||||
if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
|
||||
*uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
|
||||
else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
|
||||
*uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
|
||||
else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
|
||||
*uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
|
||||
else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
|
||||
*uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
|
||||
ucontrol->value.enumerated.item[0] =
|
||||
admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
|
||||
admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
|
||||
else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
|
||||
admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
|
||||
else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
|
||||
admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
|
||||
else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
|
||||
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
|
||||
if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
|
||||
return 0;
|
||||
|
||||
admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
|
||||
ucontrol->value.enumerated.item[0] =
|
||||
admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
|
||||
return 0;
|
||||
|
||||
admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
|
||||
ucontrol->value.enumerated.item[0] =
|
||||
admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
|
||||
return 0;
|
||||
|
||||
admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
|
||||
ucontrol->value.enumerated.item[0] =
|
||||
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
|
||||
return 0;
|
||||
|
||||
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
|
||||
@ -559,17 +635,21 @@ static const char * const tegra_admaif_mono_conv_text[] = {
|
||||
}
|
||||
|
||||
#define TEGRA_ADMAIF_CIF_CTRL(reg) \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\
|
||||
tegra_admaif_get_control, tegra_admaif_put_control, \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \
|
||||
tegra210_admaif_pget_mono_to_stereo, \
|
||||
tegra210_admaif_pput_mono_to_stereo, \
|
||||
tegra_admaif_mono_conv_text), \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\
|
||||
tegra_admaif_get_control, tegra_admaif_put_control, \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \
|
||||
tegra210_admaif_pget_stereo_to_mono, \
|
||||
tegra210_admaif_pput_stereo_to_mono, \
|
||||
tegra_admaif_stereo_conv_text), \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
|
||||
tegra_admaif_get_control, tegra_admaif_put_control, \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
|
||||
tegra210_admaif_cget_mono_to_stereo, \
|
||||
tegra210_admaif_cput_mono_to_stereo, \
|
||||
tegra_admaif_mono_conv_text), \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
|
||||
tegra_admaif_get_control, tegra_admaif_put_control, \
|
||||
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
|
||||
tegra210_admaif_cget_stereo_to_mono, \
|
||||
tegra210_admaif_cput_stereo_to_mono, \
|
||||
tegra_admaif_stereo_conv_text)
|
||||
|
||||
static struct snd_kcontrol_new tegra210_admaif_controls[] = {
|
||||
|
@ -193,6 +193,9 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;;
|
||||
|
||||
if (value == bytes_map[mc->reg])
|
||||
return 0;
|
||||
|
||||
if (value >= 0 && value <= 255) {
|
||||
/* update byte map and enable slot */
|
||||
bytes_map[mc->reg] = value;
|
||||
@ -511,8 +514,8 @@ static int tegra210_adx_platform_remove(struct platform_device *pdev)
|
||||
static const struct dev_pm_ops tegra210_adx_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
|
||||
tegra210_adx_runtime_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver tegra210_adx_driver = {
|
||||
|
@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
|
||||
unsigned int *item = uctl->value.enumerated.item;
|
||||
unsigned int value = e->values[item[0]];
|
||||
unsigned int i, bit_pos, reg_idx = 0, reg_val = 0;
|
||||
int change = 0;
|
||||
|
||||
if (item[0] >= e->items)
|
||||
return -EINVAL;
|
||||
@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
|
||||
|
||||
/* Update widget power if state has changed */
|
||||
if (snd_soc_component_test_bits(cmpnt, update[i].reg,
|
||||
update[i].mask, update[i].val))
|
||||
snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e,
|
||||
&update[i]);
|
||||
update[i].mask,
|
||||
update[i].val))
|
||||
change |= snd_soc_dapm_mux_update_power(dapm, kctl,
|
||||
item[0], e,
|
||||
&update[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return change;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_driver tegra210_ahub_dais[] = {
|
||||
|
@ -222,6 +222,9 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
|
||||
int reg = mc->reg;
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value == bytes_map[reg])
|
||||
return 0;
|
||||
|
||||
if (value >= 0 && value <= 255) {
|
||||
/* Update byte map and enable slot */
|
||||
bytes_map[reg] = value;
|
||||
@ -580,8 +583,8 @@ static int tegra210_amx_platform_remove(struct platform_device *pdev)
|
||||
static const struct dev_pm_ops tegra210_amx_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
|
||||
tegra210_amx_runtime_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver tegra210_amx_driver = {
|
||||
|
@ -156,51 +156,162 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
|
||||
if (strstr(kcontrol->id.name, "Boost Gain Volume"))
|
||||
ucontrol->value.integer.value[0] = dmic->boost_gain;
|
||||
else if (strstr(kcontrol->id.name, "Channel Select"))
|
||||
ucontrol->value.integer.value[0] = dmic->ch_select;
|
||||
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
|
||||
ucontrol->value.integer.value[0] = dmic->mono_to_stereo;
|
||||
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
|
||||
ucontrol->value.integer.value[0] = dmic->stereo_to_mono;
|
||||
else if (strstr(kcontrol->id.name, "OSR Value"))
|
||||
ucontrol->value.integer.value[0] = dmic->osr_val;
|
||||
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
|
||||
ucontrol->value.integer.value[0] = dmic->lrsel;
|
||||
ucontrol->value.integer.value[0] = dmic->boost_gain;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (strstr(kcontrol->id.name, "Boost Gain Volume"))
|
||||
dmic->boost_gain = value;
|
||||
else if (strstr(kcontrol->id.name, "Channel Select"))
|
||||
dmic->ch_select = ucontrol->value.integer.value[0];
|
||||
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
|
||||
dmic->mono_to_stereo = value;
|
||||
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
|
||||
dmic->stereo_to_mono = value;
|
||||
else if (strstr(kcontrol->id.name, "OSR Value"))
|
||||
dmic->osr_val = value;
|
||||
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
|
||||
dmic->lrsel = value;
|
||||
if (value == dmic->boost_gain)
|
||||
return 0;
|
||||
|
||||
dmic->boost_gain = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dmic->ch_select;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dmic->ch_select)
|
||||
return 0;
|
||||
|
||||
dmic->ch_select = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dmic->mono_to_stereo)
|
||||
return 0;
|
||||
|
||||
dmic->mono_to_stereo = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dmic->stereo_to_mono)
|
||||
return 0;
|
||||
|
||||
dmic->stereo_to_mono = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dmic->osr_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dmic->osr_val)
|
||||
return 0;
|
||||
|
||||
dmic->osr_val = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = dmic->lrsel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == dmic->lrsel)
|
||||
return 0;
|
||||
|
||||
dmic->lrsel = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = {
|
||||
.hw_params = tegra210_dmic_hw_params,
|
||||
};
|
||||
@ -287,19 +398,22 @@ static const struct soc_enum tegra210_dmic_lrsel_enum =
|
||||
|
||||
static const struct snd_kcontrol_new tegra210_dmic_controls[] = {
|
||||
SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0,
|
||||
tegra210_dmic_get_control, tegra210_dmic_put_control),
|
||||
tegra210_dmic_get_boost_gain,
|
||||
tegra210_dmic_put_boost_gain),
|
||||
SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum,
|
||||
tegra210_dmic_get_control, tegra210_dmic_put_control),
|
||||
tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select),
|
||||
SOC_ENUM_EXT("Mono To Stereo",
|
||||
tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control,
|
||||
tegra210_dmic_put_control),
|
||||
tegra210_dmic_mono_conv_enum,
|
||||
tegra210_dmic_get_mono_to_stereo,
|
||||
tegra210_dmic_put_mono_to_stereo),
|
||||
SOC_ENUM_EXT("Stereo To Mono",
|
||||
tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control,
|
||||
tegra210_dmic_put_control),
|
||||
tegra210_dmic_stereo_conv_enum,
|
||||
tegra210_dmic_get_stereo_to_mono,
|
||||
tegra210_dmic_put_stereo_to_mono),
|
||||
SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum,
|
||||
tegra210_dmic_get_control, tegra210_dmic_put_control),
|
||||
tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val),
|
||||
SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum,
|
||||
tegra210_dmic_get_control, tegra210_dmic_put_control),
|
||||
tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel),
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver tegra210_dmic_compnt = {
|
||||
|
@ -302,6 +302,229 @@ static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_get_loopback(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.integer.value[0] = i2s->loopback;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_put_loopback(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value == i2s->loopback)
|
||||
return 0;
|
||||
|
||||
i2s->loopback = value;
|
||||
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK,
|
||||
i2s->loopback << I2S_CTRL_LPBK_SHIFT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_get_fsync_width(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.integer.value[0] = i2s->fsync_width;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_put_fsync_width(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value == i2s->fsync_width)
|
||||
return 0;
|
||||
|
||||
i2s->fsync_width = value;
|
||||
|
||||
/*
|
||||
* Frame sync width is used only for FSYNC modes and not
|
||||
* applicable for LRCK modes. Reset value for this field is "0",
|
||||
* which means the width is one bit clock wide.
|
||||
* The width requirement may depend on the codec and in such
|
||||
* cases mixer control is used to update custom values. A value
|
||||
* of "N" here means, width is "N + 1" bit clock wide.
|
||||
*/
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
|
||||
I2S_CTRL_FSYNC_WIDTH_MASK,
|
||||
i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_TX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == i2s->stereo_to_mono[I2S_TX_PATH])
|
||||
return 0;
|
||||
|
||||
i2s->stereo_to_mono[I2S_TX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_TX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == i2s->mono_to_stereo[I2S_TX_PATH])
|
||||
return 0;
|
||||
|
||||
i2s->mono_to_stereo[I2S_TX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_RX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == i2s->stereo_to_mono[I2S_RX_PATH])
|
||||
return 0;
|
||||
|
||||
i2s->stereo_to_mono[I2S_RX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_RX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == i2s->mono_to_stereo[I2S_RX_PATH])
|
||||
return 0;
|
||||
|
||||
i2s->mono_to_stereo[I2S_RX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_pget_fifo_th(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.integer.value[0] = i2s->rx_fifo_th;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_pput_fifo_th(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value == i2s->rx_fifo_th)
|
||||
return 0;
|
||||
|
||||
i2s->rx_fifo_th = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_get_bclk_ratio(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
|
||||
ucontrol->value.integer.value[0] = i2s->bclk_ratio;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_put_bclk_ratio(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (value == i2s->bclk_ratio)
|
||||
return 0;
|
||||
|
||||
i2s->bclk_ratio = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai,
|
||||
unsigned int ratio)
|
||||
{
|
||||
@ -312,79 +535,6 @@ static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
long *uctl_val = &ucontrol->value.integer.value[0];
|
||||
|
||||
if (strstr(kcontrol->id.name, "Loopback"))
|
||||
*uctl_val = i2s->loopback;
|
||||
else if (strstr(kcontrol->id.name, "FSYNC Width"))
|
||||
*uctl_val = i2s->fsync_width;
|
||||
else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
|
||||
*uctl_val = i2s->stereo_to_mono[I2S_TX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
|
||||
*uctl_val = i2s->mono_to_stereo[I2S_TX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
|
||||
*uctl_val = i2s->stereo_to_mono[I2S_RX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
|
||||
*uctl_val = i2s->mono_to_stereo[I2S_RX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Playback FIFO Threshold"))
|
||||
*uctl_val = i2s->rx_fifo_th;
|
||||
else if (strstr(kcontrol->id.name, "BCLK Ratio"))
|
||||
*uctl_val = i2s->bclk_ratio;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
|
||||
if (strstr(kcontrol->id.name, "Loopback")) {
|
||||
i2s->loopback = value;
|
||||
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
|
||||
I2S_CTRL_LPBK_MASK,
|
||||
i2s->loopback << I2S_CTRL_LPBK_SHIFT);
|
||||
|
||||
} else if (strstr(kcontrol->id.name, "FSYNC Width")) {
|
||||
/*
|
||||
* Frame sync width is used only for FSYNC modes and not
|
||||
* applicable for LRCK modes. Reset value for this field is "0",
|
||||
* which means the width is one bit clock wide.
|
||||
* The width requirement may depend on the codec and in such
|
||||
* cases mixer control is used to update custom values. A value
|
||||
* of "N" here means, width is "N + 1" bit clock wide.
|
||||
*/
|
||||
i2s->fsync_width = value;
|
||||
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
|
||||
I2S_CTRL_FSYNC_WIDTH_MASK,
|
||||
i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT);
|
||||
|
||||
} else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) {
|
||||
i2s->stereo_to_mono[I2S_TX_PATH] = value;
|
||||
} else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) {
|
||||
i2s->mono_to_stereo[I2S_TX_PATH] = value;
|
||||
} else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) {
|
||||
i2s->stereo_to_mono[I2S_RX_PATH] = value;
|
||||
} else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) {
|
||||
i2s->mono_to_stereo[I2S_RX_PATH] = value;
|
||||
} else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) {
|
||||
i2s->rx_fifo_th = value;
|
||||
} else if (strstr(kcontrol->id.name, "BCLK Ratio")) {
|
||||
i2s->bclk_ratio = value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_set_timing_params(struct device *dev,
|
||||
unsigned int sample_size,
|
||||
unsigned int srate,
|
||||
@ -598,22 +748,28 @@ static const struct soc_enum tegra210_i2s_stereo_conv_enum =
|
||||
tegra210_i2s_stereo_conv_text);
|
||||
|
||||
static const struct snd_kcontrol_new tegra210_i2s_controls[] = {
|
||||
SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control,
|
||||
tegra210_i2s_put_control),
|
||||
SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control,
|
||||
tegra210_i2s_put_control),
|
||||
SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_loopback,
|
||||
tegra210_i2s_put_loopback),
|
||||
SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0,
|
||||
tegra210_i2s_get_fsync_width,
|
||||
tegra210_i2s_put_fsync_width),
|
||||
SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum,
|
||||
tegra210_i2s_get_control, tegra210_i2s_put_control),
|
||||
tegra210_i2s_cget_stereo_to_mono,
|
||||
tegra210_i2s_cput_stereo_to_mono),
|
||||
SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum,
|
||||
tegra210_i2s_get_control, tegra210_i2s_put_control),
|
||||
tegra210_i2s_cget_mono_to_stereo,
|
||||
tegra210_i2s_cput_mono_to_stereo),
|
||||
SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum,
|
||||
tegra210_i2s_get_control, tegra210_i2s_put_control),
|
||||
tegra210_i2s_pget_mono_to_stereo,
|
||||
tegra210_i2s_pput_mono_to_stereo),
|
||||
SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum,
|
||||
tegra210_i2s_get_control, tegra210_i2s_put_control),
|
||||
tegra210_i2s_pget_stereo_to_mono,
|
||||
tegra210_i2s_pput_stereo_to_mono),
|
||||
SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1,
|
||||
0, tegra210_i2s_get_control, tegra210_i2s_put_control),
|
||||
SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control,
|
||||
tegra210_i2s_put_control),
|
||||
0, tegra210_i2s_pget_fifo_th, tegra210_i2s_pput_fifo_th),
|
||||
SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0,
|
||||
tegra210_i2s_get_bclk_ratio,
|
||||
tegra210_i2s_put_bclk_ratio),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = {
|
||||
|
@ -192,24 +192,24 @@ static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int tegra210_mixer_apply_gain(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol,
|
||||
bool instant_gain)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
|
||||
unsigned int reg = mc->reg, id;
|
||||
bool instant_gain = false;
|
||||
int err;
|
||||
|
||||
if (strstr(kcontrol->id.name, "Instant Gain Volume"))
|
||||
instant_gain = true;
|
||||
|
||||
/* Save gain value for specific MIXER input */
|
||||
id = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) /
|
||||
TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE;
|
||||
|
||||
if (mixer->gain_value[id] == ucontrol->value.integer.value[0])
|
||||
return 0;
|
||||
|
||||
mixer->gain_value[id] = ucontrol->value.integer.value[0];
|
||||
|
||||
err = tegra210_mixer_configure_gain(cmpnt, id, instant_gain);
|
||||
@ -221,6 +221,18 @@ static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return tegra210_mixer_apply_gain(kcontrol, ucontrol, false);
|
||||
}
|
||||
|
||||
static int tegra210_mixer_put_instant_gain(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return tegra210_mixer_apply_gain(kcontrol, ucontrol, true);
|
||||
}
|
||||
|
||||
static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
|
||||
struct snd_pcm_hw_params *params,
|
||||
unsigned int reg,
|
||||
@ -388,7 +400,7 @@ ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG);
|
||||
SOC_SINGLE_EXT("RX" #id " Instant Gain Volume", \
|
||||
MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \
|
||||
0x20000, 0, tegra210_mixer_get_gain, \
|
||||
tegra210_mixer_put_gain),
|
||||
tegra210_mixer_put_instant_gain),
|
||||
|
||||
/* Volume controls for all MIXER inputs */
|
||||
static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = {
|
||||
@ -654,8 +666,8 @@ static int tegra210_mixer_platform_remove(struct platform_device *pdev)
|
||||
static const struct dev_pm_ops tegra210_mixer_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend,
|
||||
tegra210_mixer_runtime_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver tegra210_mixer_driver = {
|
||||
|
@ -136,7 +136,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
|
||||
unsigned int value;
|
||||
u8 mute_mask;
|
||||
u8 new_mask, old_mask;
|
||||
int err;
|
||||
|
||||
pm_runtime_get_sync(cmpnt->dev);
|
||||
@ -148,15 +148,23 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol,
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
mute_mask = ucontrol->value.integer.value[0];
|
||||
regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &value);
|
||||
|
||||
old_mask = (value >> TEGRA210_MVC_MUTE_SHIFT) & TEGRA210_MUTE_MASK_EN;
|
||||
new_mask = ucontrol->value.integer.value[0];
|
||||
|
||||
if (new_mask == old_mask) {
|
||||
err = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
err = regmap_update_bits(mvc->regmap, mc->reg,
|
||||
TEGRA210_MVC_MUTE_MASK,
|
||||
mute_mask << TEGRA210_MVC_MUTE_SHIFT);
|
||||
new_mask << TEGRA210_MVC_MUTE_SHIFT);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
return 1;
|
||||
err = 1;
|
||||
|
||||
end:
|
||||
pm_runtime_put(cmpnt->dev);
|
||||
@ -195,7 +203,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int value;
|
||||
u8 chan;
|
||||
int err;
|
||||
int err, old_volume;
|
||||
|
||||
pm_runtime_get_sync(cmpnt->dev);
|
||||
|
||||
@ -207,10 +215,16 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
|
||||
goto end;
|
||||
|
||||
chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE;
|
||||
old_volume = mvc->volume[chan];
|
||||
|
||||
tegra210_mvc_conv_vol(mvc, chan,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
if (mvc->volume[chan] == old_volume) {
|
||||
err = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Configure init volume same as target volume */
|
||||
regmap_write(mvc->regmap,
|
||||
TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan),
|
||||
@ -222,7 +236,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
|
||||
TEGRA210_MVC_VOLUME_SWITCH_MASK,
|
||||
TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
|
||||
|
||||
return 1;
|
||||
err = 1;
|
||||
|
||||
end:
|
||||
pm_runtime_put(cmpnt->dev);
|
||||
@ -275,7 +289,7 @@ static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
|
||||
|
||||
ucontrol->value.integer.value[0] = mvc->curve_type;
|
||||
ucontrol->value.enumerated.item[0] = mvc->curve_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -285,7 +299,7 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
|
||||
int value;
|
||||
unsigned int value;
|
||||
|
||||
regmap_read(mvc->regmap, TEGRA210_MVC_ENABLE, &value);
|
||||
if (value & TEGRA210_MVC_EN) {
|
||||
@ -294,10 +308,10 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mvc->curve_type == ucontrol->value.integer.value[0])
|
||||
if (mvc->curve_type == ucontrol->value.enumerated.item[0])
|
||||
return 0;
|
||||
|
||||
mvc->curve_type = ucontrol->value.integer.value[0];
|
||||
mvc->curve_type = ucontrol->value.enumerated.item[0];
|
||||
|
||||
tegra210_mvc_reset_vol_settings(mvc, cmpnt->dev);
|
||||
|
||||
@ -625,8 +639,8 @@ static int tegra210_mvc_platform_remove(struct platform_device *pdev)
|
||||
static const struct dev_pm_ops tegra210_mvc_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend,
|
||||
tegra210_mvc_runtime_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver tegra210_mvc_driver = {
|
||||
|
@ -3244,46 +3244,107 @@ static int tegra210_sfc_init(struct snd_soc_dapm_widget *w,
|
||||
return tegra210_sfc_write_coeff_ram(cmpnt);
|
||||
}
|
||||
|
||||
static int tegra210_sfc_get_control(struct snd_kcontrol *kcontrol,
|
||||
static int tegra210_sfc_iget_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
|
||||
if (strstr(kcontrol->id.name, "Input Stereo To Mono"))
|
||||
ucontrol->value.integer.value[0] =
|
||||
sfc->stereo_to_mono[SFC_RX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Input Mono To Stereo"))
|
||||
ucontrol->value.integer.value[0] =
|
||||
sfc->mono_to_stereo[SFC_RX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Output Stereo To Mono"))
|
||||
ucontrol->value.integer.value[0] =
|
||||
sfc->stereo_to_mono[SFC_TX_PATH];
|
||||
else if (strstr(kcontrol->id.name, "Output Mono To Stereo"))
|
||||
ucontrol->value.integer.value[0] =
|
||||
sfc->mono_to_stereo[SFC_TX_PATH];
|
||||
ucontrol->value.enumerated.item[0] = sfc->stereo_to_mono[SFC_RX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_put_control(struct snd_kcontrol *kcontrol,
|
||||
static int tegra210_sfc_iput_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (strstr(kcontrol->id.name, "Input Stereo To Mono"))
|
||||
sfc->stereo_to_mono[SFC_RX_PATH] = value;
|
||||
else if (strstr(kcontrol->id.name, "Input Mono To Stereo"))
|
||||
sfc->mono_to_stereo[SFC_RX_PATH] = value;
|
||||
else if (strstr(kcontrol->id.name, "Output Stereo To Mono"))
|
||||
sfc->stereo_to_mono[SFC_TX_PATH] = value;
|
||||
else if (strstr(kcontrol->id.name, "Output Mono To Stereo"))
|
||||
sfc->mono_to_stereo[SFC_TX_PATH] = value;
|
||||
else
|
||||
if (value == sfc->stereo_to_mono[SFC_RX_PATH])
|
||||
return 0;
|
||||
|
||||
sfc->stereo_to_mono[SFC_RX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_iget_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = sfc->mono_to_stereo[SFC_RX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_iput_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == sfc->mono_to_stereo[SFC_RX_PATH])
|
||||
return 0;
|
||||
|
||||
sfc->mono_to_stereo[SFC_RX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_oget_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = sfc->stereo_to_mono[SFC_TX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_oput_stereo_to_mono(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == sfc->stereo_to_mono[SFC_TX_PATH])
|
||||
return 0;
|
||||
|
||||
sfc->stereo_to_mono[SFC_TX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_oget_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = sfc->mono_to_stereo[SFC_TX_PATH];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_oput_mono_to_stereo(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
|
||||
unsigned int value = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (value == sfc->mono_to_stereo[SFC_TX_PATH])
|
||||
return 0;
|
||||
|
||||
sfc->mono_to_stereo[SFC_TX_PATH] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3384,13 +3445,17 @@ static const struct soc_enum tegra210_sfc_mono_conv_enum =
|
||||
|
||||
static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
|
||||
SOC_ENUM_EXT("Input Stereo To Mono", tegra210_sfc_stereo_conv_enum,
|
||||
tegra210_sfc_get_control, tegra210_sfc_put_control),
|
||||
tegra210_sfc_iget_stereo_to_mono,
|
||||
tegra210_sfc_iput_stereo_to_mono),
|
||||
SOC_ENUM_EXT("Input Mono To Stereo", tegra210_sfc_mono_conv_enum,
|
||||
tegra210_sfc_get_control, tegra210_sfc_put_control),
|
||||
tegra210_sfc_iget_mono_to_stereo,
|
||||
tegra210_sfc_iput_mono_to_stereo),
|
||||
SOC_ENUM_EXT("Output Stereo To Mono", tegra210_sfc_stereo_conv_enum,
|
||||
tegra210_sfc_get_control, tegra210_sfc_put_control),
|
||||
tegra210_sfc_oget_stereo_to_mono,
|
||||
tegra210_sfc_oput_stereo_to_mono),
|
||||
SOC_ENUM_EXT("Output Mono To Stereo", tegra210_sfc_mono_conv_enum,
|
||||
tegra210_sfc_get_control, tegra210_sfc_put_control),
|
||||
tegra210_sfc_oget_mono_to_stereo,
|
||||
tegra210_sfc_oput_mono_to_stereo),
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver tegra210_sfc_cmpnt = {
|
||||
@ -3529,8 +3594,8 @@ static int tegra210_sfc_platform_remove(struct platform_device *pdev)
|
||||
static const struct dev_pm_ops tegra210_sfc_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
|
||||
tegra210_sfc_runtime_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver tegra210_sfc_driver = {
|
||||
|
Loading…
Reference in New Issue
Block a user