mtk led驱动总结1

来源:互联网 发布:淘宝静电消除器原理 编辑:程序博客网 时间:2024/04/29 16:58

代码路径

mt8163-kernel-3.18\drivers\misc\mediatek\leds\leds_drv.c
mt8163-kernel-3.18\drivers\misc\mediatek\leds\leds_drv.h

\mt8163-kernel-3.18\drivers\misc\mediatek\leds\mt8163\leds.c
\mt8163-kernel-3.18\drivers\misc\mediatek\leds\mt8163\leds_hal.h
\mt8163-kernel-3.18\drivers\misc\mediatek\leds\mt8163\leds_sw.h
mt8163-kernel-3.18\drivers\misc\mediatek\leds\leds_drv.c

注册led平台驱动

static struct platform_driver mt65xx_leds_driver = {    .driver = {           .name = "leds-mt65xx",           .owner = THIS_MODULE,           },    .probe = mt65xx_leds_probe,    .remove = mt65xx_leds_remove,    /* .suspend      = mt65xx_leds_suspend, */    .shutdown = mt65xx_leds_shutdown,};

mt65xx_leds_probe函数

struct cust_mt65xx_led *cust_led_list = mt_get_cust_led_list();//获取客制化的led配置信息,该函数的具体实现后面再来看
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;        }//将客制化的led配置信息赋值给全局变量g_leds_data        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;//亮度设置函数        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);//向内核注册led驱动,会在/sys/class/leds下产生相应的节点,当操作节点下的brghtness属性时就会调用到上面的brightness_set对应的函数mt65xx_led_set,后面分析mt65xx_led_set和mt65xx_blink_set具体实现

回过头来看客制化的led配置是如何解析的?

