Skip to content

Commit d08c5b7

Browse files
committed
Merge series "ASoC: adds new .auto_selectable_formats support" from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:
Hi Mark These are v3 of "ASoC: adds new .get_fmt support", but renamed Subject. This is a little bit challenging patch-set. The idea/code is almost same as v1 / v2. v3 has "priority" support. We need to set dai_link->dai_fmt to select CPU/Codec settings, and it is selected by Sound Card Driver, today. Because of it, Sound Card user need to know both CPU / Codec available dai_fmt, and needs to select it. For example simple-card / audio-graph case, it is selected by "format" and "bitclock/frame-master/inversion" on DT. But, it can be automatically selected if both CPU and Codec drivers indicate it to ALSA SoC Framework, somehow. By this patch, dai_fmt can be automatically selected from each driver if both CPU / Codec driver had .auto_selectable_formats. Automatically selectable *field* is depends on each drivers. For example, some driver want to select format "automatically", but want to select other fields "manually", because of complex limitation. Or other example, in case of both CPU and Codec are possible to be clock provider, but the quality was different. In these case, user need/want to *manually* select each fields from Sound Card driver. It uses Sound Card specified fields preferentially, and try to select non-specific fields from CPU and Codec driver settings if driver had .auto_selectable_formats. In other words, we can select all dai_fmt via Sound Card driver same as before. Select dai_fmt 100% automatically is very difficult and will be very complex, but select automatically some fields only is very easy, I guess. This patch-set is based on such assumption. v1 -> v2 - Add more detail explanation on git-log, code, comment. - Possible to be Clock/Frame provider is depends on driver's situation. v2 -> v3 - has priority - tidyup function explanation for snd_soc_dai_get_fmt() - Each driver don't try to have SND_SOC_DAIFMT_CBx_CFx to avoid confusion Link: https://lore.kernel.org/r/871rb3hypy.wl-kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/871racbx0w.wl-kuninori.morimoto.gx@renesas.com Kuninori Morimoto (7): ASoC: soc-core: move snd_soc_runtime_set_dai_fmt() to upside ASoC: soc-core: add snd_soc_runtime_get_dai_fmt() ASoC: ak4613: add .auto_selectable_formats support ASoC: pcm3168a: add .auto_selectable_formats support ASoC: rsnd: add .auto_selectable_formats support ASoC: fsi: add .auto_selectable_formats support ASoC: hdmi-codec: add .auto_selectable_formats support include/sound/soc-dai.h | 55 +++++++ sound/soc/codecs/ak4613.c | 11 ++ sound/soc/codecs/hdmi-codec.c | 21 +++ sound/soc/codecs/pcm3168a.c | 26 +++ sound/soc/sh/fsi.c | 15 ++ sound/soc/sh/rcar/core.c | 31 +++- sound/soc/soc-core.c | 288 ++++++++++++++++++++++++++-------- sound/soc/soc-dai.c | 63 ++++++++ sound/soc/soc-utils.c | 29 ++++ 9 files changed, 475 insertions(+), 64 deletions(-) -- 2.25.1
2 parents d50b86b + 68d8b7b commit d08c5b7

File tree

9 files changed

+475
-64
lines changed

9 files changed

+475
-64
lines changed

include/sound/soc-dai.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ struct snd_compr_stream;
3636
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
3737
#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
3838

39+
/* Describes the possible PCM format */
40+
/*
41+
* use SND_SOC_DAI_FORMAT_xx as eash shift.
42+
* see
43+
* snd_soc_runtime_get_dai_fmt()
44+
*/
45+
#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT 0
46+
#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT)
47+
#define SND_SOC_POSSIBLE_DAIFMT_I2S (1 << SND_SOC_DAI_FORMAT_I2S)
48+
#define SND_SOC_POSSIBLE_DAIFMT_RIGHT_J (1 << SND_SOC_DAI_FORMAT_RIGHT_J)
49+
#define SND_SOC_POSSIBLE_DAIFMT_LEFT_J (1 << SND_SOC_DAI_FORMAT_LEFT_J)
50+
#define SND_SOC_POSSIBLE_DAIFMT_DSP_A (1 << SND_SOC_DAI_FORMAT_DSP_A)
51+
#define SND_SOC_POSSIBLE_DAIFMT_DSP_B (1 << SND_SOC_DAI_FORMAT_DSP_B)
52+
#define SND_SOC_POSSIBLE_DAIFMT_AC97 (1 << SND_SOC_DAI_FORMAT_AC97)
53+
#define SND_SOC_POSSIBLE_DAIFMT_PDM (1 << SND_SOC_DAI_FORMAT_PDM)
54+
3955
/*
4056
* DAI Clock gating.
4157
*
@@ -45,6 +61,17 @@ struct snd_compr_stream;
4561
#define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */
4662
#define SND_SOC_DAIFMT_GATED (0 << 4) /* clock is gated */
4763

