当前位置: 首页>編程日記>正文

全志平台速鼎模块的BT调试记录

全志平台速鼎模块的BT调试记录

1、电路原理:

2、需要配置的接口

控制管脚:
AP_WAKE_BT<---->PL06
BT_LDO_EN<----->PL07
BT_POWER <------>VCC_CTP(CLDO1-3.3V)
通信管脚:
UART1_TXD<----->PG06
UART1_RXD<----->PG07
UART1_RTS<----->PG08
UART1_CTS<----->PG09
PCM蓝牙音频通路管脚(对应I2S1,需要配置成PCM模式):
PCM_SYNC<------->PG10
PCM_BCLK<------->PG11
PCM_DO  <------->PG12
PCO_DI  <------->PG13
32K_OUT <------->PG14

3、上电时序,需要对控制空间和串口流控进行操作,具体如下:

lichee\linux-4.9\drivers\misc\sunxi-rf\sunxi-bluetooth.c
//以下代码是linux4.9 android8.x的代码,满足开机打开电源,上层Open时打开使能,close时关闭使能。
struct sunxi_bt_platdata {struct regulator *bt_power;struct regulator *io_regulator;struct clk *lpo;int gpio_bt_rst;char *bt_power_name;char *io_regulator_name;int power_state;int uart_enable;struct rfkill *rfkill;struct platform_device *pdev;
};
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/clk.h>
#include <linux/rfkill.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
#include <linux/sunxi-gpio.h>
#include <linux/pm_runtime.h>#include "sunxi-rfkill.h"static struct sunxi_bt_platdata *bluetooth_data = NULL;
static int sunxi_bt_on(struct sunxi_bt_platdata *data, bool on_off);
static DEFINE_MUTEX(sunxi_bluetooth_mutex);static int set_bt_uart_enable(struct sunxi_bt_platdata *platdata, int enable)
{int gpio_tx = GPIOG(6);int gpio_rx = GPIOG(7);int UART_FUNC = 2;char pin_name_tx[SUNXI_PIN_NAME_MAX_LEN];char pin_name_rx[SUNXI_PIN_NAME_MAX_LEN];long unsigned int config_set;long unsigned int config_get;sunxi_gpio_to_name(gpio_tx, pin_name_tx);sunxi_gpio_to_name(gpio_rx, pin_name_rx);if (0 == enable) {config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,SUNXI_PIN_OUTPUT_FUNC);pin_config_set(SUNXI_PINCTRL, pin_name_tx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_tx, &config_get);if (SUNXI_PIN_OUTPUT_FUNC != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set output func failed\n",pin_name_tx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set output func success\n",pin_name_tx);}config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT,SUNXI_PIN_DATA_LOW);pin_config_set(SUNXI_PINCTRL, pin_name_tx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_tx, &config_get);if (SUNXI_PIN_DATA_LOW != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set output LOW failed\n",pin_name_tx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set output LOW success\n",pin_name_tx);}config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC,SUNXI_PIN_OUTPUT_FUNC);pin_config_set(SUNXI_PINCTRL, pin_name_rx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_rx, &config_get);if (SUNXI_PIN_OUTPUT_FUNC != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set output func failed\n",pin_name_rx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set output func success\n",pin_name_rx);}config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT,SUNXI_PIN_DATA_LOW);pin_config_set(SUNXI_PINCTRL, pin_name_rx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_rx, &config_get);if (SUNXI_PIN_DATA_LOW != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set output LOW failed\n",pin_name_rx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set output LOW success\n",pin_name_rx);}} else if (1 == enable) {config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, UART_FUNC);pin_config_set(SUNXI_PINCTRL, pin_name_tx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_tx, &config_get);if (UART_FUNC != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set uart func failed\n",pin_name_tx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set uart func success\n",pin_name_tx);}config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD,SUNXI_PIN_PULL_UP);pin_config_set(SUNXI_PINCTRL, pin_name_tx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_tx, &config_get);if (SUNXI_PIN_PULL_UP != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set uart pull failed\n",pin_name_tx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set uart pull success\n",pin_name_tx);}config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, UART_FUNC);pin_config_set(SUNXI_PINCTRL, pin_name_rx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_rx, &config_get);if (UART_FUNC != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set uart func failed\n",pin_name_rx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set uart func success\n",pin_name_rx);}config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD,SUNXI_PIN_PULL_UP);pin_config_set(SUNXI_PINCTRL, pin_name_rx, config_set);config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, 0XFFFF);pin_config_get(SUNXI_PINCTRL, pin_name_rx, &config_get);if (SUNXI_PIN_PULL_UP != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {dev_err(&platdata->pdev->dev, "[%s] set uart pull failed\n",pin_name_rx);return -EINVAL;} else {dev_info(&platdata->pdev->dev, "[%s] set uart pull success\n",pin_name_rx);}}platdata->uart_enable = enable;return 0;
}static int sunxi_bt_on(struct sunxi_bt_platdata *data, bool on_off)
{struct platform_device *pdev = data->pdev;struct device *dev = &pdev->dev;int ret = 0;pr_err("%s ---sunxi_bt_on()\n", __FUNCTION__);
#if 0if (!on_off && gpio_is_valid(data->gpio_bt_rst))gpio_set_value(data->gpio_bt_rst, 0);
#endifif (data->bt_power_name) { //bt_powerdata->bt_power = regulator_get(dev, data->bt_power_name);if (!IS_ERR(data->bt_power)) {if (on_off) {regulator_set_voltage(data->bt_power,(int)3300*1000,(int)3300*1000);ret = regulator_enable(data->bt_power);if (ret < 0) {dev_err(dev, "regulator bt_power enable failed\n");regulator_put(data->bt_power);return ret;}ret = regulator_get_voltage(data->bt_power);if (ret < 0) {dev_err(dev, "regulator bt_power get voltage failed\n");regulator_put(data->bt_power);return ret;}dev_info(dev, "check bluetooth bt_power voltage: %d\n", ret);} else {ret = regulator_disable(data->bt_power);if (ret < 0) {dev_err(dev, "regulator bt_power disable failed\n");regulator_put(data->bt_power);return ret;}}regulator_put(data->bt_power);}}#if 0if(data->io_regulator_name){data->io_regulator = regulator_get(dev, data->io_regulator_name);if (!IS_ERR(data->io_regulator)) {if (on_off) {regulator_set_voltage(data->io_regulator,(int)3300*1000,(int)3300*1000);ret = regulator_enable(data->io_regulator);if (ret < 0) {dev_err(dev, "regulator io_regulator enable failed\n");regulator_put(data->io_regulator);return ret;}ret = regulator_get_voltage(data->io_regulator);if (ret < 0) {dev_err(dev, "regulator io_regulator get voltage failed\n");regulator_put(data->io_regulator);return ret;}dev_info(dev, "check bluetooth io_regulator voltage: %d\n",ret);}else{ret = regulator_disable(data->io_regulator);if (ret < 0) {dev_err(dev, "regulator io_regulator disable failed\n");regulator_put(data->io_regulator);return ret;}}regulator_put(data->io_regulator);}}if (on_off && gpio_is_valid(data->gpio_bt_rst)) {mdelay(10);gpio_set_value(data->gpio_bt_rst, 1);}
#endifdata->power_state = on_off;return 0;
}static int sunxi_bt_set_block(void *data, bool blocked)
{struct sunxi_bt_platdata *platdata = data;struct platform_device *pdev = platdata->pdev;int ret;if (blocked != platdata->power_state) {dev_warn(&pdev->dev, "block state already is %d\n", blocked);return 0;}dev_info(&pdev->dev, "set block: %d\n", blocked);//ret = sunxi_bt_on(platdata, !blocked);//if (ret) {//	dev_err(&pdev->dev, "set block failed\n");//	return ret;//}//sunxi_wl_chipen_set(1, !blocked);return 0;
}static const struct rfkill_ops sunxi_bt_rfkill_ops = {.set_block = sunxi_bt_set_block,
};static ssize_t power_state_show(struct class *class,struct class_attribute *attr, char *buf)
{return sprintf(buf, "%d\n", bluetooth_data->power_state);
}void bt_xr829_enable(int enable);
//主要由这个函数在上层调用/sys/class/bt_power/power_state接口,1:使能 0:不使能
static ssize_t power_state_store(struct class *class,struct class_attribute *attr, const char *buf, size_t count)
{unsigned long state;int err;pr_err("%s ---power_state_store()\n", __FUNCTION__);err = kstrtoul(buf, 0, &state);if (err)return err;bluetooth_data->power_state = state;pr_err("%s ---bt_xr829_enable = %ld\n",__FUNCTION__,state);if(state)bt_xr829_enable(1);elsebt_xr829_enable(0);return count;#if 0if (state > 1)return count;mutex_lock(&sunxi_bluetooth_mutex);if (state != bluetooth_data->power_state) {dev_info(&bluetooth_data->pdev->dev, "set power: %s\n", state ? "on" : "off");err = sunxi_bt_on(bluetooth_data, state);if (err) {dev_err(&bluetooth_data->pdev->dev, "set power failed\n");}}sunxi_wl_chipen_set(1, state);mutex_unlock(&sunxi_bluetooth_mutex);return count;
#endif
}static ssize_t uart_enable_store(struct class *class,struct class_attribute *attr, const char *buf, size_t count)
{unsigned long enable;int err;err = kstrtoul(buf, 0, &enable);if (err)return err;if (enable > 1)return count;pr_err("%s ---enable:%d\n", __FUNCTION__,enable);if (enable != bluetooth_data->uart_enable) {dev_info(&bluetooth_data->pdev->dev, "bt uart: %s\n", enable ? "on" : "off");err = set_bt_uart_enable(bluetooth_data, enable);if(0==err){if (0 == enable){bluetooth_data->uart_enable = 0;} else {bluetooth_data->uart_enable = 1;}}else{dev_err(&bluetooth_data->pdev->dev, "set uart failed\n");}}return count;
}static struct class_attribute bt_attribute_group[] = {__ATTR(power_state, S_IRUGO | S_IWUSR | S_IWGRP,power_state_show, power_state_store),__ATTR(uart_enable, S_IWUSR | S_IWGRP,NULL, uart_enable_store),__ATTR_NULL
};static struct class bt_power_class = {.name = "bt_power",.class_attrs = bt_attribute_group,
};
static int bt_xr829_reset = 0;
static int bt_xr829_wake = 0;
void bt_xr829_enable(int enable)
{pr_err("%s aa enable=%d\n",__FUNCTION__,enable);if(enable){gpio_direction_output(bt_xr829_reset, 1); //AP_WAKE_BT<---->PL06和BT_LDO_EN<----->PL07同时打开gpio_direction_output(bt_xr829_wake, 1);}else{gpio_direction_output(bt_xr829_wake, 0);gpio_direction_output(bt_xr829_reset, 0);}
}static int sunxi_bt_probe(struct platform_device *pdev)
{struct device_node *np = pdev->dev.of_node;struct device *dev = &pdev->dev;struct sunxi_bt_platdata *data;struct gpio_config config;const char *power, *io_regulator;int ret = 0;dev_info(dev, "sunxi_bt_probe()\n");data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);if (!dev)return -ENOMEM;data->pdev = pdev;bluetooth_data = data;if (of_property_read_string(np, "bt_power", &power)) {dev_warn(dev, "Missing bt_power.\n");} else {data->bt_power_name = devm_kzalloc(dev, 64, GFP_KERNEL);if (!data->bt_power_name)return -ENOMEM;elsestrcpy(data->bt_power_name,power);}dev_info(dev, "bt_power_name (%s)\n", data->bt_power_name);bt_xr829_reset = of_get_named_gpio_flags(np, "bt_rst_n", 0, (enum of_gpio_flags *)&config);if (!gpio_is_valid(bt_xr829_reset)) {pr_err("get gpio bt_rst failed\n");} else {pr_err("bt_rst gpio=%d gpio=%d  mul-sel=%d  pull=%d  drv_level=%d  data=%d\n",bt_xr829_reset,config.gpio,config.mul_sel,config.pull,config.drv_level,config.data);ret = devm_gpio_request(dev, bt_xr829_reset, "bt_xr829_reset");if (ret < 0) {dev_err(dev, "can't request bt_rst gpio %d\n",bt_xr829_reset);return ret;}ret = gpio_direction_output(bt_xr829_reset, 0);if (ret < 0) {dev_err(dev, "can't request output direction bt_rst gpio %d\n",bt_xr829_reset);return ret;}}bt_xr829_wake = of_get_named_gpio_flags(np, "ap_wakeup_bt", 0, (enum of_gpio_flags *)&config);if (!gpio_is_valid(bt_xr829_wake)) {pr_err("get gpio bt_xr829_wake failed\n");} else {pr_err("bt_xr829_wake gpio=%d gpio=%d  mul-sel=%d  pull=%d  drv_level=%d  data=%d\n",bt_xr829_wake,config.gpio,config.mul_sel,config.pull,config.drv_level,config.data);ret = devm_gpio_request(dev, bt_xr829_wake, "ap_wakeup_bt");if (ret < 0) {dev_err(dev, "can't request bt_xr829_wake gpio %d\n",bt_xr829_wake);return ret;}ret = gpio_direction_output(bt_xr829_wake, 0);if (ret < 0) {dev_err(dev, "can't request output direction bt_xr829_wake %d\n",bt_xr829_wake);return ret;}}#if 0if (of_property_read_string(np, "bt_io_regulator", &io_regulator)) {dev_warn(dev, "Missing bt_io_regulator.\n");} else {data->io_regulator_name = devm_kzalloc(dev, 64, GFP_KERNEL);if (!data->io_regulator_name)return -ENOMEM;elsestrcpy(data->io_regulator_name,io_regulator);}dev_info(dev, "io_regulator_name (%s)\n", data->io_regulator_name);data->gpio_bt_rst = of_get_named_gpio_flags(np, "bt_rst_n", 0, (enum of_gpio_flags *)&config);if (!gpio_is_valid(data->gpio_bt_rst)) {dev_err(dev, "get gpio bt_rst failed\n");} else {dev_info(dev, "bt_rst gpio=%d  mul-sel=%d  pull=%d  drv_level=%d  data=%d\n",config.gpio,config.mul_sel,config.pull,config.drv_level,config.data);ret = devm_gpio_request(dev, data->gpio_bt_rst, "bt_rst");if (ret < 0) {dev_err(dev, "can't request bt_rst gpio %d\n",data->gpio_bt_rst);return ret;}ret = gpio_direction_output(data->gpio_bt_rst, 0);if (ret < 0) {dev_err(dev, "can't request output direction bt_rst gpio %d\n",data->gpio_bt_rst);return ret;}}data->lpo = devm_clk_get(dev, NULL);if (IS_ERR_OR_NULL(data->lpo)) {dev_warn(dev, "clk not config\n");} else {ret = clk_prepare_enable(data->lpo);if (ret < 0)dev_warn(dev, "can't enable clk\n");}
#endifdata->rfkill = rfkill_alloc("sunxi-bt", dev, RFKILL_TYPE_BLUETOOTH,&sunxi_bt_rfkill_ops, data);if (!data->rfkill) {ret = -ENOMEM;goto failed_alloc;}rfkill_set_states(data->rfkill, true, false);ret = rfkill_register(data->rfkill);if (ret){goto fail_rfkill;}platform_set_drvdata(pdev, data);class_register(&bt_power_class);data->power_state = 0; //power_state为0,不使能data->uart_enable = 1; //UART口OK,状态为1//电源管理pm_runtime_set_active(dev); pm_runtime_get(dev);pm_runtime_enable(dev);if (1 != data->power_state) {sunxi_bt_on(data, 1); //打开模块电源}return 0;fail_rfkill:if (data->rfkill) rfkill_destroy(data->rfkill);
failed_alloc://if (!IS_ERR_OR_NULL(data->lpo)) {//	clk_disable_unprepare(data->lpo);//	clk_put(data->lpo);//}return ret;
}static int sunxi_bt_remove(struct platform_device *pdev)
{struct sunxi_bt_platdata *data = platform_get_drvdata(pdev);struct rfkill *rfk = data->rfkill;pm_runtime_disable(&pdev->dev);pm_runtime_set_suspended(&pdev->dev);class_unregister(&bt_power_class);platform_set_drvdata(pdev, NULL);if(rfk){rfkill_unregister(rfk);rfkill_destroy(rfk);}//if (!IS_ERR_OR_NULL(data->lpo)) {//	clk_disable_unprepare(data->lpo);//	clk_put(data->lpo);//}return 0;
}static int bt_pm_suspend(struct device *dev)
{struct sunxi_bt_platdata *platdata = dev_get_drvdata(dev);printk("CONFIG_PM:enter bt_pm_suspend.\n");if (pm_runtime_suspended(dev))return 0;if (platdata) {if (0 != platdata->power_state) {sunxi_bt_on(platdata, 0);}}return 0;
}static int bt_pm_resume(struct device *dev)
{struct sunxi_bt_platdata *platdata = dev_get_drvdata(dev);printk("CONFIG_PM:enter bt_pm_resume.\n");if (pm_runtime_suspended(dev))return 0;if (platdata) {if (1 != platdata->power_state) {sunxi_bt_on(platdata, 1);}}return 0;
}
static struct dev_pm_ops bt_pm_ops = {.suspend = bt_pm_suspend,.resume  = bt_pm_resume,
};static const struct of_device_id sunxi_bt_ids[] = {{ .compatible = "allwinner,sunxi-bt" },{ /* Sentinel */ }
};static struct platform_driver sunxi_bt_driver = {.probe	= sunxi_bt_probe,.remove	= sunxi_bt_remove,.driver	= {.owner	= THIS_MODULE,.name	= "sunxi-bt",.pm     = &bt_pm_ops,.of_match_table	= sunxi_bt_ids,},
};module_platform_driver(sunxi_bt_driver);MODULE_DESCRIPTION("sunxi bluetooth driver");
MODULE_LICENSE(GPL);//BT的管脚系统配置
tools\pack\chips\sun8iw17p1\configs\k23x3-wb\sys_config.fex
;--------------------------------------------------------------------------------
;bluetooth configuration
;bt_used:           0- no used, 1- used
;clocks:            external low power clock input (32.768KHz)
;bt_power:          input supply voltage
;bt_io_regulator:   bluetooth I/O voltage
;bt_rst_n:          power up/down internal regulators used by BT section
;--------------------------------------------------------------------------------
[bt]
bt_used             = 1
compatible = "allwinner,sunxi-bt"
bt_power            = "vcc-ctp" //cldo1 vcc-ctp
;clocks             = 0x55
bt_rst_n            = port:PL07<1><default><default><0> //BT_LDO_EN<----->PL07
ap_wakeup_bt        = port:PL06<1><default><1><0> //AP_WAKE_BT<---->PL06

