xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/aw883xx/aw_spin.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * aw_spin.c   aw883xx spin module
4  *
5  * Copyright (c) 2020 AWINIC Technology CO., LTD
6  *
7  *  Author: Bruce zhao <zhaolei@awinic.com>
8  *
9  * This program is free software; you can redistribute  it and/or modify it
10  * under  the terms of  the GNU General  Public License as published by the
11  * Free Software Foundation;  either version 2 of the  License, or (at your
12  * option) any later version.
13  */
14 #include <linux/module.h>
15 #include <linux/i2c.h>
16 #include <sound/soc.h>
17 #include <linux/of_gpio.h>
18 #include <linux/delay.h>
19 #include <linux/device.h>
20 #include <linux/version.h>
21 #include <linux/syscalls.h>
22 #include <sound/control.h>
23 #include <linux/uaccess.h>
24 #include <linux/debugfs.h>
25 #include <linux/slab.h>
26 #include <linux/fs.h>
27 #include <linux/kernel.h>
28 #include <linux/of.h>
29 #include "aw_spin.h"
30 #include "aw_device.h"
31 #include "aw883xx.h"
32 #include "aw_log.h"
33 
34 static DEFINE_MUTEX(g_aw_spin_lock);
35 
36 static unsigned int g_spin_angle = AW_SPIN_0;
37 static unsigned int g_spin_mode = AW_SPIN_OFF_MODE;
38 
39 static const char *const aw_spin[] = {"spin_0", "spin_90",
40 					"spin_180", "spin_270"};
41 
42 #ifdef AW_MTK_PLATFORM_SPIN
43 extern int mtk_spk_send_ipi_buf_to_dsp(void *data_buffer, uint32_t data_size);
44 extern int mtk_spk_recv_ipi_buf_from_dsp(int8_t *buffer, int16_t size, uint32_t *buf_len);
45 #elif defined AW_QCOM_PLATFORM_SPIN
46 extern int afe_get_topology(int port_id);
47 extern int aw_send_afe_cal_apr(uint32_t param_id,
48 	void *buf, int cmd_size, bool write);
49 #else
aw_send_afe_cal_apr(uint32_t param_id,void * buf,int cmd_size,bool write)50 static int aw_send_afe_cal_apr(uint32_t param_id,
51 		void *buf, int cmd_size, bool write)
52 {
53 	return 0;
54 }
55 
afe_get_topology(int port_id)56 static int afe_get_topology(int port_id)
57 {
58 	return 0;
59 }
60 #endif
aw_get_msg_id(int dev_ch,uint32_t * msg_id)61 static int aw_get_msg_id(int dev_ch, uint32_t *msg_id)
62 {
63 	switch (dev_ch) {
64 	case AW_DEV_CH_PRI_L:
65 		*msg_id = AFE_MSG_ID_MSG_0;
66 		break;
67 	case AW_DEV_CH_PRI_R:
68 		*msg_id = AFE_MSG_ID_MSG_0;
69 		break;
70 	case AW_DEV_CH_SEC_L:
71 		*msg_id = AFE_MSG_ID_MSG_1;
72 		break;
73 	case AW_DEV_CH_SEC_R:
74 		*msg_id = AFE_MSG_ID_MSG_1;
75 		break;
76 	default:
77 		pr_err("%s: can not find msg num, channel %d ", __func__, dev_ch);
78 		return -EINVAL;
79 	}
80 
81 	pr_debug("%s: msg id[%d] ", __func__, *msg_id);
82 	return 0;
83 }
84 
85 #ifdef AW_MTK_PLATFORM_SPIN
aw_mtk_write_data_to_dsp(int msg_id,void * data,int size)86 static int aw_mtk_write_data_to_dsp(int msg_id, void *data, int size)
87 {
88 	int32_t *dsp_data = NULL;
89 	struct aw_msg_hdr *hdr = NULL;
90 	int ret;
91 
92 	dsp_data = kzalloc(sizeof(struct aw_msg_hdr) + size, GFP_KERNEL);
93 	if (!dsp_data) {
94 		pr_err("%s: kzalloc dsp_msg error\n", __func__);
95 		return -ENOMEM;
96 	}
97 
98 	hdr = (struct aw_msg_hdr *)dsp_data;
99 	hdr->type = AW_DSP_MSG_TYPE_DATA;
100 	hdr->opcode_id = msg_id;
101 	hdr->version = AW_DSP_MSG_HDR_VER;
102 
103 	memcpy(((char *)dsp_data) + sizeof(struct aw_msg_hdr), data, size);
104 
105 	ret = mtk_spk_send_ipi_buf_to_dsp(dsp_data,
106 				sizeof(struct aw_msg_hdr) + size);
107 	if (ret < 0) {
108 		pr_err("%s: write data failed\n", __func__);
109 		kfree(dsp_data);
110 		dsp_data = NULL;
111 		return ret;
112 	}
113 
114 	kfree(dsp_data);
115 	dsp_data = NULL;
116 	return 0;
117 }
118 
aw_mtk_set_spin_angle(struct aw_device * aw_dev,uint32_t spin_angle)119 static int aw_mtk_set_spin_angle(struct aw_device *aw_dev, uint32_t spin_angle)
120 {
121 	int ret;
122 
123 	ret = aw_mtk_write_data_to_dsp(AW_MSG_ID_SPIN, &spin_angle, sizeof(uint32_t));
124 	if (ret)
125 		aw_dev_err(aw_dev->dev, "write data to dsp failed");
126 
127 	return ret;
128 }
129 
aw_mtk_get_spin_angle(void * spin_angle,int size)130 static int aw_mtk_get_spin_angle(void *spin_angle, int size)
131 {
132 	int ret;
133 	struct aw_msg_hdr hdr;
134 
135 	hdr.type = AW_DSP_MSG_TYPE_CMD;
136 	hdr.opcode_id = AW_MSG_ID_SPIN;
137 	hdr.version = AW_DSP_MSG_HDR_VER;
138 
139 	ret = mtk_spk_send_ipi_buf_to_dsp(&hdr, sizeof(struct aw_msg_hdr));
140 	if (ret < 0) {
141 		pr_err("%s:send cmd failed\n", __func__);
142 		return ret;
143 	}
144 
145 	ret = mtk_spk_recv_ipi_buf_from_dsp(spin_angle, size, &size);
146 	if (ret < 0) {
147 		pr_err("%s:get data failed\n", __func__);
148 		return ret;
149 	}
150 	return 0;
151 }
152 
aw_mtk_set_mixer_en(struct aw_device * aw_dev,uint32_t msg_id,int32_t is_enable)153 static int aw_mtk_set_mixer_en(struct aw_device *aw_dev, uint32_t msg_id, int32_t is_enable)
154 {
155 	int32_t *dsp_msg = NULL;
156 	struct aw_msg_hdr *hdr = NULL;
157 	int ret;
158 
159 	dsp_msg = kzalloc(sizeof(struct aw_msg_hdr) + sizeof(int32_t), GFP_KERNEL);
160 	if (!dsp_msg) {
161 		aw_dev_err(aw_dev->dev, "kzalloc dsp_msg error");
162 		return -ENOMEM;
163 	}
164 	hdr = (struct aw_msg_hdr *)dsp_msg;
165 	hdr->type = AW_DSP_MSG_TYPE_DATA;
166 	hdr->opcode_id = AW_INLINE_ID_AUDIO_MIX;
167 	hdr->version = AW_DSP_MSG_HDR_VER;
168 
169 	memcpy(((char *)dsp_msg) + sizeof(struct aw_msg_hdr),
170 				(char *)&is_enable, sizeof(int32_t));
171 
172 	ret = aw_mtk_write_data_to_dsp(msg_id, (void *)dsp_msg,
173 				sizeof(struct aw_msg_hdr) + sizeof(int32_t));
174 	if (ret < 0) {
175 		aw_dev_err(aw_dev->dev, " write data failed");
176 		kfree(dsp_msg);
177 		dsp_msg = NULL;
178 		return ret;
179 	}
180 
181 	kfree(dsp_msg);
182 	dsp_msg = NULL;
183 	return 0;
184 }
185 #else
aw_check_dsp_ready(void)186 static int aw_check_dsp_ready(void)
187 {
188 	int ret;
189 
190 	ret = afe_get_topology(AW_RX_PORT_ID);
191 
192 	pr_debug("topo_id 0x%x ", ret);
193 
194 	if (ret != AW_RX_TOPO_ID)
195 		return false;
196 	else
197 		return true;
198 }
199 
aw_qcom_write_data_to_dsp(uint32_t msg_id,void * data,int size)200 static int aw_qcom_write_data_to_dsp(uint32_t msg_id, void *data, int size)
201 {
202 	int ret;
203 	int try = 0;
204 
205 	while (try < AW_DSP_TRY_TIME) {
206 		if (aw_check_dsp_ready()) {
207 			ret = aw_send_afe_cal_apr(msg_id, data, size, true);
208 			return ret;
209 		} else {
210 			try++;
211 			usleep_range(AW_10000_US, AW_10000_US + 10);
212 			pr_info("%s: afe topo not ready try again\n", __func__);
213 		}
214 	}
215 
216 	return -EINVAL;
217 }
218 
aw_qcom_read_data_from_dsp(uint32_t msg_id,void * data,int size)219 static int aw_qcom_read_data_from_dsp(uint32_t msg_id, void *data, int size)
220 {
221 	int ret;
222 	int try = 0;
223 
224 	while (try < AW_DSP_TRY_TIME) {
225 		if (aw_check_dsp_ready()) {
226 			ret = aw_send_afe_cal_apr(msg_id, data, size, false);
227 			return ret;
228 		} else {
229 			try++;
230 			usleep_range(AW_10000_US, AW_10000_US + 10);
231 			pr_info("%s: afe topo not ready try again\n", __func__);
232 		}
233 	}
234 	return -EINVAL;
235 }
236 
aw_qcom_set_spin_angle(struct aw_device * aw_dev,uint32_t spin_angle)237 static int aw_qcom_set_spin_angle(struct aw_device *aw_dev,
238 					uint32_t spin_angle)
239 {
240 	int ret;
241 
242 	ret = aw_qcom_write_data_to_dsp(AW_MSG_ID_SPIN, &spin_angle, sizeof(uint32_t));
243 	if (ret)
244 		aw_dev_err(aw_dev->dev, "write spin angle to dsp failed");
245 	else
246 		aw_dev_info(aw_dev->dev, "write spin angle to dsp successful");
247 
248 	return ret;
249 }
250 
aw_qcom_get_spin_angle(uint32_t * spin_angle,int size)251 static int aw_qcom_get_spin_angle(uint32_t *spin_angle, int size)
252 {
253 	int ret;
254 
255 	ret = aw_qcom_read_data_from_dsp(AW_MSG_ID_SPIN, spin_angle, size);
256 	if (ret)
257 		pr_err("%s: get spin angle failed\n", __func__);
258 	else
259 		pr_info("%s: get spin angle successful\n", __func__);
260 
261 	return ret;
262 }
263 
aw_qcom_set_mixer_en(struct aw_device * aw_dev,uint32_t msg_id,int32_t is_enable)264 static int aw_qcom_set_mixer_en(struct aw_device *aw_dev,
265 						uint32_t msg_id, int32_t is_enable)
266 {
267 	int32_t *dsp_msg;
268 	int ret = 0;
269 	int msg_len = (int)(sizeof(struct aw_msg_hdr) + sizeof(int32_t));
270 
271 	dsp_msg = kzalloc(msg_len, GFP_KERNEL);
272 	if (!dsp_msg) {
273 		aw_dev_err(aw_dev->dev, "kzalloc dsp_msg error");
274 		return -ENOMEM;
275 
276 	}
277 	dsp_msg[0] = AW_DSP_MSG_TYPE_DATA;
278 	dsp_msg[1] = AW_INLINE_ID_AUDIO_MIX;
279 	dsp_msg[2] = AW_DSP_MSG_HDR_VER;
280 
281 	memcpy(dsp_msg + (sizeof(struct aw_msg_hdr) / sizeof(int32_t)),
282 		(char *)&is_enable, sizeof(int32_t));
283 
284 	ret = aw_qcom_write_data_to_dsp(msg_id, (void *)dsp_msg, msg_len);
285 	if (ret < 0) {
286 		aw_dev_err(aw_dev->dev, "write data to dsp failed");
287 		kfree(dsp_msg);
288 		return ret;
289 	}
290 
291 	aw_dev_dbg(aw_dev->dev, "write data[%d] to dsp success", msg_len);
292 	kfree(dsp_msg);
293 	return 0;
294 }
295 #endif
296 
297 /***********************************spin_angle**********************************/
aw_set_adsp_spin_angle(struct aw_device * aw_dev,uint32_t spin_angle)298 static int aw_set_adsp_spin_angle(struct aw_device *aw_dev, uint32_t spin_angle)
299 {
300 	if (spin_angle >= AW_SPIN_MAX) {
301 		aw_dev_err(aw_dev->dev, "spin_angle:%d not support",
302 				spin_angle);
303 		return -EINVAL;
304 	}
305 
306 #ifdef AW_MTK_PLATFORM_SPIN
307 	return aw_mtk_set_spin_angle(aw_dev, spin_angle);
308 #else
309 	return aw_qcom_set_spin_angle(aw_dev, spin_angle);
310 #endif
311 }
312 
aw_get_adsp_spin_angle(uint32_t * spin_angle)313 static void aw_get_adsp_spin_angle(uint32_t *spin_angle)
314 {
315 #ifdef AW_MTK_PLATFORM_SPIN
316 	aw_mtk_get_spin_angle(spin_angle, sizeof(uint32_t));
317 #else
318 	aw_qcom_get_spin_angle(spin_angle, sizeof(uint32_t));
319 #endif
320 }
321 /*******************************************************************************/
322 
323 /**********************************mixer_status*********************************/
aw_set_mixer_en(struct aw_device * aw_dev,int32_t is_enable)324 static int aw_set_mixer_en(struct aw_device *aw_dev, int32_t is_enable)
325 {
326 	int ret;
327 	uint32_t msg_id;
328 
329 	ret = aw_get_msg_id(aw_dev->channel, &msg_id);
330 	if (ret < 0) {
331 		aw_dev_err(aw_dev->dev, "get msg_num failed");
332 		return ret;
333 	}
334 
335 #ifdef AW_MTK_PLATFORM_SPIN
336 	ret = aw_mtk_set_mixer_en(aw_dev, msg_id, is_enable);
337 #else
338 	ret = aw_qcom_set_mixer_en(aw_dev, msg_id, is_enable);
339 #endif
340 	if (ret)
341 		aw_dev_err(aw_dev->dev, "set mixer status failed");
342 
343 	return ret;
344 }
345 
aw_hold_reg_spin_st(struct aw_spin_desc * spin_desc)346 int aw_hold_reg_spin_st(struct aw_spin_desc *spin_desc)
347 {
348 	struct aw_device *aw_dev = container_of(spin_desc,
349 						struct aw_device, spin_desc);
350 	uint16_t reg_val;
351 
352 	if (aw_dev == NULL) {
353 		aw_pr_err("aw_dev is NULL");
354 		return -EINVAL;
355 	}
356 
357 	mutex_lock(&g_aw_spin_lock);
358 	if ((g_spin_mode == AW_REG_SPIN_MODE) ||
359 		(g_spin_mode == AW_REG_MIXER_SPIN_MODE)) {
360 		/*set rx*/
361 		aw_dev->ops.aw_reg_read(aw_dev,
362 			aw_dev->chansel_desc.rxchan_reg, &reg_val);
363 		reg_val &= aw_dev->chansel_desc.rxchan_mask;
364 		reg_val |= spin_desc->spin_table[g_spin_angle].rx_val;
365 		aw_dev->ops.aw_reg_write(aw_dev,
366 			aw_dev->chansel_desc.rxchan_reg, reg_val);
367 
368 		/*set tx*/
369 		aw_dev->ops.aw_reg_read(aw_dev,
370 			aw_dev->chansel_desc.txchan_reg, &reg_val);
371 		reg_val &= aw_dev->chansel_desc.txchan_mask;
372 		reg_val |= spin_desc->spin_table[g_spin_angle].tx_val;
373 		aw_dev->ops.aw_reg_write(aw_dev,
374 			aw_dev->chansel_desc.txchan_reg, reg_val);
375 	}
376 	mutex_unlock(&g_aw_spin_lock);
377 
378 	return 0;
379 }
380 
aw_check_spin_mode(struct aw_spin_desc * spin_desc)381 int aw_check_spin_mode(struct aw_spin_desc *spin_desc)
382 {
383 	struct list_head *pos = NULL;
384 	struct list_head *dev_list = NULL;
385 	struct aw_device *local_pa = NULL;
386 	int ret = -1;
387 	int spin_mode = AW_SPIN_OFF_MODE;
388 	struct aw_device *aw_dev = container_of(spin_desc,
389 						struct aw_device, spin_desc);
390 	struct aw883xx *aw883xx = (struct aw883xx *)aw_dev->private_data;
391 
392 	if (g_spin_mode == AW_SPIN_OFF_MODE) {
393 		aw883xx->spin_flag = AW_SPIN_OFF;
394 		return 0;
395 	}
396 
397 	ret = aw_dev_get_list_head(&dev_list);
398 	if (ret) {
399 		aw_pr_err("get dev list failed");
400 		return ret;
401 	}
402 
403 	list_for_each(pos, dev_list) {
404 		local_pa = container_of(pos, struct aw_device, list_node);
405 		spin_mode = local_pa->spin_desc.spin_mode;
406 		if (g_spin_mode != spin_mode) {
407 			aw_pr_err("dev[%d] spin mode:%d not equal g_spin_mode:%d, check failed",
408 				local_pa->channel, spin_mode, g_spin_mode);
409 			aw883xx->spin_flag = AW_SPIN_OFF;
410 			return -EINVAL;
411 		}
412 	}
413 	aw883xx->spin_flag = AW_SPIN_ON;
414 
415 	return 0;
416 }
417 
aw_hold_dsp_spin_st(struct aw_spin_desc * spin_desc)418 int aw_hold_dsp_spin_st(struct aw_spin_desc *spin_desc)
419 {
420 	struct aw_device *aw_dev = container_of(spin_desc,
421 						struct aw_device, spin_desc);
422 	int ret = -1;
423 
424 	if (aw_dev == NULL) {
425 		aw_pr_err("aw_dev is NULL");
426 		return -EINVAL;
427 	}
428 
429 	if (aw_dev->channel == 0) {
430 		if (g_spin_mode == AW_ADSP_SPIN_MODE) {
431 			ret = aw_set_adsp_spin_angle(aw_dev,
432 							g_spin_angle);
433 			if (ret < 0)
434 				return ret;
435 		}
436 	}
437 
438 	return ret;
439 }
440 
aw_set_channal_mode(struct aw_device * aw_pa,uint32_t spin_angle)441 static int aw_set_channal_mode(struct aw_device *aw_pa,
442 					uint32_t spin_angle)
443 {
444 	int ret;
445 	struct aw_chansel_desc *chansel_desc = &aw_pa->chansel_desc;
446 	struct aw_spin_ch *spin_ch = &aw_pa->spin_desc.spin_table[spin_angle];
447 	ret = aw_pa->ops.aw_reg_write_bits(aw_pa, chansel_desc->rxchan_reg,
448 				chansel_desc->rxchan_mask, spin_ch->rx_val);
449 	if (ret < 0) {
450 		aw_dev_err(aw_pa->dev, "set rx failed");
451 		return ret;
452 	}
453 
454 	ret = aw_pa->ops.aw_reg_write_bits(aw_pa, chansel_desc->txchan_reg,
455 				chansel_desc->txchan_mask, spin_ch->tx_val);
456 	if (ret < 0) {
457 		aw_dev_err(aw_pa->dev, "set tx failed");
458 		return ret;
459 	}
460 
461 	aw_dev_dbg(aw_pa->dev, "set channel mode done!");
462 
463 	return 0;
464 }
465 
aw_set_reg_spin_angle(struct aw883xx * aw883xx,uint32_t spin_angle)466 static int aw_set_reg_spin_angle(struct aw883xx *aw883xx, uint32_t spin_angle)
467 {
468 	struct list_head *pos = NULL;
469 	struct list_head *dev_list = NULL;
470 	struct aw_device *local_pa = NULL;
471 	int ret;
472 
473 	if (spin_angle >= ARRAY_SIZE(aw_spin)) {
474 		aw_dev_err(aw883xx->dev, "spin_angle:%d not support",
475 					spin_angle);
476 		return -EINVAL;
477 	}
478 
479 	ret = aw_dev_get_list_head(&dev_list);
480 	if (ret) {
481 		aw_dev_err(aw883xx->dev, "get dev list failed");
482 		return ret;
483 	}
484 
485 	list_for_each(pos, dev_list) {
486 		local_pa = container_of(pos, struct aw_device, list_node);
487 		ret = aw_set_channal_mode(local_pa, spin_angle);
488 		if (ret < 0) {
489 			aw_dev_err(aw883xx->dev, "set channal mode failed");
490 			return ret;
491 		}
492 	}
493 
494 	return 0;
495 }
496 
aw_set_reg_mixer_spin_angle(struct aw883xx * aw883xx,uint32_t spin_angle)497 static int aw_set_reg_mixer_spin_angle(struct aw883xx *aw883xx, uint32_t spin_angle)
498 {
499 	int ret;
500 
501 	if (spin_angle >= ARRAY_SIZE(aw_spin)) {
502 		aw_dev_err(aw883xx->dev, "spin_angle:%d not support",
503 					spin_angle);
504 		return -EINVAL;
505 	}
506 
507 	ret = aw_set_mixer_en(aw883xx->aw_pa, AW_AUDIO_MIX_ENABLE);
508 	if (ret)
509 		return ret;
510 
511 	usleep_range(AW_100000_US, AW_100000_US + 10);
512 
513 	aw_set_reg_spin_angle(aw883xx, spin_angle);
514 
515 	ret = aw_set_mixer_en(aw883xx->aw_pa, AW_AUDIO_MIX_DISABLE);
516 	if (ret)
517 		return ret;
518 
519 	return ret;
520 }
521 
aw_get_reg_spin_angle(uint32_t * spin_angle)522 static void aw_get_reg_spin_angle(uint32_t *spin_angle)
523 {
524 	*spin_angle = g_spin_angle;
525 
526 	pr_debug("%s: get spin:%s\n", __func__, aw_spin[g_spin_angle]);
527 }
528 
aw_set_spin_angle(struct aw883xx * aw883xx,uint32_t spin_angle)529 static int aw_set_spin_angle(struct aw883xx *aw883xx, uint32_t spin_angle)
530 {
531 	switch (g_spin_mode) {
532 	case AW_REG_SPIN_MODE:
533 		return aw_set_reg_spin_angle(aw883xx, spin_angle);
534 	case AW_ADSP_SPIN_MODE:
535 		return aw_set_adsp_spin_angle(aw883xx->aw_pa, spin_angle);
536 	case AW_REG_MIXER_SPIN_MODE:
537 		return aw_set_reg_mixer_spin_angle(aw883xx, spin_angle);
538 	default:
539 		aw_pr_err("unsupported spin mode:%d", g_spin_mode);
540 		return -EINVAL;
541 	}
542 }
543 
aw_set_spin_mode(int mode)544 static void aw_set_spin_mode(int mode)
545 {
546 	g_spin_mode = mode;
547 }
548 
aw_set_spin(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)549 static int aw_set_spin(struct snd_kcontrol *kcontrol,
550 	struct snd_ctl_elem_value *ucontrol)
551 {
552 	struct aw883xx *aw883xx = (struct aw883xx *)kcontrol->private_value;
553 	uint32_t ctrl_value;
554 	int ret;
555 
556 	aw_dev_dbg(aw883xx->dev, "ucontrol->value.integer.value[0]=%ld",
557 			ucontrol->value.integer.value[0]);
558 
559 	if (aw883xx->spin_flag == AW_SPIN_OFF) {
560 		aw_dev_dbg(aw883xx->dev, "spin func not enable");
561 		return 0;
562 	}
563 
564 	ctrl_value = ucontrol->value.integer.value[0];
565 
566 	mutex_lock(&g_aw_spin_lock);
567 	if (aw883xx->pstream == AW883XX_STREAM_OPEN) {
568 		ret = aw_set_spin_angle(aw883xx, ctrl_value);
569 		if (ret < 0)
570 			aw_dev_err(aw883xx->dev, "set spin error, ret=%d\n",
571 				ret);
572 	} else {
573 		if ((g_spin_mode == AW_REG_SPIN_MODE) || (g_spin_mode == AW_REG_MIXER_SPIN_MODE))
574 			aw_set_reg_spin_angle(aw883xx, ctrl_value);
575 		else
576 			aw_dev_info(aw883xx->dev, "stream no start only record spin angle");
577 	}
578 	g_spin_angle = ctrl_value;
579 	mutex_unlock(&g_aw_spin_lock);
580 
581 	return 0;
582 }
583 
aw_get_spin_angle(uint32_t * spin_angle)584 static void aw_get_spin_angle(uint32_t *spin_angle)
585 {
586 	if ((g_spin_mode == AW_REG_SPIN_MODE) || (g_spin_mode == AW_REG_MIXER_SPIN_MODE))
587 		aw_get_reg_spin_angle(spin_angle);
588 	else if (g_spin_mode == AW_ADSP_SPIN_MODE)
589 		aw_get_adsp_spin_angle(spin_angle);
590 }
591 
aw_get_spin(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)592 static int aw_get_spin(struct snd_kcontrol *kcontrol,
593 	struct snd_ctl_elem_value *ucontrol)
594 {
595 	struct aw883xx *aw883xx = (struct aw883xx *)kcontrol->private_value;
596 	uint32_t ctrl_value = 0;
597 
598 	mutex_lock(&g_aw_spin_lock);
599 	if (aw883xx->pstream == AW883XX_STREAM_OPEN) {
600 		aw_get_spin_angle(&ctrl_value);
601 		ucontrol->value.integer.value[0] = ctrl_value;
602 	} else {
603 		ucontrol->value.integer.value[0] = g_spin_angle;
604 		aw_dev_dbg(aw883xx->dev, "no stream, use record value");
605 	}
606 	mutex_unlock(&g_aw_spin_lock);
607 
608 	return 0;
609 }
610 
aw_spin_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)611 static int aw_spin_info(struct snd_kcontrol *kcontrol,
612 			struct snd_ctl_elem_info *uinfo)
613 {
614 	struct aw883xx *aw883xx = (struct aw883xx *)kcontrol->private_value;
615 	int count = 0;
616 
617 	if (aw883xx == NULL) {
618 		aw_pr_err("get struct aw883xx failed");
619 		return -EINVAL;
620 	}
621 
622 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
623 	uinfo->count = 1;
624 	count = ARRAY_SIZE(aw_spin);
625 
626 	uinfo->value.enumerated.items = count;
627 		if (uinfo->value.enumerated.item >= count)
628 			uinfo->value.enumerated.item = count - 1;
629 
630 	strlcpy(uinfo->value.enumerated.name,
631 			aw_spin[uinfo->value.enumerated.item],
632 			strlen(aw_spin[uinfo->value.enumerated.item]) + 1);
633 
634 	return 0;
635 }
636 
aw_spin_control_create(struct aw883xx * aw883xx)637 static int aw_spin_control_create(struct aw883xx *aw883xx)
638 {
639 	int kcontrol_num = 1;
640 	struct snd_kcontrol_new *aw_spin_control = NULL;
641 	char *kctl_name = NULL;
642 
643 	aw_spin_control = devm_kzalloc(aw883xx->codec->dev,
644 			sizeof(struct snd_kcontrol_new) * 1, GFP_KERNEL);
645 	if (aw_spin_control == NULL) {
646 		aw_dev_err(aw883xx->codec->dev, "kcontrol malloc failed!");
647 		return -ENOMEM;
648 	}
649 
650 	kctl_name = devm_kzalloc(aw883xx->codec->dev, AW_NAME_BUF_MAX, GFP_KERNEL);
651 	if (kctl_name == NULL)
652 		return -ENOMEM;
653 
654 	snprintf(kctl_name, AW_NAME_BUF_MAX, "aw_spin_switch");
655 
656 	aw_spin_control[0].name = kctl_name;
657 	aw_spin_control[0].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
658 	aw_spin_control[0].info = aw_spin_info;
659 	aw_spin_control[0].get = aw_get_spin;
660 	aw_spin_control[0].put = aw_set_spin;
661 	aw_spin_control[0].private_value = (unsigned long)aw883xx;
662 
663 	kctl_name = devm_kzalloc(aw883xx->codec->dev, AW_NAME_BUF_MAX, GFP_KERNEL);
664 	if (!kctl_name)
665 		return -ENOMEM;
666 
667 	aw883xx->codec_ops->add_codec_controls(aw883xx->codec,
668 		aw_spin_control, kcontrol_num);
669 
670 	return 0;
671 }
672 
aw_add_spin_controls(void * aw_dev)673 void aw_add_spin_controls(void *aw_dev)
674 {
675 	struct aw883xx *aw883xx = (struct aw883xx *)aw_dev;
676 
677 	if (aw883xx->aw_pa->spin_desc.spin_mode != AW_SPIN_OFF_MODE)
678 		aw_spin_control_create(aw883xx);
679 }
680 
aw_parse_spin_table_dt(struct aw_device * aw_dev,struct device_node * np)681 static int aw_parse_spin_table_dt(struct aw_device *aw_dev,
682 					struct device_node *np)
683 {
684 	int ret = -1;
685 	const char *str_data = NULL;
686 	char spin_table_str[AW_SPIN_MAX] = { 0 };
687 	int i, spin_count = 0;
688 
689 	ret = of_property_read_string(np, "spin-data", &str_data);
690 	if (ret < 0) {
691 		aw_dev_err(aw_dev->dev, "get spin_data failed, close spin function");
692 		return ret;
693 	}
694 
695 	ret = sscanf(str_data, "%c %c %c %c",
696 				&spin_table_str[AW_SPIN_0], &spin_table_str[AW_SPIN_90],
697 				&spin_table_str[AW_SPIN_180], &spin_table_str[AW_SPIN_270]);
698 	if  (ret != AW_SPIN_MAX) {
699 		aw_dev_err(aw_dev->dev, "unsupported str:%s, close spin function",
700 				str_data);
701 		return -EINVAL;
702 	}
703 
704 	for (i = 0; i < AW_SPIN_MAX; i++) {
705 		if (spin_table_str[i] == 'l' || spin_table_str[i] == 'L') {
706 			aw_dev->spin_desc.spin_table[i].rx_val = aw_dev->chansel_desc.rx_left;
707 			aw_dev->spin_desc.spin_table[i].tx_val = aw_dev->chansel_desc.tx_left;
708 			spin_count++;
709 		} else if (spin_table_str[i] == 'r' || spin_table_str[i] == 'R') {
710 			aw_dev->spin_desc.spin_table[i].rx_val = aw_dev->chansel_desc.rx_right;
711 			aw_dev->spin_desc.spin_table[i].tx_val = aw_dev->chansel_desc.tx_right;
712 			spin_count++;
713 		} else {
714 			aw_dev_err(aw_dev->dev, "unsupported str:%s, close spin function",
715 				str_data);
716 			return -EINVAL;
717 		}
718 	}
719 
720 	if (spin_count != ARRAY_SIZE(aw_spin)) {
721 		aw_dev_err(aw_dev->dev, "get spin_data failed, spin_count:%d", spin_count);
722 		return -EINVAL;
723 	}
724 
725 	return 0;
726 }
727 
aw_parse_spin_mode_dt(struct aw_device * aw_dev)728 static int aw_parse_spin_mode_dt(struct aw_device *aw_dev)
729 {
730 	int ret = -1;
731 	const char *spin_mode = NULL;
732 	int mode;
733 	struct device_node *np = aw_dev->dev->of_node;
734 
735 	ret = of_property_read_string(np, "spin-mode", &spin_mode);
736 	if (ret < 0) {
737 		aw_dev_info(aw_dev->dev,
738 			"spin-mode get failed, spin switch off");
739 		aw_dev->spin_desc.spin_mode = AW_SPIN_OFF_MODE;
740 		return 0;
741 	}
742 
743 	if (!strcmp(spin_mode, "dsp_spin"))
744 		mode = AW_ADSP_SPIN_MODE;
745 	else if (!strcmp(spin_mode, "reg_spin"))
746 		mode = AW_REG_SPIN_MODE;
747 	else if (!strcmp(spin_mode, "reg_mixer_spin"))
748 		mode = AW_REG_MIXER_SPIN_MODE;
749 	else
750 		mode = AW_SPIN_OFF_MODE;
751 
752 	aw_dev->spin_desc.spin_mode = mode;
753 
754 	aw_set_spin_mode(mode);
755 
756 	if ((mode == AW_REG_SPIN_MODE) || (mode == AW_REG_MIXER_SPIN_MODE)) {
757 		ret = aw_parse_spin_table_dt(aw_dev, np);
758 		if (ret < 0) {
759 			aw_dev->spin_desc.spin_mode = AW_SPIN_OFF_MODE;
760 			aw_dev_err(aw_dev->dev,
761 				"spin-table get failed, ret = %d", ret);
762 			return ret;
763 		}
764 	}
765 
766 	aw_dev_info(aw_dev->dev, "spin mode is %d", mode);
767 
768 	return 0;
769 }
770 
aw_spin_init(struct aw_spin_desc * spin_desc)771 void aw_spin_init(struct aw_spin_desc *spin_desc)
772 {
773 	struct aw_device *aw_dev = container_of(spin_desc,
774 					struct aw_device, spin_desc);
775 
776 	aw_parse_spin_mode_dt(aw_dev);
777 }
778 
779