struct cust_mt65xx_led *mt_get_cust_led_list(void){    struct cust_mt65xx_led *cust_led_list =       get_cust_led_dtsi();//直接从dtsi文件中读取led的配置信息,用户需要什么样的led效果只需要在dtsi中配置就可以了    return cust_led_list;}
struct cust_mt65xx_led *get_cust_led_dtsi(void){for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++){            char node_name[32] = "mediatek,";            pled_dtsi[i].name = leds_name[i];//指示灯的名字            led_node =                of_find_compatible_node(NULL, NULL,                            strcat(node_name,                               leds_name[i]));            if (!led_node) {                LEDS_DEBUG("Cannot find LED node from dts\n");                pled_dtsi[i].mode = 0;                pled_dtsi[i].data = -1;            } else {                isSupportDTS = true;                ret =                    of_property_read_u32(led_node, "led_mode",                             &mode);                if (!ret) {                    pled_dtsi[i].mode = mode;//指示灯模式                    LEDS_DEBUG                        ("The %s's led mode is : %d\n",                         pled_dtsi[i].name,                         pled_dtsi[i].mode);                } else {                    LEDS_DEBUG                        ("led dts can not get led mode");                    pled_dtsi[i].mode = 0;                }                ret =                    of_property_read_u32(led_node, "data",                             &data);                if (!ret) {                    pled_dtsi[i].data = data;//指示灯的data字段                    LEDS_DEBUG                        ("The %s's led data is : %ld\n",                         pled_dtsi[i].name,                         pled_dtsi[i].data);                } else {                    LEDS_DEBUG                        ("led dts can not get led data");                    pled_dtsi[i].data = -1;                }                ret =                    of_property_read_u32_array(led_node,                                   "pwm_config",                                   pwm_config,                                   ARRAY_SIZE                                   (pwm_config));                if (!ret) {                    LEDS_DEBUG                        ("The %s's pwm config data is %d %d %d %d %d\n",                         pled_dtsi[i].name, pwm_config[0],                         pwm_config[1], pwm_config[2],                         pwm_config[3], pwm_config[4]);                    pled_dtsi[i].config_data.clock_source =                        pwm_config[0];                    pled_dtsi[i].config_data.div =                        pwm_config[1];                    pled_dtsi[i].config_data.low_duration =                        pwm_config[2];                    pled_dtsi[i].config_data.High_duration =                        pwm_config[3];                    pled_dtsi[i].config_data.pmic_pad =                        pwm_config[4];//pwm配置信息                } else                    LEDS_DEBUG                        ("led dts can not get pwm config data.\n");                switch (pled_dtsi[i].mode) {                case MT65XX_LED_MODE_CUST_LCM://如果是CUST_LCM模式设置data字段                    pled_dtsi[i].data =                        (long)mtkfb_set_backlight_level;                    LEDS_DEBUG                        ("kernel:the backlight hw mode is LCM.\n");                    break;                case MT65XX_LED_MODE_CUST_BLS_PWM: //如果是CUST_BLS_PWM模式设置data字段                    pled_dtsi[i].data =                        (long)disp_bls_set_backlight;                    LEDS_DEBUG                        ("kernel:the backlight hw mode is BLS.\n");                    break;                default:                    break;                }            }        }}}

那么dtsi中又是如何定义这些客制化的led配置信息呢?

/* led part */        led0:led@0 {            compatible = "mediatek,red";//红灯配置信息            led_mode = <0>;            data = < >;            pwm_config = <0 0 0 0 0>;        };        led1:led@1 {            compatible = "mediatek,green";//绿灯配置信息            led_mode = <0>;            data = < >;            pwm_config = <0 0 0 0 0>;        };        led2:led@2 {            compatible = "mediatek,blue";//蓝灯配置信息            led_mode = <0>;            data = < >;            pwm_config = <0 0 0 0 0>;        };        led3:led@3 {            compatible = "mediatek,jogball-backlight";             led_mode = <0>;            data = < >;            pwm_config = <0 0 0 0 0>;        };        led4:led@4 {            compatible = "mediatek,keyboard-backlight";//键盘灯            led_mode = <0>;            data = < >;            pwm_config = <0 0 0 0 0>;        };        led5:led@5 {            compatible = "mediatek,button-backlight";//按键灯            led_mode = <0>;            data = < >;            pwm_config = <0 0 0 0 0>;        };        led6:led@6 {            compatible = "mediatek,lcd-backlight";//lcd背光            led_mode = <5>;            data = < >;            pwm_config = <0 0 0 0 0>;            gpios = <&pio 43 0>;        };

上面的led_mode和data具体含义是什么?下面来看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);#ifdef CONFIG_BACKLIGHT_SUPPORT_LP8557    bool flag = FALSE;    int value = 0;    int retval;    struct device_node *node = NULL;    struct i2c_client *client = g_client;    value = i2c_smbus_read_byte_data(g_client, 0x10);    LEDS_DRV_DEBUG("LEDS:mt65xx_led_set:0x10 = %d\n", value);    node = of_find_compatible_node(NULL, NULL,                            "mediatek,lcd-backlight");    if (node) {        I2C_SET_FOR_BACKLIGHT = of_get_named_gpio(node, "gpios", 0);        LEDS_DRV_DEBUG("Led_i2c gpio num for power:%d\n", I2C_SET_FOR_BACKLIGHT);    }#endif    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    }#ifdef CONFIG_BACKLIGHT_SUPPORT_LP8557    retval = gpio_request(I2C_SET_FOR_BACKLIGHT, "i2c_set_for_backlight");    if (retval)        LEDS_DRV_DEBUG("LEDS: request I2C gpio149 failed\n");    if (strcmp(led_data->cust.name, "lcd-backlight") == 0) {        if (level == 0) {            LEDS_DRV_DEBUG("LEDS:mt65xx_led_set:close the power\n");            i2c_smbus_write_byte_data(client, 0x00, 0);            gpio_direction_output(I2C_SET_FOR_BACKLIGHT, 0);        }        if (!last_level1 && level) {            LEDS_DRV_DEBUG("LEDS:mt65xx_led_set:open the power\n");            gpio_direction_output(I2C_SET_FOR_BACKLIGHT, 1);            mdelay(100);            i2c_smbus_write_byte_data(client, 0x10, 4);            flag = TRUE;        }        last_level1 = level;    }    gpio_free(I2C_SET_FOR_BACKLIGHT);#endif    mt_mt65xx_led_set(led_cdev, level);//最终是调用mt_mt65xx_led_set函数#ifdef CONFIG_BACKLIGHT_SUPPORT_LP8557    if (strcmp(led_data->cust.name, "lcd-backlight") == 0) {        if (flag) {            i2c_smbus_write_byte_data(client, 0x14, 0xdf);            i2c_smbus_write_byte_data(client, 0x04, 0xff);            i2c_smbus_write_byte_data(client, 0x00, 1);        }    }#endif}
void mt_mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness 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:        return ((cust_set_brightness) (cust->data)) (level);    case MT65XX_LED_MODE_PMIC:return mt_brightness_set_pmic(cust->data, level, bl_div_hal);case MT65XX_LED_MODE_CUST_LCM:        return ((cust_brightness_set) (cust->data)) (level, bl_div_hal);case MT65XX_LED_MODE_CUST_BLS_PWM:        return ((cust_set_brightness) (cust->data)) (level);}
int mt_brightness_set_pmic(enum mt65xx_led_pmic pmic_type, u32 level, u32 div){if (pmic_type == MT65XX_LED_PMIC_BUTTON) {        if (level) {#ifdef PMIC_MT6325            upmu_set_kpled_dim_duty(0x9);            upmu_set_kpled_en(0x1);#endif        } else {#ifdef PMIC_MT6325            upmu_set_kpled_en(0x0);#endif        }        return 0;    }else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK0) {        if (first_time == true) {#ifdef PMIC_MT6325            upmu_set_isinks_ch1_en(0x0);    /* sw workround for sync leds status */            upmu_set_isink_rsv2_isink1(0x00);            upmu_set_isinks_ch2_en(0x0);            upmu_set_isink_rsv2_isink2(0x00);#endif            first_time = false;        }#ifdef PMIC_MT6325        upmu_set_isinks_ch0_mode(ISINK_PWM_MODE);        upmu_set_isinks_ch0_step(0x0);  /* 4mA */        upmu_set_isink_dim0_duty(15);        upmu_set_isink_dim0_fsel(11);   /* 6320 0.25KHz */#endif        led_init_flag[0] = true;        if (level) {#ifdef PMIC_MT6325            upmu_set_rg_bst_drv_1m_ck_pdn(0x0);            upmu_set_isink_rsv2_isink0(0x1);            upmu_set_isinks_ch0_en(0x01);#endif        } else {#ifdef PMIC_MT6325            upmu_set_isinks_ch0_en(0x00);            upmu_set_isink_rsv2_isink0(0x00);#endif        }        return 0;    }else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK1) {        if (first_time == true) {#ifdef PMIC_MT6325            upmu_set_isinks_ch0_en(0);  /* sw workround for sync leds status */            upmu_set_isink_rsv2_isink0(0x00);            upmu_set_isinks_ch2_en(0);            upmu_set_isink_rsv2_isink2(0x00);#endif            first_time = false;        }#ifdef PMIC_MT6325        upmu_set_isinks_ch1_mode(ISINK_PWM_MODE);        upmu_set_isinks_ch1_step(0x3);  /* 4mA */        upmu_set_isink_dim1_duty(15);        upmu_set_isink_dim1_fsel(11);   /* 6320 0.25KHz */#endif        led_init_flag[1] = true;        if (level) {#ifdef PMIC_MT6325            upmu_set_rg_bst_drv_1m_ck_pdn(0x0);            upmu_set_isink_rsv2_isink1(0x1);            upmu_set_isinks_ch1_en(0x01);#endif        } else {#ifdef PMIC_MT6325            upmu_set_isinks_ch1_en(0x00);            upmu_set_isink_rsv2_isink1(0x00);#endif        }        return 0;    }else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK2) {        if (first_time == true) {#ifdef PMIC_MT6325            upmu_set_isinks_ch0_en(0);  /* sw workround for sync leds status */            upmu_set_isink_rsv2_isink0(0x00);            upmu_set_isinks_ch1_en(0);            upmu_set_isink_rsv2_isink1(0x00);#endif            first_time = false;        }#ifdef PMIC_MT6325        upmu_set_isinks_ch2_mode(ISINK_PWM_MODE);        upmu_set_isinks_ch2_step(0x3);  /* 16mA */        upmu_set_isink_dim2_duty(15);        upmu_set_isink_dim2_fsel(11);   /* 6320 0.25KHz */#endif        led_init_flag[2] = true;        if (level) {#ifdef PMIC_MT6325            upmu_set_rg_bst_drv_1m_ck_pdn(0x0);            upmu_set_isink_rsv2_isink2(0x1);            upmu_set_isinks_ch2_en(0x01);#endif        } else {#ifdef PMIC_MT6325            upmu_set_isinks_ch2_en(0x00);            upmu_set_isink_rsv2_isink2(0x00);#endif        }        return 0;    }else if (pmic_type == MT65XX_LED_PMIC_NLED_ISINK01) {#ifdef PMIC_MT6325        upmu_set_isinks_ch0_mode(ISINK_PWM_MODE);        upmu_set_isinks_ch0_step(0x0);  /* 4mA */        upmu_set_isink_dim0_duty(1);        upmu_set_isink_dim0_fsel(1);    /* 6320 1.5KHz */        upmu_set_isinks_ch1_mode(ISINK_PWM_MODE);        upmu_set_isinks_ch1_step(0x3);  /* 4mA */        upmu_set_isink_dim1_duty(15);        upmu_set_isink_dim1_fsel(11);   /* 6320 0.25KHz */#endif        led_init_flag[0] = true;        led_init_flag[1] = true;        if (level) {#ifdef PMIC_MT6325            upmu_set_rg_bst_drv_1m_ck_pdn(0x0);            upmu_set_isinks_ch0_en(0x01);            upmu_set_isinks_ch1_en(0x01);#endif        } else {#ifdef PMIC_MT6325            upmu_set_isinks_ch0_en(0x00);            upmu_set_isinks_ch1_en(0x00);#endif        }        return 0;    }}
原创粉丝点击