4、UART口和PCM通道的系统管脚和模式配置:

lichee\tools\pack\chips\sun8iw17p1\configs\k23x3-wb\sys_config.fex
...............
[uart1]
uart1_used       = 1  //这里必须设置成1
uart1_port       = 1
uart1_type       = 2
uart1_tx         = port:PG06<2><1><default><default>
uart1_rx         = port:PG07<2><1><default><default>
uart1_rts        = port:PG08<2><1><default><default>
uart1_cts        = port:PG09<2><1><default><default>
[uart1_suspend]
uart1_tx         = port:PG06<7><1><default><default>
uart1_rx         = port:PG07<7><1><default><default>
uart1_rts        = port:PG08<7><1><default><default>
uart1_cts        = port:PG09<7><1><default><default>
..............
;--------------------------------------------------------------------------------
;		NOTE :Make sure daudio1mach_used = 0x1,daudio1_used = 0x1,
;         if register the sound card DAUDIO1.
;--------------------------------------------------------------------------------
;--------------------------------------------------------------------------------
;allwinner,pcm_lrck_period 	:16/32/64/128/256
;allwinner,pcm_lrckr_period :no use
;allwinner,slot_width_select 	:16bits/20bits/24bits/32bits
;allwinner,pcm_lsb_first 	:0: msb first; 1: lsb first
;allwinner,tx_data_mode 	:0: 16bit linear PCM; 1: 8bit linear PCM; 2: 8bit u-law; 3: 8bit a-law
;allwinner,rx_data_mode 	:0: 16bit linear PCM; 1: 8bit linear PCM; 2: 8bit u-law; 3: 8bit a-law
;allwinner,daudio_master :1: SND_SOC_DAIFMT_CBM_CFM(codec clk & FRM master)        use
;						  2: SND_SOC_DAIFMT_CBS_CFM(codec clk slave & FRM master)  not use
;						  3: SND_SOC_DAIFMT_CBM_CFS(codec clk master & frame slave) not use
;						  4: SND_SOC_DAIFMT_CBS_CFS(codec clk & FRM slave)         use
;allwinner,audio_format: 1:SND_SOC_DAIFMT_I2S(standard i2s format).            use
;			   2:SND_SOC_DAIFMT_RIGHT_J(right justfied format).
;			   3:SND_SOC_DAIFMT_LEFT_J(left justfied format)
;			   4:SND_SOC_DAIFMT_DSP_A(pcm. MSB is available on 2nd BCLK rising edge after LRC rising edge). use
;			   5:SND_SOC_DAIFMT_DSP_B(pcm. MSB is available on 1nd BCLK rising edge after LRC rising edge)
;allwinner,signal_inversion:1:SND_SOC_DAIFMT_NB_NF(normal bit clock + frame)  use
;				  2:SND_SOC_DAIFMT_NB_IF(normal BCLK + inv FRM)
;				  3:SND_SOC_DAIFMT_IB_NF(invert BCLK + nor FRM)  use
;				  4:SND_SOC_DAIFMT_IB_IF(invert BCLK + FRM)
;allwinner,frametype :0: short frame = 1 clock width;  1: long frame = 2 clock width
;allwinner,tdm_config :0:pcm 1:i2s
;allwinner,mclk_div :0: not output(normal setting this) 1/2/4/6/8/12/16/24/32/48/64/96/128/176/192:
;			setting mclk as input clock to external codec, freq is pll_audio/mclk_div
;allwinner,daudio0_used :0:not use 1:use
;-------------------------------------------------------------------------------
;		NOTE :Make sure daudio0mach_used = 0x1,daudio0_used = 0x1,
;         if register the sound card DAUDIO0.
;--------------------------------------------------------------------------------
[snddaudio1]
snddaudio1_used = 1
;-----------------------------------------------------------------------------
[daudio1]
;pcm_lrck_period =   0x20
pcm_lrck_period =   0x40
pcm_lrckr_period =   0x01
slot_width_select =   0x10
pcm_lsb_first =   0x0
tx_data_mode =   0x0
rx_data_mode =   0x0
;daudio_master =   0x04
;audio_format =   0x01
;signal_inversion =   0x01
daudio_master =   0x01
audio_format =   0x04
signal_inversion =   0x02
frametype =   0x0
;tdm_config =   0x01
tdm_config =   0x00
mclk_div = 0x0
;daudio1_used = 0
daudio1_used = 1  //这里一定要配置成1
//以上参数请参考BT模组中PCM输出的时序