64+
/* Describes the possible PCM format */
65+
/*
66+
* define GATED -> CONT. GATED will be selected if both are selected.
67+
* see
68+
* snd_soc_runtime_get_dai_fmt()
69+
*/
70+
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16
71+
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
72+
#define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
73+
#define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
74+
4875
/*
4976
* DAI hardware signal polarity.
5077
*
@@ -71,6 +98,14 @@ struct snd_compr_stream;
7198
#define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */
7299
#define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */
73100

101+
/* Describes the possible PCM format */
102+
#define SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT 32
103+
#define SND_SOC_POSSIBLE_DAIFMT_INV_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
104+
#define SND_SOC_POSSIBLE_DAIFMT_NB_NF (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
105+
#define SND_SOC_POSSIBLE_DAIFMT_NB_IF (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
106+
#define SND_SOC_POSSIBLE_DAIFMT_IB_NF (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
107+
#define SND_SOC_POSSIBLE_DAIFMT_IB_IF (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
108+
74109
/*
75110
* DAI hardware clock providers/consumers
76111
*
@@ -89,6 +124,14 @@ struct snd_compr_stream;
89124
#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC
90125
#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC
91126

127+
/* Describes the possible PCM format */
128+
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48
129+
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
130+
#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFP (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
131+
#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFP (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
132+
#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFC (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
133+
#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFC (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
134+
92135
#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
93136
#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
94137
#define SND_SOC_DAIFMT_INV_MASK 0x0f00
@@ -131,6 +174,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
131174
int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
132175

133176
/* Digital Audio interface formatting */
177+
int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd);
178+
u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority);
134179
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
135180

136181
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
@@ -292,6 +337,16 @@ struct snd_soc_dai_ops {
292337
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
293338
struct snd_soc_dai *);
294339

340+
/*
341+
* Format list for auto selection.
342+
* Format will be increased if priority format was
343+
* not selected.
344+
* see
345+
* snd_soc_dai_get_fmt()
346+
*/
347+
u64 *auto_selectable_formats;
348+
int num_auto_selectable_formats;
349+
295350
/* bit field */
296351
unsigned int no_capture_mute:1;
297352
};

sound/soc/codecs/ak4613.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,13 +539,24 @@ static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd,
539539
return 0;
540540
}
541541

542+
/*
543+
* Select below from Sound Card, not Auto
544+
* SND_SOC_DAIFMT_CBC_CFC
545+
* SND_SOC_DAIFMT_CBP_CFP
546+
*/
547+
static u64 ak4613_dai_formats =
548+
SND_SOC_POSSIBLE_DAIFMT_I2S |
549+
SND_SOC_POSSIBLE_DAIFMT_LEFT_J;
550+
542551
static const struct snd_soc_dai_ops ak4613_dai_ops = {
543552
.startup = ak4613_dai_startup,
544553
.shutdown = ak4613_dai_shutdown,
545554
.set_sysclk = ak4613_dai_set_sysclk,
546555
.set_fmt = ak4613_dai_set_fmt,
547556
.trigger = ak4613_dai_trigger,
548557
.hw_params = ak4613_dai_hw_params,
558+
.auto_selectable_formats = &ak4613_dai_formats,
559+
.num_auto_selectable_formats = 1,
549560
};
550561

551562
#define AK4613_PCM_RATE (SNDRV_PCM_RATE_32000 |\

sound/soc/codecs/hdmi-codec.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,12 +580,33 @@ static int hdmi_codec_mute(struct snd_soc_dai *dai, int mute, int direction)
580580
return -ENOTSUPP;
581581
}
582582

583+
/*
584+
* This driver can select all SND_SOC_DAIFMT_CBx_CFx,
585+
* but need to be selected from Sound Card, not be auto selected.
586+
* Because it might be used from other driver.
587+
* For example,
588+
* ${LINUX}/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
589+
*/
590+
static u64 hdmi_codec_formats =
591+
SND_SOC_POSSIBLE_DAIFMT_NB_NF |
592+
SND_SOC_POSSIBLE_DAIFMT_NB_IF |
593+
SND_SOC_POSSIBLE_DAIFMT_IB_NF |
594+
SND_SOC_POSSIBLE_DAIFMT_IB_IF |
595+
SND_SOC_POSSIBLE_DAIFMT_I2S |
596+
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
597+
SND_SOC_POSSIBLE_DAIFMT_DSP_B |
598+
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
599+
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
600+
SND_SOC_POSSIBLE_DAIFMT_AC97;
601+
583602
static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = {
584603
.startup = hdmi_codec_startup,
585604
.shutdown = hdmi_codec_shutdown,
586605
.hw_params = hdmi_codec_hw_params,
587606
.set_fmt = hdmi_codec_i2s_set_fmt,
588607
.mute_stream = hdmi_codec_mute,
608+
.auto_selectable_formats = &hdmi_codec_formats,
609+
.num_auto_selectable_formats = 1,
589610
};
590611

591612
static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {

sound/soc/codecs/pcm3168a.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,13 +573,39 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
573573
return 0;
574574
}
575575

