MTK LIGHT 代码分析

MTK LIGHT 代码分析

项目上需要做些客制化的东西,需要用到light 一块的东西,好久以前看过,但是没有记录下来,这次重新看看,然后记录下来。

lightservice start

private void startCoreServices() {
    // Manages LEDs and display backlight.
    mSystemServiceManager.startService(LightsService.class);

应用中怎么用

get service

    final LightsManager lights = getLocalService(LightsManager.class);
    mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
    返回一个 lightmanager, 只有一个方法。

    public abstract class LightsManager {
    public static final int LIGHT_ID_BACKLIGHT = 0;
    public static final int LIGHT_ID_KEYBOARD = 1;
    public static final int LIGHT_ID_BUTTONS = 2;
    public static final int LIGHT_ID_BATTERY = 3;
    public static final int LIGHT_ID_NOTIFICATIONS = 4;
    public static final int LIGHT_ID_ATTENTION = 5;
    public static final int LIGHT_ID_BLUETOOTH = 6;
    public static final int LIGHT_ID_WIFI = 7;
    public static final int LIGHT_ID_COUNT = 8;

    public abstract Light getLight(int id);
    }

关掉

    mNotificationLight.turnOff();
    NotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,ledOnMS, ledOffMS);

setFlashing 从service 到 HAL分析

LightsManager getLight 实现

private final LightsManager mService = new LightsManager() {
    @Override
    public com.android.server.lights.Light getLight(int id) {
        if (id < LIGHT_ID_COUNT) {
            return mLights[id];
        } else {
            return null;
        }
    }
};


final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];  LightsService 成员变量

setFlashing在 LightImpl 中实现 ###

private final class LightImpl extends Light {

public void setFlashing(int color, int mode, int onMS, int offMS) {
        synchronized (this) {
            setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
        }
    }

————》

private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
        if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
            if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                    + Integer.toHexString(color));
            mColor = color;
            mMode = mode;
            mOnMS = onMS;
            mOffMS = offMS;
            Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", " + color + ")");
            try {
                setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_POWER);
            }
        }
    }

————》

 native 端 setLight_native, 在文件 com_android_server_lights_LightsService.cpp (35_smt\frameworks\base\services\core\jni) 中

static void setLight_native(JNIEnv *env, jobject clazz, jlong ptr,
    jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
    Devices* devices = (Devices*)ptr;
    light_state_t state;

    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
        return ;
    }

    memset(&state, 0, sizeof(light_state_t));
    state.color = colorARGB;
    state.flashMode = flashMode;
    state.flashOnMS = onMS;
    state.flashOffMS = offMS;
    state.brightnessMode = brightnessMode;

    {
        ALOGD_IF_SLOW(50, "Excessive delay setting light");
        **devices->lights[light]->set_light(devices->lights[light], &state);**
    }
}

————–》

Lights.c (35_smt\vendor\mediatek\proprietary\hardware\liblights)



static int open_lights(const struct hw_module_t* module, char const* name,
    struct hw_device_t** device)
{
    int (*set_light)(struct light_device_t* dev,
            struct light_state_t const* state);
     // 根据NAME 来分辨操作,  #define LIGHT_ID_BACKLIGHT          "backlight" 在light.h 中定义。
    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
        set_light = set_light_backlight;
    } 
    else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
        set_light = set_light_keyboard;
    }
    else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
        set_light = set_light_buttons;
    }
    else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
        set_light = set_light_battery;
    }
    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
        set_light = set_light_notifications;
    }
    else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
        set_light = set_light_attention;
    }
    else {
        return -EINVAL;
    }

    pthread_once(&g_init, init_globals);

    struct light_device_t *dev = malloc(sizeof(struct light_device_t));
    memset(dev, 0, sizeof(*dev));

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;
    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    dev->set_light = set_light;

    *device = (struct hw_device_t*)dev;
    return 0;
}


static struct hw_module_methods_t lights_module_methods = {
    .open =  open_lights,
};

/*
 * The lights Module
 */
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    //.version_major = 1,
    //.version_minor = 0,
    .id = LIGHTS_HARDWARE_MODULE_ID,
    .name = "MTK lights Module",
    .author = "MediaTek",
    .methods = &lights_module_methods,
};

————》
我们的是LIGHT_ID_NOTIFICATIONS,接下来我们来看 set_light_notifications

