1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2020 Intel Corporation
5 * sof_sdw_rt1308 - Helpers to handle RT1308 from generic machine driver
8 #include <linux/device.h>
9 #include <linux/errno.h>
10 #include <sound/control.h>
11 #include <sound/soc.h>
12 #include <sound/soc-acpi.h>
13 #include <sound/soc-dapm.h>
14 #include "sof_sdw_common.h"
15 #include "../../codecs/rt1308.h"
17 static const struct snd_soc_dapm_widget rt1308_widgets
[] = {
18 SND_SOC_DAPM_SPK("Speaker", NULL
),
22 * dapm routes for rt1308 will be registered dynamically according
23 * to the number of rt1308 used. The first two entries will be registered
24 * for one codec case, and the last two entries are also registered
25 * if two 1308s are used.
27 static const struct snd_soc_dapm_route rt1308_map
[] = {
28 { "Speaker", NULL
, "rt1308-1 SPOL" },
29 { "Speaker", NULL
, "rt1308-1 SPOR" },
30 { "Speaker", NULL
, "rt1308-2 SPOL" },
31 { "Speaker", NULL
, "rt1308-2 SPOR" },
34 static const struct snd_kcontrol_new rt1308_controls
[] = {
35 SOC_DAPM_PIN_SWITCH("Speaker"),
38 static int first_spk_init(struct snd_soc_pcm_runtime
*rtd
)
40 struct snd_soc_card
*card
= rtd
->card
;
43 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
,
46 if (!card
->components
)
49 ret
= snd_soc_add_card_controls(card
, rt1308_controls
,
50 ARRAY_SIZE(rt1308_controls
));
52 dev_err(card
->dev
, "rt1308 controls addition failed: %d\n", ret
);
56 ret
= snd_soc_dapm_new_controls(&card
->dapm
, rt1308_widgets
,
57 ARRAY_SIZE(rt1308_widgets
));
59 dev_err(card
->dev
, "rt1308 widgets addition failed: %d\n", ret
);
63 ret
= snd_soc_dapm_add_routes(&card
->dapm
, rt1308_map
, 2);
65 dev_err(rtd
->dev
, "failed to add first SPK map: %d\n", ret
);
70 static int second_spk_init(struct snd_soc_pcm_runtime
*rtd
)
72 struct snd_soc_card
*card
= rtd
->card
;
75 ret
= snd_soc_dapm_add_routes(&card
->dapm
, rt1308_map
+ 2, 2);
77 dev_err(rtd
->dev
, "failed to add second SPK map: %d\n", ret
);
82 static int all_spk_init(struct snd_soc_pcm_runtime
*rtd
)
86 ret
= first_spk_init(rtd
);
90 return second_spk_init(rtd
);
93 static int rt1308_i2s_hw_params(struct snd_pcm_substream
*substream
,
94 struct snd_pcm_hw_params
*params
)
96 struct snd_soc_pcm_runtime
*rtd
= asoc_substream_to_rtd(substream
);
97 struct snd_soc_card
*card
= rtd
->card
;
98 struct snd_soc_dai
*codec_dai
= asoc_rtd_to_codec(rtd
, 0);
99 int clk_id
, clk_freq
, pll_out
;
102 clk_id
= RT1308_PLL_S_MCLK
;
105 pll_out
= params_rate(params
) * 512;
108 err
= snd_soc_dai_set_pll(codec_dai
, 0, clk_id
, clk_freq
, pll_out
);
110 dev_err(card
->dev
, "Failed to set RT1308 PLL: %d\n", err
);
114 /* Set rt1308 sysclk */
115 err
= snd_soc_dai_set_sysclk(codec_dai
, RT1308_FS_SYS_S_PLL
, pll_out
,
118 dev_err(card
->dev
, "Failed to set RT1308 SYSCLK: %d\n", err
);
125 /* machine stream operations */
126 struct snd_soc_ops sof_sdw_rt1308_i2s_ops
= {
127 .hw_params
= rt1308_i2s_hw_params
,
130 int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr
*link
,
131 struct snd_soc_dai_link
*dai_links
,
132 struct sof_sdw_codec_info
*info
,
135 /* Count amp number and do init on playback link only. */
140 if (info
->amp_num
== 1)
141 dai_links
->init
= first_spk_init
;
143 if (info
->amp_num
== 2) {
145 * if two 1308s are in one dai link, the init function
146 * in this dai link will be first set for the first speaker,
147 * and it should be reset to initialize all speakers when
148 * the second speaker is found.
151 dai_links
->init
= all_spk_init
;
153 dai_links
->init
= second_spk_init
;