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; }}
阅读全文
0 0
- mtk led驱动总结1
- mtk 驱动笔记 lcd camera led tp
- mtk 驱动笔记 lcd camera led tp
- Mtk ALPS Led驱动的加载过程
- MTK驱动总结
- mtk驱动总结
- mtk驱动总结
- mtk led
- linux驱动:[1]LED驱动/dev/led
- MTK BT驱动调试总结
- MTK BT驱动调试总结
- [MTK] BT驱动调试总结
- MTK 串口驱动 PART-1
- MTK Android Driver:led
- mtk led 呼吸灯
- MTK平台LED配置
- MTK Android Driver:led
- mtk led子系统概略
- 连续三代产品打进苹果店的iBaby如何以硅谷创新为基因打出蓝海市场
- 机械硬盘
- 汉罗塔问题java数学模型(从数学原型到数学模型)
- 智能手机哪家强,2015高性价比手机推荐
- IO流、序列化和反序列化
- mtk led驱动总结1
- 为什么唯独Mac缺席了苹果发布会?
- centos 6.x 关闭防火墙和selinux
- 中国日报:OPPO与巴萨合作意义重大,其海外布局亮眼
- 更快、更省电、更安全——UU安全资深评测
- 你扭着屁股四处撒欢,小黄人非“小黄人”?
- 中港之战收视率创新高 金立体育营销首战告捷
- 高斯判别分析(GDA)和朴素贝叶斯(NB)
- 单用户模式<修改root密码>