xref: /OK3568_Linux_fs/kernel/sound/soc/mediatek/common/mtk-btcvsd.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Mediatek ALSA BT SCO CVSD/MSBC Driver
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright (c) 2019 MediaTek Inc.
6*4882a593Smuzhiyun // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/of_address.h>
11*4882a593Smuzhiyun #include <linux/sched/clock.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <sound/soc.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define BTCVSD_SND_NAME "mtk-btcvsd-snd"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define BT_CVSD_TX_NREADY	BIT(21)
18*4882a593Smuzhiyun #define BT_CVSD_RX_READY	BIT(22)
19*4882a593Smuzhiyun #define BT_CVSD_TX_UNDERFLOW	BIT(23)
20*4882a593Smuzhiyun #define BT_CVSD_RX_OVERFLOW	BIT(24)
21*4882a593Smuzhiyun #define BT_CVSD_INTERRUPT	BIT(31)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define BT_CVSD_CLEAR \
24*4882a593Smuzhiyun 	(BT_CVSD_TX_NREADY | BT_CVSD_RX_READY | BT_CVSD_TX_UNDERFLOW |\
25*4882a593Smuzhiyun 	 BT_CVSD_RX_OVERFLOW | BT_CVSD_INTERRUPT)
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* TX */
28*4882a593Smuzhiyun #define SCO_TX_ENCODE_SIZE (60)
29*4882a593Smuzhiyun /* 18 = 6 * 180 / SCO_TX_ENCODE_SIZE */
30*4882a593Smuzhiyun #define SCO_TX_PACKER_BUF_NUM (18)
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /* RX */
33*4882a593Smuzhiyun #define SCO_RX_PLC_SIZE (30)
34*4882a593Smuzhiyun #define SCO_RX_PACKER_BUF_NUM (64)
35*4882a593Smuzhiyun #define SCO_RX_PACKET_MASK (0x3F)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define SCO_CVSD_PACKET_VALID_SIZE 2
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define SCO_PACKET_120 120
40*4882a593Smuzhiyun #define SCO_PACKET_180 180
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define BTCVSD_RX_PACKET_SIZE (SCO_RX_PLC_SIZE + SCO_CVSD_PACKET_VALID_SIZE)
43*4882a593Smuzhiyun #define BTCVSD_TX_PACKET_SIZE (SCO_TX_ENCODE_SIZE)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #define BTCVSD_RX_BUF_SIZE (BTCVSD_RX_PACKET_SIZE * SCO_RX_PACKER_BUF_NUM)
46*4882a593Smuzhiyun #define BTCVSD_TX_BUF_SIZE (BTCVSD_TX_PACKET_SIZE * SCO_TX_PACKER_BUF_NUM)
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun enum bt_sco_state {
49*4882a593Smuzhiyun 	BT_SCO_STATE_IDLE,
50*4882a593Smuzhiyun 	BT_SCO_STATE_RUNNING,
51*4882a593Smuzhiyun 	BT_SCO_STATE_ENDING,
52*4882a593Smuzhiyun 	BT_SCO_STATE_LOOPBACK,
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun enum bt_sco_direct {
56*4882a593Smuzhiyun 	BT_SCO_DIRECT_BT2ARM,
57*4882a593Smuzhiyun 	BT_SCO_DIRECT_ARM2BT,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun enum bt_sco_packet_len {
61*4882a593Smuzhiyun 	BT_SCO_CVSD_30 = 0,
62*4882a593Smuzhiyun 	BT_SCO_CVSD_60,
63*4882a593Smuzhiyun 	BT_SCO_CVSD_90,
64*4882a593Smuzhiyun 	BT_SCO_CVSD_120,
65*4882a593Smuzhiyun 	BT_SCO_CVSD_10,
66*4882a593Smuzhiyun 	BT_SCO_CVSD_20,
67*4882a593Smuzhiyun 	BT_SCO_CVSD_MAX,
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun enum BT_SCO_BAND {
71*4882a593Smuzhiyun 	BT_SCO_NB,
72*4882a593Smuzhiyun 	BT_SCO_WB,
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun struct mtk_btcvsd_snd_hw_info {
76*4882a593Smuzhiyun 	unsigned int num_valid_addr;
77*4882a593Smuzhiyun 	unsigned long bt_sram_addr[20];
78*4882a593Smuzhiyun 	unsigned int packet_length;
79*4882a593Smuzhiyun 	unsigned int packet_num;
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun struct mtk_btcvsd_snd_stream {
83*4882a593Smuzhiyun 	struct snd_pcm_substream *substream;
84*4882a593Smuzhiyun 	int stream;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	enum bt_sco_state state;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	unsigned int packet_size;
89*4882a593Smuzhiyun 	unsigned int buf_size;
90*4882a593Smuzhiyun 	u8 temp_packet_buf[SCO_PACKET_180];
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	int packet_w;
93*4882a593Smuzhiyun 	int packet_r;
94*4882a593Smuzhiyun 	snd_pcm_uframes_t prev_frame;
95*4882a593Smuzhiyun 	int prev_packet_idx;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	unsigned int xrun:1;
98*4882a593Smuzhiyun 	unsigned int timeout:1;
99*4882a593Smuzhiyun 	unsigned int mute:1;
100*4882a593Smuzhiyun 	unsigned int trigger_start:1;
101*4882a593Smuzhiyun 	unsigned int wait_flag:1;
102*4882a593Smuzhiyun 	unsigned int rw_cnt;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	unsigned long long time_stamp;
105*4882a593Smuzhiyun 	unsigned long long buf_data_equivalent_time;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_hw_info buffer_info;
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun struct mtk_btcvsd_snd {
111*4882a593Smuzhiyun 	struct device *dev;
112*4882a593Smuzhiyun 	int irq_id;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	struct regmap *infra;
115*4882a593Smuzhiyun 	void __iomem *bt_pkv_base;
116*4882a593Smuzhiyun 	void __iomem *bt_sram_bank2_base;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	unsigned int infra_misc_offset;
119*4882a593Smuzhiyun 	unsigned int conn_bt_cvsd_mask;
120*4882a593Smuzhiyun 	unsigned int cvsd_mcu_read_offset;
121*4882a593Smuzhiyun 	unsigned int cvsd_mcu_write_offset;
122*4882a593Smuzhiyun 	unsigned int cvsd_packet_indicator;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	u32 *bt_reg_pkt_r;
125*4882a593Smuzhiyun 	u32 *bt_reg_pkt_w;
126*4882a593Smuzhiyun 	u32 *bt_reg_ctl;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	unsigned int irq_disabled:1;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	spinlock_t tx_lock;	/* spinlock for bt tx stream control */
131*4882a593Smuzhiyun 	spinlock_t rx_lock;	/* spinlock for bt rx stream control */
132*4882a593Smuzhiyun 	wait_queue_head_t tx_wait;
133*4882a593Smuzhiyun 	wait_queue_head_t rx_wait;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_stream *tx;
136*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_stream *rx;
137*4882a593Smuzhiyun 	u8 tx_packet_buf[BTCVSD_TX_BUF_SIZE];
138*4882a593Smuzhiyun 	u8 rx_packet_buf[BTCVSD_RX_BUF_SIZE];
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	enum BT_SCO_BAND band;
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun struct mtk_btcvsd_snd_time_buffer_info {
144*4882a593Smuzhiyun 	unsigned long long data_count_equi_time;
145*4882a593Smuzhiyun 	unsigned long long time_stamp_us;
146*4882a593Smuzhiyun };
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun static const unsigned int btsco_packet_valid_mask[BT_SCO_CVSD_MAX][6] = {
149*4882a593Smuzhiyun 	{0x1, 0x1 << 1, 0x1 << 2, 0x1 << 3, 0x1 << 4, 0x1 << 5},
150*4882a593Smuzhiyun 	{0x1, 0x1, 0x2, 0x2, 0x4, 0x4},
151*4882a593Smuzhiyun 	{0x1, 0x1, 0x1, 0x2, 0x2, 0x2},
152*4882a593Smuzhiyun 	{0x1, 0x1, 0x1, 0x1, 0x0, 0x0},
153*4882a593Smuzhiyun 	{0x7, 0x7 << 3, 0x7 << 6, 0x7 << 9, 0x7 << 12, 0x7 << 15},
154*4882a593Smuzhiyun 	{0x3, 0x3 << 1, 0x3 << 3, 0x3 << 4, 0x3 << 6, 0x3 << 7},
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun static const unsigned int btsco_packet_info[BT_SCO_CVSD_MAX][4] = {
158*4882a593Smuzhiyun 	{30, 6, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,
159*4882a593Smuzhiyun 	 SCO_PACKET_180 / SCO_RX_PLC_SIZE},
160*4882a593Smuzhiyun 	{60, 3, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,
161*4882a593Smuzhiyun 	 SCO_PACKET_180 / SCO_RX_PLC_SIZE},
162*4882a593Smuzhiyun 	{90, 2, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,
163*4882a593Smuzhiyun 	 SCO_PACKET_180 / SCO_RX_PLC_SIZE},
164*4882a593Smuzhiyun 	{120, 1, SCO_PACKET_120 / SCO_TX_ENCODE_SIZE,
165*4882a593Smuzhiyun 	 SCO_PACKET_120 / SCO_RX_PLC_SIZE},
166*4882a593Smuzhiyun 	{10, 18, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,
167*4882a593Smuzhiyun 	 SCO_PACKET_180 / SCO_RX_PLC_SIZE},
168*4882a593Smuzhiyun 	{20, 9, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,
169*4882a593Smuzhiyun 	 SCO_PACKET_180 / SCO_RX_PLC_SIZE},
170*4882a593Smuzhiyun };
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static const u8 table_msbc_silence[SCO_PACKET_180] = {
173*4882a593Smuzhiyun 	0x01, 0x38, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,
174*4882a593Smuzhiyun 	0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d,
175*4882a593Smuzhiyun 	0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7,
176*4882a593Smuzhiyun 	0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd,
177*4882a593Smuzhiyun 	0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
178*4882a593Smuzhiyun 	0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00,
179*4882a593Smuzhiyun 	0x01, 0xc8, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,
180*4882a593Smuzhiyun 	0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d,
181*4882a593Smuzhiyun 	0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7,
182*4882a593Smuzhiyun 	0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd,
183*4882a593Smuzhiyun 	0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
184*4882a593Smuzhiyun 	0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00,
185*4882a593Smuzhiyun 	0x01, 0xf8, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,
186*4882a593Smuzhiyun 	0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d,
187*4882a593Smuzhiyun 	0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7,
188*4882a593Smuzhiyun 	0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd,
189*4882a593Smuzhiyun 	0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
190*4882a593Smuzhiyun 	0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00
191*4882a593Smuzhiyun };
192*4882a593Smuzhiyun 
mtk_btcvsd_snd_irq_enable(struct mtk_btcvsd_snd * bt)193*4882a593Smuzhiyun static void mtk_btcvsd_snd_irq_enable(struct mtk_btcvsd_snd *bt)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	regmap_update_bits(bt->infra, bt->infra_misc_offset,
196*4882a593Smuzhiyun 			   bt->conn_bt_cvsd_mask, 0);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
mtk_btcvsd_snd_irq_disable(struct mtk_btcvsd_snd * bt)199*4882a593Smuzhiyun static void mtk_btcvsd_snd_irq_disable(struct mtk_btcvsd_snd *bt)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	regmap_update_bits(bt->infra, bt->infra_misc_offset,
202*4882a593Smuzhiyun 			   bt->conn_bt_cvsd_mask, bt->conn_bt_cvsd_mask);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
mtk_btcvsd_snd_set_state(struct mtk_btcvsd_snd * bt,struct mtk_btcvsd_snd_stream * bt_stream,int state)205*4882a593Smuzhiyun static void mtk_btcvsd_snd_set_state(struct mtk_btcvsd_snd *bt,
206*4882a593Smuzhiyun 				     struct mtk_btcvsd_snd_stream *bt_stream,
207*4882a593Smuzhiyun 				     int state)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), stream %d, state %d, tx->state %d, rx->state %d, irq_disabled %d\n",
210*4882a593Smuzhiyun 		__func__,
211*4882a593Smuzhiyun 		bt_stream->stream, state,
212*4882a593Smuzhiyun 		bt->tx->state, bt->rx->state, bt->irq_disabled);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	bt_stream->state = state;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	if (bt->tx->state == BT_SCO_STATE_IDLE &&
217*4882a593Smuzhiyun 	    bt->rx->state == BT_SCO_STATE_IDLE) {
218*4882a593Smuzhiyun 		if (!bt->irq_disabled) {
219*4882a593Smuzhiyun 			disable_irq(bt->irq_id);
220*4882a593Smuzhiyun 			mtk_btcvsd_snd_irq_disable(bt);
221*4882a593Smuzhiyun 			bt->irq_disabled = 1;
222*4882a593Smuzhiyun 		}
223*4882a593Smuzhiyun 	} else {
224*4882a593Smuzhiyun 		if (bt->irq_disabled) {
225*4882a593Smuzhiyun 			enable_irq(bt->irq_id);
226*4882a593Smuzhiyun 			mtk_btcvsd_snd_irq_enable(bt);
227*4882a593Smuzhiyun 			bt->irq_disabled = 0;
228*4882a593Smuzhiyun 		}
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
mtk_btcvsd_snd_tx_init(struct mtk_btcvsd_snd * bt)232*4882a593Smuzhiyun static int mtk_btcvsd_snd_tx_init(struct mtk_btcvsd_snd *bt)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	memset(bt->tx, 0, sizeof(*bt->tx));
235*4882a593Smuzhiyun 	memset(bt->tx_packet_buf, 0, sizeof(bt->tx_packet_buf));
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	bt->tx->packet_size = BTCVSD_TX_PACKET_SIZE;
238*4882a593Smuzhiyun 	bt->tx->buf_size = BTCVSD_TX_BUF_SIZE;
239*4882a593Smuzhiyun 	bt->tx->timeout = 0;
240*4882a593Smuzhiyun 	bt->tx->rw_cnt = 0;
241*4882a593Smuzhiyun 	bt->tx->stream = SNDRV_PCM_STREAM_PLAYBACK;
242*4882a593Smuzhiyun 	return 0;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
mtk_btcvsd_snd_rx_init(struct mtk_btcvsd_snd * bt)245*4882a593Smuzhiyun static int mtk_btcvsd_snd_rx_init(struct mtk_btcvsd_snd *bt)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	memset(bt->rx, 0, sizeof(*bt->rx));
248*4882a593Smuzhiyun 	memset(bt->rx_packet_buf, 0, sizeof(bt->rx_packet_buf));
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	bt->rx->packet_size = BTCVSD_RX_PACKET_SIZE;
251*4882a593Smuzhiyun 	bt->rx->buf_size = BTCVSD_RX_BUF_SIZE;
252*4882a593Smuzhiyun 	bt->rx->timeout = 0;
253*4882a593Smuzhiyun 	bt->rx->rw_cnt = 0;
254*4882a593Smuzhiyun 	bt->rx->stream = SNDRV_PCM_STREAM_CAPTURE;
255*4882a593Smuzhiyun 	return 0;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
get_tx_time_stamp(struct mtk_btcvsd_snd * bt,struct mtk_btcvsd_snd_time_buffer_info * ts)258*4882a593Smuzhiyun static void get_tx_time_stamp(struct mtk_btcvsd_snd *bt,
259*4882a593Smuzhiyun 			      struct mtk_btcvsd_snd_time_buffer_info *ts)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	ts->time_stamp_us = bt->tx->time_stamp;
262*4882a593Smuzhiyun 	ts->data_count_equi_time = bt->tx->buf_data_equivalent_time;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
get_rx_time_stamp(struct mtk_btcvsd_snd * bt,struct mtk_btcvsd_snd_time_buffer_info * ts)265*4882a593Smuzhiyun static void get_rx_time_stamp(struct mtk_btcvsd_snd *bt,
266*4882a593Smuzhiyun 			      struct mtk_btcvsd_snd_time_buffer_info *ts)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	ts->time_stamp_us = bt->rx->time_stamp;
269*4882a593Smuzhiyun 	ts->data_count_equi_time = bt->rx->buf_data_equivalent_time;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
btcvsd_bytes_to_frame(struct snd_pcm_substream * substream,int bytes)272*4882a593Smuzhiyun static int btcvsd_bytes_to_frame(struct snd_pcm_substream *substream,
273*4882a593Smuzhiyun 				 int bytes)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	int count = bytes;
276*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = substream->runtime;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (runtime->format == SNDRV_PCM_FORMAT_S32_LE ||
279*4882a593Smuzhiyun 	    runtime->format == SNDRV_PCM_FORMAT_U32_LE)
280*4882a593Smuzhiyun 		count = count >> 2;
281*4882a593Smuzhiyun 	else
282*4882a593Smuzhiyun 		count = count >> 1;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	count = count / runtime->channels;
285*4882a593Smuzhiyun 	return count;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
mtk_btcvsd_snd_data_transfer(enum bt_sco_direct dir,u8 * src,u8 * dst,unsigned int blk_size,unsigned int blk_num)288*4882a593Smuzhiyun static void mtk_btcvsd_snd_data_transfer(enum bt_sco_direct dir,
289*4882a593Smuzhiyun 					 u8 *src, u8 *dst,
290*4882a593Smuzhiyun 					 unsigned int blk_size,
291*4882a593Smuzhiyun 					 unsigned int blk_num)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	unsigned int i, j;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	if (blk_size == 60 || blk_size == 120 || blk_size == 20) {
296*4882a593Smuzhiyun 		u32 *src_32 = (u32 *)src;
297*4882a593Smuzhiyun 		u32 *dst_32 = (u32 *)dst;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 		for (i = 0; i < (blk_size * blk_num / 4); i++)
300*4882a593Smuzhiyun 			*dst_32++ = *src_32++;
301*4882a593Smuzhiyun 	} else {
302*4882a593Smuzhiyun 		u16 *src_16 = (u16 *)src;
303*4882a593Smuzhiyun 		u16 *dst_16 = (u16 *)dst;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 		for (j = 0; j < blk_num; j++) {
306*4882a593Smuzhiyun 			for (i = 0; i < (blk_size / 2); i++)
307*4882a593Smuzhiyun 				*dst_16++ = *src_16++;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 			if (dir == BT_SCO_DIRECT_BT2ARM)
310*4882a593Smuzhiyun 				src_16++;
311*4882a593Smuzhiyun 			else
312*4882a593Smuzhiyun 				dst_16++;
313*4882a593Smuzhiyun 		}
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun /* write encoded mute data to bt sram */
btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd * bt)318*4882a593Smuzhiyun static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	unsigned int i;
321*4882a593Smuzhiyun 	unsigned int num_valid_addr;
322*4882a593Smuzhiyun 	unsigned long flags;
323*4882a593Smuzhiyun 	enum BT_SCO_BAND band = bt->band;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	/* prepare encoded mute data */
326*4882a593Smuzhiyun 	if (band == BT_SCO_NB)
327*4882a593Smuzhiyun 		memset(bt->tx->temp_packet_buf, 170, SCO_PACKET_180);
328*4882a593Smuzhiyun 	else
329*4882a593Smuzhiyun 		memcpy(bt->tx->temp_packet_buf,
330*4882a593Smuzhiyun 		       table_msbc_silence, SCO_PACKET_180);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	/* write mute data to bt tx sram buffer */
333*4882a593Smuzhiyun 	spin_lock_irqsave(&bt->tx_lock, flags);
334*4882a593Smuzhiyun 	num_valid_addr = bt->tx->buffer_info.num_valid_addr;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	dev_info(bt->dev, "%s(), band %d, num_valid_addr %u\n",
337*4882a593Smuzhiyun 		 __func__, band, num_valid_addr);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	for (i = 0; i < num_valid_addr; i++) {
340*4882a593Smuzhiyun 		void *dst;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 		dev_info(bt->dev, "%s(), clean addr 0x%lx\n", __func__,
343*4882a593Smuzhiyun 			 bt->tx->buffer_info.bt_sram_addr[i]);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 		dst = (void *)bt->tx->buffer_info.bt_sram_addr[i];
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 		mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,
348*4882a593Smuzhiyun 					     bt->tx->temp_packet_buf, dst,
349*4882a593Smuzhiyun 					     bt->tx->buffer_info.packet_length,
350*4882a593Smuzhiyun 					     bt->tx->buffer_info.packet_num);
351*4882a593Smuzhiyun 	}
352*4882a593Smuzhiyun 	spin_unlock_irqrestore(&bt->tx_lock, flags);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd * bt,enum bt_sco_packet_len packet_type,unsigned int packet_length,unsigned int packet_num,unsigned int blk_size,unsigned int control)357*4882a593Smuzhiyun static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt,
358*4882a593Smuzhiyun 				   enum bt_sco_packet_len packet_type,
359*4882a593Smuzhiyun 				   unsigned int packet_length,
360*4882a593Smuzhiyun 				   unsigned int packet_num,
361*4882a593Smuzhiyun 				   unsigned int blk_size,
362*4882a593Smuzhiyun 				   unsigned int control)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	unsigned int i;
365*4882a593Smuzhiyun 	int pv;
366*4882a593Smuzhiyun 	u8 *src;
367*4882a593Smuzhiyun 	unsigned int packet_buf_ofs;
368*4882a593Smuzhiyun 	unsigned long flags;
369*4882a593Smuzhiyun 	unsigned long connsys_addr_rx, ap_addr_rx;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	connsys_addr_rx = *bt->bt_reg_pkt_r;
372*4882a593Smuzhiyun 	ap_addr_rx = (unsigned long)bt->bt_sram_bank2_base +
373*4882a593Smuzhiyun 		     (connsys_addr_rx & 0xFFFF);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	if (connsys_addr_rx == 0xdeadfeed) {
376*4882a593Smuzhiyun 		/* bt return 0xdeadfeed if read register during bt sleep */
377*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), connsys_addr_rx == 0xdeadfeed",
378*4882a593Smuzhiyun 			 __func__);
379*4882a593Smuzhiyun 		return -EIO;
380*4882a593Smuzhiyun 	}
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	src = (u8 *)ap_addr_rx;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_BT2ARM, src,
385*4882a593Smuzhiyun 				     bt->rx->temp_packet_buf, packet_length,
386*4882a593Smuzhiyun 				     packet_num);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	spin_lock_irqsave(&bt->rx_lock, flags);
389*4882a593Smuzhiyun 	for (i = 0; i < blk_size; i++) {
390*4882a593Smuzhiyun 		packet_buf_ofs = (bt->rx->packet_w & SCO_RX_PACKET_MASK) *
391*4882a593Smuzhiyun 				 bt->rx->packet_size;
392*4882a593Smuzhiyun 		memcpy(bt->rx_packet_buf + packet_buf_ofs,
393*4882a593Smuzhiyun 		       bt->rx->temp_packet_buf + (SCO_RX_PLC_SIZE * i),
394*4882a593Smuzhiyun 		       SCO_RX_PLC_SIZE);
395*4882a593Smuzhiyun 		if ((control & btsco_packet_valid_mask[packet_type][i]) ==
396*4882a593Smuzhiyun 		    btsco_packet_valid_mask[packet_type][i])
397*4882a593Smuzhiyun 			pv = 1;
398*4882a593Smuzhiyun 		else
399*4882a593Smuzhiyun 			pv = 0;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 		packet_buf_ofs += SCO_RX_PLC_SIZE;
402*4882a593Smuzhiyun 		memcpy(bt->rx_packet_buf + packet_buf_ofs, (void *)&pv,
403*4882a593Smuzhiyun 		       SCO_CVSD_PACKET_VALID_SIZE);
404*4882a593Smuzhiyun 		bt->rx->packet_w++;
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun 	spin_unlock_irqrestore(&bt->rx_lock, flags);
407*4882a593Smuzhiyun 	return 0;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd * bt,enum bt_sco_packet_len packet_type,unsigned int packet_length,unsigned int packet_num,unsigned int blk_size)410*4882a593Smuzhiyun static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt,
411*4882a593Smuzhiyun 				  enum bt_sco_packet_len packet_type,
412*4882a593Smuzhiyun 				  unsigned int packet_length,
413*4882a593Smuzhiyun 				  unsigned int packet_num,
414*4882a593Smuzhiyun 				  unsigned int blk_size)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	unsigned int i;
417*4882a593Smuzhiyun 	unsigned long flags;
418*4882a593Smuzhiyun 	u8 *dst;
419*4882a593Smuzhiyun 	unsigned long connsys_addr_tx, ap_addr_tx;
420*4882a593Smuzhiyun 	bool new_ap_addr_tx = true;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	connsys_addr_tx = *bt->bt_reg_pkt_w;
423*4882a593Smuzhiyun 	ap_addr_tx = (unsigned long)bt->bt_sram_bank2_base +
424*4882a593Smuzhiyun 		     (connsys_addr_tx & 0xFFFF);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	if (connsys_addr_tx == 0xdeadfeed) {
427*4882a593Smuzhiyun 		/* bt return 0xdeadfeed if read register during bt sleep */
428*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), connsys_addr_tx == 0xdeadfeed\n",
429*4882a593Smuzhiyun 			 __func__);
430*4882a593Smuzhiyun 		return -EIO;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	spin_lock_irqsave(&bt->tx_lock, flags);
434*4882a593Smuzhiyun 	for (i = 0; i < blk_size; i++) {
435*4882a593Smuzhiyun 		memcpy(bt->tx->temp_packet_buf + (bt->tx->packet_size * i),
436*4882a593Smuzhiyun 		       (bt->tx_packet_buf +
437*4882a593Smuzhiyun 			(bt->tx->packet_r % SCO_TX_PACKER_BUF_NUM) *
438*4882a593Smuzhiyun 			bt->tx->packet_size),
439*4882a593Smuzhiyun 		       bt->tx->packet_size);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 		bt->tx->packet_r++;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 	spin_unlock_irqrestore(&bt->tx_lock, flags);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	dst = (u8 *)ap_addr_tx;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	if (!bt->tx->mute) {
448*4882a593Smuzhiyun 		mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,
449*4882a593Smuzhiyun 					     bt->tx->temp_packet_buf, dst,
450*4882a593Smuzhiyun 					     packet_length, packet_num);
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	/* store bt tx buffer sram info */
454*4882a593Smuzhiyun 	bt->tx->buffer_info.packet_length = packet_length;
455*4882a593Smuzhiyun 	bt->tx->buffer_info.packet_num = packet_num;
456*4882a593Smuzhiyun 	for (i = 0; i < bt->tx->buffer_info.num_valid_addr; i++) {
457*4882a593Smuzhiyun 		if (bt->tx->buffer_info.bt_sram_addr[i] == ap_addr_tx) {
458*4882a593Smuzhiyun 			new_ap_addr_tx = false;
459*4882a593Smuzhiyun 			break;
460*4882a593Smuzhiyun 		}
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 	if (new_ap_addr_tx) {
463*4882a593Smuzhiyun 		unsigned int next_idx;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 		spin_lock_irqsave(&bt->tx_lock, flags);
466*4882a593Smuzhiyun 		bt->tx->buffer_info.num_valid_addr++;
467*4882a593Smuzhiyun 		next_idx = bt->tx->buffer_info.num_valid_addr - 1;
468*4882a593Smuzhiyun 		bt->tx->buffer_info.bt_sram_addr[next_idx] = ap_addr_tx;
469*4882a593Smuzhiyun 		spin_unlock_irqrestore(&bt->tx_lock, flags);
470*4882a593Smuzhiyun 		dev_info(bt->dev, "%s(), new ap_addr_tx = 0x%lx, num_valid_addr %d\n",
471*4882a593Smuzhiyun 			 __func__, ap_addr_tx,
472*4882a593Smuzhiyun 			 bt->tx->buffer_info.num_valid_addr);
473*4882a593Smuzhiyun 	}
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	if (bt->tx->mute)
476*4882a593Smuzhiyun 		btcvsd_tx_clean_buffer(bt);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	return 0;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
mtk_btcvsd_snd_irq_handler(int irq_id,void * dev)481*4882a593Smuzhiyun static irqreturn_t mtk_btcvsd_snd_irq_handler(int irq_id, void *dev)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = dev;
484*4882a593Smuzhiyun 	unsigned int packet_type, packet_num, packet_length;
485*4882a593Smuzhiyun 	unsigned int buf_cnt_tx, buf_cnt_rx, control;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	if (bt->rx->state != BT_SCO_STATE_RUNNING &&
488*4882a593Smuzhiyun 	    bt->rx->state != BT_SCO_STATE_ENDING &&
489*4882a593Smuzhiyun 	    bt->tx->state != BT_SCO_STATE_RUNNING &&
490*4882a593Smuzhiyun 	    bt->tx->state != BT_SCO_STATE_ENDING &&
491*4882a593Smuzhiyun 	    bt->tx->state != BT_SCO_STATE_LOOPBACK) {
492*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), in idle state: rx->state: %d, tx->state: %d\n",
493*4882a593Smuzhiyun 			 __func__, bt->rx->state, bt->tx->state);
494*4882a593Smuzhiyun 		goto irq_handler_exit;
495*4882a593Smuzhiyun 	}
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	control = *bt->bt_reg_ctl;
498*4882a593Smuzhiyun 	packet_type = (control >> 18) & 0x7;
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	if (((control >> 31) & 1) == 0) {
501*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), ((control >> 31) & 1) == 0, control 0x%x\n",
502*4882a593Smuzhiyun 			 __func__, control);
503*4882a593Smuzhiyun 		goto irq_handler_exit;
504*4882a593Smuzhiyun 	}
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	if (packet_type >= BT_SCO_CVSD_MAX) {
507*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), invalid packet_type %u, exit\n",
508*4882a593Smuzhiyun 			 __func__, packet_type);
509*4882a593Smuzhiyun 		goto irq_handler_exit;
510*4882a593Smuzhiyun 	}
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	packet_length = btsco_packet_info[packet_type][0];
513*4882a593Smuzhiyun 	packet_num = btsco_packet_info[packet_type][1];
514*4882a593Smuzhiyun 	buf_cnt_tx = btsco_packet_info[packet_type][2];
515*4882a593Smuzhiyun 	buf_cnt_rx = btsco_packet_info[packet_type][3];
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	if (bt->tx->state == BT_SCO_STATE_LOOPBACK) {
518*4882a593Smuzhiyun 		u8 *src, *dst;
519*4882a593Smuzhiyun 		unsigned long connsys_addr_rx, ap_addr_rx;
520*4882a593Smuzhiyun 		unsigned long connsys_addr_tx, ap_addr_tx;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 		connsys_addr_rx = *bt->bt_reg_pkt_r;
523*4882a593Smuzhiyun 		ap_addr_rx = (unsigned long)bt->bt_sram_bank2_base +
524*4882a593Smuzhiyun 			     (connsys_addr_rx & 0xFFFF);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 		connsys_addr_tx = *bt->bt_reg_pkt_w;
527*4882a593Smuzhiyun 		ap_addr_tx = (unsigned long)bt->bt_sram_bank2_base +
528*4882a593Smuzhiyun 			     (connsys_addr_tx & 0xFFFF);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 		if (connsys_addr_tx == 0xdeadfeed ||
531*4882a593Smuzhiyun 		    connsys_addr_rx == 0xdeadfeed) {
532*4882a593Smuzhiyun 			/* bt return 0xdeadfeed if read reg during bt sleep */
533*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), connsys_addr_tx == 0xdeadfeed\n",
534*4882a593Smuzhiyun 				 __func__);
535*4882a593Smuzhiyun 			goto irq_handler_exit;
536*4882a593Smuzhiyun 		}
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 		src = (u8 *)ap_addr_rx;
539*4882a593Smuzhiyun 		dst = (u8 *)ap_addr_tx;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 		mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_BT2ARM, src,
542*4882a593Smuzhiyun 					     bt->tx->temp_packet_buf,
543*4882a593Smuzhiyun 					     packet_length,
544*4882a593Smuzhiyun 					     packet_num);
545*4882a593Smuzhiyun 		mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,
546*4882a593Smuzhiyun 					     bt->tx->temp_packet_buf, dst,
547*4882a593Smuzhiyun 					     packet_length,
548*4882a593Smuzhiyun 					     packet_num);
549*4882a593Smuzhiyun 		bt->rx->rw_cnt++;
550*4882a593Smuzhiyun 		bt->tx->rw_cnt++;
551*4882a593Smuzhiyun 	}
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	if (bt->rx->state == BT_SCO_STATE_RUNNING ||
554*4882a593Smuzhiyun 	    bt->rx->state == BT_SCO_STATE_ENDING) {
555*4882a593Smuzhiyun 		if (bt->rx->xrun) {
556*4882a593Smuzhiyun 			if (bt->rx->packet_w - bt->rx->packet_r <=
557*4882a593Smuzhiyun 			    SCO_RX_PACKER_BUF_NUM - 2 * buf_cnt_rx) {
558*4882a593Smuzhiyun 				/*
559*4882a593Smuzhiyun 				 * free space is larger then
560*4882a593Smuzhiyun 				 * twice interrupt rx data size
561*4882a593Smuzhiyun 				 */
562*4882a593Smuzhiyun 				bt->rx->xrun = 0;
563*4882a593Smuzhiyun 				dev_warn(bt->dev, "%s(), rx->xrun 0!\n",
564*4882a593Smuzhiyun 					 __func__);
565*4882a593Smuzhiyun 			}
566*4882a593Smuzhiyun 		}
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 		if (!bt->rx->xrun &&
569*4882a593Smuzhiyun 		    (bt->rx->packet_w - bt->rx->packet_r <=
570*4882a593Smuzhiyun 		     SCO_RX_PACKER_BUF_NUM - buf_cnt_rx)) {
571*4882a593Smuzhiyun 			mtk_btcvsd_read_from_bt(bt,
572*4882a593Smuzhiyun 						packet_type,
573*4882a593Smuzhiyun 						packet_length,
574*4882a593Smuzhiyun 						packet_num,
575*4882a593Smuzhiyun 						buf_cnt_rx,
576*4882a593Smuzhiyun 						control);
577*4882a593Smuzhiyun 			bt->rx->rw_cnt++;
578*4882a593Smuzhiyun 		} else {
579*4882a593Smuzhiyun 			bt->rx->xrun = 1;
580*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), rx->xrun 1\n", __func__);
581*4882a593Smuzhiyun 		}
582*4882a593Smuzhiyun 	}
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	/* tx */
585*4882a593Smuzhiyun 	bt->tx->timeout = 0;
586*4882a593Smuzhiyun 	if ((bt->tx->state == BT_SCO_STATE_RUNNING ||
587*4882a593Smuzhiyun 	     bt->tx->state == BT_SCO_STATE_ENDING) &&
588*4882a593Smuzhiyun 	    bt->tx->trigger_start) {
589*4882a593Smuzhiyun 		if (bt->tx->xrun) {
590*4882a593Smuzhiyun 			/* prepared data is larger then twice
591*4882a593Smuzhiyun 			 * interrupt tx data size
592*4882a593Smuzhiyun 			 */
593*4882a593Smuzhiyun 			if (bt->tx->packet_w - bt->tx->packet_r >=
594*4882a593Smuzhiyun 			    2 * buf_cnt_tx) {
595*4882a593Smuzhiyun 				bt->tx->xrun = 0;
596*4882a593Smuzhiyun 				dev_warn(bt->dev, "%s(), tx->xrun 0\n",
597*4882a593Smuzhiyun 					 __func__);
598*4882a593Smuzhiyun 			}
599*4882a593Smuzhiyun 		}
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 		if ((!bt->tx->xrun &&
602*4882a593Smuzhiyun 		     (bt->tx->packet_w - bt->tx->packet_r >= buf_cnt_tx)) ||
603*4882a593Smuzhiyun 		    bt->tx->state == BT_SCO_STATE_ENDING) {
604*4882a593Smuzhiyun 			mtk_btcvsd_write_to_bt(bt,
605*4882a593Smuzhiyun 					       packet_type,
606*4882a593Smuzhiyun 					       packet_length,
607*4882a593Smuzhiyun 					       packet_num,
608*4882a593Smuzhiyun 					       buf_cnt_tx);
609*4882a593Smuzhiyun 			bt->tx->rw_cnt++;
610*4882a593Smuzhiyun 		} else {
611*4882a593Smuzhiyun 			bt->tx->xrun = 1;
612*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), tx->xrun 1\n", __func__);
613*4882a593Smuzhiyun 		}
614*4882a593Smuzhiyun 	}
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	*bt->bt_reg_ctl &= ~BT_CVSD_CLEAR;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	if (bt->rx->state == BT_SCO_STATE_RUNNING ||
619*4882a593Smuzhiyun 	    bt->rx->state == BT_SCO_STATE_ENDING) {
620*4882a593Smuzhiyun 		bt->rx->wait_flag = 1;
621*4882a593Smuzhiyun 		wake_up_interruptible(&bt->rx_wait);
622*4882a593Smuzhiyun 		snd_pcm_period_elapsed(bt->rx->substream);
623*4882a593Smuzhiyun 	}
624*4882a593Smuzhiyun 	if (bt->tx->state == BT_SCO_STATE_RUNNING ||
625*4882a593Smuzhiyun 	    bt->tx->state == BT_SCO_STATE_ENDING) {
626*4882a593Smuzhiyun 		bt->tx->wait_flag = 1;
627*4882a593Smuzhiyun 		wake_up_interruptible(&bt->tx_wait);
628*4882a593Smuzhiyun 		snd_pcm_period_elapsed(bt->tx->substream);
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	return IRQ_HANDLED;
632*4882a593Smuzhiyun irq_handler_exit:
633*4882a593Smuzhiyun 	*bt->bt_reg_ctl &= ~BT_CVSD_CLEAR;
634*4882a593Smuzhiyun 	return IRQ_HANDLED;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
wait_for_bt_irq(struct mtk_btcvsd_snd * bt,struct mtk_btcvsd_snd_stream * bt_stream)637*4882a593Smuzhiyun static int wait_for_bt_irq(struct mtk_btcvsd_snd *bt,
638*4882a593Smuzhiyun 			   struct mtk_btcvsd_snd_stream *bt_stream)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun 	unsigned long long t1, t2;
641*4882a593Smuzhiyun 	/* one interrupt period = 22.5ms */
642*4882a593Smuzhiyun 	unsigned long long timeout_limit = 22500000;
643*4882a593Smuzhiyun 	int max_timeout_trial = 2;
644*4882a593Smuzhiyun 	int ret;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	bt_stream->wait_flag = 0;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	while (max_timeout_trial && !bt_stream->wait_flag) {
649*4882a593Smuzhiyun 		t1 = sched_clock();
650*4882a593Smuzhiyun 		if (bt_stream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
651*4882a593Smuzhiyun 			ret = wait_event_interruptible_timeout(bt->tx_wait,
652*4882a593Smuzhiyun 				bt_stream->wait_flag,
653*4882a593Smuzhiyun 				nsecs_to_jiffies(timeout_limit));
654*4882a593Smuzhiyun 		} else {
655*4882a593Smuzhiyun 			ret = wait_event_interruptible_timeout(bt->rx_wait,
656*4882a593Smuzhiyun 				bt_stream->wait_flag,
657*4882a593Smuzhiyun 				nsecs_to_jiffies(timeout_limit));
658*4882a593Smuzhiyun 		}
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 		t2 = sched_clock();
661*4882a593Smuzhiyun 		t2 = t2 - t1; /* in ns (10^9) */
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 		if (t2 > timeout_limit) {
664*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), stream %d, timeout %llu, limit %llu, ret %d, flag %d\n",
665*4882a593Smuzhiyun 				 __func__, bt_stream->stream,
666*4882a593Smuzhiyun 				 t2, timeout_limit, ret,
667*4882a593Smuzhiyun 				 bt_stream->wait_flag);
668*4882a593Smuzhiyun 		}
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 		if (ret < 0) {
671*4882a593Smuzhiyun 			/*
672*4882a593Smuzhiyun 			 * error, -ERESTARTSYS if it was interrupted by
673*4882a593Smuzhiyun 			 * a signal
674*4882a593Smuzhiyun 			 */
675*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), stream %d, error, trial left %d\n",
676*4882a593Smuzhiyun 				 __func__,
677*4882a593Smuzhiyun 				 bt_stream->stream, max_timeout_trial);
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 			bt_stream->timeout = 1;
680*4882a593Smuzhiyun 			return ret;
681*4882a593Smuzhiyun 		} else if (ret == 0) {
682*4882a593Smuzhiyun 			/* conidtion is false after timeout */
683*4882a593Smuzhiyun 			max_timeout_trial--;
684*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), stream %d, error, timeout, condition is false, trial left %d\n",
685*4882a593Smuzhiyun 				 __func__,
686*4882a593Smuzhiyun 				 bt_stream->stream, max_timeout_trial);
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 			if (max_timeout_trial <= 0) {
689*4882a593Smuzhiyun 				bt_stream->timeout = 1;
690*4882a593Smuzhiyun 				return -ETIME;
691*4882a593Smuzhiyun 			}
692*4882a593Smuzhiyun 		}
693*4882a593Smuzhiyun 	}
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	return 0;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun 
mtk_btcvsd_snd_read(struct mtk_btcvsd_snd * bt,char __user * buf,size_t count)698*4882a593Smuzhiyun static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt,
699*4882a593Smuzhiyun 				   char __user *buf,
700*4882a593Smuzhiyun 				   size_t count)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun 	ssize_t read_size = 0, read_count = 0, cur_read_idx, cont;
703*4882a593Smuzhiyun 	unsigned int cur_buf_ofs = 0;
704*4882a593Smuzhiyun 	unsigned long avail;
705*4882a593Smuzhiyun 	unsigned long flags;
706*4882a593Smuzhiyun 	unsigned int packet_size = bt->rx->packet_size;
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	while (count) {
709*4882a593Smuzhiyun 		spin_lock_irqsave(&bt->rx_lock, flags);
710*4882a593Smuzhiyun 		/* available data in RX packet buffer */
711*4882a593Smuzhiyun 		avail = (bt->rx->packet_w - bt->rx->packet_r) * packet_size;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 		cur_read_idx = (bt->rx->packet_r & SCO_RX_PACKET_MASK) *
714*4882a593Smuzhiyun 			       packet_size;
715*4882a593Smuzhiyun 		spin_unlock_irqrestore(&bt->rx_lock, flags);
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 		if (!avail) {
718*4882a593Smuzhiyun 			int ret = wait_for_bt_irq(bt, bt->rx);
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 			if (ret)
721*4882a593Smuzhiyun 				return read_count;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 			continue;
724*4882a593Smuzhiyun 		}
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 		/* count must be multiple of packet_size */
727*4882a593Smuzhiyun 		if (count % packet_size != 0 ||
728*4882a593Smuzhiyun 		    avail % packet_size != 0) {
729*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), count %zu or d %lu is not multiple of packet_size %dd\n",
730*4882a593Smuzhiyun 				 __func__, count, avail, packet_size);
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 			count -= count % packet_size;
733*4882a593Smuzhiyun 			avail -= avail % packet_size;
734*4882a593Smuzhiyun 		}
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 		if (count > avail)
737*4882a593Smuzhiyun 			read_size = avail;
738*4882a593Smuzhiyun 		else
739*4882a593Smuzhiyun 			read_size = count;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 		/* calculate continue space */
742*4882a593Smuzhiyun 		cont = bt->rx->buf_size - cur_read_idx;
743*4882a593Smuzhiyun 		if (read_size > cont)
744*4882a593Smuzhiyun 			read_size = cont;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 		if (copy_to_user(buf + cur_buf_ofs,
747*4882a593Smuzhiyun 				 bt->rx_packet_buf + cur_read_idx,
748*4882a593Smuzhiyun 				 read_size)) {
749*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), copy_to_user fail\n",
750*4882a593Smuzhiyun 				 __func__);
751*4882a593Smuzhiyun 			return -EFAULT;
752*4882a593Smuzhiyun 		}
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 		spin_lock_irqsave(&bt->rx_lock, flags);
755*4882a593Smuzhiyun 		bt->rx->packet_r += read_size / packet_size;
756*4882a593Smuzhiyun 		spin_unlock_irqrestore(&bt->rx_lock, flags);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 		read_count += read_size;
759*4882a593Smuzhiyun 		cur_buf_ofs += read_size;
760*4882a593Smuzhiyun 		count -= read_size;
761*4882a593Smuzhiyun 	}
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	/*
764*4882a593Smuzhiyun 	 * save current timestamp & buffer time in times_tamp and
765*4882a593Smuzhiyun 	 * buf_data_equivalent_time
766*4882a593Smuzhiyun 	 */
767*4882a593Smuzhiyun 	bt->rx->time_stamp = sched_clock();
768*4882a593Smuzhiyun 	bt->rx->buf_data_equivalent_time =
769*4882a593Smuzhiyun 		(unsigned long long)(bt->rx->packet_w - bt->rx->packet_r) *
770*4882a593Smuzhiyun 		SCO_RX_PLC_SIZE * 16 * 1000 / 2 / 64;
771*4882a593Smuzhiyun 	bt->rx->buf_data_equivalent_time += read_count * SCO_RX_PLC_SIZE *
772*4882a593Smuzhiyun 					    16 * 1000 / packet_size / 2 / 64;
773*4882a593Smuzhiyun 	/* return equivalent time(us) to data count */
774*4882a593Smuzhiyun 	bt->rx->buf_data_equivalent_time *= 1000;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	return read_count;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun 
mtk_btcvsd_snd_write(struct mtk_btcvsd_snd * bt,char __user * buf,size_t count)779*4882a593Smuzhiyun static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt,
780*4882a593Smuzhiyun 				    char __user *buf,
781*4882a593Smuzhiyun 				    size_t count)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun 	int written_size = count, avail = 0, cur_write_idx, write_size, cont;
784*4882a593Smuzhiyun 	unsigned int cur_buf_ofs = 0;
785*4882a593Smuzhiyun 	unsigned long flags;
786*4882a593Smuzhiyun 	unsigned int packet_size = bt->tx->packet_size;
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	/*
789*4882a593Smuzhiyun 	 * save current timestamp & buffer time in time_stamp and
790*4882a593Smuzhiyun 	 * buf_data_equivalent_time
791*4882a593Smuzhiyun 	 */
792*4882a593Smuzhiyun 	bt->tx->time_stamp = sched_clock();
793*4882a593Smuzhiyun 	bt->tx->buf_data_equivalent_time =
794*4882a593Smuzhiyun 		(unsigned long long)(bt->tx->packet_w - bt->tx->packet_r) *
795*4882a593Smuzhiyun 		packet_size * 16 * 1000 / 2 / 64;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	/* return equivalent time(us) to data count */
798*4882a593Smuzhiyun 	bt->tx->buf_data_equivalent_time *= 1000;
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	while (count) {
801*4882a593Smuzhiyun 		spin_lock_irqsave(&bt->tx_lock, flags);
802*4882a593Smuzhiyun 		/* free space of TX packet buffer */
803*4882a593Smuzhiyun 		avail = bt->tx->buf_size -
804*4882a593Smuzhiyun 			(bt->tx->packet_w - bt->tx->packet_r) * packet_size;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 		cur_write_idx = (bt->tx->packet_w % SCO_TX_PACKER_BUF_NUM) *
807*4882a593Smuzhiyun 				packet_size;
808*4882a593Smuzhiyun 		spin_unlock_irqrestore(&bt->tx_lock, flags);
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 		if (!avail) {
811*4882a593Smuzhiyun 			int ret = wait_for_bt_irq(bt, bt->rx);
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 			if (ret)
814*4882a593Smuzhiyun 				return written_size;
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 			continue;
817*4882a593Smuzhiyun 		}
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 		/* count must be multiple of bt->tx->packet_size */
820*4882a593Smuzhiyun 		if (count % packet_size != 0 ||
821*4882a593Smuzhiyun 		    avail % packet_size != 0) {
822*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), count %zu or avail %d is not multiple of packet_size %d\n",
823*4882a593Smuzhiyun 				 __func__, count, avail, packet_size);
824*4882a593Smuzhiyun 			count -= count % packet_size;
825*4882a593Smuzhiyun 			avail -= avail % packet_size;
826*4882a593Smuzhiyun 		}
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 		if (count > avail)
829*4882a593Smuzhiyun 			write_size = avail;
830*4882a593Smuzhiyun 		else
831*4882a593Smuzhiyun 			write_size = count;
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 		/* calculate continue space */
834*4882a593Smuzhiyun 		cont = bt->tx->buf_size - cur_write_idx;
835*4882a593Smuzhiyun 		if (write_size > cont)
836*4882a593Smuzhiyun 			write_size = cont;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 		if (copy_from_user(bt->tx_packet_buf +
839*4882a593Smuzhiyun 				   cur_write_idx,
840*4882a593Smuzhiyun 				   buf + cur_buf_ofs,
841*4882a593Smuzhiyun 				   write_size)) {
842*4882a593Smuzhiyun 			dev_warn(bt->dev, "%s(), copy_from_user fail\n",
843*4882a593Smuzhiyun 				 __func__);
844*4882a593Smuzhiyun 			return -EFAULT;
845*4882a593Smuzhiyun 		}
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		spin_lock_irqsave(&bt->tx_lock, flags);
848*4882a593Smuzhiyun 		bt->tx->packet_w += write_size / packet_size;
849*4882a593Smuzhiyun 		spin_unlock_irqrestore(&bt->tx_lock, flags);
850*4882a593Smuzhiyun 		cur_buf_ofs += write_size;
851*4882a593Smuzhiyun 		count -= write_size;
852*4882a593Smuzhiyun 	}
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	return written_size;
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun 
get_bt_stream(struct mtk_btcvsd_snd * bt,struct snd_pcm_substream * substream)857*4882a593Smuzhiyun static struct mtk_btcvsd_snd_stream *get_bt_stream
858*4882a593Smuzhiyun 	(struct mtk_btcvsd_snd *bt, struct snd_pcm_substream *substream)
859*4882a593Smuzhiyun {
860*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
861*4882a593Smuzhiyun 		return bt->tx;
862*4882a593Smuzhiyun 	else
863*4882a593Smuzhiyun 		return bt->rx;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun /* pcm ops */
867*4882a593Smuzhiyun static const struct snd_pcm_hardware mtk_btcvsd_hardware = {
868*4882a593Smuzhiyun 	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
869*4882a593Smuzhiyun 		 SNDRV_PCM_INFO_RESUME),
870*4882a593Smuzhiyun 	.formats = SNDRV_PCM_FMTBIT_S16_LE,
871*4882a593Smuzhiyun 	.buffer_bytes_max = 24 * 1024,
872*4882a593Smuzhiyun 	.period_bytes_max = 24 * 1024,
873*4882a593Smuzhiyun 	.periods_min = 2,
874*4882a593Smuzhiyun 	.periods_max = 16,
875*4882a593Smuzhiyun 	.fifo_size = 0,
876*4882a593Smuzhiyun };
877*4882a593Smuzhiyun 
mtk_pcm_btcvsd_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)878*4882a593Smuzhiyun static int mtk_pcm_btcvsd_open(struct snd_soc_component *component,
879*4882a593Smuzhiyun 			       struct snd_pcm_substream *substream)
880*4882a593Smuzhiyun {
881*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
882*4882a593Smuzhiyun 	int ret;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), stream %d, substream %p\n",
885*4882a593Smuzhiyun 		__func__, substream->stream, substream);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	snd_soc_set_runtime_hwparams(substream, &mtk_btcvsd_hardware);
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
890*4882a593Smuzhiyun 		ret = mtk_btcvsd_snd_tx_init(bt);
891*4882a593Smuzhiyun 		bt->tx->substream = substream;
892*4882a593Smuzhiyun 	} else {
893*4882a593Smuzhiyun 		ret = mtk_btcvsd_snd_rx_init(bt);
894*4882a593Smuzhiyun 		bt->rx->substream = substream;
895*4882a593Smuzhiyun 	}
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 	return ret;
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun 
mtk_pcm_btcvsd_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)900*4882a593Smuzhiyun static int mtk_pcm_btcvsd_close(struct snd_soc_component *component,
901*4882a593Smuzhiyun 				struct snd_pcm_substream *substream)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
904*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), stream %d\n", __func__, substream->stream);
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	mtk_btcvsd_snd_set_state(bt, bt_stream, BT_SCO_STATE_IDLE);
909*4882a593Smuzhiyun 	bt_stream->substream = NULL;
910*4882a593Smuzhiyun 	return 0;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun 
mtk_pcm_btcvsd_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)913*4882a593Smuzhiyun static int mtk_pcm_btcvsd_hw_params(struct snd_soc_component *component,
914*4882a593Smuzhiyun 				    struct snd_pcm_substream *substream,
915*4882a593Smuzhiyun 				    struct snd_pcm_hw_params *hw_params)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
920*4882a593Smuzhiyun 	    params_buffer_bytes(hw_params) % bt->tx->packet_size != 0) {
921*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), error, buffer size %d not valid\n",
922*4882a593Smuzhiyun 			 __func__,
923*4882a593Smuzhiyun 			 params_buffer_bytes(hw_params));
924*4882a593Smuzhiyun 		return -EINVAL;
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
928*4882a593Smuzhiyun 	return 0;
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun 
mtk_pcm_btcvsd_hw_free(struct snd_soc_component * component,struct snd_pcm_substream * substream)931*4882a593Smuzhiyun static int mtk_pcm_btcvsd_hw_free(struct snd_soc_component *component,
932*4882a593Smuzhiyun 				  struct snd_pcm_substream *substream)
933*4882a593Smuzhiyun {
934*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
937*4882a593Smuzhiyun 		btcvsd_tx_clean_buffer(bt);
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	return 0;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun 
mtk_pcm_btcvsd_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)942*4882a593Smuzhiyun static int mtk_pcm_btcvsd_prepare(struct snd_soc_component *component,
943*4882a593Smuzhiyun 				  struct snd_pcm_substream *substream)
944*4882a593Smuzhiyun {
945*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
946*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), stream %d\n", __func__, substream->stream);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	mtk_btcvsd_snd_set_state(bt, bt_stream, BT_SCO_STATE_RUNNING);
951*4882a593Smuzhiyun 	return 0;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun 
mtk_pcm_btcvsd_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)954*4882a593Smuzhiyun static int mtk_pcm_btcvsd_trigger(struct snd_soc_component *component,
955*4882a593Smuzhiyun 				  struct snd_pcm_substream *substream, int cmd)
956*4882a593Smuzhiyun {
957*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
958*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);
959*4882a593Smuzhiyun 	int stream = substream->stream;
960*4882a593Smuzhiyun 	int hw_packet_ptr;
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), stream %d, cmd %d\n",
963*4882a593Smuzhiyun 		__func__, substream->stream, cmd);
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 	switch (cmd) {
966*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_START:
967*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_RESUME:
968*4882a593Smuzhiyun 		hw_packet_ptr = stream == SNDRV_PCM_STREAM_PLAYBACK ?
969*4882a593Smuzhiyun 				bt_stream->packet_r : bt_stream->packet_w;
970*4882a593Smuzhiyun 		bt_stream->prev_packet_idx = hw_packet_ptr;
971*4882a593Smuzhiyun 		bt_stream->prev_frame = 0;
972*4882a593Smuzhiyun 		bt_stream->trigger_start = 1;
973*4882a593Smuzhiyun 		return 0;
974*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_STOP:
975*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_SUSPEND:
976*4882a593Smuzhiyun 		bt_stream->trigger_start = 0;
977*4882a593Smuzhiyun 		mtk_btcvsd_snd_set_state(bt, bt_stream, BT_SCO_STATE_ENDING);
978*4882a593Smuzhiyun 		return 0;
979*4882a593Smuzhiyun 	default:
980*4882a593Smuzhiyun 		return -EINVAL;
981*4882a593Smuzhiyun 	}
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun 
mtk_pcm_btcvsd_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)984*4882a593Smuzhiyun static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer(
985*4882a593Smuzhiyun 	struct snd_soc_component *component,
986*4882a593Smuzhiyun 	struct snd_pcm_substream *substream)
987*4882a593Smuzhiyun {
988*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
989*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_stream *bt_stream;
990*4882a593Smuzhiyun 	snd_pcm_uframes_t frame = 0;
991*4882a593Smuzhiyun 	int byte = 0;
992*4882a593Smuzhiyun 	int hw_packet_ptr;
993*4882a593Smuzhiyun 	int packet_diff;
994*4882a593Smuzhiyun 	spinlock_t *lock;	/* spinlock for bt stream control */
995*4882a593Smuzhiyun 	unsigned long flags;
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
998*4882a593Smuzhiyun 		lock = &bt->tx_lock;
999*4882a593Smuzhiyun 		bt_stream = bt->tx;
1000*4882a593Smuzhiyun 	} else {
1001*4882a593Smuzhiyun 		lock = &bt->rx_lock;
1002*4882a593Smuzhiyun 		bt_stream = bt->rx;
1003*4882a593Smuzhiyun 	}
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	spin_lock_irqsave(lock, flags);
1006*4882a593Smuzhiyun 	hw_packet_ptr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
1007*4882a593Smuzhiyun 			bt->tx->packet_r : bt->rx->packet_w;
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun 	/* get packet diff from last time */
1010*4882a593Smuzhiyun 	if (hw_packet_ptr >= bt_stream->prev_packet_idx) {
1011*4882a593Smuzhiyun 		packet_diff = hw_packet_ptr - bt_stream->prev_packet_idx;
1012*4882a593Smuzhiyun 	} else {
1013*4882a593Smuzhiyun 		/* integer overflow */
1014*4882a593Smuzhiyun 		packet_diff = (INT_MAX - bt_stream->prev_packet_idx) +
1015*4882a593Smuzhiyun 			      (hw_packet_ptr - INT_MIN) + 1;
1016*4882a593Smuzhiyun 	}
1017*4882a593Smuzhiyun 	bt_stream->prev_packet_idx = hw_packet_ptr;
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	/* increased bytes */
1020*4882a593Smuzhiyun 	byte = packet_diff * bt_stream->packet_size;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	frame = btcvsd_bytes_to_frame(substream, byte);
1023*4882a593Smuzhiyun 	frame += bt_stream->prev_frame;
1024*4882a593Smuzhiyun 	frame %= substream->runtime->buffer_size;
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	bt_stream->prev_frame = frame;
1027*4882a593Smuzhiyun 
1028*4882a593Smuzhiyun 	spin_unlock_irqrestore(lock, flags);
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	return frame;
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun 
mtk_pcm_btcvsd_copy(struct snd_soc_component * component,struct snd_pcm_substream * substream,int channel,unsigned long pos,void __user * buf,unsigned long count)1033*4882a593Smuzhiyun static int mtk_pcm_btcvsd_copy(struct snd_soc_component *component,
1034*4882a593Smuzhiyun 			       struct snd_pcm_substream *substream,
1035*4882a593Smuzhiyun 			       int channel, unsigned long pos,
1036*4882a593Smuzhiyun 			       void __user *buf, unsigned long count)
1037*4882a593Smuzhiyun {
1038*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1041*4882a593Smuzhiyun 		mtk_btcvsd_snd_write(bt, buf, count);
1042*4882a593Smuzhiyun 	else
1043*4882a593Smuzhiyun 		mtk_btcvsd_snd_read(bt, buf, count);
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun 	return 0;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun /* kcontrol */
1049*4882a593Smuzhiyun static const char *const btsco_band_str[] = {"NB", "WB"};
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun static const struct soc_enum btcvsd_enum[] = {
1052*4882a593Smuzhiyun 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(btsco_band_str), btsco_band_str),
1053*4882a593Smuzhiyun };
1054*4882a593Smuzhiyun 
btcvsd_band_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1055*4882a593Smuzhiyun static int btcvsd_band_get(struct snd_kcontrol *kcontrol,
1056*4882a593Smuzhiyun 			   struct snd_ctl_elem_value *ucontrol)
1057*4882a593Smuzhiyun {
1058*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1059*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = bt->band;
1062*4882a593Smuzhiyun 	return 0;
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun 
btcvsd_band_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1065*4882a593Smuzhiyun static int btcvsd_band_set(struct snd_kcontrol *kcontrol,
1066*4882a593Smuzhiyun 			   struct snd_ctl_elem_value *ucontrol)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1069*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1070*4882a593Smuzhiyun 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	if (ucontrol->value.enumerated.item[0] >= e->items)
1073*4882a593Smuzhiyun 		return -EINVAL;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	bt->band = ucontrol->value.integer.value[0];
1076*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), band %d\n", __func__, bt->band);
1077*4882a593Smuzhiyun 	return 0;
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun 
btcvsd_loopback_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1080*4882a593Smuzhiyun static int btcvsd_loopback_get(struct snd_kcontrol *kcontrol,
1081*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *ucontrol)
1082*4882a593Smuzhiyun {
1083*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1084*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1085*4882a593Smuzhiyun 	bool lpbk_en = bt->tx->state == BT_SCO_STATE_LOOPBACK;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = lpbk_en;
1088*4882a593Smuzhiyun 	return 0;
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun 
btcvsd_loopback_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1091*4882a593Smuzhiyun static int btcvsd_loopback_set(struct snd_kcontrol *kcontrol,
1092*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *ucontrol)
1093*4882a593Smuzhiyun {
1094*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1095*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	if (ucontrol->value.integer.value[0]) {
1098*4882a593Smuzhiyun 		mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_LOOPBACK);
1099*4882a593Smuzhiyun 		mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_LOOPBACK);
1100*4882a593Smuzhiyun 	} else {
1101*4882a593Smuzhiyun 		mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_RUNNING);
1102*4882a593Smuzhiyun 		mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_RUNNING);
1103*4882a593Smuzhiyun 	}
1104*4882a593Smuzhiyun 	return 0;
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun 
btcvsd_tx_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1107*4882a593Smuzhiyun static int btcvsd_tx_mute_get(struct snd_kcontrol *kcontrol,
1108*4882a593Smuzhiyun 			      struct snd_ctl_elem_value *ucontrol)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1111*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 	if (!bt->tx) {
1114*4882a593Smuzhiyun 		ucontrol->value.integer.value[0] = 0;
1115*4882a593Smuzhiyun 		return 0;
1116*4882a593Smuzhiyun 	}
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = bt->tx->mute;
1119*4882a593Smuzhiyun 	return 0;
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun 
btcvsd_tx_mute_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1122*4882a593Smuzhiyun static int btcvsd_tx_mute_set(struct snd_kcontrol *kcontrol,
1123*4882a593Smuzhiyun 			      struct snd_ctl_elem_value *ucontrol)
1124*4882a593Smuzhiyun {
1125*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1126*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1127*4882a593Smuzhiyun 
1128*4882a593Smuzhiyun 	if (!bt->tx)
1129*4882a593Smuzhiyun 		return 0;
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	bt->tx->mute = ucontrol->value.integer.value[0];
1132*4882a593Smuzhiyun 	return 0;
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
btcvsd_rx_irq_received_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1135*4882a593Smuzhiyun static int btcvsd_rx_irq_received_get(struct snd_kcontrol *kcontrol,
1136*4882a593Smuzhiyun 				      struct snd_ctl_elem_value *ucontrol)
1137*4882a593Smuzhiyun {
1138*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1139*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	if (!bt->rx)
1142*4882a593Smuzhiyun 		return 0;
1143*4882a593Smuzhiyun 
1144*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = bt->rx->rw_cnt ? 1 : 0;
1145*4882a593Smuzhiyun 	return 0;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun 
btcvsd_rx_timeout_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1148*4882a593Smuzhiyun static int btcvsd_rx_timeout_get(struct snd_kcontrol *kcontrol,
1149*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
1150*4882a593Smuzhiyun {
1151*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1152*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	if (!bt->rx)
1155*4882a593Smuzhiyun 		return 0;
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = bt->rx->timeout;
1158*4882a593Smuzhiyun 	bt->rx->timeout = 0;
1159*4882a593Smuzhiyun 	return 0;
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun 
btcvsd_rx_timestamp_get(struct snd_kcontrol * kcontrol,unsigned int __user * data,unsigned int size)1162*4882a593Smuzhiyun static int btcvsd_rx_timestamp_get(struct snd_kcontrol *kcontrol,
1163*4882a593Smuzhiyun 				   unsigned int __user *data, unsigned int size)
1164*4882a593Smuzhiyun {
1165*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1166*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1167*4882a593Smuzhiyun 	int ret = 0;
1168*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_time_buffer_info time_buffer_info_rx;
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	if (size > sizeof(struct mtk_btcvsd_snd_time_buffer_info))
1171*4882a593Smuzhiyun 		return -EINVAL;
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	get_rx_time_stamp(bt, &time_buffer_info_rx);
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), time_stamp_us %llu, data_count_equi_time %llu",
1176*4882a593Smuzhiyun 		__func__,
1177*4882a593Smuzhiyun 		time_buffer_info_rx.time_stamp_us,
1178*4882a593Smuzhiyun 		time_buffer_info_rx.data_count_equi_time);
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	if (copy_to_user(data, &time_buffer_info_rx,
1181*4882a593Smuzhiyun 			 sizeof(struct mtk_btcvsd_snd_time_buffer_info))) {
1182*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), copy_to_user fail", __func__);
1183*4882a593Smuzhiyun 		ret = -EFAULT;
1184*4882a593Smuzhiyun 	}
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun 	return ret;
1187*4882a593Smuzhiyun }
1188*4882a593Smuzhiyun 
btcvsd_tx_irq_received_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1189*4882a593Smuzhiyun static int btcvsd_tx_irq_received_get(struct snd_kcontrol *kcontrol,
1190*4882a593Smuzhiyun 				      struct snd_ctl_elem_value *ucontrol)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1193*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 	if (!bt->tx)
1196*4882a593Smuzhiyun 		return 0;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = bt->tx->rw_cnt ? 1 : 0;
1199*4882a593Smuzhiyun 	return 0;
1200*4882a593Smuzhiyun }
1201*4882a593Smuzhiyun 
btcvsd_tx_timeout_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1202*4882a593Smuzhiyun static int btcvsd_tx_timeout_get(struct snd_kcontrol *kcontrol,
1203*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
1204*4882a593Smuzhiyun {
1205*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1206*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = bt->tx->timeout;
1209*4882a593Smuzhiyun 	return 0;
1210*4882a593Smuzhiyun }
1211*4882a593Smuzhiyun 
btcvsd_tx_timestamp_get(struct snd_kcontrol * kcontrol,unsigned int __user * data,unsigned int size)1212*4882a593Smuzhiyun static int btcvsd_tx_timestamp_get(struct snd_kcontrol *kcontrol,
1213*4882a593Smuzhiyun 				   unsigned int __user *data, unsigned int size)
1214*4882a593Smuzhiyun {
1215*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
1216*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
1217*4882a593Smuzhiyun 	int ret = 0;
1218*4882a593Smuzhiyun 	struct mtk_btcvsd_snd_time_buffer_info time_buffer_info_tx;
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	if (size > sizeof(struct mtk_btcvsd_snd_time_buffer_info))
1221*4882a593Smuzhiyun 		return -EINVAL;
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	get_tx_time_stamp(bt, &time_buffer_info_tx);
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 	dev_dbg(bt->dev, "%s(), time_stamp_us %llu, data_count_equi_time %llu",
1226*4882a593Smuzhiyun 		__func__,
1227*4882a593Smuzhiyun 		time_buffer_info_tx.time_stamp_us,
1228*4882a593Smuzhiyun 		time_buffer_info_tx.data_count_equi_time);
1229*4882a593Smuzhiyun 
1230*4882a593Smuzhiyun 	if (copy_to_user(data, &time_buffer_info_tx,
1231*4882a593Smuzhiyun 			 sizeof(struct mtk_btcvsd_snd_time_buffer_info))) {
1232*4882a593Smuzhiyun 		dev_warn(bt->dev, "%s(), copy_to_user fail", __func__);
1233*4882a593Smuzhiyun 		ret = -EFAULT;
1234*4882a593Smuzhiyun 	}
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun 	return ret;
1237*4882a593Smuzhiyun }
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun static const struct snd_kcontrol_new mtk_btcvsd_snd_controls[] = {
1240*4882a593Smuzhiyun 	SOC_ENUM_EXT("BTCVSD Band", btcvsd_enum[0],
1241*4882a593Smuzhiyun 		     btcvsd_band_get, btcvsd_band_set),
1242*4882a593Smuzhiyun 	SOC_SINGLE_BOOL_EXT("BTCVSD Loopback Switch", 0,
1243*4882a593Smuzhiyun 			    btcvsd_loopback_get, btcvsd_loopback_set),
1244*4882a593Smuzhiyun 	SOC_SINGLE_BOOL_EXT("BTCVSD Tx Mute Switch", 0,
1245*4882a593Smuzhiyun 			    btcvsd_tx_mute_get, btcvsd_tx_mute_set),
1246*4882a593Smuzhiyun 	SOC_SINGLE_BOOL_EXT("BTCVSD Tx Irq Received Switch", 0,
1247*4882a593Smuzhiyun 			    btcvsd_tx_irq_received_get, NULL),
1248*4882a593Smuzhiyun 	SOC_SINGLE_BOOL_EXT("BTCVSD Tx Timeout Switch", 0,
1249*4882a593Smuzhiyun 			    btcvsd_tx_timeout_get, NULL),
1250*4882a593Smuzhiyun 	SOC_SINGLE_BOOL_EXT("BTCVSD Rx Irq Received Switch", 0,
1251*4882a593Smuzhiyun 			    btcvsd_rx_irq_received_get, NULL),
1252*4882a593Smuzhiyun 	SOC_SINGLE_BOOL_EXT("BTCVSD Rx Timeout Switch", 0,
1253*4882a593Smuzhiyun 			    btcvsd_rx_timeout_get, NULL),
1254*4882a593Smuzhiyun 	SND_SOC_BYTES_TLV("BTCVSD Rx Timestamp",
1255*4882a593Smuzhiyun 			  sizeof(struct mtk_btcvsd_snd_time_buffer_info),
1256*4882a593Smuzhiyun 			  btcvsd_rx_timestamp_get, NULL),
1257*4882a593Smuzhiyun 	SND_SOC_BYTES_TLV("BTCVSD Tx Timestamp",
1258*4882a593Smuzhiyun 			  sizeof(struct mtk_btcvsd_snd_time_buffer_info),
1259*4882a593Smuzhiyun 			  btcvsd_tx_timestamp_get, NULL),
1260*4882a593Smuzhiyun };
1261*4882a593Smuzhiyun 
mtk_btcvsd_snd_component_probe(struct snd_soc_component * component)1262*4882a593Smuzhiyun static int mtk_btcvsd_snd_component_probe(struct snd_soc_component *component)
1263*4882a593Smuzhiyun {
1264*4882a593Smuzhiyun 	return snd_soc_add_component_controls(component,
1265*4882a593Smuzhiyun 		mtk_btcvsd_snd_controls,
1266*4882a593Smuzhiyun 		ARRAY_SIZE(mtk_btcvsd_snd_controls));
1267*4882a593Smuzhiyun }
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun static const struct snd_soc_component_driver mtk_btcvsd_snd_platform = {
1270*4882a593Smuzhiyun 	.name		= BTCVSD_SND_NAME,
1271*4882a593Smuzhiyun 	.probe		= mtk_btcvsd_snd_component_probe,
1272*4882a593Smuzhiyun 	.open		= mtk_pcm_btcvsd_open,
1273*4882a593Smuzhiyun 	.close		= mtk_pcm_btcvsd_close,
1274*4882a593Smuzhiyun 	.hw_params	= mtk_pcm_btcvsd_hw_params,
1275*4882a593Smuzhiyun 	.hw_free	= mtk_pcm_btcvsd_hw_free,
1276*4882a593Smuzhiyun 	.prepare	= mtk_pcm_btcvsd_prepare,
1277*4882a593Smuzhiyun 	.trigger	= mtk_pcm_btcvsd_trigger,
1278*4882a593Smuzhiyun 	.pointer	= mtk_pcm_btcvsd_pointer,
1279*4882a593Smuzhiyun 	.copy_user	= mtk_pcm_btcvsd_copy,
1280*4882a593Smuzhiyun };
1281*4882a593Smuzhiyun 
mtk_btcvsd_snd_probe(struct platform_device * pdev)1282*4882a593Smuzhiyun static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
1283*4882a593Smuzhiyun {
1284*4882a593Smuzhiyun 	int ret;
1285*4882a593Smuzhiyun 	int irq_id;
1286*4882a593Smuzhiyun 	u32 offset[5] = {0, 0, 0, 0, 0};
1287*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *btcvsd;
1288*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun 	/* init btcvsd private data */
1291*4882a593Smuzhiyun 	btcvsd = devm_kzalloc(dev, sizeof(*btcvsd), GFP_KERNEL);
1292*4882a593Smuzhiyun 	if (!btcvsd)
1293*4882a593Smuzhiyun 		return -ENOMEM;
1294*4882a593Smuzhiyun 	platform_set_drvdata(pdev, btcvsd);
1295*4882a593Smuzhiyun 	btcvsd->dev = dev;
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	/* init tx/rx */
1298*4882a593Smuzhiyun 	btcvsd->rx = devm_kzalloc(btcvsd->dev, sizeof(*btcvsd->rx), GFP_KERNEL);
1299*4882a593Smuzhiyun 	if (!btcvsd->rx)
1300*4882a593Smuzhiyun 		return -ENOMEM;
1301*4882a593Smuzhiyun 
1302*4882a593Smuzhiyun 	btcvsd->tx = devm_kzalloc(btcvsd->dev, sizeof(*btcvsd->tx), GFP_KERNEL);
1303*4882a593Smuzhiyun 	if (!btcvsd->tx)
1304*4882a593Smuzhiyun 		return -ENOMEM;
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	spin_lock_init(&btcvsd->tx_lock);
1307*4882a593Smuzhiyun 	spin_lock_init(&btcvsd->rx_lock);
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun 	init_waitqueue_head(&btcvsd->tx_wait);
1310*4882a593Smuzhiyun 	init_waitqueue_head(&btcvsd->rx_wait);
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 	mtk_btcvsd_snd_tx_init(btcvsd);
1313*4882a593Smuzhiyun 	mtk_btcvsd_snd_rx_init(btcvsd);
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun 	/* irq */
1316*4882a593Smuzhiyun 	irq_id = platform_get_irq(pdev, 0);
1317*4882a593Smuzhiyun 	if (irq_id <= 0)
1318*4882a593Smuzhiyun 		return irq_id < 0 ? irq_id : -ENXIO;
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 	ret = devm_request_irq(dev, irq_id, mtk_btcvsd_snd_irq_handler,
1321*4882a593Smuzhiyun 			       IRQF_TRIGGER_LOW, "BTCVSD_ISR_Handle",
1322*4882a593Smuzhiyun 			       (void *)btcvsd);
1323*4882a593Smuzhiyun 	if (ret) {
1324*4882a593Smuzhiyun 		dev_err(dev, "could not request_irq for BTCVSD_ISR_Handle\n");
1325*4882a593Smuzhiyun 		return ret;
1326*4882a593Smuzhiyun 	}
1327*4882a593Smuzhiyun 
1328*4882a593Smuzhiyun 	btcvsd->irq_id = irq_id;
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 	/* iomap */
1331*4882a593Smuzhiyun 	btcvsd->bt_pkv_base = of_iomap(dev->of_node, 0);
1332*4882a593Smuzhiyun 	if (!btcvsd->bt_pkv_base) {
1333*4882a593Smuzhiyun 		dev_err(dev, "iomap bt_pkv_base fail\n");
1334*4882a593Smuzhiyun 		return -EIO;
1335*4882a593Smuzhiyun 	}
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 	btcvsd->bt_sram_bank2_base = of_iomap(dev->of_node, 1);
1338*4882a593Smuzhiyun 	if (!btcvsd->bt_sram_bank2_base) {
1339*4882a593Smuzhiyun 		dev_err(dev, "iomap bt_sram_bank2_base fail\n");
1340*4882a593Smuzhiyun 		ret = -EIO;
1341*4882a593Smuzhiyun 		goto unmap_pkv_err;
1342*4882a593Smuzhiyun 	}
1343*4882a593Smuzhiyun 
1344*4882a593Smuzhiyun 	btcvsd->infra = syscon_regmap_lookup_by_phandle(dev->of_node,
1345*4882a593Smuzhiyun 							"mediatek,infracfg");
1346*4882a593Smuzhiyun 	if (IS_ERR(btcvsd->infra)) {
1347*4882a593Smuzhiyun 		dev_err(dev, "cannot find infra controller: %ld\n",
1348*4882a593Smuzhiyun 			PTR_ERR(btcvsd->infra));
1349*4882a593Smuzhiyun 		ret = PTR_ERR(btcvsd->infra);
1350*4882a593Smuzhiyun 		goto unmap_bank2_err;
1351*4882a593Smuzhiyun 	}
1352*4882a593Smuzhiyun 
1353*4882a593Smuzhiyun 	/* get offset */
1354*4882a593Smuzhiyun 	ret = of_property_read_u32_array(dev->of_node, "mediatek,offset",
1355*4882a593Smuzhiyun 					 offset,
1356*4882a593Smuzhiyun 					 ARRAY_SIZE(offset));
1357*4882a593Smuzhiyun 	if (ret) {
1358*4882a593Smuzhiyun 		dev_warn(dev, "%s(), get offset fail, ret %d\n", __func__, ret);
1359*4882a593Smuzhiyun 		goto unmap_bank2_err;
1360*4882a593Smuzhiyun 	}
1361*4882a593Smuzhiyun 	btcvsd->infra_misc_offset = offset[0];
1362*4882a593Smuzhiyun 	btcvsd->conn_bt_cvsd_mask = offset[1];
1363*4882a593Smuzhiyun 	btcvsd->cvsd_mcu_read_offset = offset[2];
1364*4882a593Smuzhiyun 	btcvsd->cvsd_mcu_write_offset = offset[3];
1365*4882a593Smuzhiyun 	btcvsd->cvsd_packet_indicator = offset[4];
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 	btcvsd->bt_reg_pkt_r = btcvsd->bt_pkv_base +
1368*4882a593Smuzhiyun 			       btcvsd->cvsd_mcu_read_offset;
1369*4882a593Smuzhiyun 	btcvsd->bt_reg_pkt_w = btcvsd->bt_pkv_base +
1370*4882a593Smuzhiyun 			       btcvsd->cvsd_mcu_write_offset;
1371*4882a593Smuzhiyun 	btcvsd->bt_reg_ctl = btcvsd->bt_pkv_base +
1372*4882a593Smuzhiyun 			     btcvsd->cvsd_packet_indicator;
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun 	/* init state */
1375*4882a593Smuzhiyun 	mtk_btcvsd_snd_set_state(btcvsd, btcvsd->tx, BT_SCO_STATE_IDLE);
1376*4882a593Smuzhiyun 	mtk_btcvsd_snd_set_state(btcvsd, btcvsd->rx, BT_SCO_STATE_IDLE);
1377*4882a593Smuzhiyun 
1378*4882a593Smuzhiyun 	ret = devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform,
1379*4882a593Smuzhiyun 					      NULL, 0);
1380*4882a593Smuzhiyun 	if (ret)
1381*4882a593Smuzhiyun 		goto unmap_bank2_err;
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun 	return 0;
1384*4882a593Smuzhiyun 
1385*4882a593Smuzhiyun unmap_bank2_err:
1386*4882a593Smuzhiyun 	iounmap(btcvsd->bt_sram_bank2_base);
1387*4882a593Smuzhiyun unmap_pkv_err:
1388*4882a593Smuzhiyun 	iounmap(btcvsd->bt_pkv_base);
1389*4882a593Smuzhiyun 	return ret;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun 
mtk_btcvsd_snd_remove(struct platform_device * pdev)1392*4882a593Smuzhiyun static int mtk_btcvsd_snd_remove(struct platform_device *pdev)
1393*4882a593Smuzhiyun {
1394*4882a593Smuzhiyun 	struct mtk_btcvsd_snd *btcvsd = dev_get_drvdata(&pdev->dev);
1395*4882a593Smuzhiyun 
1396*4882a593Smuzhiyun 	iounmap(btcvsd->bt_pkv_base);
1397*4882a593Smuzhiyun 	iounmap(btcvsd->bt_sram_bank2_base);
1398*4882a593Smuzhiyun 	return 0;
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun 
1401*4882a593Smuzhiyun static const struct of_device_id mtk_btcvsd_snd_dt_match[] = {
1402*4882a593Smuzhiyun 	{ .compatible = "mediatek,mtk-btcvsd-snd", },
1403*4882a593Smuzhiyun 	{},
1404*4882a593Smuzhiyun };
1405*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mtk_btcvsd_snd_dt_match);
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun static struct platform_driver mtk_btcvsd_snd_driver = {
1408*4882a593Smuzhiyun 	.driver = {
1409*4882a593Smuzhiyun 		.name = "mtk-btcvsd-snd",
1410*4882a593Smuzhiyun 		.of_match_table = mtk_btcvsd_snd_dt_match,
1411*4882a593Smuzhiyun 	},
1412*4882a593Smuzhiyun 	.probe = mtk_btcvsd_snd_probe,
1413*4882a593Smuzhiyun 	.remove = mtk_btcvsd_snd_remove,
1414*4882a593Smuzhiyun };
1415*4882a593Smuzhiyun 
1416*4882a593Smuzhiyun module_platform_driver(mtk_btcvsd_snd_driver);
1417*4882a593Smuzhiyun 
1418*4882a593Smuzhiyun MODULE_DESCRIPTION("Mediatek ALSA BT SCO CVSD/MSBC Driver");
1419*4882a593Smuzhiyun MODULE_AUTHOR("KaiChieh Chuang <kaichieh.chuang@mediatek.com>");
1420*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1421