diff options
author | Jyri Sarha | 2019-09-05 05:15:22 -0500 |
---|---|---|
committer | Jyri Sarha | 2019-09-05 05:15:22 -0500 |
commit | 48923bc2dea31c65a56d4a5ca372ff28823d2d16 (patch) | |
tree | 417ab7e4a6a04607873f9c79cc93724a43b873a3 | |
parent | fdf99522176bd41fe6c60927b37e8d74e6e16267 (diff) | |
parent | d66acd0675d91cd3ee1d3da63114b3bc1aab2798 (diff) | |
download | kernel-48923bc2dea31c65a56d4a5ca372ff28823d2d16.tar.gz kernel-48923bc2dea31c65a56d4a5ca372ff28823d2d16.tar.xz kernel-48923bc2dea31c65a56d4a5ca372ff28823d2d16.zip |
Merge branch 'peter/ti-linux-4.19.y/topic/audio' of https://github.com/omap-audio/linux-audio into audio_display-ti-linux-4.19.y
new ASoC machine driver for j721e CPB
* 'peter/ti-linux-4.19.y/topic/audio' of https://github.com/omap-audio/linux-audio:
arm64: dts: ti: k3-j721e-common-proc-board: Switch to custom audio support
ti_config_fragments: audio_display.cfg: Enable custom audio driver for j721e-evm
ASoC: ti: Add custom machine driver for j721e Common Processor Board
bindings: sound: Add documentation for TI j721e Common Processor Board
ASoC: pcm3168a: Allow reconfiguration of tdm_slots and slot_width
ASoC: pcm3168a: Retain the independence of DAC and ADC side of the codec
ASoC: core: Move pcm_mutex up to card level from snd_soc_pcm_runtime
-rw-r--r-- | Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.txt | 53 | ||||
-rw-r--r-- | arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts | 89 | ||||
-rw-r--r-- | include/sound/soc.h | 6 | ||||
-rw-r--r-- | sound/soc/codecs/pcm3168a.c | 129 | ||||
-rw-r--r-- | sound/soc/soc-compress.c | 48 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 2 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 36 | ||||
-rw-r--r-- | sound/soc/ti/Kconfig | 8 | ||||
-rw-r--r-- | sound/soc/ti/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/ti/j721e-evm.c | 459 | ||||
-rw-r--r-- | ti_config_fragments/audio_display.cfg | 1 |
11 files changed, 637 insertions, 196 deletions
diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.txt b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.txt new file mode 100644 index 000000000000..55a7864534de --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.txt | |||
@@ -0,0 +1,53 @@ | |||
1 | * Audio support for j721e Common Processor Board | ||
2 | |||
3 | The audio support on the board is using pcm3168a codec connected to McASP10 | ||
4 | serializers in parallel setup. | ||
5 | The pcm3168a SCKI clock is coming via the j721e AUDIO_REFCLK2 pin. | ||
6 | In order to support 48KHz and 44.1KHz family of sampling rates the parent clock | ||
7 | for AUDIO_REFCLK2 needs to be changed between PLL4 (for 48KHz) and PLL15 (for | ||
8 | 44.1KHz). The same PLLs are used for McASP10's AUXCLK clock via different | ||
9 | HSDIVIDER. | ||
10 | |||
11 | Required properties: | ||
12 | - compatible : "ti,j721e-cpb-audio" | ||
13 | - ti,model : Sound card name, should be "j721e-cpb-analog" | ||
14 | - ti,cpb-mcasp : phandle to McASP10 | ||
15 | - ti,cpb-codec : phandle to the pcm3168a codec on the CPB | ||
16 | - pll4-rate : Rate of the PLL4 in Hz. Must be chacked agains how it is | ||
17 | configured by sysfw. | ||
18 | - pll15-rate : Rate of the PLL15 in Hz. Must be chacked agains how it is | ||
19 | configured by sysfw. | ||
20 | - clocks : Must contain an entry for each entry in clock-names. | ||
21 | - clock-names : Must include the following entries: | ||
22 | "cpb-mcasp" (McASP10 auxclk clock) | ||
23 | "cpb-mcasp-48000" (PLL4_HSDIV0 parent for McASP10 auxclk) | ||
24 | "cpb-mcasp-44100" (PLL15_HSDIV0 parent for McASP10 auxclk) | ||
25 | "audio-refclk2" (AUDIO_REFCLK2 clock) | ||
26 | "audio-refclk2-48000" (PLL4_HSDIV2 parent for AUDIO_REFCLK2 | ||
27 | clock) | ||
28 | "audio-refclk2-44100" (PLL15_HSDIV2 parent for AUDIO_REFCLK2 | ||
29 | clock) | ||
30 | |||
31 | Example: | ||
32 | |||
33 | sound0: sound@0 { | ||
34 | compatible = "ti,j721e-cpb-audio"; | ||
35 | ti,model = "j721e-cpb-analog"; | ||
36 | |||
37 | status = "okay"; | ||
38 | |||
39 | ti,cpb-mcasp = <&mcasp10>; | ||
40 | ti,cpb-codec = <&pcm3168a_1>; | ||
41 | |||
42 | pll4-rate = <1179648000>; /* Used for 48KHz family */ | ||
43 | pll15-rate = <1083801600>; /* Used for 44.1KHz family */ | ||
44 | |||
45 | clocks = <&k3_clks 184 1>, | ||
46 | <&k3_clks 184 2>, <&k3_clks 184 4>, | ||
47 | <&k3_clks 157 371>, | ||
48 | <&k3_clks 157 400>, <&k3_clks 157 401>; | ||
49 | clock-names = "cpb-mcasp", | ||
50 | "cpb-mcasp-48000", "cpb-mcasp-44100", | ||
51 | "audio-refclk2", | ||
52 | "audio-refclk2-48000", "audio-refclk2-44100"; | ||
53 | }; | ||
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts index c21b228e48df..b6d6fa684a08 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts | |||
@@ -50,78 +50,23 @@ | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | sound0: sound@0 { | 52 | sound0: sound@0 { |
53 | compatible = "simple-audio-card"; | 53 | compatible = "ti,j721e-cpb-audio"; |
54 | simple-audio-card,name = "j721e-cpb-analog"; | 54 | ti,model = "j721e-cpb-analog"; |
55 | simple-audio-card,widgets = | 55 | |
56 | "Headphone", "Stereo HP 1", | 56 | ti,cpb-mcasp = <&mcasp10>; |
57 | "Headphone", "Stereo HP 2", | 57 | ti,cpb-codec = <&pcm3168a_1>; |
58 | "Headphone", "Stereo HP 3", | 58 | |
59 | "Line", "Line Out", | 59 | pll4-rate = <1179648000>; /* Used for 48KHz family */ |
60 | "Microphone", "Stereo Mic 1", | 60 | pll15-rate = <1083801600>; /* Used for 44.1KHz family */ |
61 | "Microphone", "Stereo Mic 2", | 61 | |
62 | "Line", "Line In"; | 62 | clocks = <&k3_clks 184 1>, |
63 | simple-audio-card,routing = | 63 | <&k3_clks 184 2>, <&k3_clks 184 4>, |
64 | "Stereo HP 1", "AOUT1L", | 64 | <&k3_clks 157 371>, |
65 | "Stereo HP 1", "AOUT1R", | 65 | <&k3_clks 157 400>, <&k3_clks 157 401>; |
66 | "Stereo HP 2", "AOUT2L", | 66 | clock-names = "cpb-mcasp", |
67 | "Stereo HP 2", "AOUT2R", | 67 | "cpb-mcasp-48000", "cpb-mcasp-44100", |
68 | "Stereo HP 3", "AOUT3L", | 68 | "audio-refclk2", |
69 | "Stereo HP 3", "AOUT3R", | 69 | "audio-refclk2-48000", "audio-refclk2-44100"; |
70 | "Line Out", "AOUT4L", | ||
71 | "Line Out", "AOUT4R", | ||
72 | "AIN1L", "Stereo Mic 1", | ||
73 | "AIN1R", "Stereo Mic 1", | ||
74 | "AIN2L", "Stereo Mic 2", | ||
75 | "AIN2R", "Stereo Mic 2", | ||
76 | "AIN3L", "Line In", | ||
77 | "AIN3R", "Line In"; | ||
78 | simple-audio-card,mclk-fs = <256>; | ||
79 | |||
80 | simple-audio-card,dai-link@0 { | ||
81 | format = "dsp_a"; | ||
82 | bitclock-master = <&sound0_0_master>; | ||
83 | frame-master = <&sound0_0_master>; | ||
84 | sound0_0_master: cpu { | ||
85 | sound-dai = <&mcasp10>; | ||
86 | clocks = <&k3_clks 184 1>; | ||
87 | system-clock-id = <MCASP_CLK_HCLK_AUXCLK>; | ||
88 | dai-tdm-slot-num = <2>; | ||
89 | dai-tdm-slot-width = <32>; | ||
90 | dai-tdm-slot-tx-mask = <1 1>; | ||
91 | dai-tdm-slot-rx-mask = <1 1>; | ||
92 | }; | ||
93 | |||
94 | codec { | ||
95 | sound-dai = <&pcm3168a_1 0>; | ||
96 | dai-tdm-slot-num = <2>; | ||
97 | dai-tdm-slot-width = <32>; | ||
98 | dai-tdm-slot-tx-mask = <1 1>; | ||
99 | dai-tdm-slot-rx-mask = <1 1>; | ||
100 | }; | ||
101 | }; | ||
102 | |||
103 | simple-audio-card,dai-link@1 { | ||
104 | format = "dsp_a"; | ||
105 | bitclock-master = <&sound0_1_master>; | ||
106 | frame-master = <&sound0_1_master>; | ||
107 | sound0_1_master: cpu { | ||
108 | sound-dai = <&mcasp10>; | ||
109 | clocks = <&k3_clks 184 1>; | ||
110 | system-clock-id = <MCASP_CLK_HCLK_AUXCLK>; | ||
111 | dai-tdm-slot-num = <2>; | ||
112 | dai-tdm-slot-width = <32>; | ||
113 | dai-tdm-slot-tx-mask = <1 1>; | ||
114 | dai-tdm-slot-rx-mask = <1 1>; | ||
115 | }; | ||
116 | |||
117 | codec { | ||
118 | sound-dai = <&pcm3168a_1 1>; | ||
119 | dai-tdm-slot-num = <2>; | ||
120 | dai-tdm-slot-width = <32>; | ||
121 | dai-tdm-slot-tx-mask = <1 1>; | ||
122 | dai-tdm-slot-rx-mask = <1 1>; | ||
123 | }; | ||
124 | }; | ||
125 | }; | 70 | }; |
126 | 71 | ||
127 | vdd_mmc1: fixedregulator-sd { | 72 | vdd_mmc1: fixedregulator-sd { |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 966caee06166..3b8caab69b5a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -1021,6 +1021,10 @@ struct snd_soc_card { | |||
1021 | struct mutex mutex; | 1021 | struct mutex mutex; |
1022 | struct mutex dapm_mutex; | 1022 | struct mutex dapm_mutex; |
1023 | 1023 | ||
1024 | /* Mutex for PCM operations */ | ||
1025 | struct mutex pcm_mutex; | ||
1026 | enum snd_soc_pcm_subclass pcm_subclass; | ||
1027 | |||
1024 | int id_hint; | 1028 | int id_hint; |
1025 | bool instantiated; | 1029 | bool instantiated; |
1026 | bool topology_shortname_created; | 1030 | bool topology_shortname_created; |
@@ -1121,8 +1125,6 @@ struct snd_soc_pcm_runtime { | |||
1121 | struct device *dev; | 1125 | struct device *dev; |
1122 | struct snd_soc_card *card; | 1126 | struct snd_soc_card *card; |
1123 | struct snd_soc_dai_link *dai_link; | 1127 | struct snd_soc_dai_link *dai_link; |
1124 | struct mutex pcm_mutex; | ||
1125 | enum snd_soc_pcm_subclass pcm_subclass; | ||
1126 | struct snd_pcm_ops ops; | 1128 | struct snd_pcm_ops ops; |
1127 | 1129 | ||
1128 | /* Dynamic PCM BE runtime data */ | 1130 | /* Dynamic PCM BE runtime data */ |
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 890afd7dd224..122afb7c39a8 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c | |||
@@ -47,18 +47,25 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { | |||
47 | "VCCDA2" | 47 | "VCCDA2" |
48 | }; | 48 | }; |
49 | 49 | ||
50 | #define PCM3168A_DAI_DAC 0 | ||
51 | #define PCM3168A_DAI_ADC 1 | ||
52 | |||
53 | /* ADC/DAC side parameters */ | ||
54 | struct pcm3168a_io_params { | ||
55 | bool master_mode; | ||
56 | unsigned int fmt; | ||
57 | int tdm_slots; | ||
58 | u32 tdm_mask; | ||
59 | int slot_width; | ||
60 | }; | ||
61 | |||
50 | struct pcm3168a_priv { | 62 | struct pcm3168a_priv { |
51 | struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; | 63 | struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; |
52 | struct regmap *regmap; | 64 | struct regmap *regmap; |
53 | struct clk *scki; | 65 | struct clk *scki; |
54 | bool adc_master_mode; | ||
55 | bool dac_master_mode; | ||
56 | unsigned long sysclk; | 66 | unsigned long sysclk; |
57 | unsigned int adc_fmt; | 67 | |
58 | unsigned int dac_fmt; | 68 | struct pcm3168a_io_params io_params[2]; |
59 | int tdm_slots; | ||
60 | u32 tdm_mask[2]; | ||
61 | int slot_width; | ||
62 | }; | 69 | }; |
63 | 70 | ||
64 | static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; | 71 | static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; |
@@ -311,8 +318,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, | |||
311 | return 0; | 318 | return 0; |
312 | } | 319 | } |
313 | 320 | ||
314 | static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, | 321 | static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) |
315 | unsigned int format, bool dac) | ||
316 | { | 322 | { |
317 | struct snd_soc_component *component = dai->component; | 323 | struct snd_soc_component *component = dai->component; |
318 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 324 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
@@ -359,43 +365,31 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, | |||
359 | return -EINVAL; | 365 | return -EINVAL; |
360 | } | 366 | } |
361 | 367 | ||
362 | if (dac) { | 368 | if (dai->id == PCM3168A_DAI_DAC) { |
363 | reg = PCM3168A_DAC_PWR_MST_FMT; | 369 | reg = PCM3168A_DAC_PWR_MST_FMT; |
364 | mask = PCM3168A_DAC_FMT_MASK; | 370 | mask = PCM3168A_DAC_FMT_MASK; |
365 | shift = PCM3168A_DAC_FMT_SHIFT; | 371 | shift = PCM3168A_DAC_FMT_SHIFT; |
366 | pcm3168a->dac_master_mode = master_mode; | ||
367 | pcm3168a->dac_fmt = fmt; | ||
368 | } else { | 372 | } else { |
369 | reg = PCM3168A_ADC_MST_FMT; | 373 | reg = PCM3168A_ADC_MST_FMT; |
370 | mask = PCM3168A_ADC_FMTAD_MASK; | 374 | mask = PCM3168A_ADC_FMTAD_MASK; |
371 | shift = PCM3168A_ADC_FMTAD_SHIFT; | 375 | shift = PCM3168A_ADC_FMTAD_SHIFT; |
372 | pcm3168a->adc_master_mode = master_mode; | ||
373 | pcm3168a->adc_fmt = fmt; | ||
374 | } | 376 | } |
375 | 377 | ||
378 | pcm3168a->io_params[dai->id].master_mode = master_mode; | ||
379 | pcm3168a->io_params[dai->id].fmt = fmt; | ||
380 | |||
376 | regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); | 381 | regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); |
377 | 382 | ||
378 | return 0; | 383 | return 0; |
379 | } | 384 | } |
380 | 385 | ||
381 | static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai, | ||
382 | unsigned int format) | ||
383 | { | ||
384 | return pcm3168a_set_dai_fmt(dai, format, true); | ||
385 | } | ||
386 | |||
387 | static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai, | ||
388 | unsigned int format) | ||
389 | { | ||
390 | return pcm3168a_set_dai_fmt(dai, format, false); | ||
391 | } | ||
392 | |||
393 | static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | 386 | static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
394 | unsigned int rx_mask, int slots, | 387 | unsigned int rx_mask, int slots, |
395 | int slot_width) | 388 | int slot_width) |
396 | { | 389 | { |
397 | struct snd_soc_component *component = dai->component; | 390 | struct snd_soc_component *component = dai->component; |
398 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 391 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
392 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; | ||
399 | 393 | ||
400 | if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { | 394 | if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { |
401 | dev_err(component->dev, | 395 | dev_err(component->dev, |
@@ -411,22 +405,13 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
411 | return -EINVAL; | 405 | return -EINVAL; |
412 | } | 406 | } |
413 | 407 | ||
414 | if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) { | 408 | io_params->tdm_slots = slots; |
415 | dev_err(component->dev, "Not matching slots %d vs %d\n", | 409 | io_params->slot_width = slot_width; |
416 | pcm3168a->tdm_slots, slots); | 410 | /* Ignore the not relevant mask for the DAI/direction */ |
417 | return -EINVAL; | 411 | if (dai->id == PCM3168A_DAI_DAC) |
418 | } | 412 | io_params->tdm_mask = tx_mask; |
419 | 413 | else | |
420 | if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { | 414 | io_params->tdm_mask = rx_mask; |
421 | dev_err(component->dev, "Not matching slot_width %d vs %d\n", | ||
422 | pcm3168a->slot_width, slot_width); | ||
423 | return -EINVAL; | ||
424 | } | ||
425 | |||
426 | pcm3168a->tdm_slots = slots; | ||
427 | pcm3168a->slot_width = slot_width; | ||
428 | pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; | ||
429 | pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; | ||
430 | 415 | ||
431 | return 0; | 416 | return 0; |
432 | } | 417 | } |
@@ -437,7 +422,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
437 | { | 422 | { |
438 | struct snd_soc_component *component = dai->component; | 423 | struct snd_soc_component *component = dai->component; |
439 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 424 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
440 | bool tx, master_mode; | 425 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; |
426 | bool master_mode; | ||
441 | u32 val, mask, shift, reg; | 427 | u32 val, mask, shift, reg; |
442 | unsigned int rate, fmt, ratio, max_ratio; | 428 | unsigned int rate, fmt, ratio, max_ratio; |
443 | unsigned int tdm_slots; | 429 | unsigned int tdm_slots; |
@@ -447,23 +433,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
447 | 433 | ||
448 | ratio = pcm3168a->sysclk / rate; | 434 | ratio = pcm3168a->sysclk / rate; |
449 | 435 | ||
450 | tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 436 | if (dai->id == PCM3168A_DAI_DAC) { |
451 | if (tx) { | ||
452 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; | 437 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; |
453 | reg = PCM3168A_DAC_PWR_MST_FMT; | 438 | reg = PCM3168A_DAC_PWR_MST_FMT; |
454 | mask = PCM3168A_DAC_MSDA_MASK; | 439 | mask = PCM3168A_DAC_MSDA_MASK; |
455 | shift = PCM3168A_DAC_MSDA_SHIFT; | 440 | shift = PCM3168A_DAC_MSDA_SHIFT; |
456 | master_mode = pcm3168a->dac_master_mode; | ||
457 | fmt = pcm3168a->dac_fmt; | ||
458 | } else { | 441 | } else { |
459 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; | 442 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; |
460 | reg = PCM3168A_ADC_MST_FMT; | 443 | reg = PCM3168A_ADC_MST_FMT; |
461 | mask = PCM3168A_ADC_MSAD_MASK; | 444 | mask = PCM3168A_ADC_MSAD_MASK; |
462 | shift = PCM3168A_ADC_MSAD_SHIFT; | 445 | shift = PCM3168A_ADC_MSAD_SHIFT; |
463 | master_mode = pcm3168a->adc_master_mode; | ||
464 | fmt = pcm3168a->adc_fmt; | ||
465 | } | 446 | } |
466 | 447 | ||
448 | master_mode = io_params->master_mode; | ||
449 | fmt = io_params->fmt; | ||
450 | |||
467 | for (i = 0; i < max_ratio; i++) { | 451 | for (i = 0; i < max_ratio; i++) { |
468 | if (pcm3168a_scki_ratios[i] == ratio) | 452 | if (pcm3168a_scki_ratios[i] == ratio) |
469 | break; | 453 | break; |
@@ -474,8 +458,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
474 | return -EINVAL; | 458 | return -EINVAL; |
475 | } | 459 | } |
476 | 460 | ||
477 | if (pcm3168a->slot_width) | 461 | if (io_params->slot_width) |
478 | slot_width = pcm3168a->slot_width; | 462 | slot_width = io_params->slot_width; |
479 | else | 463 | else |
480 | slot_width = params_width(params); | 464 | slot_width = params_width(params); |
481 | 465 | ||
@@ -500,8 +484,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
500 | return -EINVAL; | 484 | return -EINVAL; |
501 | } | 485 | } |
502 | 486 | ||
503 | if (pcm3168a->tdm_slots) | 487 | if (io_params->tdm_slots) |
504 | tdm_slots = pcm3168a->tdm_slots; | 488 | tdm_slots = io_params->tdm_slots; |
505 | else | 489 | else |
506 | tdm_slots = params_channels(params); | 490 | tdm_slots = params_channels(params); |
507 | 491 | ||
@@ -537,7 +521,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
537 | 521 | ||
538 | regmap_update_bits(pcm3168a->regmap, reg, mask, val); | 522 | regmap_update_bits(pcm3168a->regmap, reg, mask, val); |
539 | 523 | ||
540 | if (tx) { | 524 | if (dai->id == PCM3168A_DAI_DAC) { |
541 | mask = PCM3168A_DAC_FMT_MASK; | 525 | mask = PCM3168A_DAC_FMT_MASK; |
542 | shift = PCM3168A_DAC_FMT_SHIFT; | 526 | shift = PCM3168A_DAC_FMT_SHIFT; |
543 | } else { | 527 | } else { |
@@ -555,20 +539,13 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
555 | { | 539 | { |
556 | struct snd_soc_component *component = dai->component; | 540 | struct snd_soc_component *component = dai->component; |
557 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 541 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
558 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
559 | unsigned int fmt; | ||
560 | unsigned int sample_min; | 542 | unsigned int sample_min; |
561 | unsigned int channel_max; | 543 | unsigned int channel_max; |
562 | unsigned int channel_maxs[] = { | 544 | unsigned int channel_maxs[] = { |
563 | 6, /* rx */ | 545 | 8, /* DAC */ |
564 | 8 /* tx */ | 546 | 6 /* ADC */ |
565 | }; | 547 | }; |
566 | 548 | ||
567 | if (tx) | ||
568 | fmt = pcm3168a->dac_fmt; | ||
569 | else | ||
570 | fmt = pcm3168a->adc_fmt; | ||
571 | |||
572 | /* | 549 | /* |
573 | * Available Data Bits | 550 | * Available Data Bits |
574 | * | 551 | * |
@@ -581,7 +558,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
581 | * I2S | 558 | * I2S |
582 | * LEFT_J | 559 | * LEFT_J |
583 | */ | 560 | */ |
584 | switch (fmt) { | 561 | switch (pcm3168a->io_params[dai->id].fmt) { |
585 | case PCM3168A_FMT_RIGHT_J: | 562 | case PCM3168A_FMT_RIGHT_J: |
586 | sample_min = 16; | 563 | sample_min = 16; |
587 | channel_max = 2; | 564 | channel_max = 2; |
@@ -591,7 +568,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
591 | case PCM3168A_FMT_DSP_A: | 568 | case PCM3168A_FMT_DSP_A: |
592 | case PCM3168A_FMT_DSP_B: | 569 | case PCM3168A_FMT_DSP_B: |
593 | sample_min = 24; | 570 | sample_min = 24; |
594 | channel_max = channel_maxs[tx]; | 571 | channel_max = channel_maxs[dai->id]; |
595 | break; | 572 | break; |
596 | default: | 573 | default: |
597 | sample_min = 24; | 574 | sample_min = 24; |
@@ -603,8 +580,8 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
603 | sample_min, 32); | 580 | sample_min, 32); |
604 | 581 | ||
605 | /* Allow all channels in multi DIN/DOUT mode */ | 582 | /* Allow all channels in multi DIN/DOUT mode */ |
606 | if (pcm3168a->tdm_slots == 2) | 583 | if (pcm3168a->io_params[dai->id].tdm_slots == 2) |
607 | channel_max = channel_maxs[tx]; | 584 | channel_max = channel_maxs[dai->id]; |
608 | 585 | ||
609 | snd_pcm_hw_constraint_minmax(substream->runtime, | 586 | snd_pcm_hw_constraint_minmax(substream->runtime, |
610 | SNDRV_PCM_HW_PARAM_CHANNELS, | 587 | SNDRV_PCM_HW_PARAM_CHANNELS, |
@@ -612,26 +589,19 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
612 | 589 | ||
613 | return 0; | 590 | return 0; |
614 | } | 591 | } |
615 | static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { | 592 | static const struct snd_soc_dai_ops pcm3168a_dai_ops = { |
616 | .startup = pcm3168a_startup, | 593 | .startup = pcm3168a_startup, |
617 | .set_fmt = pcm3168a_set_dai_fmt_dac, | 594 | .set_fmt = pcm3168a_set_dai_fmt, |
618 | .set_sysclk = pcm3168a_set_dai_sysclk, | 595 | .set_sysclk = pcm3168a_set_dai_sysclk, |
619 | .hw_params = pcm3168a_hw_params, | 596 | .hw_params = pcm3168a_hw_params, |
620 | .digital_mute = pcm3168a_digital_mute, | 597 | .digital_mute = pcm3168a_digital_mute, |
621 | .set_tdm_slot = pcm3168a_set_tdm_slot, | 598 | .set_tdm_slot = pcm3168a_set_tdm_slot, |
622 | }; | 599 | }; |
623 | 600 | ||
624 | static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { | ||
625 | .startup = pcm3168a_startup, | ||
626 | .set_fmt = pcm3168a_set_dai_fmt_adc, | ||
627 | .set_sysclk = pcm3168a_set_dai_sysclk, | ||
628 | .hw_params = pcm3168a_hw_params, | ||
629 | .set_tdm_slot = pcm3168a_set_tdm_slot, | ||
630 | }; | ||
631 | |||
632 | static struct snd_soc_dai_driver pcm3168a_dais[] = { | 601 | static struct snd_soc_dai_driver pcm3168a_dais[] = { |
633 | { | 602 | { |
634 | .name = "pcm3168a-dac", | 603 | .name = "pcm3168a-dac", |
604 | .id = PCM3168A_DAI_DAC, | ||
635 | .playback = { | 605 | .playback = { |
636 | .stream_name = "Playback", | 606 | .stream_name = "Playback", |
637 | .channels_min = 1, | 607 | .channels_min = 1, |
@@ -639,10 +609,11 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = { | |||
639 | .rates = SNDRV_PCM_RATE_8000_192000, | 609 | .rates = SNDRV_PCM_RATE_8000_192000, |
640 | .formats = PCM3168A_FORMATS | 610 | .formats = PCM3168A_FORMATS |
641 | }, | 611 | }, |
642 | .ops = &pcm3168a_dac_dai_ops | 612 | .ops = &pcm3168a_dai_ops |
643 | }, | 613 | }, |
644 | { | 614 | { |
645 | .name = "pcm3168a-adc", | 615 | .name = "pcm3168a-adc", |
616 | .id = PCM3168A_DAI_ADC, | ||
646 | .capture = { | 617 | .capture = { |
647 | .stream_name = "Capture", | 618 | .stream_name = "Capture", |
648 | .channels_min = 1, | 619 | .channels_min = 1, |
@@ -650,7 +621,7 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = { | |||
650 | .rates = SNDRV_PCM_RATE_8000_96000, | 621 | .rates = SNDRV_PCM_RATE_8000_96000, |
651 | .formats = PCM3168A_FORMATS | 622 | .formats = PCM3168A_FORMATS |
652 | }, | 623 | }, |
653 | .ops = &pcm3168a_adc_dai_ops | 624 | .ops = &pcm3168a_dai_ops |
654 | }, | 625 | }, |
655 | }; | 626 | }; |
656 | 627 | ||
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 409d082e80d1..2ea87145ca05 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -80,7 +80,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 83 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
84 | 84 | ||
85 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { | 85 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { |
86 | ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); | 86 | ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); |
@@ -108,7 +108,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
108 | 108 | ||
109 | snd_soc_runtime_activate(rtd, cstream->direction); | 109 | snd_soc_runtime_activate(rtd, cstream->direction); |
110 | 110 | ||
111 | mutex_unlock(&rtd->pcm_mutex); | 111 | mutex_unlock(&rtd->card->pcm_mutex); |
112 | 112 | ||
113 | return 0; | 113 | return 0; |
114 | 114 | ||
@@ -118,7 +118,7 @@ machine_err: | |||
118 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) | 118 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) |
119 | cpu_dai->driver->cops->shutdown(cstream, cpu_dai); | 119 | cpu_dai->driver->cops->shutdown(cstream, cpu_dai); |
120 | out: | 120 | out: |
121 | mutex_unlock(&rtd->pcm_mutex); | 121 | mutex_unlock(&rtd->card->pcm_mutex); |
122 | return ret; | 122 | return ret; |
123 | } | 123 | } |
124 | 124 | ||
@@ -224,7 +224,7 @@ static void close_delayed_work(struct work_struct *work) | |||
224 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 224 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
226 | 226 | ||
227 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 227 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
228 | 228 | ||
229 | dev_dbg(rtd->dev, | 229 | dev_dbg(rtd->dev, |
230 | "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n", | 230 | "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n", |
@@ -239,7 +239,7 @@ static void close_delayed_work(struct work_struct *work) | |||
239 | SND_SOC_DAPM_STREAM_STOP); | 239 | SND_SOC_DAPM_STREAM_STOP); |
240 | } | 240 | } |
241 | 241 | ||
242 | mutex_unlock(&rtd->pcm_mutex); | 242 | mutex_unlock(&rtd->card->pcm_mutex); |
243 | } | 243 | } |
244 | 244 | ||
245 | static int soc_compr_free(struct snd_compr_stream *cstream) | 245 | static int soc_compr_free(struct snd_compr_stream *cstream) |
@@ -249,7 +249,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
249 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 249 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
250 | int stream; | 250 | int stream; |
251 | 251 | ||
252 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 252 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
253 | 253 | ||
254 | if (cstream->direction == SND_COMPRESS_PLAYBACK) | 254 | if (cstream->direction == SND_COMPRESS_PLAYBACK) |
255 | stream = SNDRV_PCM_STREAM_PLAYBACK; | 255 | stream = SNDRV_PCM_STREAM_PLAYBACK; |
@@ -292,7 +292,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
292 | SND_SOC_DAPM_STREAM_STOP); | 292 | SND_SOC_DAPM_STREAM_STOP); |
293 | } | 293 | } |
294 | 294 | ||
295 | mutex_unlock(&rtd->pcm_mutex); | 295 | mutex_unlock(&rtd->card->pcm_mutex); |
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | 298 | ||
@@ -355,7 +355,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | |||
355 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 355 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
356 | int ret = 0, __ret; | 356 | int ret = 0, __ret; |
357 | 357 | ||
358 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 358 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
359 | 359 | ||
360 | for_each_rtdcom(rtd, rtdcom) { | 360 | for_each_rtdcom(rtd, rtdcom) { |
361 | component = rtdcom->component; | 361 | component = rtdcom->component; |
@@ -384,7 +384,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | out: | 386 | out: |
387 | mutex_unlock(&rtd->pcm_mutex); | 387 | mutex_unlock(&rtd->card->pcm_mutex); |
388 | return ret; | 388 | return ret; |
389 | } | 389 | } |
390 | 390 | ||
@@ -474,7 +474,7 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, | |||
474 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 474 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
475 | int ret = 0, __ret; | 475 | int ret = 0, __ret; |
476 | 476 | ||
477 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 477 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
478 | 478 | ||
479 | /* | 479 | /* |
480 | * First we call set_params for the CPU DAI, then the component | 480 | * First we call set_params for the CPU DAI, then the component |
@@ -518,14 +518,14 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, | |||
518 | 518 | ||
519 | /* cancel any delayed stream shutdown that is pending */ | 519 | /* cancel any delayed stream shutdown that is pending */ |
520 | rtd->pop_wait = 0; | 520 | rtd->pop_wait = 0; |
521 | mutex_unlock(&rtd->pcm_mutex); | 521 | mutex_unlock(&rtd->card->pcm_mutex); |
522 | 522 | ||
523 | cancel_delayed_work_sync(&rtd->delayed_work); | 523 | cancel_delayed_work_sync(&rtd->delayed_work); |
524 | 524 | ||
525 | return ret; | 525 | return ret; |
526 | 526 | ||
527 | err: | 527 | err: |
528 | mutex_unlock(&rtd->pcm_mutex); | 528 | mutex_unlock(&rtd->card->pcm_mutex); |
529 | return ret; | 529 | return ret; |
530 | } | 530 | } |
531 | 531 | ||
@@ -609,7 +609,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, | |||
609 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 609 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
610 | int ret = 0, __ret; | 610 | int ret = 0, __ret; |
611 | 611 | ||
612 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 612 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
613 | 613 | ||
614 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) { | 614 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) { |
615 | ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai); | 615 | ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai); |
@@ -630,7 +630,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, | |||
630 | } | 630 | } |
631 | 631 | ||
632 | err: | 632 | err: |
633 | mutex_unlock(&rtd->pcm_mutex); | 633 | mutex_unlock(&rtd->card->pcm_mutex); |
634 | return ret; | 634 | return ret; |
635 | } | 635 | } |
636 | 636 | ||
@@ -642,7 +642,7 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, | |||
642 | struct snd_soc_rtdcom_list *rtdcom; | 642 | struct snd_soc_rtdcom_list *rtdcom; |
643 | int ret = 0, __ret; | 643 | int ret = 0, __ret; |
644 | 644 | ||
645 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 645 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
646 | 646 | ||
647 | for_each_rtdcom(rtd, rtdcom) { | 647 | for_each_rtdcom(rtd, rtdcom) { |
648 | component = rtdcom->component; | 648 | component = rtdcom->component; |
@@ -656,7 +656,7 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, | |||
656 | ret = __ret; | 656 | ret = __ret; |
657 | } | 657 | } |
658 | 658 | ||
659 | mutex_unlock(&rtd->pcm_mutex); | 659 | mutex_unlock(&rtd->card->pcm_mutex); |
660 | return ret; | 660 | return ret; |
661 | } | 661 | } |
662 | 662 | ||
@@ -668,7 +668,7 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | |||
668 | struct snd_soc_rtdcom_list *rtdcom; | 668 | struct snd_soc_rtdcom_list *rtdcom; |
669 | int ret = 0, __ret; | 669 | int ret = 0, __ret; |
670 | 670 | ||
671 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 671 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
672 | 672 | ||
673 | for_each_rtdcom(rtd, rtdcom) { | 673 | for_each_rtdcom(rtd, rtdcom) { |
674 | component = rtdcom->component; | 674 | component = rtdcom->component; |
@@ -682,7 +682,7 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | |||
682 | ret = __ret; | 682 | ret = __ret; |
683 | } | 683 | } |
684 | 684 | ||
685 | mutex_unlock(&rtd->pcm_mutex); | 685 | mutex_unlock(&rtd->card->pcm_mutex); |
686 | return ret; | 686 | return ret; |
687 | } | 687 | } |
688 | 688 | ||
@@ -694,7 +694,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | |||
694 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 694 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
695 | int ret = 0, __ret; | 695 | int ret = 0, __ret; |
696 | 696 | ||
697 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 697 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
698 | 698 | ||
699 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) { | 699 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) { |
700 | ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai); | 700 | ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai); |
@@ -715,7 +715,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | |||
715 | } | 715 | } |
716 | 716 | ||
717 | err: | 717 | err: |
718 | mutex_unlock(&rtd->pcm_mutex); | 718 | mutex_unlock(&rtd->card->pcm_mutex); |
719 | return ret; | 719 | return ret; |
720 | } | 720 | } |
721 | 721 | ||
@@ -728,7 +728,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, | |||
728 | int ret = 0, __ret; | 728 | int ret = 0, __ret; |
729 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 729 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
730 | 730 | ||
731 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 731 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
732 | 732 | ||
733 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) | 733 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) |
734 | cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); | 734 | cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); |
@@ -745,7 +745,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, | |||
745 | ret = __ret; | 745 | ret = __ret; |
746 | } | 746 | } |
747 | 747 | ||
748 | mutex_unlock(&rtd->pcm_mutex); | 748 | mutex_unlock(&rtd->card->pcm_mutex); |
749 | return ret; | 749 | return ret; |
750 | } | 750 | } |
751 | 751 | ||
@@ -757,7 +757,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, | |||
757 | struct snd_soc_rtdcom_list *rtdcom; | 757 | struct snd_soc_rtdcom_list *rtdcom; |
758 | int ret = 0; | 758 | int ret = 0; |
759 | 759 | ||
760 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 760 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
761 | 761 | ||
762 | for_each_rtdcom(rtd, rtdcom) { | 762 | for_each_rtdcom(rtd, rtdcom) { |
763 | component = rtdcom->component; | 763 | component = rtdcom->component; |
@@ -770,7 +770,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, | |||
770 | break; | 770 | break; |
771 | } | 771 | } |
772 | 772 | ||
773 | mutex_unlock(&rtd->pcm_mutex); | 773 | mutex_unlock(&rtd->card->pcm_mutex); |
774 | return ret; | 774 | return ret; |
775 | } | 775 | } |
776 | 776 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 272183654c07..d971dcddcb42 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1352,7 +1352,6 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1352 | rtd->dev->groups = soc_dev_attr_groups; | 1352 | rtd->dev->groups = soc_dev_attr_groups; |
1353 | dev_set_name(rtd->dev, "%s", name); | 1353 | dev_set_name(rtd->dev, "%s", name); |
1354 | dev_set_drvdata(rtd->dev, rtd); | 1354 | dev_set_drvdata(rtd->dev, rtd); |
1355 | mutex_init(&rtd->pcm_mutex); | ||
1356 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients); | 1355 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients); |
1357 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients); | 1356 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients); |
1358 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients); | 1357 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients); |
@@ -2743,6 +2742,7 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2743 | card->instantiated = 0; | 2742 | card->instantiated = 0; |
2744 | mutex_init(&card->mutex); | 2743 | mutex_init(&card->mutex); |
2745 | mutex_init(&card->dapm_mutex); | 2744 | mutex_init(&card->dapm_mutex); |
2745 | mutex_init(&card->pcm_mutex); | ||
2746 | 2746 | ||
2747 | ret = snd_soc_instantiate_card(card); | 2747 | ret = snd_soc_instantiate_card(card); |
2748 | if (ret != 0) | 2748 | if (ret != 0) |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 74f54c275d78..edb7c5290f94 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -54,14 +54,14 @@ static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) | |||
54 | * Increments the active count for all the DAIs and components attached to a PCM | 54 | * Increments the active count for all the DAIs and components attached to a PCM |
55 | * runtime. Should typically be called when a stream is opened. | 55 | * runtime. Should typically be called when a stream is opened. |
56 | * | 56 | * |
57 | * Must be called with the rtd->pcm_mutex being held | 57 | * Must be called with the rtd->card->pcm_mutex being held |
58 | */ | 58 | */ |
59 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | 59 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) |
60 | { | 60 | { |
61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
62 | int i; | 62 | int i; |
63 | 63 | ||
64 | lockdep_assert_held(&rtd->pcm_mutex); | 64 | lockdep_assert_held(&rtd->card->pcm_mutex); |
65 | 65 | ||
66 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 66 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
67 | cpu_dai->playback_active++; | 67 | cpu_dai->playback_active++; |
@@ -89,14 +89,14 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
89 | * Decrements the active count for all the DAIs and components attached to a PCM | 89 | * Decrements the active count for all the DAIs and components attached to a PCM |
90 | * runtime. Should typically be called when a stream is closed. | 90 | * runtime. Should typically be called when a stream is closed. |
91 | * | 91 | * |
92 | * Must be called with the rtd->pcm_mutex being held | 92 | * Must be called with the rtd->card->pcm_mutex being held |
93 | */ | 93 | */ |
94 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | 94 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) |
95 | { | 95 | { |
96 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 96 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
97 | int i; | 97 | int i; |
98 | 98 | ||
99 | lockdep_assert_held(&rtd->pcm_mutex); | 99 | lockdep_assert_held(&rtd->card->pcm_mutex); |
100 | 100 | ||
101 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 101 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
102 | cpu_dai->playback_active--; | 102 | cpu_dai->playback_active--; |
@@ -491,7 +491,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
491 | pm_runtime_get_sync(component->dev); | 491 | pm_runtime_get_sync(component->dev); |
492 | } | 492 | } |
493 | 493 | ||
494 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 494 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
495 | 495 | ||
496 | /* startup the audio subsystem */ | 496 | /* startup the audio subsystem */ |
497 | if (cpu_dai->driver->ops->startup) { | 497 | if (cpu_dai->driver->ops->startup) { |
@@ -609,7 +609,7 @@ dynamic: | |||
609 | 609 | ||
610 | snd_soc_runtime_activate(rtd, substream->stream); | 610 | snd_soc_runtime_activate(rtd, substream->stream); |
611 | 611 | ||
612 | mutex_unlock(&rtd->pcm_mutex); | 612 | mutex_unlock(&rtd->card->pcm_mutex); |
613 | return 0; | 613 | return 0; |
614 | 614 | ||
615 | config_err: | 615 | config_err: |
@@ -632,7 +632,7 @@ component_err: | |||
632 | if (cpu_dai->driver->ops->shutdown) | 632 | if (cpu_dai->driver->ops->shutdown) |
633 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 633 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
634 | out: | 634 | out: |
635 | mutex_unlock(&rtd->pcm_mutex); | 635 | mutex_unlock(&rtd->card->pcm_mutex); |
636 | 636 | ||
637 | for_each_rtdcom(rtd, rtdcom) { | 637 | for_each_rtdcom(rtd, rtdcom) { |
638 | component = rtdcom->component; | 638 | component = rtdcom->component; |
@@ -662,7 +662,7 @@ static void close_delayed_work(struct work_struct *work) | |||
662 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 662 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
663 | struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; | 663 | struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; |
664 | 664 | ||
665 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 665 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
666 | 666 | ||
667 | dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", | 667 | dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", |
668 | codec_dai->driver->playback.stream_name, | 668 | codec_dai->driver->playback.stream_name, |
@@ -676,7 +676,7 @@ static void close_delayed_work(struct work_struct *work) | |||
676 | SND_SOC_DAPM_STREAM_STOP); | 676 | SND_SOC_DAPM_STREAM_STOP); |
677 | } | 677 | } |
678 | 678 | ||
679 | mutex_unlock(&rtd->pcm_mutex); | 679 | mutex_unlock(&rtd->card->pcm_mutex); |
680 | } | 680 | } |
681 | 681 | ||
682 | /* | 682 | /* |
@@ -693,7 +693,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
693 | struct snd_soc_dai *codec_dai; | 693 | struct snd_soc_dai *codec_dai; |
694 | int i; | 694 | int i; |
695 | 695 | ||
696 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 696 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
697 | 697 | ||
698 | snd_soc_runtime_deactivate(rtd, substream->stream); | 698 | snd_soc_runtime_deactivate(rtd, substream->stream); |
699 | 699 | ||
@@ -742,7 +742,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
742 | SND_SOC_DAPM_STREAM_STOP); | 742 | SND_SOC_DAPM_STREAM_STOP); |
743 | } | 743 | } |
744 | 744 | ||
745 | mutex_unlock(&rtd->pcm_mutex); | 745 | mutex_unlock(&rtd->card->pcm_mutex); |
746 | 746 | ||
747 | for_each_rtdcom(rtd, rtdcom) { | 747 | for_each_rtdcom(rtd, rtdcom) { |
748 | component = rtdcom->component; | 748 | component = rtdcom->component; |
@@ -775,7 +775,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
775 | struct snd_soc_dai *codec_dai; | 775 | struct snd_soc_dai *codec_dai; |
776 | int i, ret = 0; | 776 | int i, ret = 0; |
777 | 777 | ||
778 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 778 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
779 | 779 | ||
780 | if (rtd->dai_link->ops->prepare) { | 780 | if (rtd->dai_link->ops->prepare) { |
781 | ret = rtd->dai_link->ops->prepare(substream); | 781 | ret = rtd->dai_link->ops->prepare(substream); |
@@ -840,7 +840,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
840 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); | 840 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); |
841 | 841 | ||
842 | out: | 842 | out: |
843 | mutex_unlock(&rtd->pcm_mutex); | 843 | mutex_unlock(&rtd->card->pcm_mutex); |
844 | return ret; | 844 | return ret; |
845 | } | 845 | } |
846 | 846 | ||
@@ -922,7 +922,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
922 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 922 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
923 | int i, ret = 0; | 923 | int i, ret = 0; |
924 | 924 | ||
925 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 925 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
926 | if (rtd->dai_link->ops->hw_params) { | 926 | if (rtd->dai_link->ops->hw_params) { |
927 | ret = rtd->dai_link->ops->hw_params(substream, params); | 927 | ret = rtd->dai_link->ops->hw_params(substream, params); |
928 | if (ret < 0) { | 928 | if (ret < 0) { |
@@ -1008,7 +1008,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1008 | if (ret) | 1008 | if (ret) |
1009 | goto component_err; | 1009 | goto component_err; |
1010 | out: | 1010 | out: |
1011 | mutex_unlock(&rtd->pcm_mutex); | 1011 | mutex_unlock(&rtd->card->pcm_mutex); |
1012 | return ret; | 1012 | return ret; |
1013 | 1013 | ||
1014 | component_err: | 1014 | component_err: |
@@ -1031,7 +1031,7 @@ codec_err: | |||
1031 | if (rtd->dai_link->ops->hw_free) | 1031 | if (rtd->dai_link->ops->hw_free) |
1032 | rtd->dai_link->ops->hw_free(substream); | 1032 | rtd->dai_link->ops->hw_free(substream); |
1033 | 1033 | ||
1034 | mutex_unlock(&rtd->pcm_mutex); | 1034 | mutex_unlock(&rtd->card->pcm_mutex); |
1035 | return ret; | 1035 | return ret; |
1036 | } | 1036 | } |
1037 | 1037 | ||
@@ -1046,7 +1046,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1046 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 1046 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
1047 | int i; | 1047 | int i; |
1048 | 1048 | ||
1049 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 1049 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
1050 | 1050 | ||
1051 | /* clear the corresponding DAIs parameters when going to be inactive */ | 1051 | /* clear the corresponding DAIs parameters when going to be inactive */ |
1052 | if (cpu_dai->active == 1) { | 1052 | if (cpu_dai->active == 1) { |
@@ -1089,7 +1089,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1089 | if (cpu_dai->driver->ops->hw_free) | 1089 | if (cpu_dai->driver->ops->hw_free) |
1090 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 1090 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
1091 | 1091 | ||
1092 | mutex_unlock(&rtd->pcm_mutex); | 1092 | mutex_unlock(&rtd->card->pcm_mutex); |
1093 | return 0; | 1093 | return 0; |
1094 | } | 1094 | } |
1095 | 1095 | ||
diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index 41342823e662..598e7f98a457 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig | |||
@@ -211,5 +211,13 @@ config SND_SOC_DM365_VOICE_CODEC | |||
211 | Say Y if you want to add support for SoC On-chip voice codec | 211 | Say Y if you want to add support for SoC On-chip voice codec |
212 | endchoice | 212 | endchoice |
213 | 213 | ||
214 | config SND_SOC_J721E_EVM | ||
215 | tristate "SoC Audio support for j721e EVM" | ||
216 | depends on ARCH_K3_J721E_SOC || COMPILE_TEST | ||
217 | select SND_SOC_PCM3168A_I2C | ||
218 | select SND_SOC_DAVINCI_MCASP | ||
219 | help | ||
220 | Say Y if you want to add support for SoC audio on j721e Common | ||
221 | Processor Board. | ||
214 | endmenu | 222 | endmenu |
215 | 223 | ||
diff --git a/sound/soc/ti/Makefile b/sound/soc/ti/Makefile index ea48c6679cc7..a21e5b0061de 100644 --- a/sound/soc/ti/Makefile +++ b/sound/soc/ti/Makefile | |||
@@ -34,6 +34,7 @@ snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o | |||
34 | snd-soc-ams-delta-objs := ams-delta.o | 34 | snd-soc-ams-delta-objs := ams-delta.o |
35 | snd-soc-omap-hdmi-objs := omap-hdmi.o | 35 | snd-soc-omap-hdmi-objs := omap-hdmi.o |
36 | snd-soc-osk5912-objs := osk5912.o | 36 | snd-soc-osk5912-objs := osk5912.o |
37 | snd-soc-j721e-evm-objs := j721e-evm.o | ||
37 | 38 | ||
38 | obj-$(CONFIG_SND_SOC_DAVINCI_EVM) += snd-soc-davinci-evm.o | 39 | obj-$(CONFIG_SND_SOC_DAVINCI_EVM) += snd-soc-davinci-evm.o |
39 | obj-$(CONFIG_SND_SOC_NOKIA_N810) += snd-soc-n810.o | 40 | obj-$(CONFIG_SND_SOC_NOKIA_N810) += snd-soc-n810.o |
@@ -44,3 +45,4 @@ obj-$(CONFIG_SND_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o | |||
44 | obj-$(CONFIG_SND_SOC_OMAP_AMS_DELTA) += snd-soc-ams-delta.o | 45 | obj-$(CONFIG_SND_SOC_OMAP_AMS_DELTA) += snd-soc-ams-delta.o |
45 | obj-$(CONFIG_SND_SOC_OMAP_HDMI) += snd-soc-omap-hdmi.o | 46 | obj-$(CONFIG_SND_SOC_OMAP_HDMI) += snd-soc-omap-hdmi.o |
46 | obj-$(CONFIG_SND_SOC_OMAP_OSK5912) += snd-soc-osk5912.o | 47 | obj-$(CONFIG_SND_SOC_OMAP_OSK5912) += snd-soc-osk5912.o |
48 | obj-$(CONFIG_SND_SOC_J721E_EVM) += snd-soc-j721e-evm.o | ||
diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c new file mode 100644 index 000000000000..0fcc1c9c3ef8 --- /dev/null +++ b/sound/soc/ti/j721e-evm.c | |||
@@ -0,0 +1,459 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com | ||
4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
5 | */ | ||
6 | |||
7 | #include <linux/clk.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/of.h> | ||
11 | |||
12 | #include <sound/pcm_params.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <dt-bindings/sound/ti-mcasp.h> | ||
17 | |||
18 | #define J721E_CPD_DAI_CNT 2 | ||
19 | |||
20 | #define J721E_CLK_PARENT_48000 0 | ||
21 | #define J721E_CLK_PARENT_44100 1 | ||
22 | |||
23 | #define J721E_MAX_CLK_HSDIV 128 | ||
24 | |||
25 | #define J721E_DAI_FMT (SND_SOC_DAIFMT_RIGHT_J | \ | ||
26 | SND_SOC_DAIFMT_NB_NF | \ | ||
27 | SND_SOC_DAIFMT_CBS_CFS) | ||
28 | |||
29 | static unsigned int ratios_for_pcm3168a[] = { | ||
30 | 256, | ||
31 | 512, | ||
32 | 768, | ||
33 | }; | ||
34 | |||
35 | struct j721e_audio_clocks { | ||
36 | struct clk *target; | ||
37 | struct clk *parent[2]; | ||
38 | }; | ||
39 | |||
40 | struct j721e_priv { | ||
41 | struct device *dev; | ||
42 | struct snd_soc_card cpb_card; | ||
43 | struct snd_soc_dai_link cpb_dai_links[J721E_CPD_DAI_CNT]; | ||
44 | struct snd_soc_codec_conf codec_conf; | ||
45 | |||
46 | struct j721e_audio_clocks audio_refclk2; | ||
47 | struct j721e_audio_clocks cpb_mcasp; | ||
48 | u32 pll_rates[2]; | ||
49 | unsigned int current_cpb_ref_rate; | ||
50 | int current_cpb_ref_parent; | ||
51 | |||
52 | int active; | ||
53 | unsigned int rate; | ||
54 | struct mutex mutex; | ||
55 | }; | ||
56 | |||
57 | static int j721e_configure_refclk(struct j721e_priv *priv, unsigned int rate) | ||
58 | { | ||
59 | unsigned int scki; | ||
60 | int ret = -EINVAL; | ||
61 | int i, clk_id; | ||
62 | |||
63 | if (!(rate % 8000)) | ||
64 | clk_id = J721E_CLK_PARENT_48000; | ||
65 | else if (!(rate % 11025)) | ||
66 | clk_id = J721E_CLK_PARENT_44100; | ||
67 | else | ||
68 | return ret; | ||
69 | |||
70 | for (i = 0; i < ARRAY_SIZE(ratios_for_pcm3168a); i++) { | ||
71 | scki = ratios_for_pcm3168a[i] * rate; | ||
72 | |||
73 | if (priv->pll_rates[clk_id] / scki <= J721E_MAX_CLK_HSDIV) { | ||
74 | ret = 0; | ||
75 | break; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | if (ret) { | ||
80 | dev_err(priv->dev, "No valid clock configuration for %u Hz\n", | ||
81 | rate); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | if (priv->current_cpb_ref_rate != scki) { | ||
86 | dev_dbg(priv->dev, | ||
87 | "Configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", | ||
88 | rate, | ||
89 | clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15", | ||
90 | ratios_for_pcm3168a[i], scki); | ||
91 | |||
92 | if (priv->current_cpb_ref_parent != clk_id) { | ||
93 | ret = clk_set_parent(priv->audio_refclk2.target, | ||
94 | priv->audio_refclk2.parent[clk_id]); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | |||
98 | ret = clk_set_parent(priv->cpb_mcasp.target, | ||
99 | priv->cpb_mcasp.parent[clk_id]); | ||
100 | if (ret) | ||
101 | return ret; | ||
102 | |||
103 | priv->current_cpb_ref_parent = clk_id; | ||
104 | } | ||
105 | |||
106 | ret = clk_set_rate(priv->audio_refclk2.target, scki); | ||
107 | if (ret) | ||
108 | return ret; | ||
109 | |||
110 | ret = clk_set_rate(priv->cpb_mcasp.target, scki); | ||
111 | if (!ret) | ||
112 | priv->current_cpb_ref_rate = scki; | ||
113 | } | ||
114 | |||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | static int j721e_audio_startup(struct snd_pcm_substream *substream) | ||
119 | { | ||
120 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
121 | struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
122 | int ret = 0; | ||
123 | |||
124 | mutex_lock(&priv->mutex); | ||
125 | priv->active++; | ||
126 | |||
127 | if (priv->rate) | ||
128 | ret = snd_pcm_hw_constraint_single(substream->runtime, | ||
129 | SNDRV_PCM_HW_PARAM_RATE, | ||
130 | priv->rate); | ||
131 | |||
132 | mutex_unlock(&priv->mutex); | ||
133 | |||
134 | if (ret) | ||
135 | return ret; | ||
136 | |||
137 | /* Reset TDM slots to 32 */ | ||
138 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 32); | ||
139 | if (ret) | ||
140 | return ret; | ||
141 | |||
142 | ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x3, 0x3, 2, 32); | ||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int j721e_audio_hw_params(struct snd_pcm_substream *substream, | ||
150 | struct snd_pcm_hw_params *params) | ||
151 | { | ||
152 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
153 | struct snd_soc_card *card = rtd->card; | ||
154 | struct j721e_priv *priv = snd_soc_card_get_drvdata(card); | ||
155 | int slot_width = 32; | ||
156 | int ret; | ||
157 | |||
158 | mutex_lock(&priv->mutex); | ||
159 | |||
160 | if (priv->rate && priv->rate != params_rate(params)) { | ||
161 | ret = -EINVAL; | ||
162 | goto out; | ||
163 | } | ||
164 | |||
165 | if (params_width(params) == 16) | ||
166 | slot_width = 16; | ||
167 | |||
168 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, slot_width); | ||
169 | if (ret) | ||
170 | goto out; | ||
171 | |||
172 | ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x3, 0x3, 2, slot_width); | ||
173 | if (ret) | ||
174 | goto out; | ||
175 | |||
176 | ret = j721e_configure_refclk(priv, params_rate(params)); | ||
177 | if (ret) | ||
178 | goto out; | ||
179 | |||
180 | ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, | ||
181 | priv->current_cpb_ref_rate, | ||
182 | SND_SOC_CLOCK_IN); | ||
183 | if (ret) | ||
184 | goto out; | ||
185 | |||
186 | ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, MCASP_CLK_HCLK_AUXCLK, | ||
187 | priv->current_cpb_ref_rate, | ||
188 | SND_SOC_CLOCK_IN); | ||
189 | |||
190 | if (!ret) | ||
191 | priv->rate = params_rate(params); | ||
192 | |||
193 | out: | ||
194 | mutex_unlock(&priv->mutex); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static void j721e_audio_shutdown(struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
201 | struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
202 | |||
203 | mutex_lock(&priv->mutex); | ||
204 | |||
205 | priv->active--; | ||
206 | if (!priv->active) | ||
207 | priv->rate = 0; | ||
208 | |||
209 | mutex_unlock(&priv->mutex); | ||
210 | } | ||
211 | |||
212 | static const struct snd_soc_ops j721e_audio_ops = { | ||
213 | .startup = j721e_audio_startup, | ||
214 | .hw_params = j721e_audio_hw_params, | ||
215 | .shutdown = j721e_audio_shutdown, | ||
216 | }; | ||
217 | |||
218 | static int j721e_audio_init(struct snd_soc_pcm_runtime *rtd) | ||
219 | { | ||
220 | struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
221 | int ret; | ||
222 | |||
223 | /* Set up initial clock configuration */ | ||
224 | ret = j721e_configure_refclk(priv, 48000); | ||
225 | if (ret) | ||
226 | return ret; | ||
227 | |||
228 | ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, | ||
229 | priv->current_cpb_ref_rate, | ||
230 | SND_SOC_CLOCK_IN); | ||
231 | if (ret) | ||
232 | return ret; | ||
233 | |||
234 | ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, MCASP_CLK_HCLK_AUXCLK, | ||
235 | priv->current_cpb_ref_rate, | ||
236 | SND_SOC_CLOCK_IN); | ||
237 | if (ret) | ||
238 | return ret; | ||
239 | |||
240 | /* Set initial tdm slots */ | ||
241 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 32); | ||
242 | if (ret) | ||
243 | return ret; | ||
244 | |||
245 | ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x3, 0x3, 2, 32); | ||
246 | |||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = { | ||
251 | SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL), | ||
252 | SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL), | ||
253 | SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL), | ||
254 | SND_SOC_DAPM_LINE("CPB Line Out", NULL), | ||
255 | SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL), | ||
256 | SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL), | ||
257 | SND_SOC_DAPM_LINE("CPB Line In", NULL), | ||
258 | }; | ||
259 | |||
260 | static const struct snd_soc_dapm_route j721e_cpb_dapm_routes[] = { | ||
261 | {"CPB Stereo HP 1", NULL, "codec1 AOUT1L"}, | ||
262 | {"CPB Stereo HP 1", NULL, "codec1 AOUT1R"}, | ||
263 | {"CPB Stereo HP 2", NULL, "codec1 AOUT2L"}, | ||
264 | {"CPB Stereo HP 2", NULL, "codec1 AOUT2R"}, | ||
265 | {"CPB Stereo HP 3", NULL, "codec1 AOUT3L"}, | ||
266 | {"CPB Stereo HP 3", NULL, "codec1 AOUT3R"}, | ||
267 | {"CPB Line Out", NULL, "codec1 AOUT4L"}, | ||
268 | {"CPB Line Out", NULL, "codec1 AOUT4R"}, | ||
269 | |||
270 | {"codec1 AIN1L", NULL, "CPB Stereo Mic 1"}, | ||
271 | {"codec1 AIN1R", NULL, "CPB Stereo Mic 1"}, | ||
272 | {"codec1 AIN2L", NULL, "CPB Stereo Mic 2"}, | ||
273 | {"codec1 AIN2R", NULL, "CPB Stereo Mic 2"}, | ||
274 | {"codec1 AIN3L", NULL, "CPB Line In"}, | ||
275 | {"codec1 AIN3R", NULL, "CPB Line In"}, | ||
276 | }; | ||
277 | |||
278 | static int j721e_get_clocks(struct platform_device *pdev, | ||
279 | struct j721e_audio_clocks *clocks, char *prefix) | ||
280 | { | ||
281 | struct clk *parent; | ||
282 | char *clk_name; | ||
283 | int ret; | ||
284 | |||
285 | clocks->target = devm_clk_get(&pdev->dev, prefix); | ||
286 | if (IS_ERR(clocks->target)) { | ||
287 | ret = PTR_ERR(clocks->target); | ||
288 | if (ret != -EPROBE_DEFER) | ||
289 | dev_err(&pdev->dev, "failed to acquire %s': %d\n", | ||
290 | prefix, ret); | ||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | clk_name = kasprintf(GFP_KERNEL, "%s-48000", prefix); | ||
295 | if (clk_name) { | ||
296 | parent = devm_clk_get(&pdev->dev, clk_name); | ||
297 | kfree(clk_name); | ||
298 | if (IS_ERR(parent)) { | ||
299 | ret = PTR_ERR(parent); | ||
300 | if (ret != -EPROBE_DEFER) | ||
301 | dev_err(&pdev->dev, "failed to acquire %s': %d\n", | ||
302 | prefix, ret); | ||
303 | return ret; | ||
304 | } | ||
305 | clocks->parent[J721E_CLK_PARENT_48000] = parent; | ||
306 | } else { | ||
307 | return -ENOMEM; | ||
308 | } | ||
309 | |||
310 | clk_name = kasprintf(GFP_KERNEL, "%s-44100", prefix); | ||
311 | if (clk_name) { | ||
312 | parent = devm_clk_get(&pdev->dev, clk_name); | ||
313 | kfree(clk_name); | ||
314 | if (IS_ERR(parent)) { | ||
315 | ret = PTR_ERR(parent); | ||
316 | if (ret != -EPROBE_DEFER) | ||
317 | dev_err(&pdev->dev, "failed to acquire %s': %d\n", | ||
318 | prefix, ret); | ||
319 | return ret; | ||
320 | } | ||
321 | clocks->parent[J721E_CLK_PARENT_44100] = parent; | ||
322 | } else { | ||
323 | return -ENOMEM; | ||
324 | } | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int j721e_soc_probe(struct platform_device *pdev) | ||
330 | { | ||
331 | struct device_node *node = pdev->dev.of_node; | ||
332 | struct snd_soc_card *card; | ||
333 | struct device_node *cpb_dai_node, *cpb_codec_node; | ||
334 | struct j721e_priv *priv; | ||
335 | int ret; | ||
336 | |||
337 | if (!node) { | ||
338 | dev_err(&pdev->dev, "of node is missing.\n"); | ||
339 | return -ENODEV; | ||
340 | } | ||
341 | |||
342 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
343 | if (priv == NULL) | ||
344 | return -ENOMEM; | ||
345 | |||
346 | priv->current_cpb_ref_parent = -1; | ||
347 | priv->dev = &pdev->dev; | ||
348 | card = &priv->cpb_card; | ||
349 | card->dev = &pdev->dev; | ||
350 | card->owner = THIS_MODULE; | ||
351 | card->dapm_widgets = j721e_cpb_dapm_widgets; | ||
352 | card->num_dapm_widgets = ARRAY_SIZE(j721e_cpb_dapm_widgets); | ||
353 | card->dapm_routes = j721e_cpb_dapm_routes; | ||
354 | card->num_dapm_routes = ARRAY_SIZE(j721e_cpb_dapm_routes); | ||
355 | card->fully_routed = 1; | ||
356 | |||
357 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | ||
358 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
359 | return -ENODEV; | ||
360 | } | ||
361 | |||
362 | cpb_dai_node = of_parse_phandle(node, "ti,cpb-mcasp", 0); | ||
363 | if (!cpb_dai_node) { | ||
364 | dev_err(&pdev->dev, "CPB McASP node is not provided\n"); | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | |||
368 | cpb_codec_node = of_parse_phandle(node, "ti,cpb-codec", 0); | ||
369 | if (!cpb_codec_node) { | ||
370 | dev_err(&pdev->dev, "CPB codec node is not provided\n"); | ||
371 | return -EINVAL; | ||
372 | } | ||
373 | |||
374 | ret = j721e_get_clocks(pdev, &priv->audio_refclk2, "audio-refclk2"); | ||
375 | if (ret) | ||
376 | return ret; | ||
377 | |||
378 | ret = j721e_get_clocks(pdev, &priv->cpb_mcasp, "cpb-mcasp"); | ||
379 | if (ret) | ||
380 | return ret; | ||
381 | |||
382 | ret = of_property_read_u32(node, "pll4-rate", | ||
383 | &priv->pll_rates[J721E_CLK_PARENT_48000]); | ||
384 | if (ret) | ||
385 | return ret; | ||
386 | |||
387 | ret = of_property_read_u32(node, "pll15-rate", | ||
388 | &priv->pll_rates[J721E_CLK_PARENT_44100]); | ||
389 | if (ret) | ||
390 | return ret; | ||
391 | |||
392 | priv->cpb_dai_links[0].name = "CPB pcm3168a DAC"; | ||
393 | priv->cpb_dai_links[0].stream_name = "cpb pcm3168a Playback"; | ||
394 | priv->cpb_dai_links[0].cpu_of_node = cpb_dai_node; | ||
395 | priv->cpb_dai_links[0].platform_of_node = cpb_dai_node; | ||
396 | priv->cpb_dai_links[0].codec_of_node = cpb_codec_node; | ||
397 | priv->cpb_dai_links[0].codec_dai_name = "pcm3168a-dac"; | ||
398 | priv->cpb_dai_links[0].playback_only = 1; | ||
399 | priv->cpb_dai_links[0].dai_fmt = J721E_DAI_FMT; | ||
400 | priv->cpb_dai_links[0].init = j721e_audio_init; | ||
401 | priv->cpb_dai_links[0].ops = &j721e_audio_ops; | ||
402 | |||
403 | priv->cpb_dai_links[1].name = "CPB pcm3168a ADC"; | ||
404 | priv->cpb_dai_links[1].stream_name = "cpb pcm3168a Capture"; | ||
405 | priv->cpb_dai_links[1].cpu_of_node = cpb_dai_node; | ||
406 | priv->cpb_dai_links[1].platform_of_node = cpb_dai_node; | ||
407 | priv->cpb_dai_links[1].codec_of_node = cpb_codec_node; | ||
408 | priv->cpb_dai_links[1].codec_dai_name = "pcm3168a-adc"; | ||
409 | priv->cpb_dai_links[1].capture_only = 1; | ||
410 | priv->cpb_dai_links[1].dai_fmt = J721E_DAI_FMT; | ||
411 | priv->cpb_dai_links[1].init = j721e_audio_init; | ||
412 | priv->cpb_dai_links[1].ops = &j721e_audio_ops; | ||
413 | |||
414 | card->dai_link = priv->cpb_dai_links; | ||
415 | card->num_links = ARRAY_SIZE(priv->cpb_dai_links); | ||
416 | |||
417 | priv->codec_conf.of_node = cpb_codec_node; | ||
418 | priv->codec_conf.name_prefix = "codec1"; | ||
419 | if (!priv->codec_conf.name_prefix) | ||
420 | return -ENOMEM; | ||
421 | |||
422 | card->codec_conf = &priv->codec_conf; | ||
423 | card->num_configs = 1; | ||
424 | |||
425 | snd_soc_card_set_drvdata(card, priv); | ||
426 | |||
427 | mutex_init(&priv->mutex); | ||
428 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
429 | if (ret) | ||
430 | dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", | ||
431 | ret); | ||
432 | |||
433 | return ret; | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | #if defined(CONFIG_OF) | ||
439 | static const struct of_device_id j721e_audio_of_match[] = { | ||
440 | { .compatible = "ti,j721e-cpb-audio", }, | ||
441 | {}, | ||
442 | }; | ||
443 | MODULE_DEVICE_TABLE(of, j721e_audio_of_match); | ||
444 | #endif | ||
445 | |||
446 | static struct platform_driver j721e_soc_driver = { | ||
447 | .driver = { | ||
448 | .name = "j721e-audio", | ||
449 | .pm = &snd_soc_pm_ops, | ||
450 | .of_match_table = of_match_ptr(j721e_audio_of_match), | ||
451 | }, | ||
452 | .probe = j721e_soc_probe, | ||
453 | }; | ||
454 | |||
455 | module_platform_driver(j721e_soc_driver); | ||
456 | |||
457 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
458 | MODULE_DESCRIPTION("ASoC machine driver for j721e Common Processor Board"); | ||
459 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/ti_config_fragments/audio_display.cfg b/ti_config_fragments/audio_display.cfg index be96e061c321..7d19378c474f 100644 --- a/ti_config_fragments/audio_display.cfg +++ b/ti_config_fragments/audio_display.cfg | |||
@@ -152,6 +152,7 @@ CONFIG_SND_AUDIO_GRAPH_SCU_CARD=m | |||
152 | 152 | ||
153 | CONFIG_SND_SOC_DAVINCI_MCASP=y | 153 | CONFIG_SND_SOC_DAVINCI_MCASP=y |
154 | CONFIG_SND_SOC_OMAP_HDMI=m | 154 | CONFIG_SND_SOC_OMAP_HDMI=m |
155 | CONFIG_SND_SOC_J721E_EVM=m | ||
155 | 156 | ||
156 | CONFIG_SND_SOC_TLV320AIC3X=m | 157 | CONFIG_SND_SOC_TLV320AIC3X=m |
157 | CONFIG_SND_SOC_TLV320AIC31XX=m | 158 | CONFIG_SND_SOC_TLV320AIC31XX=m |