static int set_light_notifications(struct light_device_t* dev,
        struct light_state_t const* state)
{
    pthread_mutex_lock(&g_lock);
    g_notification = *state;
    ALOGV("set_light_notifications g_trackball=%d color=0x%08x",
            g_trackball, state->color);
    if (g_haveTrackballLight) {
        handle_trackball_light_locked(dev);
    }
    handle_speaker_battery_locked(dev);
    pthread_mutex_unlock(&g_lock);
    return 0;
}


static void handle_speaker_battery_locked(struct light_device_t* dev)
{
    if (is_lit(&g_battery)) {
        set_speaker_light_locked(dev, &g_battery);
    } else {
        set_speaker_light_locked(dev, &g_battery); /*Turkey workaround: notification and Low battery case, IPO bootup, NLED cannot blink*/ 处理低电压下情况
        set_speaker_light_locked(dev, &g_notification);
    }
}

我们的是LIGHT_ID_NOTIFICATIONS 会比较复杂,如果是 LIGHT_ID_KEYBOARD ,则非常简单:

static int set_light_keyboard(struct light_device_t* dev,
        struct light_state_t const* state)
{
    int err = 0;
    int on = is_lit(state);
    pthread_mutex_lock(&g_lock);
    err = write_int(KEYBOARD_FILE, on?255:0);
    pthread_mutex_unlock(&g_lock);
    return err;
}

直接写sys file, 然后就到kernel中去了。

——-》 对于notification light, 不管低电的特殊情况,我们来关注 set_speaker_light_locked(dev, &g_notification);

static int set_speaker_light_locked(struct light_device_t* dev,
        struct light_state_t const* state)
{
    int len;
    int alpha, red, green, blue;
    int onMS, offMS;
    unsigned int colorRGB;

    switch (state->flashMode) {
        case LIGHT_FLASH_TIMED:
            onMS = state->flashOnMS;
            offMS = state->flashOffMS;
            break;
        case LIGHT_FLASH_NONE:
        default:
            onMS = 0;
            offMS = 0;
            break;
    }

    colorRGB = state->color;

#ifdef LIGHTS_DBG_ON
    ALOGD("set_led_state colorRGB=%08X, onMS=%d, offMS=%d\n",
            colorRGB, onMS, offMS);
#endif

    alpha = (colorRGB >> 24) & 0xFF;
    if (alpha) {
        red = (colorRGB >> 16) & 0xFF;
        green = (colorRGB >> 8) & 0xFF;
        blue = colorRGB & 0xFF;
    } else { // alpha = 0 means turn the LED off
        red = green = blue = 0;
    }

    if (red) {
        blink_green(0, 0, 0);
        blink_blue(0, 0, 0);
        blink_red(red, onMS, offMS);
    }
    else if (green) {
        blink_red(0, 0, 0);
        blink_blue(0, 0, 0);
        blink_green(green, onMS, offMS);
    }
    else if (blue) {
        blink_red(0, 0, 0);
        blink_green(0, 0, 0);
        blink_blue(blue, onMS, offMS);
    }
    else {
        blink_red(0, 0, 0);
        blink_green(0, 0, 0);
        blink_blue(0, 0, 0);
    }

    return 0;
}

————》 接下来我们抽一个来看