576+
static u64 pcm3168a_dai_formats[] = {
577+
/*
578+
* Select below from Sound Card, not here
579+
* SND_SOC_DAIFMT_CBC_CFC
580+
* SND_SOC_DAIFMT_CBP_CFP
581+
*/
582+
583+
/*
584+
* First Priority
585+
*/
586+
SND_SOC_POSSIBLE_DAIFMT_I2S |
587+
SND_SOC_POSSIBLE_DAIFMT_LEFT_J,
588+
/*
589+
* Second Priority
590+
*
591+
* These have picky limitation.
592+
* see
593+
* pcm3168a_hw_params()
594+
*/
595+
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
596+
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
597+
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
598+
};
599+
576600
static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
577601
.set_fmt = pcm3168a_set_dai_fmt,
578602
.set_sysclk = pcm3168a_set_dai_sysclk,
579603
.hw_params = pcm3168a_hw_params,
580604
.mute_stream = pcm3168a_mute,
581605
.set_tdm_slot = pcm3168a_set_tdm_slot,
582606
.no_capture_mute = 1,
607+
.auto_selectable_formats = pcm3168a_dai_formats,
608+
.num_auto_selectable_formats = ARRAY_SIZE(pcm3168a_dai_formats),
583609
};
584610

585611
static struct snd_soc_dai_driver pcm3168a_dais[] = {

sound/soc/sh/fsi.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,12 +1694,27 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
16941694
return 0;
16951695
}
16961696

1697+
/*
1698+
* Select below from Sound Card, not auto
1699+
* SND_SOC_DAIFMT_CBC_CFC
1700+
* SND_SOC_DAIFMT_CBP_CFP
1701+
*/
1702+
static u64 fsi_dai_formats =
1703+
SND_SOC_POSSIBLE_DAIFMT_I2S |
1704+
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
1705+
SND_SOC_POSSIBLE_DAIFMT_NB_NF |
1706+
SND_SOC_POSSIBLE_DAIFMT_NB_IF |
1707+
SND_SOC_POSSIBLE_DAIFMT_IB_NF |
1708+
SND_SOC_POSSIBLE_DAIFMT_IB_IF;
1709+
16971710
static const struct snd_soc_dai_ops fsi_dai_ops = {
16981711
.startup = fsi_dai_startup,
16991712
.shutdown = fsi_dai_shutdown,
17001713
.trigger = fsi_dai_trigger,
17011714
.set_fmt = fsi_dai_set_fmt,
17021715
.hw_params = fsi_dai_hw_params,
1716+
.auto_selectable_formats = &fsi_dai_formats,
1717+
.num_auto_selectable_formats = 1,
17031718
};
17041719

17051720
/*

sound/soc/sh/rcar/core.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
756756

757757
/* set clock master for audio interface */
758758
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
759-
case SND_SOC_DAIFMT_CBM_CFM:
759+
case SND_SOC_DAIFMT_CBP_CFP:
760760
rdai->clk_master = 0;
761761
break;
762-
case SND_SOC_DAIFMT_CBS_CFS:
762+
case SND_SOC_DAIFMT_CBC_CFC:
763763
rdai->clk_master = 1; /* cpu is master */
764764
break;
765765
default:
@@ -1039,13 +1039,40 @@ static int rsnd_soc_dai_prepare(struct snd_pcm_substream *substream,
10391039
return rsnd_dai_call(prepare, io, priv);
10401040
}
10411041

1042+
static u64 rsnd_soc_dai_formats[] = {
1043+
/*
1044+
* 1st Priority
1045+
*
1046+
* Well tested formats.
1047+
* Select below from Sound Card, not auto
1048+
* SND_SOC_DAIFMT_CBC_CFC
1049+
* SND_SOC_DAIFMT_CBP_CFP
1050+
*/
1051+
SND_SOC_POSSIBLE_DAIFMT_I2S |
1052+
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
1053+
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
1054+
SND_SOC_POSSIBLE_DAIFMT_NB_NF |
1055+
SND_SOC_POSSIBLE_DAIFMT_NB_IF |
1056+
SND_SOC_POSSIBLE_DAIFMT_IB_NF |
1057+
SND_SOC_POSSIBLE_DAIFMT_IB_IF,
1058+
/*
1059+
* 2nd Priority
1060+
*
1061+
* Supported, but not well tested
1062+
*/
1063+
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
1064+
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
1065+
};
1066+
10421067
static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
10431068
.startup = rsnd_soc_dai_startup,
10441069
.shutdown = rsnd_soc_dai_shutdown,
10451070
.trigger = rsnd_soc_dai_trigger,
10461071
.set_fmt = rsnd_soc_dai_set_fmt,
10471072
.set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
10481073
.prepare = rsnd_soc_dai_prepare,
1074+
.auto_selectable_formats = rsnd_soc_dai_formats,
1075+
.num_auto_selectable_formats = ARRAY_SIZE(rsnd_soc_dai_formats),
10491076
};
10501077

10511078
static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,

0 commit comments

Comments
 (0)