Path: blob/master/sound/soc/mediatek/common/mtk-btcvsd.c
26450 views
// SPDX-License-Identifier: GPL-2.01//2// Mediatek ALSA BT SCO CVSD/MSBC Driver3//4// Copyright (c) 2019 MediaTek Inc.5// Author: KaiChieh Chuang <[email protected]>67#include <linux/mfd/syscon.h>8#include <linux/module.h>9#include <linux/of_address.h>10#include <linux/sched/clock.h>1112#include <sound/soc.h>1314#define BTCVSD_SND_NAME "mtk-btcvsd-snd"1516#define BT_CVSD_TX_NREADY BIT(21)17#define BT_CVSD_RX_READY BIT(22)18#define BT_CVSD_TX_UNDERFLOW BIT(23)19#define BT_CVSD_RX_OVERFLOW BIT(24)20#define BT_CVSD_INTERRUPT BIT(31)2122#define BT_CVSD_CLEAR \23(BT_CVSD_TX_NREADY | BT_CVSD_RX_READY | BT_CVSD_TX_UNDERFLOW |\24BT_CVSD_RX_OVERFLOW | BT_CVSD_INTERRUPT)2526/* TX */27#define SCO_TX_ENCODE_SIZE (60)28/* 18 = 6 * 180 / SCO_TX_ENCODE_SIZE */29#define SCO_TX_PACKER_BUF_NUM (18)3031/* RX */32#define SCO_RX_PLC_SIZE (30)33#define SCO_RX_PACKER_BUF_NUM (64)34#define SCO_RX_PACKET_MASK (0x3F)3536#define SCO_CVSD_PACKET_VALID_SIZE 23738#define SCO_PACKET_120 12039#define SCO_PACKET_180 1804041#define BTCVSD_RX_PACKET_SIZE (SCO_RX_PLC_SIZE + SCO_CVSD_PACKET_VALID_SIZE)42#define BTCVSD_TX_PACKET_SIZE (SCO_TX_ENCODE_SIZE)4344#define BTCVSD_RX_BUF_SIZE (BTCVSD_RX_PACKET_SIZE * SCO_RX_PACKER_BUF_NUM)45#define BTCVSD_TX_BUF_SIZE (BTCVSD_TX_PACKET_SIZE * SCO_TX_PACKER_BUF_NUM)4647enum bt_sco_state {48BT_SCO_STATE_IDLE,49BT_SCO_STATE_RUNNING,50BT_SCO_STATE_ENDING,51BT_SCO_STATE_LOOPBACK,52};5354enum bt_sco_direct {55BT_SCO_DIRECT_BT2ARM,56BT_SCO_DIRECT_ARM2BT,57};5859enum bt_sco_packet_len {60BT_SCO_CVSD_30 = 0,61BT_SCO_CVSD_60,62BT_SCO_CVSD_90,63BT_SCO_CVSD_120,64BT_SCO_CVSD_10,65BT_SCO_CVSD_20,66BT_SCO_CVSD_MAX,67};6869enum BT_SCO_BAND {70BT_SCO_NB,71BT_SCO_WB,72};7374struct mtk_btcvsd_snd_hw_info {75unsigned int num_valid_addr;76unsigned long bt_sram_addr[20];77unsigned int packet_length;78unsigned int packet_num;79};8081struct mtk_btcvsd_snd_stream {82struct snd_pcm_substream *substream;83int stream;8485enum bt_sco_state state;8687unsigned int packet_size;88unsigned int buf_size;89u8 temp_packet_buf[SCO_PACKET_180];9091int packet_w;92int packet_r;93snd_pcm_uframes_t prev_frame;94int prev_packet_idx;9596unsigned int xrun:1;97unsigned int timeout:1;98unsigned int mute:1;99unsigned int trigger_start:1;100unsigned int wait_flag:1;101unsigned int rw_cnt;102103unsigned long long time_stamp;104unsigned long long buf_data_equivalent_time;105106struct mtk_btcvsd_snd_hw_info buffer_info;107};108109struct mtk_btcvsd_snd {110struct device *dev;111int irq_id;112113struct regmap *infra;114void __iomem *bt_pkv_base;115void __iomem *bt_sram_bank2_base;116117unsigned int infra_misc_offset;118unsigned int conn_bt_cvsd_mask;119unsigned int cvsd_mcu_read_offset;120unsigned int cvsd_mcu_write_offset;121unsigned int cvsd_packet_indicator;122123u32 *bt_reg_pkt_r;124u32 *bt_reg_pkt_w;125u32 *bt_reg_ctl;126127unsigned int irq_disabled:1;128129spinlock_t tx_lock; /* spinlock for bt tx stream control */130spinlock_t rx_lock; /* spinlock for bt rx stream control */131wait_queue_head_t tx_wait;132wait_queue_head_t rx_wait;133134struct mtk_btcvsd_snd_stream *tx;135struct mtk_btcvsd_snd_stream *rx;136u8 tx_packet_buf[BTCVSD_TX_BUF_SIZE];137u8 rx_packet_buf[BTCVSD_RX_BUF_SIZE];138139enum BT_SCO_BAND band;140};141142struct mtk_btcvsd_snd_time_buffer_info {143unsigned long long data_count_equi_time;144unsigned long long time_stamp_us;145};146147static const unsigned int btsco_packet_valid_mask[BT_SCO_CVSD_MAX][6] = {148{0x1, 0x1 << 1, 0x1 << 2, 0x1 << 3, 0x1 << 4, 0x1 << 5},149{0x1, 0x1, 0x2, 0x2, 0x4, 0x4},150{0x1, 0x1, 0x1, 0x2, 0x2, 0x2},151{0x1, 0x1, 0x1, 0x1, 0x0, 0x0},152{0x7, 0x7 << 3, 0x7 << 6, 0x7 << 9, 0x7 << 12, 0x7 << 15},153{0x3, 0x3 << 1, 0x3 << 3, 0x3 << 4, 0x3 << 6, 0x3 << 7},154};155156static const unsigned int btsco_packet_info[BT_SCO_CVSD_MAX][4] = {157{30, 6, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,158SCO_PACKET_180 / SCO_RX_PLC_SIZE},159{60, 3, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,160SCO_PACKET_180 / SCO_RX_PLC_SIZE},161{90, 2, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,162SCO_PACKET_180 / SCO_RX_PLC_SIZE},163{120, 1, SCO_PACKET_120 / SCO_TX_ENCODE_SIZE,164SCO_PACKET_120 / SCO_RX_PLC_SIZE},165{10, 18, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,166SCO_PACKET_180 / SCO_RX_PLC_SIZE},167{20, 9, SCO_PACKET_180 / SCO_TX_ENCODE_SIZE,168SCO_PACKET_180 / SCO_RX_PLC_SIZE},169};170171static const u8 table_msbc_silence[SCO_PACKET_180] = {1720x01, 0x38, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,1730x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d,1740xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7,1750x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd,1760xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,1770x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00,1780x01, 0xc8, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,1790x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d,1800xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7,1810x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd,1820xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,1830x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00,1840x01, 0xf8, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,1850x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d,1860xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7,1870x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd,1880xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,1890x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00190};191192static void mtk_btcvsd_snd_irq_enable(struct mtk_btcvsd_snd *bt)193{194regmap_update_bits(bt->infra, bt->infra_misc_offset,195bt->conn_bt_cvsd_mask, 0);196}197198static void mtk_btcvsd_snd_irq_disable(struct mtk_btcvsd_snd *bt)199{200regmap_update_bits(bt->infra, bt->infra_misc_offset,201bt->conn_bt_cvsd_mask, bt->conn_bt_cvsd_mask);202}203204static void mtk_btcvsd_snd_set_state(struct mtk_btcvsd_snd *bt,205struct mtk_btcvsd_snd_stream *bt_stream,206int state)207{208dev_dbg(bt->dev, "%s(), stream %d, state %d, tx->state %d, rx->state %d, irq_disabled %d\n",209__func__,210bt_stream->stream, state,211bt->tx->state, bt->rx->state, bt->irq_disabled);212213bt_stream->state = state;214215if (bt->tx->state == BT_SCO_STATE_IDLE &&216bt->rx->state == BT_SCO_STATE_IDLE) {217if (!bt->irq_disabled) {218disable_irq(bt->irq_id);219mtk_btcvsd_snd_irq_disable(bt);220bt->irq_disabled = 1;221}222} else {223if (bt->irq_disabled) {224enable_irq(bt->irq_id);225mtk_btcvsd_snd_irq_enable(bt);226bt->irq_disabled = 0;227}228}229}230231static int mtk_btcvsd_snd_tx_init(struct mtk_btcvsd_snd *bt)232{233memset(bt->tx, 0, sizeof(*bt->tx));234memset(bt->tx_packet_buf, 0, sizeof(bt->tx_packet_buf));235236bt->tx->packet_size = BTCVSD_TX_PACKET_SIZE;237bt->tx->buf_size = BTCVSD_TX_BUF_SIZE;238bt->tx->timeout = 0;239bt->tx->rw_cnt = 0;240bt->tx->stream = SNDRV_PCM_STREAM_PLAYBACK;241return 0;242}243244static int mtk_btcvsd_snd_rx_init(struct mtk_btcvsd_snd *bt)245{246memset(bt->rx, 0, sizeof(*bt->rx));247memset(bt->rx_packet_buf, 0, sizeof(bt->rx_packet_buf));248249bt->rx->packet_size = BTCVSD_RX_PACKET_SIZE;250bt->rx->buf_size = BTCVSD_RX_BUF_SIZE;251bt->rx->timeout = 0;252bt->rx->rw_cnt = 0;253bt->rx->stream = SNDRV_PCM_STREAM_CAPTURE;254return 0;255}256257static void get_tx_time_stamp(struct mtk_btcvsd_snd *bt,258struct mtk_btcvsd_snd_time_buffer_info *ts)259{260ts->time_stamp_us = bt->tx->time_stamp;261ts->data_count_equi_time = bt->tx->buf_data_equivalent_time;262}263264static void get_rx_time_stamp(struct mtk_btcvsd_snd *bt,265struct mtk_btcvsd_snd_time_buffer_info *ts)266{267ts->time_stamp_us = bt->rx->time_stamp;268ts->data_count_equi_time = bt->rx->buf_data_equivalent_time;269}270271static int btcvsd_bytes_to_frame(struct snd_pcm_substream *substream,272int bytes)273{274int count = bytes;275struct snd_pcm_runtime *runtime = substream->runtime;276277if (runtime->format == SNDRV_PCM_FORMAT_S32_LE ||278runtime->format == SNDRV_PCM_FORMAT_U32_LE)279count = count >> 2;280else281count = count >> 1;282283count = count / runtime->channels;284return count;285}286287static void mtk_btcvsd_snd_data_transfer(enum bt_sco_direct dir,288u8 *src, u8 *dst,289unsigned int blk_size,290unsigned int blk_num)291{292unsigned int i, j;293294if (blk_size == 60 || blk_size == 120 || blk_size == 20) {295u32 *src_32 = (u32 *)src;296u32 *dst_32 = (u32 *)dst;297298for (i = 0; i < (blk_size * blk_num / 4); i++)299*dst_32++ = *src_32++;300} else {301u16 *src_16 = (u16 *)src;302u16 *dst_16 = (u16 *)dst;303304for (j = 0; j < blk_num; j++) {305for (i = 0; i < (blk_size / 2); i++)306*dst_16++ = *src_16++;307308if (dir == BT_SCO_DIRECT_BT2ARM)309src_16++;310else311dst_16++;312}313}314}315316/* write encoded mute data to bt sram */317static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt)318{319unsigned int i;320unsigned int num_valid_addr;321unsigned long flags;322enum BT_SCO_BAND band = bt->band;323324/* prepare encoded mute data */325if (band == BT_SCO_NB)326memset(bt->tx->temp_packet_buf, 170, SCO_PACKET_180);327else328memcpy(bt->tx->temp_packet_buf,329table_msbc_silence, SCO_PACKET_180);330331/* write mute data to bt tx sram buffer */332spin_lock_irqsave(&bt->tx_lock, flags);333num_valid_addr = bt->tx->buffer_info.num_valid_addr;334335dev_info(bt->dev, "%s(), band %d, num_valid_addr %u\n",336__func__, band, num_valid_addr);337338for (i = 0; i < num_valid_addr; i++) {339void *dst;340341dev_info(bt->dev, "%s(), clean addr 0x%lx\n", __func__,342bt->tx->buffer_info.bt_sram_addr[i]);343344dst = (void *)bt->tx->buffer_info.bt_sram_addr[i];345346mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,347bt->tx->temp_packet_buf, dst,348bt->tx->buffer_info.packet_length,349bt->tx->buffer_info.packet_num);350}351spin_unlock_irqrestore(&bt->tx_lock, flags);352353return 0;354}355356static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt,357enum bt_sco_packet_len packet_type,358unsigned int packet_length,359unsigned int packet_num,360unsigned int blk_size,361unsigned int control)362{363unsigned int i;364int pv;365u8 *src;366unsigned int packet_buf_ofs;367unsigned long flags;368unsigned long connsys_addr_rx, ap_addr_rx;369370connsys_addr_rx = *bt->bt_reg_pkt_r;371ap_addr_rx = (unsigned long)bt->bt_sram_bank2_base +372(connsys_addr_rx & 0xFFFF);373374if (connsys_addr_rx == 0xdeadfeed) {375/* bt return 0xdeadfeed if read register during bt sleep */376dev_warn(bt->dev, "%s(), connsys_addr_rx == 0xdeadfeed",377__func__);378return -EIO;379}380381src = (u8 *)ap_addr_rx;382383mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_BT2ARM, src,384bt->rx->temp_packet_buf, packet_length,385packet_num);386387spin_lock_irqsave(&bt->rx_lock, flags);388for (i = 0; i < blk_size; i++) {389packet_buf_ofs = (bt->rx->packet_w & SCO_RX_PACKET_MASK) *390bt->rx->packet_size;391memcpy(bt->rx_packet_buf + packet_buf_ofs,392bt->rx->temp_packet_buf + (SCO_RX_PLC_SIZE * i),393SCO_RX_PLC_SIZE);394if ((control & btsco_packet_valid_mask[packet_type][i]) ==395btsco_packet_valid_mask[packet_type][i])396pv = 1;397else398pv = 0;399400packet_buf_ofs += SCO_RX_PLC_SIZE;401memcpy(bt->rx_packet_buf + packet_buf_ofs, (void *)&pv,402SCO_CVSD_PACKET_VALID_SIZE);403bt->rx->packet_w++;404}405spin_unlock_irqrestore(&bt->rx_lock, flags);406return 0;407}408409static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt,410enum bt_sco_packet_len packet_type,411unsigned int packet_length,412unsigned int packet_num,413unsigned int blk_size)414{415unsigned int i;416unsigned long flags;417u8 *dst;418unsigned long connsys_addr_tx, ap_addr_tx;419bool new_ap_addr_tx = true;420421connsys_addr_tx = *bt->bt_reg_pkt_w;422ap_addr_tx = (unsigned long)bt->bt_sram_bank2_base +423(connsys_addr_tx & 0xFFFF);424425if (connsys_addr_tx == 0xdeadfeed) {426/* bt return 0xdeadfeed if read register during bt sleep */427dev_warn(bt->dev, "%s(), connsys_addr_tx == 0xdeadfeed\n",428__func__);429return -EIO;430}431432spin_lock_irqsave(&bt->tx_lock, flags);433for (i = 0; i < blk_size; i++) {434memcpy(bt->tx->temp_packet_buf + (bt->tx->packet_size * i),435(bt->tx_packet_buf +436(bt->tx->packet_r % SCO_TX_PACKER_BUF_NUM) *437bt->tx->packet_size),438bt->tx->packet_size);439440bt->tx->packet_r++;441}442spin_unlock_irqrestore(&bt->tx_lock, flags);443444dst = (u8 *)ap_addr_tx;445446if (!bt->tx->mute) {447mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,448bt->tx->temp_packet_buf, dst,449packet_length, packet_num);450}451452/* store bt tx buffer sram info */453bt->tx->buffer_info.packet_length = packet_length;454bt->tx->buffer_info.packet_num = packet_num;455for (i = 0; i < bt->tx->buffer_info.num_valid_addr; i++) {456if (bt->tx->buffer_info.bt_sram_addr[i] == ap_addr_tx) {457new_ap_addr_tx = false;458break;459}460}461if (new_ap_addr_tx) {462unsigned int next_idx;463464spin_lock_irqsave(&bt->tx_lock, flags);465bt->tx->buffer_info.num_valid_addr++;466next_idx = bt->tx->buffer_info.num_valid_addr - 1;467bt->tx->buffer_info.bt_sram_addr[next_idx] = ap_addr_tx;468spin_unlock_irqrestore(&bt->tx_lock, flags);469dev_info(bt->dev, "%s(), new ap_addr_tx = 0x%lx, num_valid_addr %d\n",470__func__, ap_addr_tx,471bt->tx->buffer_info.num_valid_addr);472}473474if (bt->tx->mute)475btcvsd_tx_clean_buffer(bt);476477return 0;478}479480static irqreturn_t mtk_btcvsd_snd_irq_handler(int irq_id, void *dev)481{482struct mtk_btcvsd_snd *bt = dev;483unsigned int packet_type, packet_num, packet_length;484unsigned int buf_cnt_tx, buf_cnt_rx, control;485486if (bt->rx->state != BT_SCO_STATE_RUNNING &&487bt->rx->state != BT_SCO_STATE_ENDING &&488bt->tx->state != BT_SCO_STATE_RUNNING &&489bt->tx->state != BT_SCO_STATE_ENDING &&490bt->tx->state != BT_SCO_STATE_LOOPBACK) {491dev_warn(bt->dev, "%s(), in idle state: rx->state: %d, tx->state: %d\n",492__func__, bt->rx->state, bt->tx->state);493goto irq_handler_exit;494}495496control = *bt->bt_reg_ctl;497packet_type = (control >> 18) & 0x7;498499if (((control >> 31) & 1) == 0) {500dev_warn(bt->dev, "%s(), ((control >> 31) & 1) == 0, control 0x%x\n",501__func__, control);502goto irq_handler_exit;503}504505if (packet_type >= BT_SCO_CVSD_MAX) {506dev_warn(bt->dev, "%s(), invalid packet_type %u, exit\n",507__func__, packet_type);508goto irq_handler_exit;509}510511packet_length = btsco_packet_info[packet_type][0];512packet_num = btsco_packet_info[packet_type][1];513buf_cnt_tx = btsco_packet_info[packet_type][2];514buf_cnt_rx = btsco_packet_info[packet_type][3];515516if (bt->tx->state == BT_SCO_STATE_LOOPBACK) {517u8 *src, *dst;518unsigned long connsys_addr_rx, ap_addr_rx;519unsigned long connsys_addr_tx, ap_addr_tx;520521connsys_addr_rx = *bt->bt_reg_pkt_r;522ap_addr_rx = (unsigned long)bt->bt_sram_bank2_base +523(connsys_addr_rx & 0xFFFF);524525connsys_addr_tx = *bt->bt_reg_pkt_w;526ap_addr_tx = (unsigned long)bt->bt_sram_bank2_base +527(connsys_addr_tx & 0xFFFF);528529if (connsys_addr_tx == 0xdeadfeed ||530connsys_addr_rx == 0xdeadfeed) {531/* bt return 0xdeadfeed if read reg during bt sleep */532dev_warn(bt->dev, "%s(), connsys_addr_tx == 0xdeadfeed\n",533__func__);534goto irq_handler_exit;535}536537src = (u8 *)ap_addr_rx;538dst = (u8 *)ap_addr_tx;539540mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_BT2ARM, src,541bt->tx->temp_packet_buf,542packet_length,543packet_num);544mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,545bt->tx->temp_packet_buf, dst,546packet_length,547packet_num);548bt->rx->rw_cnt++;549bt->tx->rw_cnt++;550}551552if (bt->rx->state == BT_SCO_STATE_RUNNING ||553bt->rx->state == BT_SCO_STATE_ENDING) {554if (bt->rx->xrun) {555if (bt->rx->packet_w - bt->rx->packet_r <=556SCO_RX_PACKER_BUF_NUM - 2 * buf_cnt_rx) {557/*558* free space is larger then559* twice interrupt rx data size560*/561bt->rx->xrun = 0;562dev_warn(bt->dev, "%s(), rx->xrun 0!\n",563__func__);564}565}566567if (!bt->rx->xrun &&568(bt->rx->packet_w - bt->rx->packet_r <=569SCO_RX_PACKER_BUF_NUM - buf_cnt_rx)) {570mtk_btcvsd_read_from_bt(bt,571packet_type,572packet_length,573packet_num,574buf_cnt_rx,575control);576bt->rx->rw_cnt++;577} else {578bt->rx->xrun = 1;579dev_warn(bt->dev, "%s(), rx->xrun 1\n", __func__);580}581}582583/* tx */584bt->tx->timeout = 0;585if ((bt->tx->state == BT_SCO_STATE_RUNNING ||586bt->tx->state == BT_SCO_STATE_ENDING) &&587bt->tx->trigger_start) {588if (bt->tx->xrun) {589/* prepared data is larger then twice590* interrupt tx data size591*/592if (bt->tx->packet_w - bt->tx->packet_r >=5932 * buf_cnt_tx) {594bt->tx->xrun = 0;595dev_warn(bt->dev, "%s(), tx->xrun 0\n",596__func__);597}598}599600if ((!bt->tx->xrun &&601(bt->tx->packet_w - bt->tx->packet_r >= buf_cnt_tx)) ||602bt->tx->state == BT_SCO_STATE_ENDING) {603mtk_btcvsd_write_to_bt(bt,604packet_type,605packet_length,606packet_num,607buf_cnt_tx);608bt->tx->rw_cnt++;609} else {610bt->tx->xrun = 1;611dev_warn(bt->dev, "%s(), tx->xrun 1\n", __func__);612}613}614615*bt->bt_reg_ctl &= ~BT_CVSD_CLEAR;616617if (bt->rx->state == BT_SCO_STATE_RUNNING ||618bt->rx->state == BT_SCO_STATE_ENDING) {619bt->rx->wait_flag = 1;620wake_up_interruptible(&bt->rx_wait);621snd_pcm_period_elapsed(bt->rx->substream);622}623if (bt->tx->state == BT_SCO_STATE_RUNNING ||624bt->tx->state == BT_SCO_STATE_ENDING) {625bt->tx->wait_flag = 1;626wake_up_interruptible(&bt->tx_wait);627snd_pcm_period_elapsed(bt->tx->substream);628}629630return IRQ_HANDLED;631irq_handler_exit:632*bt->bt_reg_ctl &= ~BT_CVSD_CLEAR;633return IRQ_HANDLED;634}635636static int wait_for_bt_irq(struct mtk_btcvsd_snd *bt,637struct mtk_btcvsd_snd_stream *bt_stream)638{639unsigned long long t1, t2;640/* one interrupt period = 22.5ms */641unsigned long long timeout_limit = 22500000;642int max_timeout_trial = 2;643int ret;644645bt_stream->wait_flag = 0;646647while (max_timeout_trial && !bt_stream->wait_flag) {648t1 = sched_clock();649if (bt_stream->stream == SNDRV_PCM_STREAM_PLAYBACK) {650ret = wait_event_interruptible_timeout(bt->tx_wait,651bt_stream->wait_flag,652nsecs_to_jiffies(timeout_limit));653} else {654ret = wait_event_interruptible_timeout(bt->rx_wait,655bt_stream->wait_flag,656nsecs_to_jiffies(timeout_limit));657}658659t2 = sched_clock();660t2 = t2 - t1; /* in ns (10^9) */661662if (t2 > timeout_limit) {663dev_warn(bt->dev, "%s(), stream %d, timeout %llu, limit %llu, ret %d, flag %d\n",664__func__, bt_stream->stream,665t2, timeout_limit, ret,666bt_stream->wait_flag);667}668669if (ret < 0) {670/*671* error, -ERESTARTSYS if it was interrupted by672* a signal673*/674dev_warn(bt->dev, "%s(), stream %d, error, trial left %d\n",675__func__,676bt_stream->stream, max_timeout_trial);677678bt_stream->timeout = 1;679return ret;680} else if (ret == 0) {681/* conidtion is false after timeout */682max_timeout_trial--;683dev_warn(bt->dev, "%s(), stream %d, error, timeout, condition is false, trial left %d\n",684__func__,685bt_stream->stream, max_timeout_trial);686687if (max_timeout_trial <= 0) {688bt_stream->timeout = 1;689return -ETIME;690}691}692}693694return 0;695}696697static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt,698struct iov_iter *buf,699size_t count)700{701ssize_t read_size = 0, read_count = 0, cur_read_idx, cont;702unsigned long avail;703unsigned long flags;704unsigned int packet_size = bt->rx->packet_size;705706while (count) {707spin_lock_irqsave(&bt->rx_lock, flags);708/* available data in RX packet buffer */709avail = (bt->rx->packet_w - bt->rx->packet_r) * packet_size;710711cur_read_idx = (bt->rx->packet_r & SCO_RX_PACKET_MASK) *712packet_size;713spin_unlock_irqrestore(&bt->rx_lock, flags);714715if (!avail) {716int ret = wait_for_bt_irq(bt, bt->rx);717718if (ret)719return read_count;720721continue;722}723724/* count must be multiple of packet_size */725if (count % packet_size != 0 ||726avail % packet_size != 0) {727dev_warn(bt->dev, "%s(), count %zu or d %lu is not multiple of packet_size %dd\n",728__func__, count, avail, packet_size);729730count -= count % packet_size;731avail -= avail % packet_size;732}733734if (count > avail)735read_size = avail;736else737read_size = count;738739/* calculate continue space */740cont = bt->rx->buf_size - cur_read_idx;741if (read_size > cont)742read_size = cont;743744if (copy_to_iter(bt->rx_packet_buf + cur_read_idx,745read_size, buf) != read_size) {746dev_warn(bt->dev, "%s(), copy_to_iter fail\n",747__func__);748return -EFAULT;749}750751spin_lock_irqsave(&bt->rx_lock, flags);752bt->rx->packet_r += read_size / packet_size;753spin_unlock_irqrestore(&bt->rx_lock, flags);754755read_count += read_size;756count -= read_size;757}758759/*760* save current timestamp & buffer time in times_tamp and761* buf_data_equivalent_time762*/763bt->rx->time_stamp = sched_clock();764bt->rx->buf_data_equivalent_time =765(unsigned long long)(bt->rx->packet_w - bt->rx->packet_r) *766SCO_RX_PLC_SIZE * 16 * 1000 / 2 / 64;767bt->rx->buf_data_equivalent_time += read_count * SCO_RX_PLC_SIZE *76816 * 1000 / packet_size / 2 / 64;769/* return equivalent time(us) to data count */770bt->rx->buf_data_equivalent_time *= 1000;771772return read_count;773}774775static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt,776struct iov_iter *buf,777size_t count)778{779int written_size = count, avail, cur_write_idx, write_size, cont;780unsigned long flags;781unsigned int packet_size = bt->tx->packet_size;782783/*784* save current timestamp & buffer time in time_stamp and785* buf_data_equivalent_time786*/787bt->tx->time_stamp = sched_clock();788bt->tx->buf_data_equivalent_time =789(unsigned long long)(bt->tx->packet_w - bt->tx->packet_r) *790packet_size * 16 * 1000 / 2 / 64;791792/* return equivalent time(us) to data count */793bt->tx->buf_data_equivalent_time *= 1000;794795while (count) {796spin_lock_irqsave(&bt->tx_lock, flags);797/* free space of TX packet buffer */798avail = bt->tx->buf_size -799(bt->tx->packet_w - bt->tx->packet_r) * packet_size;800801cur_write_idx = (bt->tx->packet_w % SCO_TX_PACKER_BUF_NUM) *802packet_size;803spin_unlock_irqrestore(&bt->tx_lock, flags);804805if (!avail) {806int ret = wait_for_bt_irq(bt, bt->tx);807808if (ret)809return written_size;810811continue;812}813814/* count must be multiple of bt->tx->packet_size */815if (count % packet_size != 0 ||816avail % packet_size != 0) {817dev_warn(bt->dev, "%s(), count %zu or avail %d is not multiple of packet_size %d\n",818__func__, count, avail, packet_size);819count -= count % packet_size;820avail -= avail % packet_size;821}822823if (count > avail)824write_size = avail;825else826write_size = count;827828/* calculate continue space */829cont = bt->tx->buf_size - cur_write_idx;830if (write_size > cont)831write_size = cont;832833if (copy_from_iter(bt->tx_packet_buf + cur_write_idx,834write_size, buf) != write_size) {835dev_warn(bt->dev, "%s(), copy_from_iter fail\n",836__func__);837return -EFAULT;838}839840spin_lock_irqsave(&bt->tx_lock, flags);841bt->tx->packet_w += write_size / packet_size;842spin_unlock_irqrestore(&bt->tx_lock, flags);843count -= write_size;844}845846return written_size;847}848849static struct mtk_btcvsd_snd_stream *get_bt_stream850(struct mtk_btcvsd_snd *bt, struct snd_pcm_substream *substream)851{852if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)853return bt->tx;854else855return bt->rx;856}857858/* pcm ops */859static const struct snd_pcm_hardware mtk_btcvsd_hardware = {860.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |861SNDRV_PCM_INFO_RESUME),862.formats = SNDRV_PCM_FMTBIT_S16_LE,863.buffer_bytes_max = 24 * 1024,864.period_bytes_max = 24 * 1024,865.periods_min = 2,866.periods_max = 16,867.fifo_size = 0,868};869870static int mtk_pcm_btcvsd_open(struct snd_soc_component *component,871struct snd_pcm_substream *substream)872{873struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);874int ret;875876dev_dbg(bt->dev, "%s(), stream %d, substream %p\n",877__func__, substream->stream, substream);878879snd_soc_set_runtime_hwparams(substream, &mtk_btcvsd_hardware);880881if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {882ret = mtk_btcvsd_snd_tx_init(bt);883bt->tx->substream = substream;884} else {885ret = mtk_btcvsd_snd_rx_init(bt);886bt->rx->substream = substream;887}888889return ret;890}891892static int mtk_pcm_btcvsd_close(struct snd_soc_component *component,893struct snd_pcm_substream *substream)894{895struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);896struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);897898dev_dbg(bt->dev, "%s(), stream %d\n", __func__, substream->stream);899900mtk_btcvsd_snd_set_state(bt, bt_stream, BT_SCO_STATE_IDLE);901bt_stream->substream = NULL;902return 0;903}904905static int mtk_pcm_btcvsd_hw_params(struct snd_soc_component *component,906struct snd_pcm_substream *substream,907struct snd_pcm_hw_params *hw_params)908{909struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);910911if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&912params_buffer_bytes(hw_params) % bt->tx->packet_size != 0) {913dev_warn(bt->dev, "%s(), error, buffer size %d not valid\n",914__func__,915params_buffer_bytes(hw_params));916return -EINVAL;917}918919substream->runtime->dma_bytes = params_buffer_bytes(hw_params);920return 0;921}922923static int mtk_pcm_btcvsd_hw_free(struct snd_soc_component *component,924struct snd_pcm_substream *substream)925{926struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);927928if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)929btcvsd_tx_clean_buffer(bt);930931return 0;932}933934static int mtk_pcm_btcvsd_prepare(struct snd_soc_component *component,935struct snd_pcm_substream *substream)936{937struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);938struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);939940dev_dbg(bt->dev, "%s(), stream %d\n", __func__, substream->stream);941942mtk_btcvsd_snd_set_state(bt, bt_stream, BT_SCO_STATE_RUNNING);943return 0;944}945946static int mtk_pcm_btcvsd_trigger(struct snd_soc_component *component,947struct snd_pcm_substream *substream, int cmd)948{949struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);950struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);951int stream = substream->stream;952int hw_packet_ptr;953954dev_dbg(bt->dev, "%s(), stream %d, cmd %d\n",955__func__, substream->stream, cmd);956957switch (cmd) {958case SNDRV_PCM_TRIGGER_START:959case SNDRV_PCM_TRIGGER_RESUME:960hw_packet_ptr = stream == SNDRV_PCM_STREAM_PLAYBACK ?961bt_stream->packet_r : bt_stream->packet_w;962bt_stream->prev_packet_idx = hw_packet_ptr;963bt_stream->prev_frame = 0;964bt_stream->trigger_start = 1;965return 0;966case SNDRV_PCM_TRIGGER_STOP:967case SNDRV_PCM_TRIGGER_SUSPEND:968bt_stream->trigger_start = 0;969mtk_btcvsd_snd_set_state(bt, bt_stream, BT_SCO_STATE_ENDING);970return 0;971default:972return -EINVAL;973}974}975976static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer(977struct snd_soc_component *component,978struct snd_pcm_substream *substream)979{980struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);981struct mtk_btcvsd_snd_stream *bt_stream;982snd_pcm_uframes_t frame = 0;983int byte = 0;984int hw_packet_ptr;985int packet_diff;986spinlock_t *lock; /* spinlock for bt stream control */987unsigned long flags;988989if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {990lock = &bt->tx_lock;991bt_stream = bt->tx;992} else {993lock = &bt->rx_lock;994bt_stream = bt->rx;995}996997spin_lock_irqsave(lock, flags);998hw_packet_ptr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?999bt->tx->packet_r : bt->rx->packet_w;10001001/* get packet diff from last time */1002if (hw_packet_ptr >= bt_stream->prev_packet_idx) {1003packet_diff = hw_packet_ptr - bt_stream->prev_packet_idx;1004} else {1005/* integer overflow */1006packet_diff = (INT_MAX - bt_stream->prev_packet_idx) +1007(hw_packet_ptr - INT_MIN) + 1;1008}1009bt_stream->prev_packet_idx = hw_packet_ptr;10101011/* increased bytes */1012byte = packet_diff * bt_stream->packet_size;10131014frame = btcvsd_bytes_to_frame(substream, byte);1015frame += bt_stream->prev_frame;1016frame %= substream->runtime->buffer_size;10171018bt_stream->prev_frame = frame;10191020spin_unlock_irqrestore(lock, flags);10211022return frame;1023}10241025static int mtk_pcm_btcvsd_copy(struct snd_soc_component *component,1026struct snd_pcm_substream *substream,1027int channel, unsigned long pos,1028struct iov_iter *buf, unsigned long count)1029{1030struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);10311032if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)1033return mtk_btcvsd_snd_write(bt, buf, count);1034else1035return mtk_btcvsd_snd_read(bt, buf, count);1036}10371038/* kcontrol */1039static const char *const btsco_band_str[] = {"NB", "WB"};10401041static const struct soc_enum btcvsd_enum[] = {1042SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(btsco_band_str), btsco_band_str),1043};10441045static int btcvsd_band_get(struct snd_kcontrol *kcontrol,1046struct snd_ctl_elem_value *ucontrol)1047{1048struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1049struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);10501051ucontrol->value.integer.value[0] = bt->band;1052return 0;1053}10541055static int btcvsd_band_set(struct snd_kcontrol *kcontrol,1056struct snd_ctl_elem_value *ucontrol)1057{1058struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1059struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);1060struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;10611062if (ucontrol->value.enumerated.item[0] >= e->items)1063return -EINVAL;10641065bt->band = ucontrol->value.integer.value[0];1066dev_dbg(bt->dev, "%s(), band %d\n", __func__, bt->band);1067return 0;1068}10691070static int btcvsd_loopback_get(struct snd_kcontrol *kcontrol,1071struct snd_ctl_elem_value *ucontrol)1072{1073struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1074struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);1075bool lpbk_en = bt->tx->state == BT_SCO_STATE_LOOPBACK;10761077ucontrol->value.integer.value[0] = lpbk_en;1078return 0;1079}10801081static int btcvsd_loopback_set(struct snd_kcontrol *kcontrol,1082struct snd_ctl_elem_value *ucontrol)1083{1084struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1085struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);10861087if (ucontrol->value.integer.value[0]) {1088mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_LOOPBACK);1089mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_LOOPBACK);1090} else {1091mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_RUNNING);1092mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_RUNNING);1093}1094return 0;1095}10961097static int btcvsd_tx_mute_get(struct snd_kcontrol *kcontrol,1098struct snd_ctl_elem_value *ucontrol)1099{1100struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1101struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);11021103if (!bt->tx) {1104ucontrol->value.integer.value[0] = 0;1105return 0;1106}11071108ucontrol->value.integer.value[0] = bt->tx->mute;1109return 0;1110}11111112static int btcvsd_tx_mute_set(struct snd_kcontrol *kcontrol,1113struct snd_ctl_elem_value *ucontrol)1114{1115struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1116struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);11171118if (!bt->tx)1119return 0;11201121bt->tx->mute = ucontrol->value.integer.value[0];1122return 0;1123}11241125static int btcvsd_rx_irq_received_get(struct snd_kcontrol *kcontrol,1126struct snd_ctl_elem_value *ucontrol)1127{1128struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1129struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);11301131if (!bt->rx)1132return 0;11331134ucontrol->value.integer.value[0] = bt->rx->rw_cnt ? 1 : 0;1135return 0;1136}11371138static int btcvsd_rx_timeout_get(struct snd_kcontrol *kcontrol,1139struct snd_ctl_elem_value *ucontrol)1140{1141struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1142struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);11431144if (!bt->rx)1145return 0;11461147ucontrol->value.integer.value[0] = bt->rx->timeout;1148bt->rx->timeout = 0;1149return 0;1150}11511152static int btcvsd_rx_timestamp_get(struct snd_kcontrol *kcontrol,1153unsigned int __user *data, unsigned int size)1154{1155struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1156struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);1157int ret = 0;1158struct mtk_btcvsd_snd_time_buffer_info time_buffer_info_rx;11591160if (size > sizeof(struct mtk_btcvsd_snd_time_buffer_info))1161return -EINVAL;11621163get_rx_time_stamp(bt, &time_buffer_info_rx);11641165dev_dbg(bt->dev, "%s(), time_stamp_us %llu, data_count_equi_time %llu",1166__func__,1167time_buffer_info_rx.time_stamp_us,1168time_buffer_info_rx.data_count_equi_time);11691170if (copy_to_user(data, &time_buffer_info_rx,1171sizeof(struct mtk_btcvsd_snd_time_buffer_info))) {1172dev_warn(bt->dev, "%s(), copy_to_user fail", __func__);1173ret = -EFAULT;1174}11751176return ret;1177}11781179static int btcvsd_tx_irq_received_get(struct snd_kcontrol *kcontrol,1180struct snd_ctl_elem_value *ucontrol)1181{1182struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1183struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);11841185if (!bt->tx)1186return 0;11871188ucontrol->value.integer.value[0] = bt->tx->rw_cnt ? 1 : 0;1189return 0;1190}11911192static int btcvsd_tx_timeout_get(struct snd_kcontrol *kcontrol,1193struct snd_ctl_elem_value *ucontrol)1194{1195struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1196struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);11971198ucontrol->value.integer.value[0] = bt->tx->timeout;1199return 0;1200}12011202static int btcvsd_tx_timestamp_get(struct snd_kcontrol *kcontrol,1203unsigned int __user *data, unsigned int size)1204{1205struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);1206struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);1207int ret = 0;1208struct mtk_btcvsd_snd_time_buffer_info time_buffer_info_tx;12091210if (size > sizeof(struct mtk_btcvsd_snd_time_buffer_info))1211return -EINVAL;12121213get_tx_time_stamp(bt, &time_buffer_info_tx);12141215dev_dbg(bt->dev, "%s(), time_stamp_us %llu, data_count_equi_time %llu",1216__func__,1217time_buffer_info_tx.time_stamp_us,1218time_buffer_info_tx.data_count_equi_time);12191220if (copy_to_user(data, &time_buffer_info_tx,1221sizeof(struct mtk_btcvsd_snd_time_buffer_info))) {1222dev_warn(bt->dev, "%s(), copy_to_user fail", __func__);1223ret = -EFAULT;1224}12251226return ret;1227}12281229static const struct snd_kcontrol_new mtk_btcvsd_snd_controls[] = {1230SOC_ENUM_EXT("BTCVSD Band", btcvsd_enum[0],1231btcvsd_band_get, btcvsd_band_set),1232SOC_SINGLE_BOOL_EXT("BTCVSD Loopback Switch", 0,1233btcvsd_loopback_get, btcvsd_loopback_set),1234SOC_SINGLE_BOOL_EXT("BTCVSD Tx Mute Switch", 0,1235btcvsd_tx_mute_get, btcvsd_tx_mute_set),1236SOC_SINGLE_BOOL_EXT("BTCVSD Tx Irq Received Switch", 0,1237btcvsd_tx_irq_received_get, NULL),1238SOC_SINGLE_BOOL_EXT("BTCVSD Tx Timeout Switch", 0,1239btcvsd_tx_timeout_get, NULL),1240SOC_SINGLE_BOOL_EXT("BTCVSD Rx Irq Received Switch", 0,1241btcvsd_rx_irq_received_get, NULL),1242SOC_SINGLE_BOOL_EXT("BTCVSD Rx Timeout Switch", 0,1243btcvsd_rx_timeout_get, NULL),1244SND_SOC_BYTES_TLV("BTCVSD Rx Timestamp",1245sizeof(struct mtk_btcvsd_snd_time_buffer_info),1246btcvsd_rx_timestamp_get, NULL),1247SND_SOC_BYTES_TLV("BTCVSD Tx Timestamp",1248sizeof(struct mtk_btcvsd_snd_time_buffer_info),1249btcvsd_tx_timestamp_get, NULL),1250};12511252static int mtk_btcvsd_snd_component_probe(struct snd_soc_component *component)1253{1254return snd_soc_add_component_controls(component,1255mtk_btcvsd_snd_controls,1256ARRAY_SIZE(mtk_btcvsd_snd_controls));1257}12581259static const struct snd_soc_component_driver mtk_btcvsd_snd_platform = {1260.name = BTCVSD_SND_NAME,1261.probe = mtk_btcvsd_snd_component_probe,1262.open = mtk_pcm_btcvsd_open,1263.close = mtk_pcm_btcvsd_close,1264.hw_params = mtk_pcm_btcvsd_hw_params,1265.hw_free = mtk_pcm_btcvsd_hw_free,1266.prepare = mtk_pcm_btcvsd_prepare,1267.trigger = mtk_pcm_btcvsd_trigger,1268.pointer = mtk_pcm_btcvsd_pointer,1269.copy = mtk_pcm_btcvsd_copy,1270};12711272static int mtk_btcvsd_snd_probe(struct platform_device *pdev)1273{1274int ret;1275int irq_id;1276u32 offset[5] = {0, 0, 0, 0, 0};1277struct mtk_btcvsd_snd *btcvsd;1278struct device *dev = &pdev->dev;12791280/* init btcvsd private data */1281btcvsd = devm_kzalloc(dev, sizeof(*btcvsd), GFP_KERNEL);1282if (!btcvsd)1283return -ENOMEM;1284platform_set_drvdata(pdev, btcvsd);1285btcvsd->dev = dev;12861287/* init tx/rx */1288btcvsd->rx = devm_kzalloc(btcvsd->dev, sizeof(*btcvsd->rx), GFP_KERNEL);1289if (!btcvsd->rx)1290return -ENOMEM;12911292btcvsd->tx = devm_kzalloc(btcvsd->dev, sizeof(*btcvsd->tx), GFP_KERNEL);1293if (!btcvsd->tx)1294return -ENOMEM;12951296spin_lock_init(&btcvsd->tx_lock);1297spin_lock_init(&btcvsd->rx_lock);12981299init_waitqueue_head(&btcvsd->tx_wait);1300init_waitqueue_head(&btcvsd->rx_wait);13011302mtk_btcvsd_snd_tx_init(btcvsd);1303mtk_btcvsd_snd_rx_init(btcvsd);13041305/* irq */1306irq_id = platform_get_irq(pdev, 0);1307if (irq_id <= 0)1308return irq_id < 0 ? irq_id : -ENXIO;13091310ret = devm_request_irq(dev, irq_id, mtk_btcvsd_snd_irq_handler,1311IRQF_TRIGGER_LOW, "BTCVSD_ISR_Handle",1312(void *)btcvsd);1313if (ret) {1314dev_err(dev, "could not request_irq for BTCVSD_ISR_Handle\n");1315return ret;1316}13171318btcvsd->irq_id = irq_id;13191320/* iomap */1321btcvsd->bt_pkv_base = of_iomap(dev->of_node, 0);1322if (!btcvsd->bt_pkv_base) {1323dev_err(dev, "iomap bt_pkv_base fail\n");1324return -EIO;1325}13261327btcvsd->bt_sram_bank2_base = of_iomap(dev->of_node, 1);1328if (!btcvsd->bt_sram_bank2_base) {1329dev_err(dev, "iomap bt_sram_bank2_base fail\n");1330ret = -EIO;1331goto unmap_pkv_err;1332}13331334btcvsd->infra = syscon_regmap_lookup_by_phandle(dev->of_node,1335"mediatek,infracfg");1336if (IS_ERR(btcvsd->infra)) {1337dev_err(dev, "cannot find infra controller: %ld\n",1338PTR_ERR(btcvsd->infra));1339ret = PTR_ERR(btcvsd->infra);1340goto unmap_bank2_err;1341}13421343/* get offset */1344ret = of_property_read_u32_array(dev->of_node, "mediatek,offset",1345offset,1346ARRAY_SIZE(offset));1347if (ret) {1348dev_warn(dev, "%s(), get offset fail, ret %d\n", __func__, ret);1349goto unmap_bank2_err;1350}1351btcvsd->infra_misc_offset = offset[0];1352btcvsd->conn_bt_cvsd_mask = offset[1];1353btcvsd->cvsd_mcu_read_offset = offset[2];1354btcvsd->cvsd_mcu_write_offset = offset[3];1355btcvsd->cvsd_packet_indicator = offset[4];13561357btcvsd->bt_reg_pkt_r = btcvsd->bt_pkv_base +1358btcvsd->cvsd_mcu_read_offset;1359btcvsd->bt_reg_pkt_w = btcvsd->bt_pkv_base +1360btcvsd->cvsd_mcu_write_offset;1361btcvsd->bt_reg_ctl = btcvsd->bt_pkv_base +1362btcvsd->cvsd_packet_indicator;13631364/* init state */1365mtk_btcvsd_snd_set_state(btcvsd, btcvsd->tx, BT_SCO_STATE_IDLE);1366mtk_btcvsd_snd_set_state(btcvsd, btcvsd->rx, BT_SCO_STATE_IDLE);13671368ret = devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform,1369NULL, 0);1370if (ret)1371goto unmap_bank2_err;13721373return 0;13741375unmap_bank2_err:1376iounmap(btcvsd->bt_sram_bank2_base);1377unmap_pkv_err:1378iounmap(btcvsd->bt_pkv_base);1379return ret;1380}13811382static void mtk_btcvsd_snd_remove(struct platform_device *pdev)1383{1384struct mtk_btcvsd_snd *btcvsd = dev_get_drvdata(&pdev->dev);13851386iounmap(btcvsd->bt_pkv_base);1387iounmap(btcvsd->bt_sram_bank2_base);1388}13891390static const struct of_device_id mtk_btcvsd_snd_dt_match[] = {1391{ .compatible = "mediatek,mtk-btcvsd-snd", },1392{},1393};1394MODULE_DEVICE_TABLE(of, mtk_btcvsd_snd_dt_match);13951396static struct platform_driver mtk_btcvsd_snd_driver = {1397.driver = {1398.name = "mtk-btcvsd-snd",1399.of_match_table = mtk_btcvsd_snd_dt_match,1400},1401.probe = mtk_btcvsd_snd_probe,1402.remove = mtk_btcvsd_snd_remove,1403};14041405module_platform_driver(mtk_btcvsd_snd_driver);14061407MODULE_DESCRIPTION("Mediatek ALSA BT SCO CVSD/MSBC Driver");1408MODULE_AUTHOR("KaiChieh Chuang <[email protected]>");1409MODULE_LICENSE("GPL v2");141014111412