static int
blink_blue(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_blue, level=%d, onMS=%d, offMS=%d\n", level, onMS, offMS);
#endif
    if (nowStatus == 0) {
            write_int(BLUE_LED_FILE, 0);
    }
    else if (nowStatus == 1) {
//          write_int(BLUE_LED_FILE, level); // default full brightness
        write_str(BLUE_TRIGGER_FILE, "timer");  //  先写此 /sys/class/leds/blue/trigger  sys文件路径
        while (((access(BLUE_DELAY_OFF_FILE, F_OK) == -1) || (access(BLUE_DELAY_OFF_FILE, R_OK|W_OK) == -1)) && i<10) {
            ALOGD("BLUE_DELAY_OFF_FILE 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(BLUE_DELAY_OFF_FILE, offMS);    "/sys/class/leds/blue/delay_off";
        write_int(BLUE_DELAY_ON_FILE, onMS);   /sys/class/leds/blue/delay_on
    }
    else {
        write_str(BLUE_TRIGGER_FILE, "none");
        write_int(BLUE_LED_FILE, 255); // default full brightness
    }

    preStatus = nowStatus;

    return 0;
}

kernel light 分析

probe 分析

Leds_drv.c (35_smt\kernel-3.10\drivers\misc\mediatek\leds)

static int __init mt65xx_leds_probe(struct platform_device *pdev)
{
    int i;
    int ret, rc;
    struct cust_mt65xx_led *cust_led_list = mt_get_cust_led_list(); 

    ****************************************************************************************************************
    static struct cust_mt65xx_led cust_led_list[MT65XX_LED_TYPE_TOTAL] = {
        {"red",               MT65XX_LED_MODE_NONE, -1,{0}},
        {"green",             MT65XX_LED_MODE_NONE, -1,{0}},
        {"blue",              MT65XX_LED_MODE_NONE, -1,{0}},
        {"jogball-backlight", MT65XX_LED_MODE_NONE, -1,{0}},
        {"keyboard-backlight",MT65XX_LED_MODE_NONE, -1,{0}},
        {"button-backlight",  MT65XX_LED_MODE_NONE, -1,{0}},
        {"lcd-backlight",     MT65XX_LED_MODE_CUST_BLS_PWM, (long)disp_bls_set_backlight,{0}},

    };
    ****************************************************************************************************************
    LEDS_DRV_DEBUG("[LED]%s\n", __func__);
    get_div_array();
    for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {  
        if (cust_led_list[i].mode == MT65XX_LED_MODE_NONE) {
            g_leds_data[i] = NULL;
            continue;
        }

        g_leds_data[i] = kzalloc(sizeof(struct mt65xx_led_data), GFP_KERNEL);
        if (!g_leds_data[i]) {
            ret = -ENOMEM;
            goto err;
        }

        g_leds_data[i]->cust.mode = cust_led_list[i].mode;
        g_leds_data[i]->cust.data = cust_led_list[i].data;
        g_leds_data[i]->cust.name = cust_led_list[i].name;

        g_leds_data[i]->cdev.name = cust_led_list[i].name;
        g_leds_data[i]->cust.config_data = cust_led_list[i].config_data;    /* bei add */

        g_leds_data[i]->cdev.brightness_set = mt65xx_led_set;   // 所有的操作都在这3个函数中,后面来详细分析。
        g_leds_data[i]->cdev.blink_set = mt65xx_blink_set;

        INIT_WORK(&g_leds_data[i]->work, mt_mt65xx_led_work);

        ret = led_classdev_register(&pdev->dev, &g_leds_data[i]->cdev);

        if (strcmp(g_leds_data[i]->cdev.name, "lcd-backlight") == 0) {
            rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_duty);
            if (rc) {
                LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
            }

            rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_div);
            if (rc) {
                LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
            }

            rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_frequency);
            if (rc) {
                LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
            }

            rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_pwm_register);
            if (rc) {
                LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
            }
            bl_setting = &g_leds_data[i]->cust;
        }

        if (ret)
            goto err;

    }
#ifdef CONTROL_BL_TEMPERATURE

    last_level = 0;
    limit = 255;
    limit_flag = 0;
    current_level = 0;
    LEDS_DRV_DEBUG
        ("[LED]led probe last_level = %d, limit = %d, limit_flag = %d, current_level = %d\n",
         last_level, limit, limit_flag, current_level);
#endif


    return 0;

 err:
    if (i) {
        for (i = i - 1; i >= 0; i--) {
            if (!g_leds_data[i])
                continue;
            led_classdev_unregister(&g_leds_data[i]->cdev);
            cancel_work_sync(&g_leds_data[i]->work);
            kfree(g_leds_data[i]);
            g_leds_data[i] = NULL;
        }
    }

    return ret;
}

——–》 下面来详细分析上面3个函数,先看mt65xx_led_set

static void mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)
{
    struct mt65xx_led_data *led_data = container_of(led_cdev, struct mt65xx_led_data, cdev);
    if (strcmp(led_data->cust.name, "lcd-backlight") == 0) { 如果是背光,做些特殊处理
#ifdef CONTROL_BL_TEMPERATURE
        mutex_lock(&bl_level_limit_mutex);
        current_level = level;
        /* LEDS_DRV_DEBUG("brightness_set_cust:current_level=%d\n", current_level); */
        if (0 == limit_flag) {
            last_level = level;
            /* LEDS_DRV_DEBUG("brightness_set_cust:last_level=%d\n", last_level); */
        } else {
            if (limit < current_level) {
                level = limit;
                LEDS_DRV_DEBUG("backlight_set_cust: control level=%d\n", level);
            }
        }
        mutex_unlock(&bl_level_limit_mutex);
#endif
    }
    mt_mt65xx_led_set(led_cdev, level);  
}

———》mt_mt65xx_led_set

