[MTK] LED 客制化

文摘 MediaTek 2020-04-20 阅读:11175

LED 客制化:

主要分为以下章节:

  1. 驱动测试:检测驱动是否正常
  2. 相关文件:介绍相关文件
  3. LED驱动异常检测步骤:针对上层调用下层失败,但是adb可以控制led的情况
  4. 闪烁改为呼吸灯模式:将闪烁配置成呼吸灯
  5. PCHG_LED配置更改:切换硬件控制PCHG_LED为软件控制。

一.驱动检测:

1)MT6370/MT6371上的LED

进入对应led的文件中进行(sys/class/leds/ 下面会有对应led结点的文件夹)

闪烁测试需要4步:

1.echo pwm_mode > trigger

这时会生成pwm_dim_freq、pwm_duty两个文件(生成文件是软件实现)

2.echo 3 > pwm_dim_freq

3.echo 5 > pwm_duty

4.echo 5 > brightness

驱动正常就可以看到闪烁,下面同理

设置常亮测试:

echo cc_mode > trigger

echo 5 > brightness                 //要是不亮,写255试试,一般内部是分为0-6级,输入多了按最高算            0是设置灭

呼吸灯测试:

echo breath_mode > trigger

echo 14 > toff

echo 11 > tr1

echo 5 > brightness

可以看到进行呼吸灯

如果均成功,说明驱动可以正常驱动MT6370文件

2)平台PMIC测试:

1.点亮测试:

echo 255 > brightness

echo 0 >brightness

2.闪烁测试:

1.echo timer > trigger

2.

echo 500 > delay_on

echo 500 > delay_off

--------------------------------------- 
二.LED驱动框架相关操作接口:

1.开机

Android通过hal层接口,来完成对led驱动的控制。(lights.c)

然后通过底层驱动来完成整个下层的控制。(PMIC上面的LED :mtk_leds.cmtk_leds_drv.c/MT6370/71上面的LED:mt6370_pmu_rgbled.c

2.关机充电(KPOC)

上层调用接口:/vendor/mediatek/proprietary/external/charger/lights.cpp

然后调用的到驱动和开机的驱动一致。

--------------------------------------- 
三.LED驱动异常检测步骤:

1.命名检查:
因为HAL层(KPOC和正常开机)里面有用字符串来描述文件结点的位置,而且名字都是red/green/blue。所以,在一开始就要将Led ISINK的名字规范好,红灯的ISINK改名为red,绿灯改名为green以此类推。(具体可以查看hal层里面对路径定义的字符串,使用本平台上面的PMIC是定义名字对的,只是要看清楚ISINK是否与颜色匹配)

举例字符串:"/sys/class/leds/red/brightness";

这里以使用mt6370.dtsi结点为例(请以您使用的版本为准)

rgbled {

 compatible = "mediatek,mt6370_pmu_rgbled";//版本不同,名字不同,以实际为准。

 interrupt-names = "isink4_short", "isink3_short",

       "isink2_short", "isink1_short",

       "isink4_open", "isink3_open",

       "isink2_open", "isink1_open";

 /* name cnt must be 4 */

 mt,led_name = "mt6370_pmu_led1", "mt6370_pmu_led2",

   "mt6370_pmu_led3", "mt6370_pmu_led4";

  /* trigger cnt must be 4, mode can be selected as */

  /* cc_mode -> const current mode */

  /* pwm_mode -> pwm dimming mode */

  /* breath_mode -> as the name */

  mt,led_default_trigger = "cc_mode", "cc_mode", "cc_mode", "none";

};

其中标红字的就是您的led名字。请确认红字连接的LED灯(一般led1-4分别对应着ISINK1-4),并将红字改为对应的LED名字,若没有使用的,可以不用更改。

注意:必须是red blue green 。如下:

Led1-3 分别对应red green blue灯,而led4没有使用。

mt,led_name = "red", "green", "blue", "mt6370_pmu_led4";

补充:若是MT6370/71 的ISINK4(可以配置为硬件点亮)引脚想配置为硬件点亮,则不需要修改其名字。否则会被配置为软件点亮。

2.检测HAL层。(开机异常检查lights.c,关机检查lights.cpp)

1)文件有效性判断

不同版本,的hal中的lights.c中,有些会分别去检测led的文件是否存在,并且是检测3色灯结点同时存在,若是只定义了2个结点,少了其中某一个,都会导致上层与下层的通信中断,也就会出现adb可控led,而上层不可控led的情况:

else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
set_light = set_light_notifications;
if (access(RED_LED_FILE, F_OK) < 0)    //判断RED文件是否存在
return -errno;
if (access(GREEN_LED_FILE, F_OK) < 0)  //判断GREEN文件是否存在
return -errno;
if (access(BLUE_LED_FILE, F_OK) < 0)  //判断BLUE文件是否存在
return -errno;
}

处理方法:
将没定义的文件检测去掉,或者全部去掉。