5、修改上层访问的设备节点的权限和添加固件

android\device\softwinner\common\init.wireless.qcom.rc
在文件中添加:
......................
# to observe dnsmasq.leases file for dhcp information of soft ap.chown dhcp system /data/misc/dhcpchmod 0666 /sys/class/bt_power/power_state //添加权限
android\device\softwinner\t7-common\ueventd.sun8iw17p1.rc
............................
/dev/ttyS*                  0666    system      system
我们使用UART1接口连接蓝牙,使用/dev/ttyS1设备节点添加固件:
需要将以下固件文件拷贝到/system/etc/firmware/目录中
android\device\softwinner\k23x3-wb\hardware\bt\firmware\nvm_tlv_3.2.bin
android\device\softwinner\k23x3-wb\hardware\bt\firmware\rampatch_tlv_3.2.tlv
android\device\softwinner\k23x3-wb\hardware\bt\firmware\rampatch_tlv_3.2.tlv
android\device\softwinner\k23x3-wb\hardware\bt\firmware\rampatch_tlv_tf_1.1.tlv
修改:
android\device\softwinner\k23x3-wb\k23x3_wb.mk
# BT
PRODUCT_COPY_FILES += \    $(PRODUCT_DEVICE_PATH)/hardware/bt/firmware/nvm_tlv_3.2.bin:/system/etc/firmware/nvm_tlv_3.2.bin \    $(PRODUCT_DEVICE_PATH)/hardware/bt/firmware/rampatch_tlv_3.2.tlv:/system/etc/firmware/rampatch_tlv_3.2.tlv \    $(PRODUCT_DEVICE_PATH)/hardware/bt/firmware/nvm_tlv_tf_1.1.bin:/system/etc/firmware/nvm_tlv_tf_1.1.bin \    $(PRODUCT_DEVICE_PATH)/hardware/bt/firmware/rampatch_tlv_tf_1.1.tlv:/system/etc/firmware/rampatch_tlv_tf_1.1.tlv \