void mt_mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)
{
    struct mt65xx_led_data *led_data =
        container_of(led_cdev, struct mt65xx_led_data, cdev);
    //unsigned long flags;
    //spin_lock_irqsave(&leds_lock, flags);

#ifdef CONFIG_MTK_AAL_SUPPORT   
    if(led_data->level != level)
    {
        led_data->level = level;
        if(strcmp(led_data->cust.name,"lcd-backlight") != 0)
        {
            LEDS_DEBUG("[LED]Set NLED directly %d at time %lu\n",led_data->level,jiffies);
            schedule_work(&led_data->work);             
        }
        else
        {
            LEDS_DEBUG("[LED]Set Backlight directly %d at time %lu\n",led_data->level,jiffies);
            //mt_mt65xx_led_set_cust(&led_data->cust, led_data->level); 
            disp_aal_notify_backlight_changed( (((1 << MT_LED_INTERNAL_LEVEL_BIT_CNT) - 1)*level + 127)/255 );
        }
    }
#else                       
    // do something only when level is changed
    if(led_data->level != level)
    {
        led_data->level = level;
        if(strcmp(led_data->cust.name,"lcd-backlight") != 0)  非背光,直接到 在工作队列中处理,WORK
        {
            LEDS_DEBUG("[LED]Set NLED directly %d at time %lu\n",led_data->level,jiffies);
                schedule_work(&led_data->work);
        }
        else
        {
                LEDS_DEBUG("[LED]Set Backlight directly %d at time %lu\n",led_data->level,jiffies);
            if(MT65XX_LED_MODE_CUST_BLS_PWM == led_data->cust.mode)  背光,直接设置。 背光相应快。
            {
                mt_mt65xx_led_set_cust(&led_data->cust, ((((1 << MT_LED_INTERNAL_LEVEL_BIT_CNT) - 1)*level + 127)/255));
            }
            else
            {
                mt_mt65xx_led_set_cust(&led_data->cust, led_data->level);   
        }
    }
    }
    //spin_unlock_irqrestore(&leds_lock, flags);
#endif
//    if(0!=aee_kernel_Powerkey_is_press())
//      aee_kernel_wdt_kick_Powkey_api("mt_mt65xx_led_set",WDT_SETBY_Backlight); 
}

—–》调用WORK,会直接到WORK函数中处理,即mt_mt65xx_led_work

void mt_mt65xx_led_work(struct work_struct *work)
{
    struct mt65xx_led_data *led_data =
        container_of(work, struct mt65xx_led_data, work);

    LEDS_DEBUG("[LED]%s:%d\n", led_data->cust.name, led_data->level);
    mutex_lock(&leds_mutex);
    mt_mt65xx_led_set_cust(&led_data->cust, led_data->level);
    mutex_unlock(&leds_mutex);;
}
可以看出 实际上还是调用的 mt_mt65xx_led_set_cust处理,上面背光的特殊处理确实只是为了速度更快写而已。

———-》

int mt_mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level)
{

        switch (cust->mode) {  根据不同的模式来操作

        case MT65XX_LED_MODE_PWM:
            if(strcmp(cust->name,"lcd-backlight") == 0)
            {
                bl_brightness_hal = level;
                if(level == 0)
                {
                    mt_pwm_disable(cust->data, cust->config_data.pmic_pad);

                }else
                {

                    if (BacklightLevelSupport == BACKLIGHT_LEVEL_PWM_256_SUPPORT)
                        level = brightness_mapping(tmp_level);
                    else
                        level = brightness_mapto64(tmp_level);  
                    mt_backlight_set_pwm(cust->data, level, bl_div_hal,&cust->config_data);
                }
                bl_duty_hal = level;    

            }else
            {
                if(level == 0)
                {
                    led_tmp_setting.nled_mode = NLED_OFF;
                    mt_led_set_pwm(cust->data,&led_tmp_setting);
                    mt_pwm_disable(cust->data, cust->config_data.pmic_pad);
                }else
                {
                    led_tmp_setting.nled_mode = NLED_ON;
                    mt_led_set_pwm(cust->data,&led_tmp_setting);
                }
            }
            return 1;

        case MT65XX_LED_MODE_GPIO:  用函数指针去做相应的操作
            LEDS_DEBUG("brightness_set_cust:go GPIO mode!!!!!\n");
            return ((cust_set_brightness)(cust->data))(level);

        case MT65XX_LED_MODE_PMIC:
            //for button baclight used SINK channel, when set button ISINK, don't do disable other ISINK channel
            if((strcmp(cust->name,"button-backlight") == 0)) {
                if(button_flag==false) {
                    switch (cust->data) {
                        case MT65XX_LED_PMIC_NLED_ISINK0:
                            button_flag_isink0 = 1;
                            break;
                        case MT65XX_LED_PMIC_NLED_ISINK1:
                            button_flag_isink1 = 1;
                            break;
                        case MT65XX_LED_PMIC_NLED_ISINK2:
                            button_flag_isink2 = 1;
                            break;
                        case MT65XX_LED_PMIC_NLED_ISINK3:
                            button_flag_isink3 = 1;
                            break;
                        default:
                            break;
                    }
                    button_flag=true;
                }
            }                   
            return mt_brightness_set_pmic(cust->data, level, bl_div_hal);  PMIC的

        case MT65XX_LED_MODE_CUST_LCM:
        if (strcmp(cust->name, "lcd-backlight") == 0) {
                bl_brightness_hal = level;
            }
            LEDS_DEBUG("brightness_set_cust:backlight control by LCM\n");
            return ((cust_brightness_set)(cust->data))(level, bl_div_hal);  可以自定义背光的

        case MT65XX_LED_MODE_CUST_BLS_PWM:  实际上背光用的是 这个: MT65XX_LED_MODE_CUST_BLS_PWM
        if (strcmp(cust->name, "lcd-backlight") == 0) {
                bl_brightness_hal = level;
            }
            return ((cust_set_brightness)(cust->data))(level);

        case MT65XX_LED_MODE_NONE:
        default:
            break;
    }
}

