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