asoc: Add sysfs attr for SPDIF interfaces

The format change event signaling for SPDIF input interfaces
is adapted to provide format information through sysfs nodes.

Change-Id: Ifab1074a0e4b13e08813e27f8694023c2c47bfe1
Signed-off-by: Ralf Herz <rherz@codeaurora.org>
Signed-off-by: Mangesh Kunchamwar <mangeshk@codeaurora.org>
This commit is contained in:
Ralf Herz 2018-09-10 11:09:02 +02:00 • committed by Gerrit - the friendly Code Review server
commit 900bd738dd

View file

@ -40,6 +40,7 @@
#define CHANNEL_STATUS_MASK_INIT 0x0
#define CHANNEL_STATUS_MASK 0x4
#define AFE_API_VERSION_CLOCK_SET 1
#define MSM_DAI_SYSFS_ENTRY_MAX_LEN 64
#define DAI_FORMATS_S16_S24_S32_LE (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
@ -218,6 +219,7 @@ struct msm_dai_q6_spdif_dai_data {
u16 port_id;
struct afe_spdif_port_config spdif_port;
struct afe_event_fmt_update fmt_event;
struct kobject *kobj;
};
struct msm_dai_q6_spdif_event_msg {
@ -1459,39 +1461,6 @@ static int msm_dai_q6_spdif_source_get(struct snd_kcontrol *kcontrol,
return 0;
}
static int msm_dai_q6_spdif_ext_state_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
ucontrol->value.integer.value[0] =
dai_data->fmt_event.status & 0x3;
return 0;
}
static int msm_dai_q6_spdif_ext_format_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
ucontrol->value.integer.value[0] =
dai_data->fmt_event.data_format & 0x1;
return 0;
}
static int msm_dai_q6_spdif_ext_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
ucontrol->value.integer.value[0] =
dai_data->fmt_event.sample_rate;
return 0;
}
static const char * const spdif_format[] = {
"LPCM",
"Compr"
@ -1501,10 +1470,6 @@ static const char * const spdif_source[] = {
"Optical", "EXT-ARC", "Coaxial", "VT-ARC"
};
static const char * const spdif_state[] = {
"Inactive", "Active", "EOS"
};
static const struct soc_enum spdif_rx_config_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_format), spdif_format),
};
@ -1514,11 +1479,6 @@ static const struct soc_enum spdif_tx_config_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_format), spdif_format),
};
static const struct soc_enum spdif_tx_status_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_state), spdif_state),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_format), spdif_format),
};
static int msm_dai_q6_spdif_chstatus_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@ -1609,21 +1569,6 @@ static const struct snd_kcontrol_new spdif_tx_config_controls[] = {
msm_dai_q6_spdif_format_put)
};
static const struct snd_kcontrol_new spdif_tx_status_controls[] = {
SOC_ENUM_EXT("PRI SPDIF TX EXT State", spdif_tx_status_enum[0],
msm_dai_q6_spdif_ext_state_get, NULL),
SOC_ENUM_EXT("PRI SPDIF TX EXT Format", spdif_tx_status_enum[1],
msm_dai_q6_spdif_ext_format_get, NULL),
SOC_SINGLE_EXT("PRI SPDIF TX EXT Rate", 0, 0, 192000, 0,
msm_dai_q6_spdif_ext_rate_get, NULL),
SOC_ENUM_EXT("SEC SPDIF TX EXT State", spdif_tx_status_enum[0],
msm_dai_q6_spdif_ext_state_get, NULL),
SOC_ENUM_EXT("SEC SPDIF TX EXT Format", spdif_tx_status_enum[1],
msm_dai_q6_spdif_ext_format_get, NULL),
SOC_SINGLE_EXT("SEC SPDIF TX EXT Rate", 0, 0, 192000, 0,
msm_dai_q6_spdif_ext_rate_get, NULL)
};
static void msm_dai_q6_spdif_process_event(uint32_t opcode, uint32_t token,
uint32_t *payload, void *private_data)
{
@ -1734,6 +1679,102 @@ static int msm_dai_q6_spdif_prepare(struct snd_pcm_substream *substream,
return rc;
}
static ssize_t msm_dai_q6_spdif_sysfs_rda_audio_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret;
struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dev);
if (!dai_data) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
ret = snprintf(buf, MSM_DAI_SYSFS_ENTRY_MAX_LEN, "%d\n",
dai_data->fmt_event.status);
pr_debug("%s: '%d'\n", __func__, dai_data->fmt_event.status);
return ret;
}
static ssize_t msm_dai_q6_spdif_sysfs_rda_audio_format(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret;
struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dev);
if (!dai_data) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
ret = snprintf(buf, MSM_DAI_SYSFS_ENTRY_MAX_LEN, "%d\n",
dai_data->fmt_event.data_format);
pr_debug("%s: '%d'\n", __func__, dai_data->fmt_event.data_format);
return ret;
}
static ssize_t msm_dai_q6_spdif_sysfs_rda_audio_rate(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret;
struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dev);
if (!dai_data) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
ret = snprintf(buf, MSM_DAI_SYSFS_ENTRY_MAX_LEN, "%d\n",
dai_data->fmt_event.sample_rate);
pr_debug("%s: '%d'\n", __func__, dai_data->fmt_event.sample_rate);
return ret;
}
static DEVICE_ATTR(audio_state, 0444, msm_dai_q6_spdif_sysfs_rda_audio_state,
NULL);
static DEVICE_ATTR(audio_format, 0444, msm_dai_q6_spdif_sysfs_rda_audio_format,
NULL);
static DEVICE_ATTR(audio_rate, 0444, msm_dai_q6_spdif_sysfs_rda_audio_rate,
NULL);
static struct attribute *msm_dai_q6_spdif_fs_attrs[] = {
&dev_attr_audio_state.attr,
&dev_attr_audio_format.attr,
&dev_attr_audio_rate.attr,
NULL,
};
static struct attribute_group msm_dai_q6_spdif_fs_attrs_group = {
.attrs = msm_dai_q6_spdif_fs_attrs,
};
static int msm_dai_q6_spdif_sysfs_create(struct snd_soc_dai *dai,
struct msm_dai_q6_spdif_dai_data *dai_data)
{
int rc;
rc = sysfs_create_group(&dai->dev->kobj,
&msm_dai_q6_spdif_fs_attrs_group);
if (rc) {
pr_err("%s: failed, rc=%d\n", __func__, rc);
return rc;
}
dai_data->kobj = &dai->dev->kobj;
return 0;
}
static void msm_dai_q6_spdif_sysfs_remove(struct snd_soc_dai *dai,
struct msm_dai_q6_spdif_dai_data *dai_data)
{
if (dai_data->kobj)
sysfs_remove_group(dai_data->kobj,
&msm_dai_q6_spdif_fs_attrs_group);
dai_data->kobj = NULL;
}
static int msm_dai_q6_spdif_dai_probe(struct snd_soc_dai *dai)
{
struct msm_dai_q6_spdif_dai_data *dai_data;
@ -1773,40 +1814,24 @@ static int msm_dai_q6_spdif_dai_probe(struct snd_soc_dai *dai)
dai_data));
break;
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
rc = msm_dai_q6_spdif_sysfs_create(dai, dai_data);
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_config_controls[0],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_config_controls[1],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_status_controls[0],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_status_controls[1],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_status_controls[2],
dai_data));
break;
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
rc = msm_dai_q6_spdif_sysfs_create(dai, dai_data);
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_config_controls[2],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_config_controls[3],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_status_controls[3],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_status_controls[4],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&spdif_tx_status_controls[5],
dai_data));
break;
}
if (rc < 0)
@ -1866,6 +1891,9 @@ static int msm_dai_q6_spdif_dai_remove(struct snd_soc_dai *dai)
clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
}
msm_dai_q6_spdif_sysfs_remove(dai, dai_data);
kfree(dai_data);
return 0;