用于记录项目中乱七八糟的东西,不定期更新,没有排版。
一、G90(mt67850)-SIM卡功能
1、支持双卡,配置config文件
路径:
1 /device/mediateksample/k85v1_64/ProjectConfig.mk
修改参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 MTK_SIM1_SOCKET_TYPE = 1 MTK_SIM2_SOCKET_TYPE = 1 MTK_SIM_CARD_ONOFF = 2 MTK_SIM_HOT_SWAP = yes MTK_SIM_HOT_SWAP_COMMON_SLOT = no MTK_SIM_LOCK_POWER_ON_WRITE_PROTECT = no MTK_SIM_RECOVERY = yes MTK_MULTI_SIM_SUPPORT = dsds SIM_ME_LOCK_MODE = 3 SIM_REFRESH_RESET_BY_MODEM = yes MTK_EAP_SIM_AKA = yes MTK_EXTERNAL_SIM_ONLY_SLOTS = 0 MTK_EXTERNAL_SIM_SUPPORT = no
2、配置dct文件
路径:
1 2 3 4 \vendor\mediatek\proprietary\scripts\dct\DrvGen.exe \vendor\mediatek\proprietary\bootable\bootloader\lk\target\k85v1_64\dct\dct\codegen.dws \vendor\mediatek\proprietary\bootable\bootloader\preloader\custom\k85v1_64\dct\dct\codegen.dws \kernel-4.14 \drivers\misc\mediatek\dws\mt6785\codegen.dws
配置根据中断检测脚状态来配置
如果插入sim卡为高电平拔出时为低电平则配置 PlugOutPolarity 为低电平
如果插入sim卡为低电平拔出时为高电平则配置 PlugOutPolarity 为高电平
我的为第一种情况因此如下配置:
二、tf卡配置
1、配置中断引脚
1 2 3 4 5 6 7 8 9 路径: /arch/arm64/boot/dts/mediatek/cust_mt6785_msdc.dtsi 具体修改: 原理图使用的 msdc1 host_function = /bits/ 8 <MSDC_SD>; - cd_level = /bits/ 8 <MSDC_CD_LOW>; + cd_level = /bits/ 8 <MSDC_CD_HIGH>; cd-gpios = <&pio 8 0 >;
2、配置下电方式
mt6360 的 sdcard 的下电方式可以配置选择
我的原理图长这样
=-= 我的原理图插入 sd 卡之后,EINT_SD 会被拉高,由于它和 SD_CARD_DET_N_PMU 短接在一起的,因此 SD_CARD_DET_N_PMU 跟着被拉高了,于是满图上图第一种情况 active high,LD05 被拉低。。。。。,sd卡的供电就被拉低了,现象就是插上tf卡供电就掉下来 =w= 导致tf卡没功能。这种情况需要配置为上图的第二种状态 active low,配置如下。
1 2 3 4 5 6 7 路径: drivers/misc/mediatek/pmic/mt6360/ldo/mt6360_ldo_i2c.c 具体修改: static const struct mt6360_ldo_platform_data def_platform_data = {- .sdcard_det_en = true , + .sdcard_det_en = false , };
除此之外记得检测卡托,卡托和卡座一定要匹配,不匹配的卡托可能会在插入的过程中短路,导致 pmic 因为自身的保护机制直接关掉对应的 ldo5 引脚供电,这种情况和上面出现的现象是一样的。
三、G90(mt6785)-快充配置
这款芯片是支持快充的,默认没有打开需要手动配置一下
1、快充说明
1) 充电策略
VAT在比较小的时候,转换效率很低:假设VBAT=3.4V,IBAT=3A,当VBUS=7.5V的时候,转换效率为82.7%,当VBUS=12V的时候,转换效率为80.51%,差了接近%2;而当VBAT比较高的时候,转换效率对电压就不会很敏感,在VBAT=4V的情况下,最低一档的转换效率都有86.94%,所以mtk的充电策略:在保证充电功率的情况下,转换效率尽可能的高
2) 温度控制充电
1 2 max_charge_temp = <50 >; max_charge_temp_minux_x_degree = <47 >;
3) 充电检测
手机插入充电线之后,会走一个充电器类型检测,这个检测流程软硬件都有参与,要满足最基本的 BC1.2 协议才会充电,协议规定几种接口,DCP,SDP,CDP都是5v,mtk 有类似的机制在 dual charger 进入 PE40 的时候,会判断当前点量来决定跑不跑 dual charger 快充,涉及 dts 里面
1 pe40_stop_battery_soc,pd_stop_battery_sooc
4) 充电挡位支持
PE快充可以支持三档7v、9v、12v,三选一,
当使用 switch_charger 时没有这种机制,在 85% 电量的时候插入充电器,它一样是跑 switch_charger, 和手机插着充电器从 0% 开始一直充电没有差别
5) mtk 电量计算法
MTK的电量算法是由 driver 和上层的 daemon组成的,
电量变化时 Gauge 的硬件产生中断来通知 driver,
然后由 driver 将电量计算要用的值传到上层 daemon,
上层计算出的 SOC 会用您问题中的 CMD FG_DAEMON_CMD_SET_KERNEL_UISOC 再写到 kernel。
6) 相关参数含义
ICHG = “設定的充電電流”,
AICR = “AICR 保護下允許的最高抽電流”
MIVR = “設定的允許的充電器最低電壓”
IEOC = “設定的截止充電電流”
CV = “設定的Constant Voltage 值”
VSYS = “量測到的 VSYS 值”
VBAT = “测量到的电池电压”
IBAT = “测量到的充电电流”
IBUS = “测量到充电器的电流”
VBUS = “测量到充电器的电压”
soc = 底层电量百分比
uiso = 上层显示电量百分比
CT = 充电器类型
2、打开dts中的相关配置
具体修改:
/kernel-4.14/arch/arm64/boot/dts/mediatek/mt6785.dts b/arch/arm64/boot/dts/mediatek/mt6785.dts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 charger: charger { compatible = "mediatek,charger" ; algorithm_name = "SwitchCharging" ; - - - - - + enable_sw_jeita; + enable_pe_plus; + enable_pe_2; + enable_pe_3; + enable_pe_4; enable_type_c; power_path_support; enable_dynamic_mivr; battery_cv = <4350000 >; max_charger_voltage = <6500000 >; min_charger_voltage = <4600000 >; min_charger_voltage_1 = <4400000 >; min_charger_voltage_2 = <4200000 >; max_dmivr_charger_current = <1400000 >; usb_charger_current_suspend = <0 >; usb_charger_current_unconfigured = <70000 >; usb_charger_current_configured = <500000 >; usb_charger_current = <500000 >; ac_charger_current = <2050000 >; ac_charger_input_current = <2050000 >; non_std_ac_charger_current = <500000 >; charging_host_charger_current = <1500000 >; apple_1_0a_charger_current = <650000 >; apple_2_1a_charger_current = <800000 >; ta_ac_charger_current = <3000000 >; ...... pd_vbus_low_bound = <5000000 >; pd_vbus_upper_bound = <9000000 >; pd_ichg_level_threshold = <1000000 >; pd_stop_battery_soc = <90 >; ibus_err = <14 >; vsys_watt = <5000000 >;
kernel-4.14/arch/arm64/boot/dts/mediatek/bat_setting/mt6765_battery_prop.dtsi
1 2 3 4 5 6 7 8 9 10 11 12 13 bat_gm30: battery{ compatible = "mediatek,bat_gm30" ; ...... R_FG_VALUE = <(10 )>; ...... ACTIVE_TABLE = <(4 )>; MULTI_TEMP_GAUGE0 = <(1 )>; #include "mt6785_battery_table.dtsi" #include "mt6785_battery_prop_dim2_ext.dtsi" };
3、修改 kernel 下的 config 文件
1 2 3 4 5 6 7 8 9 /kernel-4.14 /arch/arm64/configs/k85v1_64_defconfig b/arch/arm64/configs/k85v1_64_defconfig CONFIG_ACCDET_EINT_IRQ=y CONFIG_ACCDET_SUPPORT_EINT0=y CONFIG_MTK_LENS=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_SUPPORT=y +CONFIG_MTK_PUMP_EXPRESS_PLUS_20_SUPPORT=y
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /device/mediateksample/k85v1_64/ProjectConfig.mk b/mediateksample/k85v1_64/ProjectConfig.mk MTK_PROTOCOL2_RAT_CONFIG = L/W/G MTK_PROTOCOL3_RAT_CONFIG = G -MTK_PUMP_EXPRESS_PLUS_SUPPORT = no -MTK_PUMP_EXPRESS_PLUS_20_SUPPORT = no MTK_PUMP_EXPRESS_PLUS_30_SUPPORT = no +MTK_PUMP_EXPRESS_PLUS_20_SUPPORT = yes +MTK_PUMP_EXPRESS_PLUS_SUPPORT = yes MTK_PUMP_EXPRESS_SUPPORT = no MTK_RADIOOFF_POWER_OFF_MD = no MTK_RAT_WCDMA_PREFERRED = no
4、vendor 目录下修改lk配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /vendor/mediatek/proprietary/bootable/bootloader/lk/project/k85v1_64.mk b/mediatek/proprietary/bootable/bootloader/lk/project/k85v1_64.mk DEFINES += MTK_NEW_COMBO_EMMC_SUPPORT DEFINES += MTK_GPT_SCHEME_SUPPORT MTK_CHARGER_NEW_ARCH := yes -MTK_PUMP_EXPRESS_PLUS_SUPPORT := no +MTK_PUMP_EXPRESS_PLUS_SUPPORT := yes MTK_CHARGER_INTERFACE := yes MTK_MT6360_PMU_CHARGER_SUPPORT := yes MTK_LCM_PHYSICAL_ROTATION = 0
5、mt6360 pd 快充升压逻辑gm3.0
代码调用流程
1 2 3 4 5 6 swchg_select_charging_current_limit --> mtk_pdc_get_setting --> mtk_pdc_setup --> adapter_dev_set_cap(info->pd_adapter, MTK_PD,pd->cap.max_mv[idx], pd->cap.ma[idx]); --> mtk_pdc_get_idx(info, idx, &pd->pd_boost_idx, &pd->pd_buck_idx);
1) 升压算法
pd 的升压逻辑很简单,就是检测当前需要的功耗是否达到了需要升压的高阈值。如果是则升压,如果低于低阈值则降压,否则使用当前电压。
pd_max_watt = 12400000 //升压功耗的高阈值
pd_min_watt = 7900000 // 升压的功耗低阈值
now_max_watt = cap->max_mv[idx] * ibus + chg2_watt; //当前经过计算需要的功耗
升压举例说明:
当前的 idx = 0 使用 5v 充电各个参数如下
idx = selected_idx = 0 //选择 5000
boost_idx = 1 // 选择 9000 ,当前挡位电压下的升压电压
buck_idx = 0 // 选择 5000 ,当前挡位下的降压电压
总结: 当 now_max_watt > pd_max_watt 则选择升压到当前电压的高一级电压,当 now_max_watt < pd_min_watt 则降低一级电压,在中间则保持不变。需要注意的是 chg1_mivr 和 chg2_mivr 也会决定了是否升压,至于这两个的判定条件是啥我也没研究清除,有大佬研究的可以告知一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 int mtk_pdc_get_setting (struct charger_manager *info, int *newvbus, int *newcur, int *newidx) { int ret = 0 ; int idx, selected_idx; unsigned int pd_max_watt, pd_min_watt, now_max_watt; struct mtk_pdc *pd = &info->pdc; int ibus = 0 , vbus; int ibat = 0 , chg1_ibat = 0 , chg2_ibat = 0 ; int chg2_watt = 0 ; bool boost = false , buck = false ; struct adapter_power_cap *cap = NULL ; unsigned int mivr1 = 0 ; unsigned int mivr2 = 0 ; bool chg1_mivr = false ; bool chg2_mivr = false ; bool chg2_enable = false ; mtk_pdc_init_table(info); mtk_pdc_get_reset_idx(info); mtk_pdc_get_cap_max_watt(info); cap = &pd->cap; if (cap->nr == 0 ) return -1 ; if (info->enable_hv_charging == false ) goto reset; ret = charger_dev_get_ibus(info->chg1_dev, &ibus); if (ret < 0 ) { chr_err("[%s] get ibus fail, keep default voltage\n" , __func__); return -1 ; } if (info->data.parallel_vbus) { ret = charger_dev_get_ibat(info->chg1_dev, &chg1_ibat); if (ret < 0 ) chr_err("[%s] get ibat fail\n" , __func__); ret = charger_dev_get_ibat(info->chg2_dev, &chg2_ibat); if (ret < 0 ) { ibat = battery_get_bat_current(); chg2_ibat = ibat * 100 - chg1_ibat; } if (ibat < 0 || chg2_ibat < 0 ) chg2_watt = 0 ; else chg2_watt = chg2_ibat / 1000 * battery_get_bat_voltage() / info->data.chg2_eff * 100 ; chr_err("[%s] chg2_watt:%d ibat2:%d ibat1:%d ibat:%d\n" , __func__, chg2_watt, chg2_ibat, chg1_ibat, ibat * 100 ); } charger_dev_get_mivr_state(info->chg1_dev, &chg1_mivr); charger_dev_get_mivr(info->chg1_dev, &mivr1); if (is_dual_charger_supported(info)) { charger_dev_is_enabled(info->chg2_dev, &chg2_enable); if (chg2_enable) { charger_dev_get_mivr_state(info->chg2_dev, &chg2_mivr); } } vbus = battery_get_vbus(); ibus = ibus / 1000 ; if ((chg1_mivr && (vbus < mivr1 / 1000 - 500 )) || (chg2_mivr && (vbus < mivr2 / 1000 - 500 ))) goto reset; selected_idx = cap->selected_cap_idx; idx = selected_idx; if (idx < 0 || idx >= ADAPTER_CAP_MAX_NR) idx = selected_idx = 0 ; pd_max_watt = cap->max_mv[idx] * (cap->ma[idx] / 100 * (100 - info->data.ibus_err) - 100 ); now_max_watt = cap->max_mv[idx] * ibus + chg2_watt; pd_min_watt = cap->max_mv[pd->pd_buck_idx] * cap->ma[pd->pd_buck_idx] / 100 * (100 - info->data.ibus_err) - info->data.vsys_watt; if (pd_min_watt <= 5000000 ) pd_min_watt = 5000000 ; printk("pd->pd_boost_idx: %d, pd->pd_buck_idx: %d, selected_idx: %d\n" , pd->pd_boost_idx, pd->pd_buck_idx, selected_idx); if ((now_max_watt >= pd_max_watt) || chg1_mivr || chg2_mivr) { printk("1\n" ); *newidx = pd->pd_boost_idx; boost = true ; } else if (now_max_watt <= pd_min_watt) { printk("2\n" ); *newidx = pd->pd_buck_idx; buck = true ; } else { printk("333\n" ); *newidx = selected_idx; boost = false ; buck = false ; } *newvbus = cap->max_mv[*newidx]; *newcur = cap->ma[*newidx]; chr_err("[%s]watt:%d,%d,%d up:%d,%d vbus:%d ibus:%d, mivr:%d,%d\n" , __func__, pd_max_watt, now_max_watt, pd_min_watt, boost, buck, vbus, ibus, chg1_mivr, chg2_mivr); chr_err("[%s]vbus:%d:%d:%d current:%d idx:%d default_idx:%d\n" , __func__, pd->vbus_h, pd->vbus_l, *newvbus, *newcur, *newidx, selected_idx); return 0 ; reset: mtk_pdc_reset(info); *newidx = pd->pd_reset_idx; *newvbus = cap->max_mv[*newidx]; *newcur = cap->ma[*newidx]; return 0 ; }
2)更新当前挡位下的升压、降压 idx
该函数基于当前的 selected_idx 来更新升压,降压 idx,举例说明:
6360 当前可以供选择的电压挡位如下
max_mv[0] = 5000 ,ma[0] = 3000 //数组下标就是 idx
max_mv[1] = 9000 ,ma[1] = 2660
max_mv[2] = 12000, ma[2] = 2000
maxwatt[i] = max_mv[i] * ma[i]; // 表示功率
maxwatt[0] = 15000000
maxwatt[1] = 23940000
maxwatt[2] = 24000000
pd 支持的范围为 5000 - 9000
第一次插上充电器,默认使用当前挡位为最低档 0 档即设置 5000 mv 充电,同时下面参数也是默认状态 0
idx = selected_idx = 0 //选择 5000
boost_idx = 0 // 选择 5000
buck_idx = 0 // 选择 5000
调用 mtk_pdc_get_idx 更新当前状态更新完状态后如下
idx = selected_idx = 0 //选择 5000
boost_idx = 1 // 选择 9000 ,当前挡位电压下的升压电压
buck_idx = 0 // 选择 5000 ,当前挡位下的降压电压
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 int mtk_pdc_get_idx (struct charger_manager *info, int selected_idx, int *boost_idx, int *buck_idx) { struct mtk_pdc *pd = &info->pdc; struct adapter_power_cap *cap ; int i = 0 ; int idx = 0 ; cap = &pd->cap; idx = selected_idx; if (idx < 0 ) { chr_err("[%s] invalid idx:%d\n" , __func__, idx); *boost_idx = 0 ; *buck_idx = 0 ; return -1 ; } for (i = 0 ; i < cap->nr; i++) { chr_err("min_mv:%d %d %d %d\n" , cap->min_mv[i], cap->max_mv[i], pd->vbus_l, pd->vbus_h); if (cap->min_mv[i] < pd->vbus_l || cap->max_mv[i] < pd->vbus_l) { chr_err("min_mv error:%d %d %d\n" , cap->min_mv[i], cap->max_mv[i], pd->vbus_l); continue ; } if (cap->min_mv[i] > pd->vbus_h || cap->max_mv[i] > pd->vbus_h) { chr_err("max_mv error:%d %d %d\n" , cap->min_mv[i], cap->max_mv[i], pd->vbus_h); continue ; } if (idx == selected_idx) { if (cap->maxwatt[i] > cap->maxwatt[idx]) idx = i; } else { if (cap->maxwatt[i] < cap->maxwatt[idx] && cap->maxwatt[i] > cap->maxwatt[selected_idx]) idx = i; } } *boost_idx = idx; idx = selected_idx; for (i = 0 ; i < cap->nr; i++) { chr_err("min_mv error:%d %d %d %d\n" , cap->min_mv[i], cap->max_mv[i], pd->vbus_l, pd->vbus_h); if (cap->min_mv[i] < pd->vbus_l || cap->max_mv[i] < pd->vbus_l) { chr_err("min_mv error:%d %d %d\n" , cap->min_mv[i], cap->max_mv[i], pd->vbus_l); continue ; } if (cap->min_mv[i] > pd->vbus_h || cap->max_mv[i] > pd->vbus_h) { chr_err("max_mv error:%d %d %d\n" , cap->min_mv[i], cap->max_mv[i], pd->vbus_h); continue ; } if (idx == selected_idx) { if (cap->maxwatt[i] < cap->maxwatt[idx]) idx = i; } else { if (cap->maxwatt[i] > cap->maxwatt[idx] && cap->maxwatt[i] < cap->maxwatt[selected_idx]) idx = i; } } *buck_idx = idx; return 0 ; }
四、G90(mt6785)-功放调试之控制
1、耳机检测代码
G90 的功放和 8788 平台的有点不一样,在插上耳机的时候功放不会自动停止播放,因此在耳机检测的时候手动添加开关功放的使能引脚的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 /drivers/misc/mediatek/accdet/mt6359/accdet.c #if PMIC_ACCDET_KERNEL static void eint_work_callback (struct work_struct *work) #else static void eint_work_callback (void ) #endif { pr_info("accdet %s(),DCC EINT func\n" , __func__); if (cur_eint_state == EINT_PIN_PLUG_IN) { pmic_write(PMIC_RG_LDO_VUSB_HW0_OP_EN_ADDR, 0x8000 ); pr_info("%s VUSB LP dis\n" , __func__); pr_info("accdet cur: plug-in, cur_eint_state = %d\n" , cur_eint_state); amplifier_control_off(); mutex_lock(&accdet_eint_irq_sync_mutex); eint_accdet_sync_flag = true ; mutex_unlock(&accdet_eint_irq_sync_mutex); __pm_wakeup_event(accdet_timer_lock, jiffies_to_msecs(7 * HZ)); accdet_init(); pr_info("%s VUSB LP dis done\n" , __func__); enable_accdet(0 ); } else { pr_info("accdet cur:plug-out, cur_eint_state = %d\n" , cur_eint_state); amplifier_control_on(); mutex_lock(&accdet_eint_irq_sync_mutex); eint_accdet_sync_flag = false ; accdet_thing_in_flag = false ; mutex_unlock(&accdet_eint_irq_sync_mutex); if (accdet_dts.moisture_detect_mode != 0x5 ) del_timer_sync(&micbias_timer); pmic_write_clr(PMIC_ACCDET_SW_EN_ADDR, PMIC_ACCDET_SW_EN_SHIFT); disable_accdet(); headset_plug_out(); } #ifdef CONFIG_ACCDET_EINT_IRQ if (get_moisture_det_en() == 0x1 ) recover_moisture_setting(gmoistureID); else recover_eint_setting(gmoistureID); #endif #ifdef CONFIG_ACCDET_EINT enable_irq(accdet_irq); pr_info("accdet %s enable_irq !!\n" , __func__); #endif }
2、耳机有声音功放没声音
插上耳机 pmu 才有功放信号输出,拔出耳机就没有信号输出,这里的信号指 pmu 端的信号,其实就是外置功放修改,修改如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 /device/mediateksample/k85v1_64/ProjectConfig.mk b/mediateksample/k85v1_64/ProjectConfig.mk MTK_AUDIO_MIC_INVERSE = no MTK_AUDIO_NUMBER_OF_MIC = 2 MTK_AUDIO_NUMBER_OF_SPEAKER = 1 -MTK_AUDIO_SPEAKER_PATH = smartpa_mtk_mt6660 +MTK_AUDIO_SPEAKER_PATH = int_hp_buf MTK_AUDIO_TUNING_TOOL_VERSION = V2.2 MTK_AUDIO_TUNNELING_SUPPORT = no MTK_AUIDO_MIC_INVERSE = no
3、喇叭尾音
Android系统默认播放停止后3秒会进入Standby模式以节省电源.standby里面有pcm_close接口,会关闭speaker的输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 diff --git a/av/services/audioflinger/AudioFlinger.h b/av/services/audioflinger/AudioFlinger.h old mode 100644 new mode 100755 index 978 d39132..73 db1b203 --- a/av/services/audioflinger/AudioFlinger.h +++ b/av/services/audioflinger/AudioFlinger.h @@ -97 ,7 +97 ,7 @@ class ServerProxy; -static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3 ); +static const nsecs_t kDefaultStandbyTimeInNsecs = milliseconds(200 ); static const nsecs_t kDefaultA2dpStandbyTimeInNsecs = milliseconds(500 );
四、耳机立体声修改
1 2 vendor/mediatek/proprietary/custom/tb8788p1_64_bsp/hal/audioflinger/audio/audio_custom_exp.h
4、 打开 ATCI
Log and Debugging -> ATCI -> ALWAYS ENABLE ATCI
喇叭文件频响曲线存放目录
device/mediatek/common/audio_param
三、G90(mt6785)-sensorhub
四、背光能调到黑屏
当打开自动调节背光功能的时候,手动调节设置中背光滚动条将背光设置到最小,屏幕会完全变黑,这种现象可能与lcm的最小亮度有关,可以采用如下方式解决:
1、adb comand设置背光,确定可以使lcm点亮的最小背光值
1 adb shell echo xx >/sys/class /leds /lcd -backlight /brightness xx 为backlight level
2、修改alps/frameworks/base/core/res/res/values/config.xml中如下参数的值为步骤1中所获取的最小背光值
1 2 3 4 5 6 7 8 <!-- Minimum allowable screen brightness to use in a very dark room. This value sets the floor for the darkest possible auto -brightness adjustment. It is expected to be somewhat less than the first entry in config_autoBrightnessLcdBacklightValues so as to allow the user to have some range of adjustment to dim the screen further than usual in very dark rooms. The contents of the screen must still be clearly visible in darkness (although they may not be visible in a bright room) . --> <integer name="config_screenBrightnessDark" >1 </integer>
五、摄像头
1、摄像头引脚
IOVDD(input output vdd): 负责i2c电压,没有这路电无法读到id,电压一般为 1.8, 少数为2.8内部转化为1.8
DVDD(digital vdd): 用于给数字信号供电,1.2v
AVDD( VDD):用于给 cmos 供电,放大模拟信号,2.8v
PWDN(power wdn): 给摄像头芯片供电,1.8
RESET: 芯片复位信号
MCLK:一般为 24/26MHZ
2、摄像头去掉af
vendor/mediatek/proprietary/custom/mt6785/hal/imgsensor_metadata/gc5035_mipi_raw/config_static_metadata.module.gc5035mipiraw.h
将 MTK_CONTROL_AF_MODE_CONTINUOUS_PICTRUE 改为 MTK_CONTROL_AF_MODE_OFF
同时修改
vendor/mediatek/proprietary/custom/mt6785/hal/lens/src/lenslist.cpp
将对应的配置改为 “Dummy” 如下
1 {S5K3M3_SENSOR_ID, DUMMY_MODULE_ID, AK7371AF_LENS_ID, "Dummy" , pAK7371AF_MAIN2_getDefaultData},
3、修改摄像头方向以及mipi通道
vendor\mediatek\proprietary\custom\mt8168\hal\imgsensor_src\cfg_setting_imgsensor.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 static CUSTOM_CFG gCustomCfg[] = { { .sensorIdx = IMGSENSOR_SENSOR_IDX_MAIN, .mclk = CUSTOM_CFG_MCLK_3, .port = CUSTOM_CFG_CSI_PORT_2, .dir = CUSTOM_CFG_DIR_REAR, .bitOrder = CUSTOM_CFG_BITORDER_9_2, .orientation = 90 , .horizontalFov = 67 , .verticalFov = 49 }, { .sensorIdx = IMGSENSOR_SENSOR_IDX_SUB, .mclk = CUSTOM_CFG_MCLK_1, .port = CUSTOM_CFG_CSI_PORT_0, .dir = CUSTOM_CFG_DIR_FRONT, .bitOrder = CUSTOM_CFG_BITORDER_9_2, .orientation = 270 , .horizontalFov = 63 , .verticalFov = 40 , .secure = CUSTOM_CFG_SECURE_M0 }, ....... };
4、摄像头连不上cct
请检查是否设置了 SENSOR_OUTPUT_FORMAT_RAW_Gb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +++ b/drivers/misc/mediatek/imgsensor/src/common/v1_1/s5k5e9_mipi_raw/s5k5e9mipiraw_Sensor.c @@ -156 ,7 +156 ,7 @@ static imgsensor_info_struct imgsensor_info = { .sensor_interface_type = SENSOR_INTERFACE_TYPE_MIPI, .mipi_sensor_type = MIPI_OPHY_NCSI2, .mipi_settle_delay_mode = MIPI_SETTLEDELAY_AUTO, - .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gb, + .sensor_output_dataformat = SENSOR_OUTPUT_FORMAT_RAW_Gr, .mclk = 24 , .mipi_lane_num = SENSOR_MIPI_2_LANE, .i2c_addr_table = {0x5a ,0x20 ,0xff }, @@ -165 ,7 +165 ,7 @@ static imgsensor_info_struct imgsensor_info = { static imgsensor_struct imgsensor = { - .mirror = IMAGE_HV_MIRROR, + .mirror = IMAGE_NORMAL, .sensor_mode = IMGSENSOR_MODE_INIT, .shutter = 0x3D0 , .gain = 0x100 ,
六、adb remount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 adb reboot bootloader echo 等待进入bootloader pause fastboot flashing unlock echo 按照界面提示按小机音量+按键 pause fastboot reboot echo 等待开机完成 pause adb root pause adb disable-verity adb reboot pause adb root adb remount pause
七、安卓11打开串口log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 --- a/drivers/misc/mediatek/mtprintk/mtk_printk_ctrl.c +++ b/drivers/misc/mediatek/mtprintk/mtk_printk_ctrl.c @@ -34 ,7 +34 ,7 @@ #ifdef CONFIG_MTK_ENG_BUILD int printk_ctrl; #else -int printk_ctrl = 1 ; +int printk_ctrl = 0 ; #endif module_param_named(disable_uart, printk_ctrl, int , 0644 ); @@ -51 ,7 +51 ,7 @@ bool mt_get_uartlog_status (void ) void mt_disable_uart (void ) { - if (printk_ctrl != 2 ) + if (printk_ctrl != 0 ) printk_ctrl = 1 ; }
八、安卓按键映射
1 \out\target\product\tb8168p1_64_bsp\system\usr\keylayout\Generic.kl
九、mtk 平台反汇编 dts
1 out/target/product/tb8788p1_64_bsp/obj/KERNEL_OBJ/scripts/dtc/dtc -I dtb -O dts -o out/target/product/tb8788p1_64_bsp/obj/KERNEL_OBJ/arch/arm64/boot/dts/mediatek/mt6771.dtb
1、dtbo img -> dtb
1 2 ./out/host/linux-x86/bin/mkdtimg dump out/target/product/tb8788p1_64_bsp/dtbo-verified.img -b a.0 执行后生成a.0 .0
2、dtb->dts
1 2 ./out/target/product/tb8788p1_64_bsp/obj/KERNEL_OBJ/scripts/dtc/dtc -I dtb -O dts -o x100.dts a.0 .0 执行后生成x100.dts
十、快速打包patch
将脚本 outdiff 拷贝进需要打包的目录
运行 git status > a.txt 创建 a.txt 文件
运行脚本 ./outdiff 创建出 patch 目录 out_diff 该目录有 modified 文件
对比 a.txt 将新曾文件拷贝进对应目录
十一、打开mtklog
1 adb shell am start -n com.mediatek.mtklogger/com.mediatek.mtklogger.MainActivity
十二、给sys节点权限
1.并非所有的 Linux distributions 都支持 SELinux
目前 SELinux 支持三种模式,分别如下:
enforcing : 强制模式,代表 SELInux 运作中,且已经 正确的开始限制domain/type
permisssive:宽容模式,代表 SELinux 运座钟,不过仅会有警告讯息并不会限制
domain/type的存取。这个模式可以用来运作为 SELinux 的 debug 之用。
disabled: 关闭, SELinux 并没有实际运作
2.查看 SELinux 的模式
get enforcing =》enforcing
在 MTK 的平台下查看 SELinux 的方法是使用 getenforce
如果显示是 enforcing 就说明 SELinux 是打开的
如果显示是 disabled 就说明 SELinux 是关闭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 第一处修改 system/core/init/selinux.cpp bool IsEnforcing () { + return false ; if (ALLOW_PERMISSIVE_SELINUX) { return StatusFromCmdline() == SELINUX_ENFORCING; } 第二处修改 diff --git a/mediateksample/k71v1_64_bsp/init.project.rc b/mediateksample/k71v1_64_bsp/init.project.rc index 8722 a5a5..c87338c3 100755 --- a/mediateksample/k71v1_64_bsp/init.project.rc +++ b/mediateksample/k71v1_64_bsp/init.project.rc @@ -35 ,6 +35 ,11 @@ on post-fs-data chmod 0660 /dev/spm chown system system /dev/spm +#ADDNODE + chmod 0666 /sys/class /led_ctrl /led_ctrl + chmod 0666 /sys /class /hall /hall_1 + chmod 0666 /sys /class /hall /hall_2
十三、安卓11编译相关
1、 Split command build for system product
1)Build system project
1 2 3 4 source build/envsetup.sh export OUT_DIR=out_sys lunch sys_mssi_64_ww-eng make sys_images
2)Partial build
1 2 3 4 5 source build/envsetup.sh export OUT_DIR=out_sys lunch sys_mssi_64_ww-eng mmma system/related/paths (or make system_module_name, or mm, mmm google default command.)
2、Split command build for vendor product
1)Build vendor project
1 2 3 4 source build/envsetup.sh export OUT_DIR=out lunch vnd_k71v1_64_bsp-eng make vnd_images krn_images
2) Partial build
1 2 3 4 source build/envsetup.sh export OUT_DIR=out lunch vnd_k71v1_64_bsp-eng mmma vendor/related/paths
3、Image post process
1) Normal load
1 python out/target/product/mssi_t_64_cn/images/split_build.py --system-dir out/target/product/mssi_t_64_cn/images --vendor-dir out/target/product/tb8789p2_64/images --kernel-dir out/target/product/tb8789p2_64/images --output-dir out/target/product/tb8789p2_64/merged
2) Normal + OTA
1 2 3 python out_sys/target/product/mssi_64_ww/images/split_build.py --system-dir out_sys/target/product/mssi _64_ww/images --vendor-dir out/target/product/k71v1_64_bsp/images --kernel-dir out/target/product/k71v1 _64_bsp/images --output-dir output_load --otapackage
3) Normal + CTS
1 2 3 python out_sys/target/product/mssi_64_ww/images/split_build.py --system-dir out_sys/target/product/mssi _64_ww/images --vendor-dir out/target/product/k71v1_64_bsp/images --kernel-dir out/target/product/k71v1 _64_bsp/images --output-dir output_load --certs-dir $CTS_SECURITY_KEY
4) Normal + OTA + CTS
1 2 3 python out_sys/target/product/mssi_64_ww/images/split_build.py --system-dir out_sys/target/product/mssi _64_ww/images --vendor-dir out/target/product/k71v1_64_bsp/images --kernel-dir out/target/product/k71v1 _64_bsp/images --output-dir output_load --otapackage --certs-dir $CTS_SECURITY_KEY
5)编译命令
1 source build/envsetup.sh && lunch sys_mssi_t_64_cn-userdebug && make sys_images && lunch vnd_tb8789p2_64-userdebug && make -j24 vnd_images krn_images
十四、linux 查看内存空间
df -h
十五、设置蓝牙开机默认状态
开机设置系统将 wifi 蓝牙 gsensor 默认打开
1 2 3 4 5 vendor/mediatek/proprietary/packages/apps/SettingsProvider/ res/values/defaults.xml <bool name="def_accelerometer_rotation" >true </bool > <integer name="def_user_rotation" >1 </integer> <bool name="def_bluetooth_on" >true </bool > <bool name="def_wifi_on" >true </bool >
十六、快速获取设备路径
1 2 3 4 path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %s\n" , dev->name ? dev->name : "Unspecified device" , path ? path : "N/A" );
十七、lk 阶段到 kernel 阶段屏幕会闪一下
抓取 mipi 波形发现,mipi 波形从 lk 到 kernel 阶段时波形被拉宽了
最终发现原因如下 lk 阶段直接使用
1 2 3 4 5 6 mediatek/proprietary/bootable/bootloader/lk/platform/mt6785/ddp_dsi.c horizontal_backporch_byte = ((dsi_params->horizontal_backporch + dsi_params->horizontal_sync_active) * dsiTmpBufBpp - 10 );
这个公式计算这里的 horizontal_sync_active = 16 计算出来得到 188
但是 kernel 阶段对 t_hsa 多做了一个处理
1 2 3 4 5 6 7 drivers/misc/mediatek/video/mt6785/dispsys/ddp_dsi.c t_hsa = ALIGN_TO(t_hsa * dsiTmpBufBpp - 4 , 4 ); ASSERT((t_hbp + t_hsa) * dsiTmpBufBpp > 9 ); t_hbp = ALIGN_TO((t_hbp + t_hsa) * dsiTmpBufBpp - 10 , 4 );
在kernel 多了这个算法使得 t_hsa 从 16 变成了 44, 最终导致 计算结果变成了 272 ,mtk 给的解决方案如下:
1 2 t_hbp = ALIGN_TO((t_hbp + dsi_params->horizontal_sync_active) * dsiTmpBufBpp - 10 , 4 );
同时对于行同步型号 hsa,hbp 等都会调用 ALIGN_TO 函数对 4 做取整的操作(mtk 说是和内部设计相关)。因此我们填写参数可以直接将行同步信号填为 4 的整数倍
十八、安卓 11 关闭 lib 库校验
安卓 9 是默认关闭的,在 Android.mk 中增加
1 LOCAL_CHECK_ELF_FILES := false
十九、安卓 9 编译打包 dtbo
1 2 make dtboimage -j8 2 >&1 | tee build.log ./vendor/mediatek/proprietary/scripts/sign-image/sign_image.sh
二十、mkt pclk计算
1 params->dsi.PLL_CLOCK = (vertical_sync_active + vertical_backporch + vertical_frontporch + FRAME_HEIGHT) * (horizontal_sync_active + horizontal_backporch + horizontal_frontporch + FRAME_WIDTH) * fps * 24 / (4 * 2 );
二十一、闪屏debug
排除背光。
a、 把背光接固定背光,如果仍然闪屏,说明不是背光的问题;
如果屏不闪,说明是背光问题。
b、 如果是背光问题,继续分析是否有开AAL功能,如果有开
AAL功能,请将AAL功能关闭。如果关闭AAL功能后,屏不闪,说明是
AAL导致的屏闪,请提issue给MTK。如果关闭AAL功能后,屏仍然闪,
请内部确认贵司是否有在framework层做改动,很多情况是由于改动
Framework,绕过LightService直接控制背光结点导致的问题。
c、 其实当定位到是背光的问题了,这个时候就可以提问题给
MTK了,抓取Mobile log给MTK。
排除ESD。
a、如果通过第一步(a)排除说不是背光闪,第二步可以检查是否由于ESD check
导致的闪屏。可以先关闭ESD功能,看显示是否仍然会闪。如果关闭ESD功能后,lcm不
再闪动,说明是ESD check导致的闪屏。这个时候就可以提把Mobile log抓过来给MTK看了。
如果关闭ESD功能后,lcm仍然闪动,说明和ESD check无关。
其他情况。
a、如果背光和ESD都给排除了,这个时候是bug的概率比较大。(常见的情况是待机
的时候不定时的闪屏),抓取Mobilelog过来给MTK check。
二十二、g-sensor 系统不转
1 2 frameworks/base/core/res/res/values/config.xml <bool name="config_allowAllRotations" >true </bool >