blob: 17b97d3b0866e5c0877031fe46674db771355488 [file] [log] [blame]
Googler9398cc32022-12-02 17:21:52 +08001// SPDX-License-Identifier: GPL-2.0
2//
3// ASoC simple sound card support
4//
5// Copyright (C) 2012 Renesas Solutions Corp.
6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Googler4f18c0c2022-09-20 17:23:36 +08007
Googler9398cc32022-12-02 17:21:52 +08008//#define DEBUG
Googler4f18c0c2022-09-20 17:23:36 +08009#include <linux/clk.h>
10#include <linux/device.h>
11#include <linux/gpio.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_gpio.h>
15#include <linux/of_device.h>
16#include <linux/platform_device.h>
17#include <linux/string.h>
18#include <linux/timer.h>
19#include <linux/workqueue.h>
Googler9398cc32022-12-02 17:21:52 +080020//#include <linux/extcon.h>
21#include <linux/extcon-provider.h>
Googler4f18c0c2022-09-20 17:23:36 +080022#include <sound/jack.h>
23#include <sound/soc.h>
24#include <sound/soc-dai.h>
Googler9398cc32022-12-02 17:21:52 +080025#include <sound/control.h>
Googler4f18c0c2022-09-20 17:23:36 +080026#include "card.h"
27
28#include "effects.h"
Googler9398cc32022-12-02 17:21:52 +080029#include "iomap.h"
30#include "regs.h"
31#include "../common/misc.h"
32#include "../common/audio_uevent.h"
33#include "audio_controller.h"
34#ifdef CONFIG_AMLOGIC_MEDIA_VIDEO
35#include <linux/amlogic/media/video_sink/video.h>
36#endif
Googler38bda472022-08-19 10:07:08 -070037
Googler9726be62022-12-14 05:53:31 +000038/*the same as audio hal type define!*/
39static const char * const audio_format[] = {
40 "PCM",
41 "DTS_EXPRESS",
42 "DOLBY_DIGITAL",
43 "DTS",
44 "DOLBY_DIGITAL_PLUS",
45 "DTS_HD",
46 "MULTI_CHANNEL PCM",
47 "DOLBY_TRUEHD",
48 "DTS_HD_MA",
49 "HIFI PCM",
50 "DOLBY_AC4",
51 "DOLBY_MAT",
52 "DOLBY_DDP_ATMOS",
53 "DOLBY_THD_ATMOS",
54 "DOLBY_MAT_ATMOS",
55 "DOLBY_AC4_ATMOS",
56 "DTS_HP",
57 "DOLBY_DDP_ATMOS_PROMPT_ON_ATMOS",
58 "DOLBY_THD_ATMOS_PROMPT_ON_ATMOS",
59 "DOLBY_MAT_ATMOS_PROMPT_ON_ATMOS",
Googler9398cc32022-12-02 17:21:52 +080060 "DOLBY_AC4_ATMOS_PROMPT_ON_ATMOS",
Googler9726be62022-12-14 05:53:31 +000061};
62
63enum audio_hal_format {
64 TYPE_PCM = 0,
65 TYPE_DTS_EXPRESS = 1,
66 TYPE_AC3 = 2,
67 TYPE_DTS = 3,
68 TYPE_EAC3 = 4,
69 TYPE_DTS_HD = 5,
70 TYPE_MULTI_PCM = 6,
71 TYPE_TRUE_HD = 7,
72 TYPE_DTS_HD_MA = 8,
73 TYPE_PCM_HIGH_SR = 9,
74 TYPE_AC4 = 10,
75 TYPE_MAT = 11,
76 TYPE_DDP_ATMOS = 12,
77 TYPE_TRUE_HD_ATMOS = 13,
78 TYPE_MAT_ATMOS = 14,
79 TYPE_AC4_ATMOS = 15,
80 TYPE_DTS_HP = 16,
81 TYPE_DDP_ATMOS_PROMPT_ON_ATMOS = 17,
82 TYPE_TRUE_HD_ATMOS_PROMPT_ON_ATMOS = 18,
83 TYPE_MAT_ATMOS_PROMPT_ON_ATMOS = 19,
Googler9398cc32022-12-02 17:21:52 +080084 TYPE_AC4_ATMOS_PROMPT_ON_ATMOS = 20,
Googler9726be62022-12-14 05:53:31 +000085};
86
Googler4f18c0c2022-09-20 17:23:36 +080087struct aml_jack {
88 struct snd_soc_jack jack;
89 struct snd_soc_jack_pin pin;
90 struct snd_soc_jack_gpio gpio;
91};
92
Googler4f18c0c2022-09-20 17:23:36 +080093struct aml_card_data {
94 struct snd_soc_card snd_card;
95 struct aml_dai_props {
96 /* sync with android audio hal,
97 * dai link is used for which output,
98 */
99 const char *suffix_name;
100
101 struct aml_dai cpu_dai;
102 struct aml_dai codec_dai;
Googler9398cc32022-12-02 17:21:52 +0800103 struct snd_soc_dai_link_component cpus; /* single cpu */
104 struct snd_soc_dai_link_component codecs; /* single codec */
105 struct snd_soc_dai_link_component platforms;
Googler4f18c0c2022-09-20 17:23:36 +0800106 unsigned int mclk_fs;
107 } *dai_props;
108 unsigned int mclk_fs;
109 struct aml_jack hp_jack;
110 struct aml_jack mic_jack;
111 struct snd_soc_dai_link *dai_link;
112 int spk_mute_gpio;
113 bool spk_mute_active_low;
Googler9398cc32022-12-02 17:21:52 +0800114 bool spk_mute_flag;
Googler4f18c0c2022-09-20 17:23:36 +0800115 struct gpio_desc *avout_mute_desc;
Googler4f18c0c2022-09-20 17:23:36 +0800116 struct timer_list timer;
117 struct work_struct work;
Googler38bda472022-08-19 10:07:08 -0700118 struct work_struct init_work;
Googler9398cc32022-12-02 17:21:52 +0800119 int hp_last_state;
120 int hp_cur_state;
121 int hp_det_status;
Googler4f18c0c2022-09-20 17:23:36 +0800122 int hp_gpio_det;
123 int hp_detect_flag;
124 bool hp_det_enable;
Googler9398cc32022-12-02 17:21:52 +0800125 enum of_gpio_flags hp_det_flags;
126 int micphone_last_state;
127 int micphone_cur_state;
128 int micphone_det_status;
Googler4f18c0c2022-09-20 17:23:36 +0800129 int micphone_gpio_det;
130 int mic_detect_flag;
131 bool mic_det_enable;
Googler38bda472022-08-19 10:07:08 -0700132 bool av_mute_enable;
Googler9398cc32022-12-02 17:21:52 +0800133 bool spk_mute_enable;
134 int irq_exception64;
Googler9726be62022-12-14 05:53:31 +0000135 enum audio_hal_format hal_fmt;
Googler4f18c0c2022-09-20 17:23:36 +0800136};
137
138#define aml_priv_to_dev(priv) ((priv)->snd_card.dev)
139#define aml_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
140#define aml_priv_to_props(priv, i) ((priv)->dai_props + (i))
141#define aml_card_to_priv(card) \
142 (container_of(card, struct aml_card_data, snd_card))
143
144#define DAI "sound-dai"
145#define CELL "#sound-dai-cells"
146#define PREFIX "aml-audio-card,"
147
148#define aml_card_init_hp(card, sjack, prefix)\
149 aml_card_init_jack(card, sjack, 1, prefix)
150#define aml_card_init_mic(card, sjack, prefix)\
151 aml_card_init_jack(card, sjack, 0, prefix)
152
153static const unsigned int headphone_cable[] = {
154 EXTCON_JACK_HEADPHONE,
155 EXTCON_NONE,
156};
157
158static const unsigned int microphone_cable[] = {
159 EXTCON_JACK_MICROPHONE,
160 EXTCON_NONE,
161};
162
163struct extcon_dev *audio_extcon_headphone;
164struct extcon_dev *audio_extcon_microphone;
165
Googler9726be62022-12-14 05:53:31 +0000166static const struct soc_enum audio_hal_format_enum =
167 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_format),
168 audio_format);
169
170static int aml_audio_hal_format_get_enum(struct snd_kcontrol *kcontrol,
171 struct snd_ctl_elem_value *ucontrol)
172{
173 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
174 struct aml_card_data *p_aml_audio;
175
176 p_aml_audio = snd_soc_card_get_drvdata(card);
177 ucontrol->value.integer.value[0] = p_aml_audio->hal_fmt;
178
179 return 0;
180}
181
182static int aml_audio_hal_format_set_enum(struct snd_kcontrol *kcontrol,
183 struct snd_ctl_elem_value *ucontrol)
184{
185 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
186 struct aml_card_data *p_aml_audio;
187 int hal_format = ucontrol->value.integer.value[0];
188
189 p_aml_audio = snd_soc_card_get_drvdata(card);
190
Googler9398cc32022-12-02 17:21:52 +0800191 audio_send_uevent(card->dev, AUDIO_SPDIF_FMT_EVENT, hal_format);
Googler9726be62022-12-14 05:53:31 +0000192 pr_info("update audio atmos flag! audio_type = %d\n", hal_format);
193
194 if (p_aml_audio->hal_fmt != hal_format)
195 p_aml_audio->hal_fmt = hal_format;
196
197 return 0;
198}
199
Googler9398cc32022-12-02 17:21:52 +0800200static int aml_chip_id_get(struct snd_kcontrol *kcontrol,
201 struct snd_ctl_elem_value *ucontrol)
202{
203 (void)kcontrol;
204 ucontrol->value.integer.value[0] = aml_return_chip_id();
205 return 0;
206}
207
208#ifdef CONFIG_AMLOGIC_MEDIA_VIDEO
209static int aml_media_video_delay_get_enum(struct snd_kcontrol *kcontrol,
210 struct snd_ctl_elem_value *ucontrol)
211{
212 (void)kcontrol;
213 ucontrol->value.integer.value[0] = get_playback_delay_duration();
214 return 0;
215}
216#endif
217
Googler9726be62022-12-14 05:53:31 +0000218static const struct snd_kcontrol_new snd_user_controls[] = {
219 SOC_ENUM_EXT("Audio HAL Format",
Googler9398cc32022-12-02 17:21:52 +0800220 audio_hal_format_enum,
221 aml_audio_hal_format_get_enum,
222 aml_audio_hal_format_set_enum),
223
224 SND_SOC_BYTES_EXT("AML chip id", 1,
225 aml_chip_id_get, NULL),
226
227#ifdef CONFIG_AMLOGIC_MEDIA_VIDEO
228 SOC_SINGLE_EXT("Media Video Delay",
229 0, 0, 0, 0,
230 aml_media_video_delay_get_enum,
231 NULL),
232#endif
Googler9726be62022-12-14 05:53:31 +0000233};
234
Googler4f18c0c2022-09-20 17:23:36 +0800235static void jack_audio_start_timer(struct aml_card_data *card_data,
236 unsigned long delay)
237{
238 card_data->timer.expires = jiffies + delay;
239 add_timer(&card_data->timer);
240}
241
242static void jack_audio_stop_timer(struct aml_card_data *card_data)
243{
244 del_timer_sync(&card_data->timer);
245 cancel_work_sync(&card_data->work);
246}
Googler9398cc32022-12-02 17:21:52 +0800247
248static void jack_timer_func(struct timer_list *t)
Googler4f18c0c2022-09-20 17:23:36 +0800249{
Googler9398cc32022-12-02 17:21:52 +0800250 struct aml_card_data *card_data = from_timer(card_data, t, timer);
Googler4f18c0c2022-09-20 17:23:36 +0800251 unsigned long delay = msecs_to_jiffies(150);
252
253 schedule_work(&card_data->work);
254 mod_timer(&card_data->timer, jiffies + delay);
255}
256
257static int jack_audio_hp_detect(struct aml_card_data *card_data)
258{
259 int loop_num = 0;
260 int change_cnt = 0;
261
262 card_data->hp_cur_state =
263 gpio_get_value_cansleep(card_data->hp_jack.gpio.gpio);
264 if (card_data->hp_last_state != card_data->hp_cur_state) {
265 while (loop_num < 5) {
266 card_data->hp_cur_state =
Googler9398cc32022-12-02 17:21:52 +0800267 gpio_get_value_cansleep(card_data->hp_jack.gpio.gpio);
Googler4f18c0c2022-09-20 17:23:36 +0800268
269 if (card_data->hp_last_state != card_data->hp_cur_state)
270 change_cnt++;
271 else
272 change_cnt = 0;
273
274 msleep_interruptible(50);
275 loop_num = loop_num + 1;
276 }
277 if (change_cnt >= 5) {
278 card_data->hp_last_state = card_data->hp_cur_state;
279 card_data->hp_det_status = card_data->hp_last_state;
280 }
281 return card_data->hp_det_status;
282 }
283 return -1;
284}
285
286static int jack_audio_micphone_detect(struct aml_card_data *card_data)
287{
288 int loop_num = 0;
289 int change_cnt = 0;
290
291 card_data->micphone_cur_state =
292 gpio_get_value_cansleep(card_data->mic_jack.gpio.gpio);
293 if (card_data->micphone_last_state != card_data->micphone_cur_state) {
294 while (loop_num < 5) {
295 card_data->micphone_cur_state =
Googler9398cc32022-12-02 17:21:52 +0800296 gpio_get_value_cansleep(card_data->mic_jack.gpio.gpio);
Googler4f18c0c2022-09-20 17:23:36 +0800297 if (card_data->micphone_last_state !=
298 card_data->micphone_cur_state)
299 change_cnt++;
300 else
301 change_cnt = 0;
302
303 msleep_interruptible(50);
304 loop_num = loop_num + 1;
305 }
306 if (change_cnt >= 5) {
307 card_data->micphone_last_state =
308 card_data->micphone_cur_state;
309 card_data->micphone_det_status =
310 card_data->micphone_last_state;
311 }
312 return card_data->micphone_det_status;
313 }
314 return -1;
315}
Googler9398cc32022-12-02 17:21:52 +0800316
Googler4f18c0c2022-09-20 17:23:36 +0800317static void jack_work_func(struct work_struct *work)
318{
319 struct aml_card_data *card_data = NULL;
320 int status = SND_JACK_HEADPHONE;
321 int flag = 0;
322
323 card_data = container_of(work, struct aml_card_data, work);
324
325 if (card_data->hp_det_enable == 1) {
326 flag = jack_audio_hp_detect(card_data);
327 if (flag == -1)
328 return;
Googler4f18c0c2022-09-20 17:23:36 +0800329
Googler9398cc32022-12-02 17:21:52 +0800330 if (card_data->hp_detect_flag != flag) {
Googler012a81c2022-09-15 14:55:24 +0800331 card_data->hp_detect_flag = flag;
Googler38bda472022-08-19 10:07:08 -0700332
Googler9398cc32022-12-02 17:21:52 +0800333 if (card_data->hp_det_flags == OF_GPIO_ACTIVE_LOW)
334 flag = (flag) ? 0 : 1;
335
Googler4f18c0c2022-09-20 17:23:36 +0800336 if (flag) {
337 extcon_set_state_sync(audio_extcon_headphone,
338 EXTCON_JACK_HEADPHONE, 1);
339 snd_soc_jack_report(&card_data->hp_jack.jack,
340 status, SND_JACK_HEADPHONE);
Googler9398cc32022-12-02 17:21:52 +0800341 audio_send_uevent(card_data->snd_card.dev,
342 HEADPHONE_DETECTION_EVENT, 1);
Googler4f18c0c2022-09-20 17:23:36 +0800343 } else {
344 extcon_set_state_sync(audio_extcon_headphone,
345 EXTCON_JACK_HEADPHONE, 0);
346 snd_soc_jack_report(&card_data->hp_jack.jack, 0,
Googler9398cc32022-12-02 17:21:52 +0800347 SND_JACK_HEADPHONE);
348 audio_send_uevent(card_data->snd_card.dev,
349 HEADPHONE_DETECTION_EVENT, 0);
Googler4f18c0c2022-09-20 17:23:36 +0800350 }
Googler4f18c0c2022-09-20 17:23:36 +0800351 }
352 }
353 if (card_data->mic_det_enable == 1) {
354 flag = jack_audio_micphone_detect(card_data);
355 if (flag == -1)
356 return;
357 if (card_data->mic_detect_flag != flag) {
Googler4f18c0c2022-09-20 17:23:36 +0800358 card_data->mic_detect_flag = flag;
359
360 if (flag) {
361 extcon_set_state_sync(audio_extcon_microphone,
362 EXTCON_JACK_MICROPHONE, 1);
363 snd_soc_jack_report(&card_data->mic_jack.jack,
364 status, SND_JACK_MICROPHONE);
Googler9398cc32022-12-02 17:21:52 +0800365 audio_send_uevent(card_data->snd_card.dev,
366 MICROPHONE_DETECTION_EVENT, 1);
Googler4f18c0c2022-09-20 17:23:36 +0800367 } else {
368 extcon_set_state_sync(audio_extcon_microphone,
369 EXTCON_JACK_MICROPHONE, 0);
370 snd_soc_jack_report(&card_data->mic_jack.jack,
371 0, SND_JACK_MICROPHONE);
Googler9398cc32022-12-02 17:21:52 +0800372 audio_send_uevent(card_data->snd_card.dev,
373 MICROPHONE_DETECTION_EVENT, 0);
Googler4f18c0c2022-09-20 17:23:36 +0800374 }
Googler4f18c0c2022-09-20 17:23:36 +0800375 }
376 }
377}
378
379static int aml_card_init_jack(struct snd_soc_card *card,
380 struct aml_jack *sjack,
381 int is_hp, char *prefix)
382{
383 struct aml_card_data *priv = aml_card_to_priv(card);
384 struct device *dev = card->dev;
Googler9398cc32022-12-02 17:21:52 +0800385 enum of_gpio_flags flags = 0;
Googler4f18c0c2022-09-20 17:23:36 +0800386 char prop[128];
387 char *pin_name;
388 char *gpio_name;
389 int mask;
390 int det;
391
392 sjack->gpio.gpio = -ENOENT;
393
394 if (is_hp) {
395 snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
396 pin_name = "Headphones";
397 gpio_name = "Headphone detection";
398 mask = SND_JACK_HEADPHONE;
399
Googler9398cc32022-12-02 17:21:52 +0800400 det = of_get_named_gpio_flags(dev->of_node, prop, 0, &priv->hp_det_flags);
401 if (det < 0) {
Googler4f18c0c2022-09-20 17:23:36 +0800402 priv->hp_det_enable = 0;
403 return -1;
404 }
405 priv->hp_det_enable = 1;
Googler4f18c0c2022-09-20 17:23:36 +0800406 gpio_request(det, "hp-det-gpio");
407 } else {
408 snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
409 pin_name = "Mic Jack";
410 gpio_name = "Mic detection";
411 mask = SND_JACK_MICROPHONE;
412
Googler9398cc32022-12-02 17:21:52 +0800413 det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
414 if (det < 0) {
Googler4f18c0c2022-09-20 17:23:36 +0800415 priv->mic_det_enable = 0;
416 return -1;
417 }
418 priv->mic_det_enable = 1;
Googler4f18c0c2022-09-20 17:23:36 +0800419 gpio_request(det, "mic-det-gpio");
420 }
421
422 if (gpio_is_valid(det)) {
Googler9398cc32022-12-02 17:21:52 +0800423 int state;
424
Googler4f18c0c2022-09-20 17:23:36 +0800425 sjack->pin.pin = pin_name;
426 sjack->pin.mask = mask;
427
428 sjack->gpio.name = gpio_name;
429 sjack->gpio.report = mask;
430 sjack->gpio.gpio = det;
431 sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
432 sjack->gpio.debounce_time = 150;
433
434 gpio_direction_input(det);
Googler9398cc32022-12-02 17:21:52 +0800435 state = gpiod_set_pull(gpio_to_desc(det), GPIOD_PULL_DIS);
436 if (state)
437 pr_err("set gpiod pull failed, ret %d\n", state);
Googler4f18c0c2022-09-20 17:23:36 +0800438 snd_soc_card_jack_new(card, pin_name, mask,
439 &sjack->jack,
440 &sjack->pin, 1);
441
442 snd_soc_jack_add_gpios(&sjack->jack, 1,
443 &sjack->gpio);
Googler9398cc32022-12-02 17:21:52 +0800444 } else {
Googler4f18c0c2022-09-20 17:23:36 +0800445 pr_info("detect gpio is invalid\n");
Googler9398cc32022-12-02 17:21:52 +0800446 }
Googler4f18c0c2022-09-20 17:23:36 +0800447
448 if (is_hp) {
449 if (det >= 0)
450 priv->hp_gpio_det = det;
451 } else {
452 if (det >= 0)
453 priv->micphone_gpio_det = det;
454 }
455 return 0;
456}
457
458static void audio_jack_detect(struct aml_card_data *card_data)
459{
Googler9398cc32022-12-02 17:21:52 +0800460 timer_setup(&card_data->timer, jack_timer_func, 0);
Googler4f18c0c2022-09-20 17:23:36 +0800461
462 INIT_WORK(&card_data->work, jack_work_func);
463
464 jack_audio_start_timer(card_data,
465 msecs_to_jiffies(5000));
466}
467
468static void audio_extcon_register(struct aml_card_data *priv,
469 struct device *dev)
470{
471 struct extcon_dev *edev;
472 int ret;
473
474 if (priv->hp_det_enable == 1) {
475 /*audio extcon headphone*/
Googler9398cc32022-12-02 17:21:52 +0800476 edev = devm_extcon_dev_allocate(dev, headphone_cable);
Googler4f18c0c2022-09-20 17:23:36 +0800477 if (IS_ERR(edev)) {
478 pr_info("failed to allocate audio extcon headphone\n");
479 return;
480 }
Googler9398cc32022-12-02 17:21:52 +0800481 /*
482 * edev->dev.parent = dev;
483 * edev->name = "audio_extcon_headphone";
484 * dev_set_name(&edev->dev, "headphone");
485 */
486 ret = devm_extcon_dev_register(dev, edev);
Googler4f18c0c2022-09-20 17:23:36 +0800487 if (ret < 0) {
488 pr_info("failed to register audio extcon headphone\n");
489 return;
490 }
491 audio_extcon_headphone = edev;
492 }
493 if (priv->mic_det_enable == 1) {
494 /*audio extcon microphone*/
Googler9398cc32022-12-02 17:21:52 +0800495 edev = devm_extcon_dev_allocate(dev, microphone_cable);
Googler4f18c0c2022-09-20 17:23:36 +0800496 if (IS_ERR(edev)) {
497 pr_info("failed to allocate audio extcon microphone\n");
498 return;
499 }
500
Googler9398cc32022-12-02 17:21:52 +0800501 /*
502 * edev->dev.parent = dev;
503 * edev->name = "audio_extcon_microphone";
504 * dev_set_name(&edev->dev, "microphone");
505 */
506 ret = devm_extcon_dev_register(dev, edev);
Googler4f18c0c2022-09-20 17:23:36 +0800507 if (ret < 0) {
508 pr_info("failed to register audio extcon microphone\n");
509 return;
510 }
511 audio_extcon_microphone = edev;
512 }
513}
514
515static void aml_card_remove_jack(struct aml_jack *sjack)
516{
517 if (gpio_is_valid(sjack->gpio.gpio))
518 snd_soc_jack_free_gpios(&sjack->jack, 1, &sjack->gpio);
519}
520
Googler4f18c0c2022-09-20 17:23:36 +0800521static int aml_card_hw_params(struct snd_pcm_substream *substream,
522 struct snd_pcm_hw_params *params)
523{
524 struct snd_soc_pcm_runtime *rtd = substream->private_data;
525 struct snd_soc_dai *codec_dai = rtd->codec_dai;
526 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
527 struct aml_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
528 struct snd_soc_dai_link *dai_link = aml_priv_to_link(priv, rtd->num);
529 struct aml_dai_props *dai_props =
530 aml_priv_to_props(priv, rtd->num);
531 unsigned int mclk = 0, mclk_fs = 0;
532 int i = 0, ret = 0;
533 int clk_idx = substream->stream;
534
535 if (priv->mclk_fs)
536 mclk_fs = priv->mclk_fs;
537 else if (dai_props->mclk_fs)
538 mclk_fs = dai_props->mclk_fs;
539
540 if (mclk_fs) {
541 mclk = params_rate(params) * mclk_fs;
542
543 for (i = 0; i < rtd->num_codecs; i++) {
544 codec_dai = rtd->codec_dais[i];
545 ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
546 SND_SOC_CLOCK_IN);
547
Googler9398cc32022-12-02 17:21:52 +0800548 if (ret && ret != -ENOTSUPP) {
549 pr_err("codec_dai soc dai set sysclk failed\n");
Googler4f18c0c2022-09-20 17:23:36 +0800550 goto err;
Googler9398cc32022-12-02 17:21:52 +0800551 }
Googler4f18c0c2022-09-20 17:23:36 +0800552 }
553
554 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_idx, mclk,
555 SND_SOC_CLOCK_OUT);
Googler9398cc32022-12-02 17:21:52 +0800556 if (ret && ret != -ENOTSUPP) {
557 pr_err("cpu_dai soc dai set sysclk failed\n");
Googler4f18c0c2022-09-20 17:23:36 +0800558 goto err;
Googler9398cc32022-12-02 17:21:52 +0800559 }
Googler4f18c0c2022-09-20 17:23:36 +0800560
561 ret = snd_soc_dai_set_fmt(cpu_dai, dai_link->dai_fmt);
Googler9398cc32022-12-02 17:21:52 +0800562 if (ret && ret != -ENOTSUPP) {
563 pr_err("cpu_dai soc dai set fmt failed\n");
Googler4f18c0c2022-09-20 17:23:36 +0800564 goto err;
Googler9398cc32022-12-02 17:21:52 +0800565 }
Googler4f18c0c2022-09-20 17:23:36 +0800566 }
567
Googler4f18c0c2022-09-20 17:23:36 +0800568 return 0;
569err:
570 return ret;
571}
572
Googler4f18c0c2022-09-20 17:23:36 +0800573static struct snd_soc_ops aml_card_ops = {
Googler4f18c0c2022-09-20 17:23:36 +0800574 .hw_params = aml_card_hw_params,
Googler4f18c0c2022-09-20 17:23:36 +0800575};
576
577static int aml_card_dai_init(struct snd_soc_pcm_runtime *rtd)
578{
579 struct aml_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
580 struct snd_soc_dai *codec = rtd->codec_dai;
581 struct snd_soc_dai *cpu = rtd->cpu_dai;
582 struct aml_dai_props *dai_props =
583 aml_priv_to_props(priv, rtd->num);
584 static int hp_mic_detect_cnt;
585 bool idle_clk = false;
586 int ret, i;
587
588 /* enable dai-link mclk when CONTINUOUS clk setted */
589 idle_clk = !!(rtd->dai_link->dai_fmt & SND_SOC_DAIFMT_CONT);
590
591 for (i = 0; i < rtd->num_codecs; i++) {
592 codec = rtd->codec_dais[i];
593
594 ret = aml_card_init_dai(codec, &dai_props->codec_dai, idle_clk);
595 if (ret < 0)
596 return ret;
597 }
598
599 ret = aml_card_init_dai(cpu, &dai_props->cpu_dai, idle_clk);
600 if (ret < 0)
601 return ret;
602
603 if (hp_mic_detect_cnt == 0) {
604 aml_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
605 aml_card_init_mic(rtd->card, &priv->mic_jack, PREFIX);
606 hp_mic_detect_cnt = 1;
607 }
608
609 return 0;
610}
611
612static int aml_card_dai_link_of(struct device_node *node,
613 struct aml_card_data *priv,
614 int idx,
615 bool is_top_level_node)
616{
617 struct device *dev = aml_priv_to_dev(priv);
618 struct snd_soc_dai_link *dai_link = aml_priv_to_link(priv, idx);
619 struct aml_dai_props *dai_props = aml_priv_to_props(priv, idx);
620 struct aml_dai *cpu_dai = &dai_props->cpu_dai;
621 struct aml_dai *codec_dai = &dai_props->codec_dai;
622 struct device_node *cpu = NULL;
623 struct device_node *plat = NULL;
624 struct device_node *codec = NULL;
625 char prop[128];
626 char *prefix = "";
627 int ret, single_cpu;
628
629 /* For single DAI link & old style of DT node */
630 if (is_top_level_node)
631 prefix = PREFIX;
632
633 snprintf(prop, sizeof(prop), "%scpu", prefix);
634 cpu = of_get_child_by_name(node, prop);
635
636 snprintf(prop, sizeof(prop), "%splat", prefix);
637 plat = of_get_child_by_name(node, prop);
638
639 snprintf(prop, sizeof(prop), "%scodec", prefix);
640 codec = of_get_child_by_name(node, prop);
641
642 if (!cpu || !codec) {
643 ret = -EINVAL;
644 dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
645 goto dai_link_of_err;
646 }
647
Googler9398cc32022-12-02 17:21:52 +0800648 dai_link->cpus->of_node = of_parse_phandle(cpu, DAI, 0);
649 if (!dai_link->cpus->of_node) {
Googler9726be62022-12-14 05:53:31 +0000650 dev_err(dev, "error getting cpu phandle\n");
651 return -EINVAL;
652 }
653
Googler4f18c0c2022-09-20 17:23:36 +0800654 ret = aml_card_parse_daifmt(dev, node, codec,
655 prefix, &dai_link->dai_fmt);
Googler38bda472022-08-19 10:07:08 -0700656 if (ret < 0) {
657 dev_err(dev, "%s, dai fmt not found\n",
658 __func__);
Googler4f18c0c2022-09-20 17:23:36 +0800659 goto dai_link_of_err;
Googler38bda472022-08-19 10:07:08 -0700660 }
Googler4f18c0c2022-09-20 17:23:36 +0800661 of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
662
663 ret = aml_card_parse_cpu(cpu, dai_link,
664 DAI, CELL, &single_cpu);
Googler38bda472022-08-19 10:07:08 -0700665 if (ret < 0) {
666 dev_err(dev, "%s, dai-link idx:%d, error getting cpu dai name:%s\n",
667 __func__,
668 idx,
Googler9398cc32022-12-02 17:21:52 +0800669 dai_link->cpus->dai_name);
Googler4f18c0c2022-09-20 17:23:36 +0800670 goto dai_link_of_err;
Googler38bda472022-08-19 10:07:08 -0700671 }
Googler4f18c0c2022-09-20 17:23:36 +0800672
Googler4f18c0c2022-09-20 17:23:36 +0800673 ret = snd_soc_of_get_dai_link_codecs(dev, codec, dai_link);
Googler38bda472022-08-19 10:07:08 -0700674
675 if (ret < 0) {
Googler9398cc32022-12-02 17:21:52 +0800676 dev_err(dev, "%s, error dai-link idx:%d, ret %d\n", __func__, idx, ret);
Googler4f18c0c2022-09-20 17:23:36 +0800677 goto dai_link_of_err;
Googler38bda472022-08-19 10:07:08 -0700678 }
Googler4f18c0c2022-09-20 17:23:36 +0800679
680 ret = aml_card_parse_platform(plat, dai_link, DAI, CELL);
Googler38bda472022-08-19 10:07:08 -0700681 if (ret < 0) {
682 dev_err(dev, "%s, platform not found\n",
683 __func__);
684
Googler4f18c0c2022-09-20 17:23:36 +0800685 goto dai_link_of_err;
Googler38bda472022-08-19 10:07:08 -0700686 }
Googler4f18c0c2022-09-20 17:23:36 +0800687
688 ret = snd_soc_of_parse_tdm_slot(cpu, &cpu_dai->tx_slot_mask,
689 &cpu_dai->rx_slot_mask,
690 &cpu_dai->slots,
691 &cpu_dai->slot_width);
692 if (ret < 0)
693 goto dai_link_of_err;
694
695 ret = snd_soc_of_parse_tdm_slot(codec, &codec_dai->tx_slot_mask,
696 &codec_dai->rx_slot_mask,
697 &codec_dai->slots,
698 &codec_dai->slot_width);
699 if (ret < 0)
700 goto dai_link_of_err;
701
702 ret = aml_card_parse_codec_confs(codec, &priv->snd_card);
703 if (ret < 0)
704 goto dai_link_of_err;
705
706 ret = aml_card_parse_clk_cpu(cpu, dai_link, cpu_dai);
707 if (ret < 0)
708 goto dai_link_of_err;
709
Googler4f18c0c2022-09-20 17:23:36 +0800710 ret = aml_card_canonicalize_dailink(dai_link);
711 if (ret < 0)
712 goto dai_link_of_err;
713
714 /* sync with android audio hal, what's the link used for. */
715 of_property_read_string(node, "suffix-name", &dai_props->suffix_name);
716
717 if (dai_props->suffix_name)
718 ret = aml_card_set_dailink_name(dev, dai_link,
719 "%s-%s-%s",
Googler9398cc32022-12-02 17:21:52 +0800720 dai_link->cpus->dai_name,
Googler4f18c0c2022-09-20 17:23:36 +0800721 dai_link->codecs->dai_name,
722 dai_props->suffix_name);
723 else
724 ret = aml_card_set_dailink_name(dev, dai_link,
725 "%s-%s",
Googler9398cc32022-12-02 17:21:52 +0800726 dai_link->cpus->dai_name,
Googler4f18c0c2022-09-20 17:23:36 +0800727 dai_link->codecs->dai_name);
728 if (ret < 0)
729 goto dai_link_of_err;
730
731 dai_link->ops = &aml_card_ops;
732 dai_link->init = aml_card_dai_init;
Googler38bda472022-08-19 10:07:08 -0700733 dai_link->nonatomic = 1;
Googler4f18c0c2022-09-20 17:23:36 +0800734 dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
735 dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt);
736 dev_dbg(dev, "\tcpu : %s / %d\n",
Googler9398cc32022-12-02 17:21:52 +0800737 dai_link->cpus->dai_name,
Googler4f18c0c2022-09-20 17:23:36 +0800738 dai_props->cpu_dai.sysclk);
739 dev_dbg(dev, "\tcodec : %s / %d\n",
740 dai_link->codecs->dai_name,
741 dai_props->codec_dai.sysclk);
742
743 aml_card_canonicalize_cpu(dai_link, single_cpu);
744
745dai_link_of_err:
746 of_node_put(cpu);
747 of_node_put(codec);
748
749 return ret;
750}
751
752static int aml_card_parse_aux_devs(struct device_node *node,
753 struct aml_card_data *priv)
754{
755 struct device *dev = aml_priv_to_dev(priv);
756 struct device_node *aux_node;
757 int i, n, len;
758
759 if (!of_find_property(node, PREFIX "aux-devs", &len))
760 return 0; /* Ok to have no aux-devs */
761
762 n = len / sizeof(__be32);
763 if (n <= 0)
764 return -EINVAL;
765
766 priv->snd_card.aux_dev = devm_kzalloc(dev,
767 n * sizeof(*priv->snd_card.aux_dev), GFP_KERNEL);
768 if (!priv->snd_card.aux_dev)
769 return -ENOMEM;
770
771 for (i = 0; i < n; i++) {
772 aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
773 if (!aux_node)
774 return -EINVAL;
Googler9398cc32022-12-02 17:21:52 +0800775 priv->snd_card.aux_dev[i].dlc.of_node = aux_node;
Googler4f18c0c2022-09-20 17:23:36 +0800776 }
777
778 priv->snd_card.num_aux_devs = n;
779 return 0;
780}
781
782static int spk_mute_set(struct snd_kcontrol *kcontrol,
783 struct snd_ctl_elem_value *ucontrol)
784{
785 struct snd_soc_card *soc_card = snd_kcontrol_chip(kcontrol);
786 struct aml_card_data *priv = aml_card_to_priv(soc_card);
787 int gpio = priv->spk_mute_gpio;
788 bool active_low = priv->spk_mute_active_low;
789 bool mute = ucontrol->value.integer.value[0];
790
Googler9398cc32022-12-02 17:21:52 +0800791 priv->spk_mute_flag = mute;
792
Googler4f18c0c2022-09-20 17:23:36 +0800793 if (gpio_is_valid(gpio)) {
794 bool value = active_low ? !mute : mute;
795
796 gpio_set_value(gpio, value);
Googler9398cc32022-12-02 17:21:52 +0800797 pr_info("%s: mute flag = %d\n", __func__, mute);
Googler4f18c0c2022-09-20 17:23:36 +0800798 }
799
800 return 0;
801}
802
803static int spk_mute_get(struct snd_kcontrol *kcontrol,
804 struct snd_ctl_elem_value *ucontrol)
805{
806 struct snd_soc_card *soc_card = snd_kcontrol_chip(kcontrol);
807 struct aml_card_data *priv = aml_card_to_priv(soc_card);
808 int gpio = priv->spk_mute_gpio;
809 bool active_low = priv->spk_mute_active_low;
810
811 if (gpio_is_valid(gpio)) {
812 bool value = gpio_get_value(gpio);
813 bool mute = active_low ? !value : value;
814
815 ucontrol->value.integer.value[0] = mute;
816 }
817
818 return 0;
819}
820
821static const struct snd_kcontrol_new card_controls[] = {
822 SOC_SINGLE_BOOL_EXT("SPK mute", 0,
823 spk_mute_get,
824 spk_mute_set),
825};
826
827static int aml_card_parse_gpios(struct device_node *node,
828 struct aml_card_data *priv)
829{
830 struct device *dev = aml_priv_to_dev(priv);
831 struct snd_soc_card *soc_card = &priv->snd_card;
832 enum of_gpio_flags flags;
833 int gpio;
834 bool active_low;
Googler4f18c0c2022-09-20 17:23:36 +0800835
Googler9726be62022-12-14 05:53:31 +0000836 gpio = of_get_named_gpio_flags(node, "spk_mute-gpios", 0, &flags);
Googler4f18c0c2022-09-20 17:23:36 +0800837 priv->spk_mute_gpio = gpio;
838
839 if (gpio_is_valid(gpio)) {
Googler9398cc32022-12-02 17:21:52 +0800840 int ret;
Googler4f18c0c2022-09-20 17:23:36 +0800841 active_low = !!(flags & OF_GPIO_ACTIVE_LOW);
Googler9726be62022-12-14 05:53:31 +0000842 flags = active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
Googler4f18c0c2022-09-20 17:23:36 +0800843 priv->spk_mute_active_low = active_low;
844
Googler9398cc32022-12-02 17:21:52 +0800845 snd_soc_add_card_controls(soc_card, card_controls,
846 ARRAY_SIZE(card_controls));
847
848 if (priv->spk_mute_enable) {
849 gpio_set_value(priv->spk_mute_gpio,
850 (active_low) ? GPIOF_OUT_INIT_LOW :
851 GPIOF_OUT_INIT_HIGH);
852 } else {
853 msleep(200);
854 if (!priv->spk_mute_flag)
855 gpio_set_value(priv->spk_mute_gpio,
856 (active_low) ? GPIOF_OUT_INIT_HIGH :
857 GPIOF_OUT_INIT_LOW);
858 }
859
Googler38bda472022-08-19 10:07:08 -0700860 ret = devm_gpio_request_one(dev, gpio, flags, "spk_mute");
Googler9398cc32022-12-02 17:21:52 +0800861 if (ret < 0) {
862 dev_err(dev, "spk_mute get gpio error!\n");
Googler9726be62022-12-14 05:53:31 +0000863 }
Googler38bda472022-08-19 10:07:08 -0700864 }
865 if (IS_ERR_OR_NULL(priv->avout_mute_desc)) {
Googler9726be62022-12-14 05:53:31 +0000866 priv->avout_mute_desc = gpiod_get(dev,
867 "avout_mute", GPIOF_OUT_INIT_LOW);
Googler38bda472022-08-19 10:07:08 -0700868 }
869 if (!IS_ERR(priv->avout_mute_desc)) {
870 if (!priv->av_mute_enable) {
871 msleep(500);
872 gpiod_direction_output(priv->avout_mute_desc,
Googler9726be62022-12-14 05:53:31 +0000873 GPIOF_OUT_INIT_HIGH);
Googler38bda472022-08-19 10:07:08 -0700874 pr_info("av out status: %s\n",
875 gpiod_get_value(priv->avout_mute_desc) ?
876 "high" : "low");
877 } else {
878 gpiod_direction_output(priv->avout_mute_desc,
Googler9726be62022-12-14 05:53:31 +0000879 GPIOF_OUT_INIT_LOW);
Googler38bda472022-08-19 10:07:08 -0700880 pr_info("av out status: %s\n",
881 gpiod_get_value(priv->avout_mute_desc) ?
882 "high" : "low");
883 }
Googler4f18c0c2022-09-20 17:23:36 +0800884 }
885
Googler4f18c0c2022-09-20 17:23:36 +0800886 return 0;
887}
888
Googler38bda472022-08-19 10:07:08 -0700889static void aml_init_work(struct work_struct *init_work)
890{
891 struct aml_card_data *priv = NULL;
892 struct device *dev = NULL;
893 struct device_node *np = NULL;
894
895 priv = container_of(init_work,
Googler9726be62022-12-14 05:53:31 +0000896 struct aml_card_data, init_work);
Googler38bda472022-08-19 10:07:08 -0700897 dev = aml_priv_to_dev(priv);
898 np = dev->of_node;
899 aml_card_parse_gpios(np, priv);
900}
901
Googler4f18c0c2022-09-20 17:23:36 +0800902static int aml_card_parse_of(struct device_node *node,
903 struct aml_card_data *priv)
904{
905 struct device *dev = aml_priv_to_dev(priv);
906 struct device_node *dai_link;
Googler4f18c0c2022-09-20 17:23:36 +0800907 int ret;
908
909 if (!node)
910 return -EINVAL;
911
912 dai_link = of_get_child_by_name(node, PREFIX "dai-link");
913
914 /* The off-codec widgets */
915 if (of_property_read_bool(node, PREFIX "widgets")) {
916 ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card,
917 PREFIX "widgets");
918 if (ret)
919 goto card_parse_end;
920 }
921
922 /* DAPM routes */
923 if (of_property_read_bool(node, PREFIX "routing")) {
924 ret = snd_soc_of_parse_audio_routing(&priv->snd_card,
925 PREFIX "routing");
926 if (ret)
927 goto card_parse_end;
928 }
929
930 /* Factor to mclk, used in hw_params() */
931 of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
932
Googler4f18c0c2022-09-20 17:23:36 +0800933 /* Single/Muti DAI link(s) & New style of DT node */
934 if (dai_link) {
935 struct device_node *np = NULL;
936 int i = 0;
937
938 for_each_child_of_node(node, np) {
939 dev_dbg(dev, "\tlink %d:\n", i);
940 ret = aml_card_dai_link_of(np, priv,
941 i, false);
942 if (ret < 0) {
Googler9726be62022-12-14 05:53:31 +0000943 dev_err(dev, "parse dai_link-%d fail\n", i);
Googler4f18c0c2022-09-20 17:23:36 +0800944 of_node_put(np);
945 goto card_parse_end;
946 }
947 i++;
948 }
949 } else {
950 /* For single DAI link & old style of DT node */
951 ret = aml_card_dai_link_of(node, priv, 0, true);
952 if (ret < 0)
953 goto card_parse_end;
954 }
955
956 ret = aml_card_parse_card_name(&priv->snd_card, PREFIX);
957 if (ret < 0)
958 goto card_parse_end;
959
960 ret = aml_card_parse_aux_devs(node, priv);
961
962card_parse_end:
963 of_node_put(dai_link);
Googler4f18c0c2022-09-20 17:23:36 +0800964
965 return ret;
966}
967
Googler4f18c0c2022-09-20 17:23:36 +0800968static const struct of_device_id auge_of_match[] = {
969 {
Googler9398cc32022-12-02 17:21:52 +0800970 .compatible = "amlogic, auge-sound-card",
Googler4f18c0c2022-09-20 17:23:36 +0800971 },
Googler9398cc32022-12-02 17:21:52 +0800972 {}
Googler4f18c0c2022-09-20 17:23:36 +0800973};
974MODULE_DEVICE_TABLE(of, auge_of_match);
975
Googler38bda472022-08-19 10:07:08 -0700976static int card_suspend_pre(struct snd_soc_card *card)
977{
978 struct aml_card_data *priv = snd_soc_card_get_drvdata(card);
Googler9398cc32022-12-02 17:21:52 +0800979 struct device *dev = aml_priv_to_dev(priv);
Googler38bda472022-08-19 10:07:08 -0700980
981 priv->av_mute_enable = 1;
Googler9398cc32022-12-02 17:21:52 +0800982 priv->spk_mute_enable = 1;
983 aml_card_parse_gpios(dev->of_node, priv);
Googler38bda472022-08-19 10:07:08 -0700984 pr_info("it is card_pre_suspend\n");
985 return 0;
986}
987
988static int card_resume_post(struct snd_soc_card *card)
989{
990 struct aml_card_data *priv = snd_soc_card_get_drvdata(card);
Googler9398cc32022-12-02 17:21:52 +0800991 struct device *dev = aml_priv_to_dev(priv);
Googler38bda472022-08-19 10:07:08 -0700992
993 priv->av_mute_enable = 0;
Googler9398cc32022-12-02 17:21:52 +0800994 priv->spk_mute_enable = 0;
995 aml_card_parse_gpios(dev->of_node, priv);
Googler38bda472022-08-19 10:07:08 -0700996 pr_info("it is card_post_resume\n");
997 return 0;
Googler9726be62022-12-14 05:53:31 +0000998
Googler38bda472022-08-19 10:07:08 -0700999}
1000
Googler9398cc32022-12-02 17:21:52 +08001001static irqreturn_t aml_audio_exception64_isr(int irq, void *dev_id)
1002{
1003 unsigned int intrpt_status0, intrpt_status1;
1004
1005 intrpt_status0 = audiobus_read(EE_AUDIO_EXCEPTION_IRQ_STS0);
1006 intrpt_status1 = audiobus_read(EE_AUDIO_EXCEPTION_IRQ_STS1);
1007
1008 /* clear irq bits immediametely */
1009 audiobus_write(EE_AUDIO_EXCEPTION_IRQ_CLR0, intrpt_status0);
1010 audiobus_write(EE_AUDIO_EXCEPTION_IRQ_CLR1, intrpt_status1);
1011
1012 pr_debug("0 - 31 exception status is 0x%x\n", intrpt_status0);
1013 pr_debug("32 - 63 exception status is 0x%x\n", intrpt_status1);
1014
1015 /* TODO handle exception */
1016
1017 return IRQ_HANDLED;
1018}
1019
1020static int register_audio_exception64_isr(int irq_exception64)
1021{
1022 int ret = 0;
1023
1024 /* open irq mask, default is close
1025 * audiobus_write(EE_AUDIO_EXCEPTION_IRQ_MASK0, 0xfffdff3f);
1026 * audiobus_write(EE_AUDIO_EXCEPTION_IRQ_MASK1, 0xffc3777f);
1027
1028 * set threshold value
1029 * audiobus_write(EE_AUDIO_ARB_CTRL1, 0xffff);
1030 * audiobus_write(EE_AUDIO_SPDIFIN_CTRL7, 0xffff);
1031 */
1032
1033 ret = request_irq(irq_exception64,
1034 aml_audio_exception64_isr,
1035 0,
1036 "audio_exception64",
1037 NULL);
1038
1039 if (ret)
1040 pr_err("failed claim irq_exception64 %u, ret: %d\n", irq_exception64, ret);
1041
1042 return ret;
1043}
1044
Googler4f18c0c2022-09-20 17:23:36 +08001045static int aml_card_probe(struct platform_device *pdev)
1046{
1047 struct aml_card_data *priv;
1048 struct snd_soc_dai_link *dai_link;
1049 struct aml_dai_props *dai_props;
1050 struct device_node *np = pdev->dev.of_node;
1051 struct device *dev = &pdev->dev;
Googler9398cc32022-12-02 17:21:52 +08001052 int num, ret, i;
Googler4f18c0c2022-09-20 17:23:36 +08001053
1054 /* Get the number of DAI links */
1055 if (np && of_get_child_by_name(np, PREFIX "dai-link"))
1056 num = of_get_child_count(np);
1057 else
1058 num = 1;
1059
1060 /* Allocate the private data and the DAI link array */
1061 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1062 if (!priv)
1063 return -ENOMEM;
1064
1065 dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
1066 dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
1067 if (!dai_props || !dai_link)
1068 return -ENOMEM;
1069
1070 priv->dai_props = dai_props;
1071 priv->dai_link = dai_link;
1072
Googler9398cc32022-12-02 17:21:52 +08001073 for (i = 0; i < num; i++) {
1074 dai_link[i].cpus = &dai_props[i].cpus;
1075 dai_link[i].num_cpus = 1;
1076 dai_link[i].codecs = &dai_props[i].codecs;
1077 dai_link[i].num_codecs = 1;
1078 dai_link[i].platforms = &dai_props[i].platforms;
1079 dai_link[i].num_platforms = 1;
1080 }
1081
Googler4f18c0c2022-09-20 17:23:36 +08001082 /* Init snd_soc_card */
1083 priv->snd_card.owner = THIS_MODULE;
1084 priv->snd_card.dev = dev;
1085 priv->snd_card.dai_link = priv->dai_link;
1086 priv->snd_card.num_links = num;
Googler38bda472022-08-19 10:07:08 -07001087 priv->snd_card.suspend_pre = card_suspend_pre;
1088 priv->snd_card.resume_post = card_resume_post;
Googler4f18c0c2022-09-20 17:23:36 +08001089
1090 if (np && of_device_is_available(np)) {
Googler4f18c0c2022-09-20 17:23:36 +08001091 ret = aml_card_parse_of(np, priv);
1092 if (ret < 0) {
Googler38bda472022-08-19 10:07:08 -07001093 dev_err(dev, "%s, aml_card_parse_of error %d %s\n",
Googler9726be62022-12-14 05:53:31 +00001094 __func__,
1095 ret,
1096 (ret == -EPROBE_DEFER) ? "PROBE RETRY" : "");
Googler4f18c0c2022-09-20 17:23:36 +08001097 goto err;
1098 }
1099
1100 } else {
1101 struct aml_card_info *cinfo;
1102
1103 cinfo = dev->platform_data;
1104 if (!cinfo) {
1105 dev_err(dev, "no info for asoc-aml-card\n");
1106 return -EINVAL;
1107 }
1108
1109 if (!cinfo->name ||
1110 !cinfo->codec_dai.name ||
1111 !cinfo->codec ||
1112 !cinfo->platform ||
1113 !cinfo->cpu_dai.name) {
1114 dev_err(dev, "insufficient aml_card_info settings\n");
1115 return -EINVAL;
1116 }
1117
1118 priv->snd_card.name =
1119 (cinfo->card) ? cinfo->card : cinfo->name;
1120 dai_link->name = cinfo->name;
1121 dai_link->stream_name = cinfo->name;
Googler9398cc32022-12-02 17:21:52 +08001122 dai_link->platforms->name = cinfo->platform;
1123 dai_link->codecs->name = cinfo->codec;
1124 dai_link->cpus->dai_name = cinfo->cpu_dai.name;
1125 dai_link->codecs->dai_name = cinfo->codec_dai.name;
Googler4f18c0c2022-09-20 17:23:36 +08001126 dai_link->dai_fmt = cinfo->daifmt;
1127 dai_link->init = aml_card_dai_init;
1128 memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
1129 sizeof(priv->dai_props->cpu_dai));
1130 memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
1131 sizeof(priv->dai_props->codec_dai));
1132 }
1133
Googler9398cc32022-12-02 17:21:52 +08001134 priv->irq_exception64 =
1135 platform_get_irq_byname(pdev, "audio_exception64");
1136 if (priv->irq_exception64 > 0)
1137 register_audio_exception64_isr(priv->irq_exception64);
1138
Googler9726be62022-12-14 05:53:31 +00001139 platform_set_drvdata(pdev, priv);
Googler4f18c0c2022-09-20 17:23:36 +08001140 snd_soc_card_set_drvdata(&priv->snd_card, priv);
1141
1142 ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
1143 if (ret < 0) {
1144 dev_err(dev, "failed to register sound card\n");
1145 goto err;
1146 }
1147
1148 /* Add controls */
1149 ret = aml_card_add_controls(&priv->snd_card);
1150 if (ret < 0) {
1151 dev_err(dev, "failed to register mixer kcontrols\n");
1152 goto err;
1153 }
1154
Googler9398cc32022-12-02 17:21:52 +08001155 card_add_effects_init(&priv->snd_card);
Googler4f18c0c2022-09-20 17:23:36 +08001156
1157 if (priv->hp_det_enable == 1 || priv->mic_det_enable == 1) {
Googler9398cc32022-12-02 17:21:52 +08001158 priv->hp_detect_flag = -1;
1159 priv->hp_last_state = -1;
1160 priv->mic_detect_flag = -1;
1161 priv->micphone_last_state = -1;
Googler4f18c0c2022-09-20 17:23:36 +08001162 audio_jack_detect(priv);
1163 audio_extcon_register(priv, dev);
1164 }
Googler9726be62022-12-14 05:53:31 +00001165
1166 snd_soc_add_card_controls(&priv->snd_card, snd_user_controls,
1167 ARRAY_SIZE(snd_user_controls));
1168
Googler38bda472022-08-19 10:07:08 -07001169 priv->av_mute_enable = 0;
Googler9398cc32022-12-02 17:21:52 +08001170 priv->spk_mute_enable = 0;
Googler38bda472022-08-19 10:07:08 -07001171 INIT_WORK(&priv->init_work, aml_init_work);
1172 schedule_work(&priv->init_work);
1173
1174 return 0;
Googler4f18c0c2022-09-20 17:23:36 +08001175err:
1176 pr_err("%s error ret:%d\n", __func__, ret);
1177 aml_card_clean_reference(&priv->snd_card);
1178
1179 return ret;
1180}
1181
1182static int aml_card_remove(struct platform_device *pdev)
1183{
1184 struct snd_soc_card *card = platform_get_drvdata(pdev);
1185 struct aml_card_data *priv = snd_soc_card_get_drvdata(card);
1186
1187 aml_card_remove_jack(&priv->hp_jack);
1188 aml_card_remove_jack(&priv->mic_jack);
1189 jack_audio_stop_timer(priv);
Googler9398cc32022-12-02 17:21:52 +08001190
1191 if (priv->irq_exception64 > 0)
1192 free_irq(priv->irq_exception64, NULL);
1193
Googler4f18c0c2022-09-20 17:23:36 +08001194 return aml_card_clean_reference(card);
1195}
1196
Googler38bda472022-08-19 10:07:08 -07001197static void aml_card_platform_shutdown(struct platform_device *pdev)
1198{
1199 struct snd_soc_card *card = platform_get_drvdata(pdev);
1200 struct aml_card_data *priv = snd_soc_card_get_drvdata(card);
1201
1202 priv->av_mute_enable = 1;
Googler9398cc32022-12-02 17:21:52 +08001203 priv->spk_mute_enable = 1;
1204 aml_card_parse_gpios(pdev->dev.of_node, priv);
Googler38bda472022-08-19 10:07:08 -07001205}
1206
Googler4f18c0c2022-09-20 17:23:36 +08001207static struct platform_driver aml_card = {
1208 .driver = {
1209 .name = "asoc-aml-card",
1210 .pm = &snd_soc_pm_ops,
1211 .of_match_table = auge_of_match,
1212 },
1213 .probe = aml_card_probe,
1214 .remove = aml_card_remove,
Googler38bda472022-08-19 10:07:08 -07001215 .shutdown = aml_card_platform_shutdown,
Googler4f18c0c2022-09-20 17:23:36 +08001216};
1217
Googler9398cc32022-12-02 17:21:52 +08001218int __init aml_card_init(void)
1219{
1220 return platform_driver_register(&aml_card);
1221}
Googler4f18c0c2022-09-20 17:23:36 +08001222
Googler9398cc32022-12-02 17:21:52 +08001223void __exit aml_card_exit(void)
1224{
1225 platform_driver_unregister(&aml_card);
1226}
1227
1228#ifndef MODULE
1229module_init(aml_card_init);
1230module_exit(aml_card_exit);
Googler4f18c0c2022-09-20 17:23:36 +08001231MODULE_ALIAS("platform:asoc-aml-card");
1232MODULE_LICENSE("GPL v2");
1233MODULE_DESCRIPTION("ASoC aml Sound Card");
1234MODULE_AUTHOR("AMLogic, Inc.");
Googler9398cc32022-12-02 17:21:52 +08001235#endif