蓝牙配电文件分析
1,首先分析
Msm_bluetooth_power_init()初始化函数
该函数中首先确认reset脚。
Gpio_bt_config()
主要设置gpio_bt_sys_reset_en=BT_RST;
(与实际连接一致),
然后注册i2c设备体bahama_device。
该设备体包含了fm的配电和bt重要的寄存器部分。
最后注册平台设备msm_bt_power_device,该设备体名称bt_power,该设备的平台数据platform_data=&Bluetooth_power,实现蓝牙的上电。
2,关于bahama_device
Static struct i2c_board_info bahama_devices[] = { I2C_BOARD_INFO(“marimba”,0x0c), .platform = &marimba_pdata,}
I2c结构体方便注册到系统中,提供i2c读写函数。
Static struct marimba_platform_data marimba_pdata = { .slave_id[SLAVE_ID_BAHAMA_FM] = BAHAMA_SLAVE_ID_FM_ADDR, .slave_id[SLAVE_ID_BAHAMA_QMEMBIST] = BAHAMA_SLAVE_ID_QMEMEBIST_, .bahama_setup = msm_bahama_setup_power, .bahama_shutdown = msm_bahama_shutdown_power, .bahama_core_config = msm_bahama_core_config, .fm = &marimba_fm_pdata,}
Marimba_pdata结构体包括了fm的地址,以及该结构体的电源开关,核心配置。
电源开关控制msm_bahama_setup_powe包括申请“msme1”电压,reset脚拉高。
msm_bahama_core_config判断参数为BAHAMA_ID时,i2c写寄存器参数。Reset拉低。
Static struct marimba_fm_platform_data marimba_fm_data = { .fm_Setup = fm_radio_setup, .fm_shutdown = fm_radio_shutdown, .irq = MSM_GPIO_TO_IRQ(FM_GPIO), … .is_fm_soc_i2s_master = true, .config_i2s_gpio = msm_bahama_setup_pcm_i2s,}
fm_radio_setup主要实现设置1.8v电压,申请时钟TCXO_D1,reset设置为1,reset后写FM slave地址,配置FM中断为input模式。
3,蓝牙上电配置函数作为注册设备体的平台数据
static int bluetooth_power(int on){ int pin, rc = 0; const char *id = "BTPW"; int cid = 0; cid = adie_get_detected_connectivity_type(); if (cid != BAHAMA_ID) { pr_err("%s: unexpected adie connectivity type: %d\n", __func__, cid); return -ENODEV; } if (on) { /*setup power for BT SOC*/ // BT SOC上电 rc = bt_set_gpio(on); //rest pin置1 if (rc) { pr_err("%s: bt_set_gpio = %d\n", __func__, rc); goto exit; } rc = bluetooth_switch_regulators(on);//申请2.85v电压 if (rc < 0) { pr_err("%s: bluetooth_switch_regulators rc = %d", __func__, rc); goto exit; } /*setup BT GPIO lines*///串口线配置 for (pin = 0; pin < ARRAY_SIZE(bt_config_power_on); pin++) { rc = gpio_tlmm_config(bt_config_power_on[pin], GPIO_CFG_ENABLE); if (rc < 0) { pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, bt_config_power_on[pin], rc); goto fail_power; } } /*Setup BT clocks*///申请TCXO_D1时钟 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1, PMAPP_CLOCK_VOTE_ON); if (rc < 0) { pr_err("Failed to vote for TCXO_D1 ON\n"); goto fail_clock; } msleep(20); /*I2C config for Bahama*///bahama_bt二维数组代表了fm和bt不同的开关状态,通过i2c写寄存器和值实现。 rc = bahama_bt(1); if (rc < 0) { pr_err("%s: bahama_bt rc = %d", __func__, rc); goto fail_i2c; } msleep(20); /*setup BT PCM lines*///获取bt和fm状态,设置对应pcm和i2s状态。 rc = msm_bahama_setup_pcm_i2s(BT_PCM_ON); if (rc < 0) { pr_err("%s: msm_bahama_setup_pcm_i2s , rc =%d\n", __func__, rc); goto fail_power; } rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1, PMAPP_CLOCK_VOTE_PIN_CTRL); if (rc < 0) pr_err("%s:Pin Control Failed, rc = %d", __func__, rc); } else { rc = bahama_bt(0); if (rc < 0) pr_err("%s: bahama_bt rc = %d", __func__, rc); rc = msm_bahama_setup_pcm_i2s(BT_PCM_OFF); if (rc < 0) { pr_err("%s: msm_bahama_setup_pcm_i2s, rc =%d\n", __func__, rc); } rc = bt_set_gpio(on); if (rc) { pr_err("%s: bt_set_gpio = %d\n", __func__, rc); }fail_i2c: rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1, PMAPP_CLOCK_VOTE_OFF); if (rc < 0) pr_err("%s: Failed to vote Off D1\n", __func__);fail_clock: for (pin = 0; pin < ARRAY_SIZE(bt_config_power_off); pin++) { rc = gpio_tlmm_config(bt_config_power_off[pin], GPIO_CFG_ENABLE); if (rc < 0) { pr_err("%s:" " gpio_tlmm_config(%#x)=%d\n", __func__, bt_config_power_off[pin], rc); } }fail_power: rc = bluetooth_switch_regulators(0); if (rc < 0) { pr_err("%s: switch_regulators : rc = %d",\ __func__, rc); goto exit; } } return rc;exit: pr_err("%s: failed with rc = %d", __func__, rc); return rc;}
4.该函数被bluetooth_power直接调用,因此不对fm方面的处理判断,fm状态开着的话,该函数不起作用。
Fm开的话,打开i2s,如果fm关,则判断蓝牙状态,蓝牙状态开,则保持pcm开,蓝牙状态关,直接执行关模式。
static int msm_bahama_setup_pcm_i2s(int mode){ int fm_state = 0, bt_state = 0; int rc = 0; struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};//获取bt和fm状态 fm_state = marimba_get_fm_status(&config); bt_state = marimba_get_bt_status(&config); switch (mode) { case BT_PCM_ON: case BT_PCM_OFF: if (!fm_state) rc = config_pcm(mode); break; case FM_I2S_ON: rc = config_i2s(mode); break; case FM_I2S_OFF: if (bt_state) rc = config_pcm(BT_PCM_ON); else rc = config_i2s(mode); break; default: rc = -EIO; pr_err("%s:Unsupported mode", __func__);}}