Skip to content

Commit 84b86a8

Browse files
author
Sugar Zhang
committed
ASoC: rockchip: i2s-tdm: Add support for PCM R/W Wait Time
ALSA core blocks userspace for 10 seconds for PCM R/W default. Consider the situation BT-slave which acts as SLAVE mode, when BT-master offline sometime, the CLK lost, user have to wait the core timeout(10s), it's quite bad experience. This patch allows userspace to override the WAIT_TIME to recover more quickly from terminal audio stream. especially for stream which have no mechanism to detect the LINK offline. Usage: /# amixer -c 0 contents | grep Wait numid=43,iface=PCM,name='PCM Read Wait Time MS' numid=44,iface=PCM,name='PCM Write Wait Time MS' /# amixer -c 0 cset numid=43 500 numid=43,iface=PCM,name='PCM Read Wait Time MS' ; type=INTEGER,access=rw------,values=1,min=0,max=10000,step=1 : values=500 Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com> Change-Id: I53a35344238557813ea3683dd19474819e987d19
1 parent 1f9b5c6 commit 84b86a8

1 file changed

Lines changed: 81 additions & 2 deletions

File tree

sound/soc/rockchip/rockchip_i2s_tdm.c

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#define CLK_PPM_MIN (-1000)
7171
#define CLK_PPM_MAX (1000)
7272
#define MAXBURST_PER_FIFO 8
73+
#define WAIT_TIME_MS_MAX 10000
7374

7475
#define QUIRK_ALWAYS_ON BIT(0)
7576
#define QUIRK_HDMI_PATH BIT(1)
@@ -114,6 +115,7 @@ struct rk_i2s_tdm_dev {
114115
struct snd_dmaengine_dai_dma_data capture_dma_data;
115116
struct snd_dmaengine_dai_dma_data playback_dma_data;
116117
struct snd_pcm_substream *substreams[SNDRV_PCM_STREAM_LAST + 1];
118+
unsigned int wait_time[SNDRV_PCM_STREAM_LAST + 1];
117119
struct reset_control *tx_reset;
118120
struct reset_control *rx_reset;
119121
struct pinctrl *pinctrl;
@@ -1943,6 +1945,73 @@ static SOC_ENUM_SINGLE_DECL(rpath2_enum, I2S_RXCR, 21, rpaths_text);
19431945
static SOC_ENUM_SINGLE_DECL(rpath1_enum, I2S_RXCR, 19, rpaths_text);
19441946
static SOC_ENUM_SINGLE_DECL(rpath0_enum, I2S_RXCR, 17, rpaths_text);
19451947

1948+
static int rockchip_i2s_tdm_wait_time_info(struct snd_kcontrol *kcontrol,
1949+
struct snd_ctl_elem_info *uinfo)
1950+
{
1951+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1952+
uinfo->count = 1;
1953+
uinfo->value.integer.min = 0;
1954+
uinfo->value.integer.max = WAIT_TIME_MS_MAX;
1955+
uinfo->value.integer.step = 1;
1956+
1957+
return 0;
1958+
}
1959+
1960+
static int rockchip_i2s_tdm_rd_wait_time_get(struct snd_kcontrol *kcontrol,
1961+
struct snd_ctl_elem_value *ucontrol)
1962+
{
1963+
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1964+
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component);
1965+
1966+
ucontrol->value.integer.value[0] = i2s_tdm->wait_time[SNDRV_PCM_STREAM_CAPTURE];
1967+
1968+
return 0;
1969+
}
1970+
1971+
static int rockchip_i2s_tdm_rd_wait_time_put(struct snd_kcontrol *kcontrol,
1972+
struct snd_ctl_elem_value *ucontrol)
1973+
{
1974+
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1975+
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component);
1976+
1977+
if (ucontrol->value.integer.value[0] > WAIT_TIME_MS_MAX)
1978+
return -EINVAL;
1979+
1980+
i2s_tdm->wait_time[SNDRV_PCM_STREAM_CAPTURE] = ucontrol->value.integer.value[0];
1981+
1982+
return 1;
1983+
}
1984+
1985+
static int rockchip_i2s_tdm_wr_wait_time_get(struct snd_kcontrol *kcontrol,
1986+
struct snd_ctl_elem_value *ucontrol)
1987+
{
1988+
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1989+
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component);
1990+
1991+
ucontrol->value.integer.value[0] = i2s_tdm->wait_time[SNDRV_PCM_STREAM_PLAYBACK];
1992+
1993+
return 0;
1994+
}
1995+
1996+
static int rockchip_i2s_tdm_wr_wait_time_put(struct snd_kcontrol *kcontrol,
1997+
struct snd_ctl_elem_value *ucontrol)
1998+
{
1999+
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2000+
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component);
2001+
2002+
if (ucontrol->value.integer.value[0] > WAIT_TIME_MS_MAX)
2003+
return -EINVAL;
2004+
2005+
i2s_tdm->wait_time[SNDRV_PCM_STREAM_PLAYBACK] = ucontrol->value.integer.value[0];
2006+
2007+
return 1;
2008+
}
2009+
2010+
#define SAI_PCM_WAIT_TIME(xname, xhandler_get, xhandler_put) \
2011+
{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, \
2012+
.info = rockchip_i2s_tdm_wait_time_info, \
2013+
.get = xhandler_get, .put = xhandler_put }
2014+
19462015
static const struct snd_kcontrol_new rockchip_i2s_tdm_snd_controls[] = {
19472016
SOC_ENUM("Receive PATH3 Source Select", rpath3_enum),
19482017
SOC_ENUM("Receive PATH2 Source Select", rpath2_enum),
@@ -1962,6 +2031,12 @@ static const struct snd_kcontrol_new rockchip_i2s_tdm_snd_controls[] = {
19622031
SOC_ENUM_EXT("Receive SDIx Select", rx_lanes_enum,
19632032
rockchip_i2s_tdm_rx_lanes_get, rockchip_i2s_tdm_rx_lanes_put),
19642033
#endif
2034+
SAI_PCM_WAIT_TIME("PCM Read Wait Time MS",
2035+
rockchip_i2s_tdm_rd_wait_time_get,
2036+
rockchip_i2s_tdm_rd_wait_time_put),
2037+
SAI_PCM_WAIT_TIME("PCM Write Wait Time MS",
2038+
rockchip_i2s_tdm_wr_wait_time_get,
2039+
rockchip_i2s_tdm_wr_wait_time_put),
19652040
};
19662041

19672042
static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
@@ -2005,11 +2080,15 @@ static int rockchip_i2s_tdm_startup(struct snd_pcm_substream *substream,
20052080
struct snd_soc_dai *dai)
20062081
{
20072082
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
2083+
int stream = substream->stream;
20082084

2009-
if (i2s_tdm->substreams[substream->stream])
2085+
if (i2s_tdm->substreams[stream])
20102086
return -EBUSY;
20112087

2012-
i2s_tdm->substreams[substream->stream] = substream;
2088+
if (i2s_tdm->wait_time[stream])
2089+
substream->wait_time = msecs_to_jiffies(i2s_tdm->wait_time[stream]);
2090+
2091+
i2s_tdm->substreams[stream] = substream;
20132092

20142093
return 0;
20152094
}

0 commit comments

Comments
 (0)