以上的信息配置OK,之后。直接找模组供应商,要协议栈的相关程序,因为模组用于车载项目,不能使用Android自带的framework层部分,直接使用BT模块的CHI模式,不是CMD模式,如果使用CMD模式,直接跟模组发AT指令即可,如果使用chi模式,需要模组厂家或第第三方给出协议栈的相关文件,具体跟APP有关,到这个步骤,OS层面就OK了。而通过跟速鼎调试来看,速鼎将提供:

system/bin/gocsdk
system/etc/firmware/nvm_tlv_tf_1.1.bin
system/etc/firmware/rampatch_tlv_tf_1.1.tlv
system/config_具体公司.ini //不同厂家内容可能不同

其中system/bin/gocsdk文件将在系统启动的时候用服务进行加载,将使能 BT模块,打开/dev/ttyS1,打开PCM通道,同时处理蓝牙连接,播放音乐,打电话,同步电话本等操作,主要是协议栈的处理。

系统启动加载的蓝牙服务
android\device\softwinner\k23x3-wb\init.device.rc
service gocsdk /system/bin/gocsdk /dev/ttyS1 500000 //这个主要是供应商给的协议栈等class mainuser rootgroup rootservice gocsdk_be130 /system/bin/gocsdk_be130 /dev/ttyS1 500000class mainuser rootgroup rootdisabled

将以上文件导入到系统中对应目录之后,重启系统,然后基本就可以连接手机,打电话、播放音乐了。


https://www.fengoutiyan.com/post/14143.html

相关文章:

  • 鼎信2205模块接线图
  • 全志固件修改工具
  • 全志h3 311
  • 全志B300
  • 全志A83T
  • 鼎信模块
  • 鼎信载波模块原理
  • 鼎信单相载波模块
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機