2)将PMIC框架修改为MT6370框架:
此步仅针对使用MT6370上LED的,PMIC上面的不需要修改此步骤。
因为默认的lights.c是针对PMIC上面的LED的,所以在使用MT6370上面的LED的时候,请在lights.c中做如下更改,以绿灯为例(其他灯同理):
(1)添加对应闪烁灯结点路径:
/MT6370 LED/

char const*const GREEN_PWM_DUTY        = "/sys/class/leds/green/pwm_duty";

char const*const GREEN_PWM_DIM_FREQ        = "/sys/class/leds/green/pwm_dim_freq";   

(2)修改对应的blink_xx().

static int blink_green(int level, int onMS, int offMS)

{

            static int preStatus = 0; // 0: off, 1: blink, 2: no blink

            int nowStatus;

            int i = 0;

            if (level == 0)

                        nowStatus = 0;

            else if (onMS && offMS)

                        nowStatus = 1;

            else

                        nowStatus = 2;

            if (preStatus == nowStatus)

                        return -1;

#ifdef LIGHTS_DBG_ON

            ALOGD("blink_green, level=%d, onMS=%d, offMS=%d\n", level, onMS, offMS);

#endif

            if (nowStatus == 0) {

            write_int(GREEN_LED_FILE, 0);

            }

            else if (nowStatus == 1) {

                        ALOGD("MTK:blink green\n");

            write_str(GREEN_TRIGGER_FILE, "pwm_mode");

            while (((access(GREEN_PWM_DUTY, F_OK) == -1) || (access(GREEN_PWM_DIM_FREQ, R_OK|W_OK) == -1)) && i<10) {

                        ALOGD("GREEN_PWM_DUTY/FREQ doesn't exist or cannot write!!\n");

                        led_wait_delay(5);//sleep 5ms for wait kernel LED class create led node of fs

                        i++;

            }

                        write_int(GREEN_PWM_DUTY, 5);

                        write_int(GREEN_PWM_DIM_FREQ, 3);

                        write_int(GREEN_LED_FILE, 0); // default full brightness

                        write_int(GREEN_LED_FILE, 255); // default full brightness

            }

            else {//常亮

                        ALOGD("MTK:set green brightness!!\n");

             write_str(GREEN_TRIGGER_FILE, "cc_mode");

               write_int(GREEN_LED_FILE, 255); // default full brightness

            }

            preStatus = nowStatus;

            return 0;

}

同理红灯定义:

char const*const RED_PWM_DUTY        = "/sys/class/leds/red/pwm_duty";

char const*const RED_PWM_DIM_FREQ        = "/sys/class/leds/red/pwm_dim_freq";   

修改函数为:blink_red()

写结点的结构与green一致,只是将里面所写的文件替换为red。

如:

GREEN_LED_FILE => RED_LED_FILE

GREEN_TRIGGER_FILE => RED_TRIGGER_FILE

同理绿灯。

3.修改ueventd.mtxxx.rc 文件权限

该步需要修改1.2之后重新编译才能进行修改。若是1.2修改之后,上层可以访问下层了,则可以不进行该修改。

在之前1.2检测都没问题,而上层仍旧无法访问下层的时候。基本可以判定为上层通过hal层访问结点时,权限不够。这时候需要增加对对应结点的控制权限。(若是没有该问题,可以先忽略)

修改(是Android上层调用权限相关的文件)如ueventd.mt6765.ufs.rc (mt6765平台)

在对应文件里面添加文件权限修改。

如果是使用PMIC上面的LED,则添加/检测对应led灯路径的生成文件:

真实路径    delay_on      0664  system   system

真实路径    delay_off      0664  system   system

如果是使用MT6370上面的LED,则添加/检测对应led灯路径的生成文件:

真实路径    pwm_duty      0664  system   system

真实路径    pwm_dim_freq      0664  system   system

真实路径填写,以PMIC的框架为例:

使用ADB进行如下测试:

            cd sys/class/leds/red

            echo timer > trigger     //如果是平台PMIC写 echo pwm_mode > trigger

            ls -l                  (l为L的小写)

(需要1.2修改后重新编译后,根据实际路径进行更改)

您可以看到如下情况:

(PMIC查看delay_on/delay_on结点;MT6370的查看pwm_duty/pwm_dim_freq结点)

pwm_dim_freq.png

后面的  ->箭头后面才是真的物理地址也就是真实地址。如果没有->箭头的,当前路径为真实地址。->后面的前面省略的..一般是sys/,具体还请您用ADB到对应目录下面去寻找看。