————-》 mt65xx_blink_set 分析

static int mt65xx_blink_set(struct led_classdev *led_cdev,
            unsigned long *delay_on, unsigned long *delay_off)
{
    if (mt_mt65xx_blink_set(led_cdev, delay_on, delay_off)) {
        return -1;
    } else {
        return 0;
    }
}

———-》

int  mt_mt65xx_blink_set(struct led_classdev *led_cdev,
             unsigned long *delay_on,
             unsigned long *delay_off)
{
    struct mt65xx_led_data *led_data =
        container_of(led_cdev, struct mt65xx_led_data, cdev);
    static int got_wake_lock = 0;
    struct nled_setting nled_tmp_setting = {0,0,0};

    // only allow software blink when delay_on or delay_off changed
    if (*delay_on != led_data->delay_on || *delay_off != led_data->delay_off) {
        led_data->delay_on = *delay_on;
        led_data->delay_off = *delay_off;
        if (led_data->delay_on && led_data->delay_off) { // enable blink
            led_data->level = 255; // when enable blink  then to set the level  (255)
            //AP PWM all support OLD mode 
            if(led_data->cust.mode == MT65XX_LED_MODE_PWM)
            {
                nled_tmp_setting.nled_mode = NLED_BLINK;
                nled_tmp_setting.blink_off_time = led_data->delay_off;
                nled_tmp_setting.blink_on_time = led_data->delay_on;
                mt_led_set_pwm(led_data->cust.data,&nled_tmp_setting);  PWM硬件模块能有此模式,配置好后不需要CPU参与。
                return 0;
            }
            else if((led_data->cust.mode == MT65XX_LED_MODE_PMIC) && (led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK0
                || led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK1 || led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK2
                 || led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK3))
            {
                nled_tmp_setting.nled_mode = NLED_BLINK;
                nled_tmp_setting.blink_off_time = led_data->delay_off;
                nled_tmp_setting.blink_on_time = led_data->delay_on;
                mt_led_blink_pmic(led_data->cust.data, &nled_tmp_setting);
                return 0;
            }               
            else if (!got_wake_lock) {  没有实现,需要CPU参与的,需要获取锁,实际上GPIO BLINK可以在这里实现。
                wake_lock(&leds_suspend_lock);
                got_wake_lock = 1;
            }
        }
        else if (!led_data->delay_on && !led_data->delay_off) { // disable blink
            //AP PWM all support OLD mode 
            if(led_data->cust.mode == MT65XX_LED_MODE_PWM)
            {
                nled_tmp_setting.nled_mode = NLED_OFF;
                mt_led_set_pwm(led_data->cust.data,&nled_tmp_setting);
                return 0;
            }
            else if((led_data->cust.mode == MT65XX_LED_MODE_PMIC) && (led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK0
                || led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK1 || led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK2
                 || led_data->cust.data == MT65XX_LED_PMIC_NLED_ISINK3))
            {
                mt_brightness_set_pmic(led_data->cust.data, 0, 0);
                return 0;
            }       
            else if (got_wake_lock) {
                wake_unlock(&leds_suspend_lock);
                got_wake_lock = 0;
            }
        }
        return -1;
    }

    // delay_on and delay_off are not changed
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值