Skip to content

Commit 246f388

Browse files
committed
sc7180: Add qdsp based soundcard
Merge series from Nikita Travkin <nikita@trvn.ru>: Some devices, such as Acer Aspire 1, can't use lpass dirrectly, but instead must use adsp core to play sound. Since otherwise the hardware is, usually, very similar across the devices on the same platform, it makes sense to reuse the same boardfile. This series refactors the sc7180.c slightly and adds the functions to control clocks via adsp instead of controlling the hardware directly.
2 parents 1181754 + 4531f51 commit 246f388

File tree

2 files changed

+174
-22
lines changed

2 files changed

+174
-22
lines changed

Documentation/devicetree/bindings/sound/qcom,sm8250.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ properties:
2525
- qcom,apq8016-sbc-sndcard
2626
- qcom,msm8916-qdsp6-sndcard
2727
- qcom,qrb5165-rb5-sndcard
28+
- qcom,sc7180-qdsp6-sndcard
2829
- qcom,sc8280xp-sndcard
2930
- qcom,sdm845-sndcard
3031
- qcom,sm8250-sndcard

sound/soc/qcom/sc7180.c

Lines changed: 173 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// sc7180.c -- ALSA SoC Machine driver for SC7180
66

77
#include <dt-bindings/sound/sc7180-lpass.h>
8+
#include <dt-bindings/sound/qcom,q6afe.h>
89
#include <linux/gpio.h>
910
#include <linux/gpio/consumer.h>
1011
#include <linux/module.h>
@@ -19,8 +20,10 @@
1920
#include "../codecs/rt5682.h"
2021
#include "../codecs/rt5682s.h"
2122
#include "common.h"
23+
#include "qdsp6/q6afe.h"
2224

2325
#define DEFAULT_MCLK_RATE 19200000
26+
#define MI2S_BCLK_RATE 1536000
2427
#define RT5682_PLL1_FREQ (48000 * 512)
2528

2629
#define DRIVER_NAME "SC7180"
@@ -133,12 +136,28 @@ static int sc7180_init(struct snd_soc_pcm_runtime *rtd)
133136
return 0;
134137
}
135138

136-
static int sc7180_snd_startup(struct snd_pcm_substream *substream)
139+
static int sc7180_qdsp_init(struct snd_soc_pcm_runtime *rtd)
137140
{
138-
struct snd_soc_pcm_runtime *rtd = substream->private_data;
139-
struct snd_soc_card *card = rtd->card;
140-
struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
141141
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
142+
143+
switch (cpu_dai->id) {
144+
case PRIMARY_MI2S_RX:
145+
return sc7180_headset_init(rtd);
146+
case PRIMARY_MI2S_TX:
147+
case TERTIARY_MI2S_RX:
148+
return 0;
149+
case DISPLAY_PORT_RX:
150+
return sc7180_hdmi_init(rtd);
151+
default:
152+
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
153+
cpu_dai->id);
154+
return -EINVAL;
155+
}
156+
return 0;
157+
}
158+
159+
static int sc7180_startup_realtek_codec(struct snd_soc_pcm_runtime *rtd)
160+
{
142161
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
143162
int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
144163

@@ -154,8 +173,40 @@ static int sc7180_snd_startup(struct snd_pcm_substream *substream)
154173
clk_id = RT5682S_SCLK_S_PLL2;
155174
pll_out = RT5682_PLL1_FREQ;
156175
pll_in = DEFAULT_MCLK_RATE;
176+
} else {
177+
return 0;
178+
}
179+
snd_soc_dai_set_fmt(codec_dai,
180+
SND_SOC_DAIFMT_BC_FC |
181+
SND_SOC_DAIFMT_NB_NF |
182+
SND_SOC_DAIFMT_I2S);
183+
184+
/* Configure PLL1 for codec */
185+
ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source,
186+
pll_in, pll_out);
187+
if (ret) {
188+
dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
189+
return ret;
157190
}
158191

