同时参考:linux设备模型之led子系统
1【从应用层到Framework】android LCD、键盘灯的背光亮度设置
2 原文地址: http://www.linuxidc.com/Linux/2011-03/33311p2.htm
亮度设置
应用设计
1.1 设置进度条范围
背光设置是在:设置->声音和显示->亮度,通过进度条来设置的。
文件:
packages/apps/Settings/src/com/Android/settings/BrightnessPreference.java
- private static final int MINIMUM_BACKLIGHT = Android.os.Power.BRIGHTNESS_DIM + 10;
- private static final int MAXIMUM_BACKLIGHT = Android.os.Power.BRIGHTNESS_ON;
- mSeekBar.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);
设置进度条的范围,BRIGHTNESS_DIM = 20 BRIGHTNESS_ON=255,它们的定义在:
frameworks/base/core/java/Android/os/Power.java
1.2 设置亮度
文件:packages/apps/Settings/src/com/Android/settings/BrightnessPreference.java
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- setMode(isChecked ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
- : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
- if (!isChecked) {
- setBrightness(mSeekBar.getProgress() + MINIMUM_BACKLIGHT);
- }
- }
- private void setBrightness(int brightness) {
- try {
- IPowerManager power = IPowerManager.Stub.asInterface(
- ServiceManager.getService("power"));
- if (power != null) {
- power.setBacklightBrightness(brightness);
- }
- } catch (RemoteException doe) {
- }
- }
由以上代码可知,brightness的范围是:20~255;代码通过服务管理器(ServiceManager)获得power服务,然后通过power服务设置亮度。
power.setBacklightBrightness的定义在:
rameworks/base/core/java/Android/os/IPowerManager.aidl.java
frameworks/base/core/java/Android/os/PowerManager.java
2, Power服务
文件:frameworks/base/core/java/Android/os/Power.java
/** * Brightness value for dim backlight */
public static final int BRIGHTNESS_DIM = 20;
/** * Brightness value for fully on */
public static final int BRIGHTNESS_ON = 255;
文件:frameworks/base/core/java/Android/os/PowerManager.java
Java代码
- /** * sets the brightness of the backlights (screen, keyboard, button).
- *
- * @param brightness value from 0 to 255
- *
- * {@hide}
- */
- public void setBacklightBrightness(int brightness)
- {
- try {
- mService.setBacklightBrightness(brightness);
- } catch (RemoteException e) {
- }
- }
新代码起始:
framework\base\service\java\com\android\server\PowerManagerService.java
//PowerManagerService中定义的mButtonLight和mKeyboardLight都是键盘灯,具体使用哪一个,要看底层的平台厂商使用
0196 private LightsService.Light mLcdLight;
0197 private LightsService.Light mButtonLight;
0198 private LightsService.Light mKeyboardLight;
2921 public void setBacklightBrightness(int brightness) {
2922 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2923 // Don't let applications turn the screen all the way off
2924 synchronized (mLocks) {
2925 brightness = Math.max(brightness, mScreenBrightnessDim);
//以下设备分别调用了LightsService.light的接口
2926 mLcdLight.setBrightness(brightness);
2927 mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
2928 mButtonLight.setBrightness(brightness);
2929 long identity = Binder.clearCallingIdentity();
2930 try {
2931 mBatteryStats.noteScreenBrightness(brightness);
2932 } catch (RemoteException e) {
2933 Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2934 } finally {
2935 Binder.restoreCallingIdentity(identity);
2936 }
2937
2938 // update our animation state
2939 synchronized (mLocks) {
2940 mScreenBrightness.targetValue = brightness;
2941 mScreenBrightness.jumpToTargetLocked();
2942 }
2943 }
2944 }
framework\base\service\java\com\android\server\LightsService.java
066 public void setBrightness(int brightness) {
067 setBrightness(brightness, BRIGHTNESS_MODE_USER);
068 }
069
070 public void setBrightness(int brightness, int brightnessMode) {
071 synchronized (this) {
072 int color = brightness & 0x000000ff;
073 color = 0xff000000 | (color << 16) | (color << 8) | color;
074 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
075 }
076 }
116 private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
117 if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
118 mColor = color;
119 mMode = mode;
120 mOnMS = onMS;
121 mOffMS = offMS;
//调用JNI的本地接口,mNativePointer对应具体设备,通过调用LighsService中的init接口,进一步调用init_native接口获取设备信息
122 setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
123 }
124 }
framework\base\services\jni\com_android_server_LightsService.cpp
106 static void setLight_native(JNIEnv *env, jobject clazz, int ptr,
107 int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)
108 {
109 Devices* devices = (Devices*)ptr;
110 light_state_t state;
111
112 if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
113 return ;
114 }
115
116 memset(&state, 0, sizeof(light_state_t));
117 state.color = colorARGB;
118 state.flashMode = flashMode;
119 state.flashOnMS = onMS;
120 state.flashOffMS = offMS;
121 state.brightnessMode = brightnessMode;
122
//devices->lights是一个结构体,具体定义没找到,不过根据代码看,set_light应该是一个函数指针这里会根据不同的设备devices调用对应的set_light指向的具体函数
123 devices->lights[light]->set_light(devices->lights[light], &state);
124 }
新代码截止
旧代码起始:
电源管理器(powermager)将brightness转给电源服务,该服务位置如下:
文件:frameworks/base/services/java/com/Android/server/PowerManagerService.java
- public void setBacklightBrightness(int brightness) {
- mContext.enforceCallingOrSelfPermission(Android.Manifest.permission.DEVICE_POWER, null);
- // Don't let applications turn the screen all the way off
- brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
- mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness, HardwareService.BRIGHTNESS_MODE_USER);
- mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER);
- mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness, HardwareService.BRIGHTNESS_MODE_USER);
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenBrightness(brightness);
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- // update our animation state
- if (ANIMATE_SCREEN_LIGHTS) {
- mScreenBrightness.curValue = brightness;
- mScreenBrightness.animating = false;
- mScreenBrightness.targetValue = -1;
- }
- if (ANIMATE_KEYBOARD_LIGHTS) {
- mKeyboardBrightness.curValue = brightness;
- mKeyboardBrightness.animating = false;
- mKeyboardBrightness.targetValue = -1;
- }
- if (ANIMATE_BUTTON_LIGHTS) {
- mButtonBrightness.curValue = brightness;
- mButtonBrightness.animating = false;
- mButtonBrightness.targetValue = -1;
- }
- }
文件:frameworks/base/services\java\com\Android\server\HardwareService.java
- void setLightBrightness_UNCHECKED(int light, int brightness, int brightnessMode) {
- 类型 亮度值 控制模式
- int b = brightness & 0x000000ff;
- b = 0xff000000 | (b << 16) | (b << 8) | b;
- setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
- // 函数参见3.2
- }
参数说明:
int light 表示类型,选项如下:
static final int LIGHT_ID_BACKLIGHT = 0;
static final int LIGHT_ID_KEYBOARD = 1;
static final int LIGHT_ID_BUTTONS = 2;
static final int LIGHT_ID_BATTERY = 3;
static final int LIGHT_ID_NOTIFICATIONS = 4;
static final int LIGHT_ID_ATTENTION = 5;
int brightness 表示亮度值
int brightnessMode 表示亮度的控制模式,选项如下:
static final int BRIGHTNESS_MODE_USER = 0; /** * Light brightness is managed by a user setting. */
static final int BRIGHTNESS_MODE_SENSOR = 1; /*** Light brightness is managed by a light sensor. */
由代码:
int b = brightness & 0x000000ff;
b = 0xff000000 | (b << 16) | (b <<8 | b;
可知,亮度值在此进行了修改,即亮度值的格式变成:FFRRGGBB,FF是没有的,RR、GG、BB分别是256色的红绿蓝,并且红绿蓝的值都是一样的亮度值。
旧代码截止
3 硬件调用
3.1获取硬件
新代码:在文件:frameworks/base/services/jni/com_Android_server_LightService.cpp
旧代码:文件:frameworks/base/services/jni/com_Android_server_HardwareService.cpp
- enum {
- LIGHT_INDEX_BACKLIGHT = 0,
- LIGHT_INDEX_KEYBOARD = 1,
- LIGHT_INDEX_BUTTONS = 2,
- LIGHT_INDEX_BATTERY = 3,
- LIGHT_INDEX_NOTIFICATIONS = 4,
- LIGHT_INDEX_ATTENTION = 5,
- LIGHT_COUNT
- };
- #define LIGHTS_HARDWARE_MODULE_ID "lights"
- static jint init_native(JNIEnv *env, jobject clazz)
- {
- int err;
- hw_module_t* module;
- Devices* devices;
- devices = (Devices*)malloc(sizeof(Devices));
- err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
- if (err == 0) {
- devices->lights[LIGHT_INDEX_BACKLIGHT] = get_device(module, LIGHT_ID_BACKLIGHT);
- devices->lights[LIGHT_INDEX_KEYBOARD] = get_device(module, LIGHT_ID_KEYBOARD);
- devices->lights[LIGHT_INDEX_BUTTONS] = get_device(module, LIGHT_ID_BUTTONS);
- devices->lights[LIGHT_INDEX_BATTERY] = get_device(module, LIGHT_ID_BATTERY);
- devices->lights[LIGHT_INDEX_NOTIFICATIONS] = get_device(module, LIGHT_ID_NOTIFICATIONS);
- devices->lights[LIGHT_INDEX_ATTENTION] = get_device(module, LIGHT_ID_ATTENTION);
- } else {
- memset(devices, 0, sizeof(Devices));
- }
- return (jint)devices;
- }
hw_get_module 的实现原理,如下:
文件:hardware/libhardware/Hardware.c
- #define HAL_LIBRARY_PATH "/system/lib/hw"
- static const char *variant_keys[ ] = {
- "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */
- "ro.product.board",
- "ro.board.platform",
- "ro.arch"
- };
- static const int HAL_VARIANT_KEYS_COUNT = (sizeof(variant_keys)/sizeof(variant_keys[0]));
- int hw_get_module(const char *id, const struct hw_module_t **module)
- { int status;
- int i;
- const struct hw_module_t *hmi = NULL;
- char prop[PATH_MAX];
- char path[PATH_MAX];
- /* Here we rely on the fact that calling dlopen multiple times on the same .so will simply increment a refcount (and not load
- * a new copy of the library). We also assume that dlopen() is thread-safe.
- */
- /* Loop through the configuration variants looking for a module */
- for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
- if (i < HAL_VARIANT_KEYS_COUNT) {
- if (property_get(variant_keys[i], prop, NULL) == 0) {
- continue;
- }
- snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, prop);
- }
- else {
- snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH, id);
- }
- if (access(path, R_OK)) {
- continue;
- }
- /* we found a library matching this id/variant */
- break;
- }
- status = -ENOENT;
- if (i < HAL_VARIANT_KEYS_COUNT+1) {
- /* load the module, if this fails, we're doomed, and we should not try to load a different variant. */
- status = load(id, path, module);
- }
- return status;
- }
property_get(variant_keys[i], prop, NULL) 会按如下顺序去获取如下变量所对应的值,然后返回给prop:
"ro.hardware",
"ro.product.board",
"ro.board.platform",
"ro.arch"
它们对应的变量为:
"ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME"
"ro.board.platform=$TARGET_BOARD_PLATFORM"
如vendor/htc/dream-open/BoardConfig.mk里定义的TARGET_BOARD_PLATFORM := msm7k,则prop返回"msm7k ”,所以path= /system/lib/hw/lights. msm7k.so,也就是说要获取的硬件模块为lights. msm7k.so。
3.2调用硬件
setLight_native对应的jni C/C++代码是:
文件:frameworks/base/services/jni/com_Android_server_HardwareService.cpp
- static void setLight_native(JNIEnv *env, jobject clazz, int ptr, int light, int colorARGB, int flashMode, int onMS, int offMS, int 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;
- devices->lights[light]->set_light(devices->lights[light], &state);
- }
3.3 硬件原型
msm7k的lights对应的硬件原型是在:hardware/msm7k/liblights
文件:hardware/msm7k/liblights/Android.mk
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
也就是生成模块:/system/lib/hw/lights. msm7k.so
文件:hardware/msm7k/liblights/lights.c
- /** Open a new instance of a lights device using name */
- 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);
- 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,
- };
devices->lights[LIGHT_INDEX_BACKLIGHT] = get_device(module, LIGHT_ID_BACKLIGHT);
devices->lights[LIGHT_INDEX_KEYBOARD] = get_device(module, LIGHT_ID_KEYBOARD);
devices->lights[LIGHT_INDEX_BUTTONS] = get_device(module, LIGHT_ID_BUTTONS);
devices->lights[LIGHT_INDEX_BATTERY] = get_device(module, LIGHT_ID_BATTERY);
devices->lights[LIGHT_INDEX_NOTIFICATIONS] = get_device(module, LIGHT_ID_NOTIFICATIONS);
devices->lights[LIGHT_INDEX_ATTENTION] = get_device(module, LIGHT_ID_ATTENTION);
也就是说,对不同的亮度设置给予了不同的设置函数。
举例,背光设置,背光对应的代码如下:
char const*const LCD_FILE = "/sys/class/leds/lcd-backlight/brightness";
static int rgb_to_brightness(struct light_state_t const* state)
{
int color = state->color & 0x00ffffff;
return ((77*((color>>16)&0x00ff)) + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
}
static int set_light_backlight(struct light_device_t* dev, struct light_state_t const* state)
{
int err = 0;
int brightness = rgb_to_brightness(state);
pthread_mutex_lock(&g_lock);
g_backlight = brightness;
err = write_int(LCD_FILE, brightness);
if (g_haveTrackballLight) {
handle_trackball_light_locked(dev);
}
pthread_mutex_unlock(&g_lock);
return err;
}
也就是
往文件/sys/class/leds/lcd-backlight/brightness写入亮度值,然后驱动会根据该文件更改背光的亮度。LCD_FILE的路径根据实际情况更改,同时需要在init.rc 修改其权限,使其可写rgb_to_brightness也根据实际更改,比如要直接亮度值控制,那只要获取r,g,b其中的一个值就行了,如:
static int rgb_to_brightness(struct light_state_t const* state)
{
int color = state->color & 0x000000ff;
return color;
}
4,led类驱动
4.1,驱动创建leds类,系统启动时执行leds_init在目录/sys/class/创建子目录leds
kernel\drivers\leds\Led-class.c
- static int __init leds_init(void)
- {
- leds_class = class_create(THIS_MODULE, "leds");
- if (IS_ERR(leds_class))
- return PTR_ERR(leds_class);
- leds_class->suspend = led_suspend;
- leds_class->resume = led_resume;
- leds_class->dev_attrs = led_class_attrs; //属性文件,sys下的接口,重点看一下
- return 0;
- }
4.2,led_classdev_register,调用这个函数就在目录/sys/class/leds创建子目录led_cdev->name和属性文件brightness
对brightness文件写就执行led_brightness_store,对brightness文件读就执行led_brightness_show,为下面的lcd,led注册做好准备
因为:
kernel\drivers\leds\Led-class.c
C代码
- static ssize_t led_brightness_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
- /* no lock needed for this */
- led_update_brightness(led_cdev);
- return sprintf(buf, "%u\n", led_cdev->brightness);
- }
- static ssize_t led_brightness_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
- ssize_t ret = -EINVAL;
- char *after;
- unsigned long state = simple_strtoul(buf, &after, 10);
- size_t count = after - buf;
- if (*after && isspace(*after))
- count++;
- if (count == size) {
- ret = count;
- if (state == LED_OFF)
- led_trigger_remove(led_cdev);
- led_set_brightness(led_cdev, state);
- }
- return ret;
- }
- static inline void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value > led_cdev->max_brightness)
value = led_cdev->max_brightness;
led_cdev->brightness = value;
if (!(led_cdev->flags & LED_SUSPENDED))
led_cdev->brightness_set(led_cdev, value);
} - static struct device_attribute led_class_attrs[] = {
__ATTR(brightness, 0644, led_brightness_store, led_brightness_store),
__ATTR(max_brightness, 0644, led_max_brightness_show,led_max_brightness_store),
#ifdef CONFIG_LEDS_TRIGGERS
__ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
#endif
__ATTR_NULL,
};
/* led_classdev_register - register a new object of led_classdev class. - * @parent: The device to register.
- * @led_cdev: the led_classdev structure for this device.
- */
- int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
- {
- int rc;
- led_cdev->dev = device_create(leds_class, parent, 0, led_cdev, "%s", led_cdev->name);
- if (IS_ERR(led_cdev->dev))
- return PTR_ERR(led_cdev->dev);
- /* register the attributes */
- rc = device_create_file(led_cdev->dev, &dev_attr_brightness);
- if (rc)
- goto err_out;
- #ifdef CONFIG_LEDS_TRIGGERS
- init_rwsem(&led_cdev->trigger_lock);
- #endif
- /* add to the list of leds */
- down_write(&leds_list_lock);
- list_add_tail(&led_cdev->node, &leds_list);
- up_write(&leds_list_lock);
- led_update_brightness(led_cdev);
- #ifdef CONFIG_LEDS_TRIGGERS
- rc = device_create_file(led_cdev->dev, &dev_attr_trigger);
- if (rc)
- goto err_out_led_list;
- led_trigger_set_default(led_cdev);
- #endif
- printk(KERN_INFO "Registered led device: %s\n", led_cdev->name);
- return 0;
- #ifdef CONFIG_LEDS_TRIGGERS
- err_out_led_list:
- device_remove_file(led_cdev->dev, &dev_attr_brightness);
- list_del(&led_cdev->node);
- #endif
- err_out:
- device_unregister(led_cdev->dev);
- return rc;
- }
- EXPORT_SYMBOL_GPL(led_classdev_register);
kernel\drivers\video\msm\Msm_fb.c
- static int lcd_backlight_registered;
- static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev, enum led_brightness value)
- {
- struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
- int bl_lvl;
- if (value > MAX_BACKLIGHT_BRIGHTNESS)
- value = MAX_BACKLIGHT_BRIGHTNESS;
- /* This maps Android backlight level 0 to 255 into
- driver backlight level 0 to bl_max with rounding */
- bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS) /(2 * MAX_BACKLIGHT_BRIGHTNESS);
- if (!bl_lvl && value) bl_lvl = 1;
- msm_fb_set_backlight(mfd, bl_lvl, 1);
- }
- static struct led_classdev backlight_led = {
- .name = "lcd-backlight",
- .brightness = MAX_BACKLIGHT_BRIGHTNESS,
- .brightness_set = msm_fb_set_bl_brightness,
- };
- if (!lcd_backlight_registered) {
- if (led_classdev_register(&pdev->dev, &backlight_led))
- printk(KERN_ERR "led_classdev_register failed\n");
- else
- lcd_backlight_registered = 1;
- }
就在目录/sys/class/leds创建子目录 lcd-backlight和属性文件brightness
当按键或者来的或者改变lcd亮度时,上层对属性文件/sys/class/leds/lcd-backlight/brightness写入背光的亮度数值就
调用led_brightness_store >>调用simple_strtoul(buf, &after, 10);将输入的字符串转换为10进制的数字
然后接着执行led_set_brightness ,内部会调用执行led_cdev->brightness_set(led_cdev, value),也就是调用》msm_fb_set_bl_brightness ,
因为 .brightness_set = msm_fb_set_bl_brightness,
msm_fb_set_bl_brightness函数里面代码:/* This maps Android backlight level 0 to 255 into driver backlight level 0 to bl_max with rounding */
bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS) /(2 * MAX_BACKLIGHT_BRIGHTNESS);
将输入的0--255转换为IC的0--bl_max
msm_fb_set_bl_brightness 里面同时还调用 msm_fb_set_backlight(mfd, bl_lvl, 1);
void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl)
{ struct msm_fb_panel_data *pdata;
if (!mfd->panel_power_on || !bl_updated) {
unset_bl_level = bkl_lvl;
return;
} else {
unset_bl_level = 0;
}
pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
if ((pdata) && (pdata->set_backlight)) {
down(&mfd->sem);
if (bl_level_old == bkl_lvl) {
up(&mfd->sem);
return;
}
mfd->bl_level = bkl_lvl; // mdf->bl_level在具体的lcd驱动文件中的xxx_set_backlight()函数中会调用
pdata->set_backlight(mfd); //调用xxx_set_backlight()函数
bl_level_old = mfd->bl_level;
up(&mfd->sem);
}
}
最终改变LCD的背光驱动电路的设置,调节LCD的背光的亮度
4.4 键盘背光灯
上层对属性文件/sys/class/leds/keyboard-backlight/brightness写入背光的亮度数值
(kernel\drivers\leds\Leds-msm-pmic.c
- #define MAX_KEYPAD_BL_LEVEL 16
- static void msm_keypad_bl_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
- {
- int ret;
- ret = pmic_set_led_intensity(LED_KEYPAD, value / MAX_KEYPAD_BL_LEVEL);
- if (ret)
- dev_err(led_cdev->dev, "can't set keypad backlight\n");
- }
- static struct led_classdev msm_kp_bl_led = {
- .name = "keyboard-backlight",
- .brightness_set = msm_keypad_bl_led_set,
- .brightness = LED_OFF,
- };
- static int msm_pmic_led_probe(struct platform_device *pdev)
- {
- int rc;
- rc = led_classdev_register(&pdev->dev, &msm_kp_bl_led);
- if (rc) {
- dev_err(&pdev->dev, "unable to register led class driver\n");
- return rc;
- }
- msm_keypad_bl_led_set(&msm_kp_bl_led, LED_OFF);
- return rc;
- }
- static int __devexit msm_pmic_led_remove(struct platform_device *pdev)
- {
- led_classdev_unregister(&msm_kp_bl_led);
- return 0;
- }
- #ifdef CONFIG_PM
- static int msm_pmic_led_suspend(struct platform_device *dev, pm_message_t state)
- {
- led_classdev_suspend(&msm_kp_bl_led);
- return 0;
- }
- static int msm_pmic_led_resume(struct platform_device *dev)
- {
- led_classdev_resume(&msm_kp_bl_led);
- return 0;
- }
- #else
- #define msm_pmic_led_suspend NULL
- #define msm_pmic_led_resume NULL
- #endif
- static struct platform_driver msm_pmic_led_driver = {
- .probe = msm_pmic_led_probe,
- .remove = __devexit_p(msm_pmic_led_remove),
- .suspend = msm_pmic_led_suspend,
- .resume = msm_pmic_led_resume,
- .driver = {
- .name = "pmic-leds",
- .owner = THIS_MODULE,
- },
- };
- static int __init msm_pmic_led_init(void)
- {
- return platform_driver_register(&msm_pmic_led_driver);
- }
- module_init(msm_pmic_led_init);
- static void __exit msm_pmic_led_exit(void)
- {
- platform_driver_unregister(&msm_pmic_led_driver);
- }
- module_exit(msm_pmic_led_exit);
MODULE_DESCRIPTION("MSM PMIC LEDs driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:p
系统行动执行msm_pmic_led_init(void) ,实质是调用》 platform_driver_register(&msm_pmic_led_driver);
接着调用msm_pmic_led_probe ,完成调用 led_classdev_register(&pdev->dev, &msm_kp_bl_led);
就在目录/sys/class/leds创建子目录 keyboard-backlight和属性文件brightness
当按键时,上层对属性文件/sys/class/leds/keyboard-backlight/brightness写入背光的亮度数值就
调用led_brightness_store ,从而调用simple_strtoul(buf, &after, 10);将输入的字符串转换为10进制的数字
然后执行led_set_brightness,》》》》执行led_cdev->brightness_set(led_cdev, value
调用msm_keypad_bl_led_set ,因为 .brightness_set =msm_keypad_bl_led_set,
调用 ret = pmic_set_led_intensity(LED_KEYPAD, value / MAX_KEYPAD_BL_LEVEL);
最终改变LED驱动电路的设置,调节LED的亮度
参考另外另外两文章总结: