Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
这个提交包含在:
@@ -36,6 +36,19 @@
|
||||
#define SKL_IN_DIR_BIT_MASK BIT(0)
|
||||
#define SKL_PIN_COUNT_MASK GENMASK(7, 4)
|
||||
|
||||
static const int mic_mono_list[] = {
|
||||
0, 1, 2, 3,
|
||||
};
|
||||
static const int mic_stereo_list[][SKL_CH_STEREO] = {
|
||||
{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3},
|
||||
};
|
||||
static const int mic_trio_list[][SKL_CH_TRIO] = {
|
||||
{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3},
|
||||
};
|
||||
static const int mic_quatro_list[][SKL_CH_QUATRO] = {
|
||||
{0, 1, 2, 3},
|
||||
};
|
||||
|
||||
void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
|
||||
{
|
||||
struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
|
||||
@@ -1314,6 +1327,111 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
|
||||
struct skl_module_cfg *mconfig = w->priv;
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
u32 ch_type = *((u32 *)ec->dobj.private);
|
||||
|
||||
if (mconfig->dmic_ch_type == ch_type)
|
||||
ucontrol->value.enumerated.item[0] =
|
||||
mconfig->dmic_ch_combo_index;
|
||||
else
|
||||
ucontrol->value.enumerated.item[0] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
|
||||
struct skl_mic_sel_config *mic_cfg, struct device *dev)
|
||||
{
|
||||
struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
|
||||
|
||||
sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
|
||||
sp_cfg->set_params = SKL_PARAM_SET;
|
||||
sp_cfg->param_id = 0x00;
|
||||
if (!sp_cfg->caps) {
|
||||
sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL);
|
||||
if (!sp_cfg->caps)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH;
|
||||
mic_cfg->flags = 0;
|
||||
memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
|
||||
struct skl_module_cfg *mconfig = w->priv;
|
||||
struct skl_mic_sel_config mic_cfg = {0};
|
||||
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
|
||||
u32 ch_type = *((u32 *)ec->dobj.private);
|
||||
const int *list;
|
||||
u8 in_ch, out_ch, index;
|
||||
|
||||
mconfig->dmic_ch_type = ch_type;
|
||||
mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0];
|
||||
|
||||
/* enum control index 0 is INVALID, so no channels to be set */
|
||||
if (mconfig->dmic_ch_combo_index == 0)
|
||||
return 0;
|
||||
|
||||
/* No valid channel selection map for index 0, so offset by 1 */
|
||||
index = mconfig->dmic_ch_combo_index - 1;
|
||||
|
||||
switch (ch_type) {
|
||||
case SKL_CH_MONO:
|
||||
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list))
|
||||
return -EINVAL;
|
||||
|
||||
list = &mic_mono_list[index];
|
||||
break;
|
||||
|
||||
case SKL_CH_STEREO:
|
||||
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list))
|
||||
return -EINVAL;
|
||||
|
||||
list = mic_stereo_list[index];
|
||||
break;
|
||||
|
||||
case SKL_CH_TRIO:
|
||||
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list))
|
||||
return -EINVAL;
|
||||
|
||||
list = mic_trio_list[index];
|
||||
break;
|
||||
|
||||
case SKL_CH_QUATRO:
|
||||
if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list))
|
||||
return -EINVAL;
|
||||
|
||||
list = mic_quatro_list[index];
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(w->dapm->dev,
|
||||
"Invalid channel %d for mic_select module\n",
|
||||
ch_type);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
/* channel type enum map to number of chanels for that type */
|
||||
for (out_ch = 0; out_ch < ch_type; out_ch++) {
|
||||
in_ch = list[out_ch];
|
||||
mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN;
|
||||
}
|
||||
|
||||
return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the dma id for host and link. In case of passthrough
|
||||
* pipeline, this will both host and link in the same
|
||||
@@ -1666,6 +1784,14 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
|
||||
skl_tplg_tlv_control_set},
|
||||
};
|
||||
|
||||
static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
|
||||
{
|
||||
.id = SKL_CONTROL_TYPE_MIC_SELECT,
|
||||
.get = skl_tplg_mic_control_get,
|
||||
.put = skl_tplg_mic_control_set,
|
||||
},
|
||||
};
|
||||
|
||||
static int skl_tplg_fill_pipe_tkn(struct device *dev,
|
||||
struct skl_pipe *pipe, u32 tkn,
|
||||
u32 tkn_val)
|
||||
@@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev,
|
||||
mconfig->converter = tkn_elem->value;
|
||||
break;
|
||||
|
||||
case SKL_TKL_U32_D0I3_CAPS:
|
||||
case SKL_TKN_U32_D0I3_CAPS:
|
||||
mconfig->d0i3_caps = tkn_elem->value;
|
||||
break;
|
||||
|
||||
@@ -2070,12 +2196,26 @@ static int skl_tplg_get_token(struct device *dev,
|
||||
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_CAPS_SET_PARAMS:
|
||||
mconfig->formats_config.set_params =
|
||||
tkn_elem->value;
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_CAPS_PARAMS_ID:
|
||||
mconfig->formats_config.param_id =
|
||||
tkn_elem->value;
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_PROC_DOMAIN:
|
||||
mconfig->domain =
|
||||
tkn_elem->value;
|
||||
|
||||
break;
|
||||
|
||||
case SKL_TKN_U32_DMA_BUF_SIZE:
|
||||
mconfig->dma_buffer_size = tkn_elem->value;
|
||||
break;
|
||||
|
||||
case SKL_TKN_U8_IN_PIN_TYPE:
|
||||
case SKL_TKN_U8_OUT_PIN_TYPE:
|
||||
case SKL_TKN_U8_CONN_TYPE:
|
||||
@@ -2147,7 +2287,7 @@ static int skl_tplg_get_tokens(struct device *dev,
|
||||
tuple_size += tkn_count * sizeof(*tkn_elem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return off;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2198,10 +2338,11 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
|
||||
num_blocks = ret;
|
||||
|
||||
off += array->size;
|
||||
array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off);
|
||||
|
||||
/* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
|
||||
while (num_blocks > 0) {
|
||||
array = (struct snd_soc_tplg_vendor_array *)
|
||||
(tplg_w->priv.data + off);
|
||||
|
||||
ret = skl_tplg_get_desc_blocks(dev, array);
|
||||
|
||||
if (ret < 0)
|
||||
@@ -2237,7 +2378,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
|
||||
memcpy(mconfig->formats_config.caps, data,
|
||||
mconfig->formats_config.caps_size);
|
||||
--num_blocks;
|
||||
ret = mconfig->formats_config.caps_size;
|
||||
}
|
||||
off += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2329,6 +2472,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
|
||||
ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
skl_debug_init_module(skl->debugfs, w, mconfig);
|
||||
|
||||
bind_event:
|
||||
if (tplg_w->event_type == 0) {
|
||||
dev_dbg(bus->dev, "ASoC: No event handler required\n");
|
||||
@@ -2377,14 +2523,34 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_init_enum_data(struct device *dev, struct soc_enum *se,
|
||||
struct snd_soc_tplg_enum_control *ec)
|
||||
{
|
||||
|
||||
void *data;
|
||||
|
||||
if (ec->priv.size) {
|
||||
data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
memcpy(data, ec->priv.data, ec->priv.size);
|
||||
se->dobj.private = data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
|
||||
struct snd_kcontrol_new *kctl,
|
||||
struct snd_soc_tplg_ctl_hdr *hdr)
|
||||
{
|
||||
struct soc_bytes_ext *sb;
|
||||
struct snd_soc_tplg_bytes_control *tplg_bc;
|
||||
struct snd_soc_tplg_enum_control *tplg_ec;
|
||||
struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
|
||||
struct hdac_bus *bus = ebus_to_hbus(ebus);
|
||||
struct soc_enum *se;
|
||||
|
||||
switch (hdr->ops.info) {
|
||||
case SND_SOC_TPLG_CTL_BYTES:
|
||||
@@ -2398,6 +2564,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
|
||||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_TPLG_CTL_ENUM:
|
||||
tplg_ec = container_of(hdr,
|
||||
struct snd_soc_tplg_enum_control, hdr);
|
||||
if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
|
||||
se = (struct soc_enum *)kctl->private_value;
|
||||
if (tplg_ec->priv.size)
|
||||
return skl_init_enum_data(bus->dev, se,
|
||||
tplg_ec);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
|
||||
hdr->ops.get, hdr->ops.put, hdr->ops.info);
|
||||
@@ -2626,6 +2803,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
|
||||
.control_load = skl_tplg_control_load,
|
||||
.bytes_ext_ops = skl_tlv_ops,
|
||||
.bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
|
||||
.io_ops = skl_tplg_kcontrol_ops,
|
||||
.io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
|
||||
.manifest = skl_manifest_load,
|
||||
};
|
||||
|
||||
|
在新工单中引用
屏蔽一个用户