192+
/* Configure sysclk for codec */
193+
ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, pll_out,
194+
SND_SOC_CLOCK_IN);
195+
if (ret)
196+
dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
197+
ret);
198+
199+
return ret;
200+
}
201+
202+
static int sc7180_snd_startup(struct snd_pcm_substream *substream)
203+
{
204+
struct snd_soc_pcm_runtime *rtd = substream->private_data;
205+
struct snd_soc_card *card = rtd->card;
206+
struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
207+
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
208+
int ret;
209+
159210
switch (cpu_dai->id) {
160211
case MI2S_PRIMARY:
161212
if (++data->pri_mi2s_clk_count == 1) {
@@ -165,30 +216,66 @@ static int sc7180_snd_startup(struct snd_pcm_substream *substream)
165216
SNDRV_PCM_STREAM_PLAYBACK);
166217
}
167218

168-
snd_soc_dai_set_fmt(codec_dai,
169-
SND_SOC_DAIFMT_BC_FC |
170-
SND_SOC_DAIFMT_NB_NF |
171-
SND_SOC_DAIFMT_I2S);
172-
173-
/* Configure PLL1 for codec */
174-
ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source,
175-
pll_in, pll_out);
176-
if (ret) {
177-
dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
219+
ret = sc7180_startup_realtek_codec(rtd);
220+
if (ret)
178221
return ret;
222+
223+
break;
224+
case MI2S_SECONDARY:
225+
break;
226+
case LPASS_DP_RX:
227+
break;
228+
default:
229+
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
230+
cpu_dai->id);
231+
return -EINVAL;
232+
}
233+
return 0;
234+
}
235+
236+
static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream)
237+
{
238+
struct snd_soc_pcm_runtime *rtd = substream->private_data;
239+
struct snd_soc_card *card = rtd->card;
240+
struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
241+
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
242+
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
243+
int ret;
244+
245+
switch (cpu_dai->id) {
246+
case PRIMARY_MI2S_RX:
247+
case PRIMARY_MI2S_TX:
248+
if (++data->pri_mi2s_clk_count == 1) {
249+
snd_soc_dai_set_sysclk(cpu_dai,
250+
Q6AFE_LPASS_CLK_ID_MCLK_1,
251+
DEFAULT_MCLK_RATE,
252+
SNDRV_PCM_STREAM_PLAYBACK);
253+
snd_soc_dai_set_sysclk(cpu_dai,
254+
Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
255+
MI2S_BCLK_RATE,
256+
SNDRV_PCM_STREAM_PLAYBACK);
179257
}
180258

181-
/* Configure sysclk for codec */
182-
ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, pll_out,
183-
SND_SOC_CLOCK_IN);
259+
snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP);
260+
261+
ret = sc7180_startup_realtek_codec(rtd);
184262
if (ret)
185-
dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
186-
ret);
263+
return ret;
187264

188265
break;
189-
case MI2S_SECONDARY:
266+
case TERTIARY_MI2S_RX:
267+
snd_soc_dai_set_sysclk(cpu_dai,
268+
Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
269+
MI2S_BCLK_RATE,
270+
SNDRV_PCM_STREAM_PLAYBACK);
271+
272+
snd_soc_dai_set_fmt(codec_dai,
273+
SND_SOC_DAIFMT_BC_FC |
274+
SND_SOC_DAIFMT_NB_NF |
275+
SND_SOC_DAIFMT_I2S);
276+
snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP);
190277
break;
191-
case LPASS_DP_RX:
278+
case DISPLAY_PORT_RX:
192279
break;
193280
default:
194281
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
@@ -246,6 +333,42 @@ static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
246333
}
247334
}
248335

