@@ -6,6 +6,7 @@ menuconfig SND_SOC_STI
depends on SND_SOC
depends on ARCH_STI || COMPILE_TEST
select SND_SOC_GENERIC_DMAENGINE_PCM
+ select SND_PCM_IEC958
help
Say Y if you want to enable ASoC-support for
any of the STI platforms (e.g. STIH416).
@@ -9,6 +9,7 @@
#include <linux/pinctrl/consumer.h>
#include "uniperif.h"
+#include <sound/pcm_iec958.h>
/*
* DAI
@@ -84,10 +85,14 @@ static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai)
{
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct sti_uniperiph_dai *dai_data = &priv->dai_data;
- struct uniperif *uni = priv->dai_data.uni;
+ struct uniperif *uni = dai_data->uni;
+ int ret, stream;
/* DMA settings*/
- if (of_device_is_compatible(dai->dev->of_node, "st,sti-uni-player"))
+ stream = of_device_is_compatible(dai->dev->of_node,
+ "st,sti-uni-player") ?
+ SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_soc_dai_init_dma_data(dai, &dai_data->dma_data, NULL);
else
snd_soc_dai_init_dma_data(dai, NULL, &dai_data->dma_data);
@@ -95,6 +100,19 @@ static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai)
dai_data->dma_data.addr = uni->fifo_phys_address;
dai_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ if (uni->iec_param) {
+ const struct snd_kcontrol_new *ctrl;
+ /* create generic iec control*/
+ ctrl = snd_pcm_iec958_ctl_new(stream);
+ ret = snd_soc_add_dai_pcm_controls(dai, ctrl, 1,
+ uni->iec_param);
+ if (ret < 0) {
+ dev_err(dai->dev, "%s: Failed to create iec control",
+ __func__);
+ return ret;
+ }
+ }
+
if (uni->num_ctrls)
return snd_soc_add_dai_pcm_controls(dai, uni->snd_ctrls,
uni->num_ctrls, dai);
@@ -1189,6 +1189,7 @@ struct uniperif {
/*alsa ctrl*/
struct snd_kcontrol_new *snd_ctrls;
int num_ctrls;
+ struct snd_pcm_iec958_params *iec_param;
/* dai properties */
unsigned int daifmt;
@@ -12,6 +12,7 @@
#include <sound/asoundef.h>
#include <sound/soc.h>
+#include <sound/pcm_iec958.h>
#include "uniperif.h"
@@ -250,7 +251,6 @@ static void uni_player_set_channel_status(struct uniperif *player,
* sampling frequency. If no sample rate is already specified, then
* set one.
*/
- mutex_lock(&player->ctrl_lock);
if (runtime) {
switch (runtime->rate) {
case 22050:
@@ -327,7 +327,6 @@ static void uni_player_set_channel_status(struct uniperif *player,
player->stream_settings.iec958.status[3 + (n * 4)] << 24;
SET_UNIPERIF_CHANNEL_STA_REGN(player, n, status);
}
- mutex_unlock(&player->ctrl_lock);
/* Update the channel status */
if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
@@ -390,7 +389,9 @@ static int uni_player_prepare_iec958(struct uniperif *player,
SET_UNIPERIF_CTRL_ZERO_STUFF_HW(player);
/* Update the channel status */
+ mutex_lock(&player->ctrl_lock);
uni_player_set_channel_status(player, runtime);
+ mutex_unlock(&player->ctrl_lock);
/* Clear the user validity user bits */
SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 0);
@@ -541,60 +542,16 @@ static int uni_player_prepare_pcm(struct uniperif *player,
/*
* ALSA uniperipheral iec958 controls
*/
-static int uni_player_ctl_iec958_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
- uinfo->count = 1;
-
- return 0;
-}
-static int uni_player_ctl_iec958_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int uni_player_ctl_iec958_set(void *pdata, u8 *status)
{
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
- struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
- struct uniperif *player = priv->dai_data.uni;
- struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
-
- mutex_lock(&player->ctrl_lock);
- ucontrol->value.iec958.status[0] = iec958->status[0];
- ucontrol->value.iec958.status[1] = iec958->status[1];
- ucontrol->value.iec958.status[2] = iec958->status[2];
- ucontrol->value.iec958.status[3] = iec958->status[3];
- mutex_unlock(&player->ctrl_lock);
- return 0;
-}
-
-static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
- struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
- struct uniperif *player = priv->dai_data.uni;
- struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
-
- mutex_lock(&player->ctrl_lock);
- iec958->status[0] = ucontrol->value.iec958.status[0];
- iec958->status[1] = ucontrol->value.iec958.status[1];
- iec958->status[2] = ucontrol->value.iec958.status[2];
- iec958->status[3] = ucontrol->value.iec958.status[3];
- mutex_unlock(&player->ctrl_lock);
+ struct uniperif *player = pdata;
uni_player_set_channel_status(player, NULL);
return 0;
}
-static struct snd_kcontrol_new uni_player_iec958_ctl = {
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
- .info = uni_player_ctl_iec958_info,
- .get = uni_player_ctl_iec958_get,
- .put = uni_player_ctl_iec958_put,
-};
-
/*
* uniperif rate adjustement control
*/
@@ -654,12 +611,7 @@ static struct snd_kcontrol_new uni_player_clk_adj_ctl = {
.put = snd_sti_clk_adjustment_put,
};
-static struct snd_kcontrol_new *snd_sti_pcm_ctl[] = {
- &uni_player_clk_adj_ctl,
-};
-
-static struct snd_kcontrol_new *snd_sti_iec_ctl[] = {
- &uni_player_iec958_ctl,
+static struct snd_kcontrol_new *snd_sti_ctl[] = {
&uni_player_clk_adj_ctl,
};
@@ -1106,13 +1058,21 @@ int uni_player_init(struct platform_device *pdev,
IEC958_AES4_CON_MAX_WORDLEN_24 |
IEC958_AES4_CON_WORDLEN_24_20;
- player->num_ctrls = ARRAY_SIZE(snd_sti_iec_ctl);
- player->snd_ctrls = snd_sti_iec_ctl[0];
- } else {
- player->num_ctrls = ARRAY_SIZE(snd_sti_pcm_ctl);
- player->snd_ctrls = snd_sti_pcm_ctl[0];
+ player->iec_param = devm_kzalloc(player->dev,
+ sizeof(*player->iec_param),
+ GFP_KERNEL);
+ if (!player->iec_param)
+ return -ENOMEM;
+
+ player->iec_param->iec = &player->stream_settings.iec958;
+ player->iec_param->mutex = &player->ctrl_lock;
+ player->iec_param->pdata = player;
+ player->iec_param->ctrl_set = uni_player_ctl_iec958_set;
}
+ player->num_ctrls = ARRAY_SIZE(snd_sti_ctl);
+ player->snd_ctrls = snd_sti_ctl[0];
+
return 0;
}
EXPORT_SYMBOL_GPL(uni_player_init);
Use helper function instead of internal function for iec control Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> --- sound/soc/sti/Kconfig | 1 + sound/soc/sti/sti_uniperif.c | 22 ++++++++++-- sound/soc/sti/uniperif.h | 1 + sound/soc/sti/uniperif_player.c | 78 ++++++++++------------------------------- 4 files changed, 41 insertions(+), 61 deletions(-)