需要对RED BLUE 灯所使用的三色灯添加:(注意修改该文件时,要切换成c/c++的阅读状态,不要添加在被注释的地方,有个地方是书写错误/* 改为/即可)

每个灯2条,所以使用3个灯就添加6条。每条对应其真实路径。

若还是不行,还请判断是不是上层无法写brightnesss结点或trigger结点。然后在.rc文件里面,再添加brightness和trigger结点的权限:

真实路径    brightnes      0664  system   system

真实路径    trigger      0664  system   system

补充:无法写结点在kernel log里面会出现提示(brightness的情况需要另寻判断log):

XX  doesn't exist or cannot write!!

--------------------------------------- 
四.闪烁改为呼吸灯模式

1.闪烁模式改为呼吸灯模式:(需要确保通过之前的三检测,能让上层正常控制LED)

1)PMIC的LED:
平台上本身就定义了呼吸函数:

(以o1.mp1,MT6739平台为例)

修改文件:mtk_leds.c(参考路径:/kernel-4.4/drivers/misc/mediatek/leds/mt6739/mtk_leds.c)

1.注意,需要将如下函数的#if 0改为1,让其可以编译进去。

led_switch_breath_pmic()

2.将mt_mt65xx_blink_set()中的

mt_led_blink_pmic(led_data->cust.data,&nled_tmp_setting);

改为:

led_switch_breath_pmic(led_data->cust.data,&nled_tmp_setting,1);

虽然这样可以让闪烁变成呼吸灯。但是无法控制时间,不论怎么样的闪烁时间配置,都是采用该同一种功率的呼吸。

具体呼吸灯的配置更改:

datasheet里面可以搜:breath  看其每个参数对应的图。

然后根据led_switch_breath_pmic函数里面,配置的寄存器,查看对应datasheet的寄存器地址,就可以知道可以配什么值。

2)MT6370/71上面的LED:

因为没有专门为呼吸灯设计的框架,所以这种修改,及时上层设置不同的闪烁时间,到这里也只能用固定的参数进行呼吸灯设置,这个参数修改在lights.c对应的blink_xx里面配置。

在lights.c里面,以绿灯为例添加,(规则同三种的lights.c修改一样):

char const*const GREEN_BREATH_TOFF        = "/sys/class/leds/green/ toff ";

char const*const GREEN_BREATH_TR1        = "/sys/class/leds/green/ tr1";   

修改blink_green:

static int blink_green(int level, int onMS, int offMS)

{

 static int preStatus = 0; // 0: off, 1: blink, 2: no blink
 int nowStatus;
 int i = 0;
 if (level == 0)
  nowStatus = 0;
 else if (onMS && offMS)
  nowStatus = 1;
 else
  nowStatus = 2;
 if (preStatus == nowStatus)
  return -1;

#ifdef LIGHTS_DBG_ON

 ALOGD("blink_green, level=%d, onMS=%d, offMS=%d\n", level, onMS, offMS);

#endif

 if (nowStatus == 0) {

 write_int(GREEN_LED_FILE, 0);

 }

 else if (nowStatus == 1) {

 ALOGD("MTK:blink green\n");

 write_str(GREEN_TRIGGER_FILE, " breath_mode ");

 while (((access(GREEN_BREATH_TOFF, F_OK) == -1) || (access(GREEN_BREATH_TR1, R_OK|W_OK) == -1)) && i<10) {

  ALOGD("GREEN_BREATH_TR1/TR1 doesn't exist or cannot write!!\n");

  led_wait_delay(5);//sleep 5ms for wait kernel LED class create led delay_off/delay_on node of fs

  i++;

 }

 write_int(GREEN_BREATH_TOFF, 14);
 write_int(GREEN_BREATH_TR1, 11);
 write_int(GREEN_LED_FILE, 0); // default full brightness
 write_int(GREEN_LED_FILE, 255); // default full brightness
 }
 else
 {//常亮

  ALOGD("MTK:set green brightness!!\n");

    write_str(GREEN_TRIGGER_FILE, "cc_mode");

    write_int(GREEN_LED_FILE, 255); // default full brightness

 }

 preStatus = nowStatus;

 return 0;

}

之后按照三种的检测,看是否要修改.rc文件。

同理修改red 或者blue。

因为breath 的呼吸参数不只一个,这里只是用toff和tr1来进行,更多参数可以手操adb,写breath_mode > trigger后,看生成什么文件

然后在对应blink_xx函数的如下位置中,根据逻辑,添加读写顺序。

else if (nowStatus == 1) {

}

write_int :向结点写数值

write_str :向结点写字符串


 五:PCHG_LED配置更改

不论是PMIC还是MT6370/71上面,都有一个可以通过硬件或者通过软件控制的ISINK引脚。若没有更改过配置,默认为硬件点亮。

1)PMIC的PCHG_LED

切换为软件控制LED:

除了按照三章节的修改检测之外。

需要自己在需要切换的位置,自己添加代码去写PCHG_LED的切换寄存器。

2)MT6370/71

不需要特殊的修改,因为代码逻辑配置,当配置PCHG_LED为对应green/red/blue的时候,MT6370/71的驱动已经可以自己切换从硬件到软件控制LED的功能。

切换时间是在上层第一次调用到该LED时,驱动代码里面会自动切换为软件控制。

0条评论

© 2024 芯缘异码. Powered by Typecho