1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2017 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
7 #include <linux/of_platform.h>
8 #include <linux/module.h>
12 * The everest 7134 is a very simple DA converter with no register
15 struct es7134_clock_mode
{
16 unsigned int rate_min
;
17 unsigned int rate_max
;
18 unsigned int *mclk_fs
;
19 unsigned int mclk_fs_num
;
23 struct snd_soc_dai_driver
*dai_drv
;
24 const struct es7134_clock_mode
*modes
;
25 unsigned int mode_num
;
26 const struct snd_soc_dapm_widget
*extra_widgets
;
27 unsigned int extra_widget_num
;
28 const struct snd_soc_dapm_route
*extra_routes
;
29 unsigned int extra_route_num
;
34 const struct es7134_chip
*chip
;
37 static int es7134_check_mclk(struct snd_soc_dai
*dai
,
38 struct es7134_data
*priv
,
41 unsigned int mfs
= priv
->mclk
/ rate
;
44 for (i
= 0; i
< priv
->chip
->mode_num
; i
++) {
45 const struct es7134_clock_mode
*mode
= &priv
->chip
->modes
[i
];
47 if (rate
< mode
->rate_min
|| rate
> mode
->rate_max
)
50 for (j
= 0; j
< mode
->mclk_fs_num
; j
++) {
51 if (mode
->mclk_fs
[j
] == mfs
)
55 dev_err(dai
->dev
, "unsupported mclk_fs %u for rate %u\n",
60 /* should not happen */
61 dev_err(dai
->dev
, "unsupported rate: %u\n", rate
);
65 static int es7134_hw_params(struct snd_pcm_substream
*substream
,
66 struct snd_pcm_hw_params
*params
,
67 struct snd_soc_dai
*dai
)
69 struct es7134_data
*priv
= snd_soc_dai_get_drvdata(dai
);
71 /* mclk has not been provided, assume it is OK */
75 return es7134_check_mclk(dai
, priv
, params_rate(params
));
78 static int es7134_set_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
79 unsigned int freq
, int dir
)
81 struct es7134_data
*priv
= snd_soc_dai_get_drvdata(dai
);
83 if (dir
== SND_SOC_CLOCK_IN
&& clk_id
== 0) {
91 static int es7134_set_fmt(struct snd_soc_dai
*codec_dai
, unsigned int fmt
)
93 fmt
&= (SND_SOC_DAIFMT_FORMAT_MASK
| SND_SOC_DAIFMT_INV_MASK
|
94 SND_SOC_DAIFMT_MASTER_MASK
);
96 if (fmt
!= (SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
|
97 SND_SOC_DAIFMT_CBS_CFS
)) {
98 dev_err(codec_dai
->dev
, "Invalid DAI format\n");
105 static int es7134_component_probe(struct snd_soc_component
*c
)
107 struct snd_soc_dapm_context
*dapm
= snd_soc_component_get_dapm(c
);
108 struct es7134_data
*priv
= snd_soc_component_get_drvdata(c
);
109 const struct es7134_chip
*chip
= priv
->chip
;
112 if (chip
->extra_widget_num
) {
113 ret
= snd_soc_dapm_new_controls(dapm
, chip
->extra_widgets
,
114 chip
->extra_widget_num
);
116 dev_err(c
->dev
, "failed to add extra widgets\n");
121 if (chip
->extra_route_num
) {
122 ret
= snd_soc_dapm_add_routes(dapm
, chip
->extra_routes
,
123 chip
->extra_route_num
);
125 dev_err(c
->dev
, "failed to add extra routes\n");
133 static const struct snd_soc_dai_ops es7134_dai_ops
= {
134 .set_fmt
= es7134_set_fmt
,
135 .hw_params
= es7134_hw_params
,
136 .set_sysclk
= es7134_set_sysclk
,
139 static struct snd_soc_dai_driver es7134_dai
= {
140 .name
= "es7134-hifi",
142 .stream_name
= "Playback",
145 .rates
= (SNDRV_PCM_RATE_8000_48000
|
146 SNDRV_PCM_RATE_88200
|
147 SNDRV_PCM_RATE_96000
|
148 SNDRV_PCM_RATE_176400
|
149 SNDRV_PCM_RATE_192000
),
150 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
|
151 SNDRV_PCM_FMTBIT_S18_3LE
|
152 SNDRV_PCM_FMTBIT_S20_3LE
|
153 SNDRV_PCM_FMTBIT_S24_3LE
|
154 SNDRV_PCM_FMTBIT_S24_LE
),
156 .ops
= &es7134_dai_ops
,
159 static const struct es7134_clock_mode es7134_modes
[] = {
161 /* Single speed mode */
164 .mclk_fs
= (unsigned int[]) { 256, 384, 512, 768, 1024 },
167 /* Double speed mode */
170 .mclk_fs
= (unsigned int[]) { 128, 192, 256, 384, 512 },
173 /* Quad speed mode */
176 .mclk_fs
= (unsigned int[]) { 128, 192, 256 },
181 /* Digital I/O are also supplied by VDD on the es7134 */
182 static const struct snd_soc_dapm_route es7134_extra_routes
[] = {
183 { "Playback", NULL
, "VDD", }
186 static const struct es7134_chip es7134_chip
= {
187 .dai_drv
= &es7134_dai
,
188 .modes
= es7134_modes
,
189 .mode_num
= ARRAY_SIZE(es7134_modes
),
190 .extra_routes
= es7134_extra_routes
,
191 .extra_route_num
= ARRAY_SIZE(es7134_extra_routes
),
194 static const struct snd_soc_dapm_widget es7134_dapm_widgets
[] = {
195 SND_SOC_DAPM_OUTPUT("AOUTL"),
196 SND_SOC_DAPM_OUTPUT("AOUTR"),
197 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM
, 0, 0),
198 SND_SOC_DAPM_REGULATOR_SUPPLY("VDD", 0, 0),
201 static const struct snd_soc_dapm_route es7134_dapm_routes
[] = {
202 { "AOUTL", NULL
, "DAC" },
203 { "AOUTR", NULL
, "DAC" },
204 { "DAC", NULL
, "VDD" },
207 static const struct snd_soc_component_driver es7134_component_driver
= {
208 .probe
= es7134_component_probe
,
209 .dapm_widgets
= es7134_dapm_widgets
,
210 .num_dapm_widgets
= ARRAY_SIZE(es7134_dapm_widgets
),
211 .dapm_routes
= es7134_dapm_routes
,
212 .num_dapm_routes
= ARRAY_SIZE(es7134_dapm_routes
),
214 .use_pmdown_time
= 1,
216 .non_legacy_dai_naming
= 1,
219 static struct snd_soc_dai_driver es7154_dai
= {
220 .name
= "es7154-hifi",
222 .stream_name
= "Playback",
225 .rates
= (SNDRV_PCM_RATE_8000_48000
|
226 SNDRV_PCM_RATE_88200
|
227 SNDRV_PCM_RATE_96000
),
228 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
|
229 SNDRV_PCM_FMTBIT_S18_3LE
|
230 SNDRV_PCM_FMTBIT_S20_3LE
|
231 SNDRV_PCM_FMTBIT_S24_3LE
|
232 SNDRV_PCM_FMTBIT_S24_LE
),
234 .ops
= &es7134_dai_ops
,
237 static const struct es7134_clock_mode es7154_modes
[] = {
239 /* Single speed mode */
242 .mclk_fs
= (unsigned int[]) { 32, 64, 128, 192, 256,
243 384, 512, 768, 1024 },
246 /* Double speed mode */
249 .mclk_fs
= (unsigned int[]) { 128, 192, 256, 384, 512,
255 /* Es7154 has a separate supply for digital I/O */
256 static const struct snd_soc_dapm_widget es7154_extra_widgets
[] = {
257 SND_SOC_DAPM_REGULATOR_SUPPLY("PVDD", 0, 0),
260 static const struct snd_soc_dapm_route es7154_extra_routes
[] = {
261 { "Playback", NULL
, "PVDD", }
264 static const struct es7134_chip es7154_chip
= {
265 .dai_drv
= &es7154_dai
,
266 .modes
= es7154_modes
,
267 .mode_num
= ARRAY_SIZE(es7154_modes
),
268 .extra_routes
= es7154_extra_routes
,
269 .extra_route_num
= ARRAY_SIZE(es7154_extra_routes
),
270 .extra_widgets
= es7154_extra_widgets
,
271 .extra_widget_num
= ARRAY_SIZE(es7154_extra_widgets
),
274 static int es7134_probe(struct platform_device
*pdev
)
276 struct device
*dev
= &pdev
->dev
;
277 struct es7134_data
*priv
;
279 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
282 platform_set_drvdata(pdev
, priv
);
284 priv
->chip
= of_device_get_match_data(dev
);
286 dev_err(dev
, "failed to match device\n");
290 return devm_snd_soc_register_component(&pdev
->dev
,
291 &es7134_component_driver
,
292 priv
->chip
->dai_drv
, 1);
296 static const struct of_device_id es7134_ids
[] = {
297 { .compatible
= "everest,es7134", .data
= &es7134_chip
},
298 { .compatible
= "everest,es7144", .data
= &es7134_chip
},
299 { .compatible
= "everest,es7154", .data
= &es7154_chip
},
302 MODULE_DEVICE_TABLE(of
, es7134_ids
);
305 static struct platform_driver es7134_driver
= {
308 .of_match_table
= of_match_ptr(es7134_ids
),
310 .probe
= es7134_probe
,
313 module_platform_driver(es7134_driver
);
315 MODULE_DESCRIPTION("ASoC ES7134 audio codec driver");
316 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
317 MODULE_LICENSE("GPL");