336+
static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream)
337+
{
338+
struct snd_soc_pcm_runtime *rtd = substream->private_data;
339+
struct snd_soc_card *card = rtd->card;
340+
struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
341+
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
342+
343+
switch (cpu_dai->id) {
344+
case PRIMARY_MI2S_RX:
345+
case PRIMARY_MI2S_TX:
346+
if (--data->pri_mi2s_clk_count == 0) {
347+
snd_soc_dai_set_sysclk(cpu_dai,
348+
Q6AFE_LPASS_CLK_ID_MCLK_1,
349+
0,
350+
SNDRV_PCM_STREAM_PLAYBACK);
351+
snd_soc_dai_set_sysclk(cpu_dai,
352+
Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
353+
0,
354+
SNDRV_PCM_STREAM_PLAYBACK);
355+
}
356+
break;
357+
case TERTIARY_MI2S_RX:
358+
snd_soc_dai_set_sysclk(cpu_dai,
359+
Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
360+
0,
361+
SNDRV_PCM_STREAM_PLAYBACK);
362+
break;
363+
case DISPLAY_PORT_RX:
364+
break;
365+
default:
366+
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
367+
cpu_dai->id);
368+
break;
369+
}
370+
}
371+
249372
static int sc7180_adau7002_init(struct snd_soc_pcm_runtime *rtd)
250373
{
251374
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
@@ -294,11 +417,30 @@ static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream)
294417
return 0;
295418
}
296419

420+
static int sc7180_qdsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
421+
struct snd_pcm_hw_params *params)
422+
{
423+
struct snd_interval *rate = hw_param_interval(params,
424+
SNDRV_PCM_HW_PARAM_RATE);
425+
struct snd_interval *channels = hw_param_interval(params,
426+
SNDRV_PCM_HW_PARAM_CHANNELS);
427+
428+
rate->min = rate->max = 48000;
429+
channels->min = channels->max = 2;
430+
431+
return 0;
432+
}
433+
297434
static const struct snd_soc_ops sc7180_ops = {
298435
.startup = sc7180_snd_startup,
299436
.shutdown = sc7180_snd_shutdown,
300437
};
301438

439+
static const struct snd_soc_ops sc7180_qdsp_ops = {
440+
.startup = sc7180_qdsp_snd_startup,
441+
.shutdown = sc7180_qdsp_snd_shutdown,
442+
};
443+
302444
static const struct snd_soc_ops sc7180_adau7002_ops = {
303445
.startup = sc7180_adau7002_snd_startup,
304446
};
@@ -354,7 +496,7 @@ static int sc7180_snd_platform_probe(struct platform_device *pdev)
354496
struct snd_soc_dai_link *link;
355497
int ret;
356498
int i;
357-
bool no_headphone = false;
499+
bool qdsp = false, no_headphone = false;
358500

359501
/* Allocate the private data */
360502
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
@@ -390,6 +532,8 @@ static int sc7180_snd_platform_probe(struct platform_device *pdev)
390532
no_headphone = true;
391533
card->dapm_widgets = sc7180_adau7002_snd_widgets;
392534
card->num_dapm_widgets = ARRAY_SIZE(sc7180_adau7002_snd_widgets);
535+
} else if (of_device_is_compatible(dev->of_node, "qcom,sc7180-qdsp6-sndcard")) {
536+
qdsp = true;
393537
}
394538

395539
ret = qcom_snd_parse_of(card);
@@ -400,6 +544,12 @@ static int sc7180_snd_platform_probe(struct platform_device *pdev)
400544
if (no_headphone) {
401545
link->ops = &sc7180_adau7002_ops;
402546
link->init = sc7180_adau7002_init;
547+
} else if (qdsp) {
548+
if (link->no_pcm == 1) {
549+
link->ops = &sc7180_qdsp_ops;
550+
link->be_hw_params_fixup = sc7180_qdsp_be_hw_params_fixup;
551+
link->init = sc7180_qdsp_init;
552+
}
403553
} else {
404554
link->ops = &sc7180_ops;
405555
link->init = sc7180_init;
@@ -412,6 +562,7 @@ static int sc7180_snd_platform_probe(struct platform_device *pdev)
412562
static const struct of_device_id sc7180_snd_device_id[] = {
413563
{.compatible = "google,sc7180-trogdor"},
414564
{.compatible = "google,sc7180-coachz"},
565+
{.compatible = "qcom,sc7180-qdsp6-sndcard"},
415566
{},
416567
};
417568
MODULE_DEVICE_TABLE(of, sc7180_snd_device_id);

0 commit comments

Comments
 (0)