一些重要的结构体:
struct mt65xx_led_data {
structled_classdev cdev;
structcust_mt65xx_led cust;
structwork_struct work;
intlevel;
intdelay_on;
intdelay_off;
};
struct led_classdev {
constchar *name;
int brightness;
int max_brightness;
int flags;
/*Lower 16 bits reflect status */
#define LED_SUSPENDED (1 << 0)
/*Upper 16 bits reflect control information */
#define LED_CORE_SUSPENDRESUME (1 << 16)
#define LED_BLINK_ONESHOT (1 << 17)
#define LED_BLINK_ONESHOT_STOP (1 << 18)
#define LED_BLINK_INVERT (1 << 19)
/*Set LED brightness level */
/*Must not sleep, use a workqueue if needed */
void (*brightness_set)(struct led_classdev*led_cdev,
enumled_brightness brightness);
/*Get LED brightness level */
enumled_brightness (*brightness_get)(struct led_classdev *led_cdev);
/*
* Activate hardware accelerated blink, delaysare in milliseconds
* and if both are zero then a sensible defaultshould be chosen.
* The call should adjust the timings in thatcase and if it can't
* match the values specified exactly.
* Deactivate blinking again when thebrightness is set to a fixed
* value via the brightness_set() callback.
*/
int (*blink_set)(struct led_classdev*led_cdev,
unsigned long *delay_on,
unsigned long *delay_off);
structdevice *dev;
structlist_head node; /* LED Device list */
constchar *default_trigger; /* Trigger to use */
unsignedlong blink_delay_on,blink_delay_off;
structtimer_list blink_timer;
int blink_brightness;
structwork_struct set_brightness_work;
int delayed_set_value;
#ifdef CONFIG_LEDS_TRIGGERS
/*Protects the trigger data below */
structrw_semaphore trigger_lock;
structled_trigger *trigger;
structlist_head trig_list;
void *trigger_data;
/*true if activated - deactivate routine uses it to do cleanup */
bool activated;
#endif
};
struct cust_mt65xx_led {
char *name;
enummt65xx_led_mode mode;
long data;
struct PWM_config config_data;
};
struct work_struct {
atomic_long_tdata;
structlist_head entry;
work_func_tfunc;
#ifdef CONFIG_LOCKDEP
structlockdep_map lockdep_map;
#endif
};
Linux的背光驱动层
Probe:驱动函数
mt65xx_leds_probe
//设置全局数组g_leds_data
g_leds_data[i]->cust.mode= cust_led_list[i].mode;
…….
g_leds_data[i]->cdev.brightness_set= mt65xx_led_set;
mt_mt65xx_led_set //(leds.c)
schedule_work(&led_data->work);
mt_mt65xx_led_set_cust
INIT_WORK(&g_leds_data[i]->work,mt_mt65xx_led_work);
ret =led_classdev_register(&pdev->dev, &g_leds_data[i]->cdev); //led-class.c里定义
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_fileduty fail!\n");
}
……………..
ret =led_classdev_register(&pdev->dev, &g_leds_data[i]->cdev); //led-class.c里定义
led_cdev->dev= device_create(leds_class, parent, 0, led_cdev,"%s",led_cdev->name);
//实现了创建的节点的方法
staticint __init leds_init(void)
{
leds_class= class_create(THIS_MODULE, "leds");
if(IS_ERR(leds_class))
returnPTR_ERR(leds_class);
leds_class->suspend= led_suspend;
leds_class->resume= led_resume;
leds_class->dev_attrs= led_class_attrs;
return0;
}
static struct device_attributeled_class_attrs[] = {
__ATTR(brightness,0644, led_brightness_show, led_brightness_store),
__ATTR(max_brightness,0444, led_max_brightness_show, NULL),
#ifdef CONFIG_LEDS_TRIGGERS
__ATTR(trigger,0644, led_trigger_show, led_trigger_store),
#endif
__ATTR_NULL,
};
static ssize_t led_brightness_store(structdevice *dev,
structdevice_attribute *attr, const char *buf, size_t size)
{
structled_classdev *led_cdev = dev_get_drvdata(dev);
unsignedlong state;
ssize_tret = -EINVAL;
ret= kstrtoul(buf, 10, &state);
if(ret)
returnret;
if(state == LED_OFF)
led_trigger_remove(led_cdev);
__led_set_brightness(led_cdev,state); //这里实现了写节点时立马就设置背光的原理
returnsize;
}
设置背光函数原理:
case MT65XX_LED_MODE_CUST_BLS_PWM:
if(strcmp(cust->name, "lcd-backlight") == 0) {
bl_brightness_hal= level;
}
//mdelay(5000);
LEDS_DEBUG("BLSbrightness mapping value:%ld\n",((long)((level*CONFIG_LIGHTNESS_MAPPING_VALUE)/255)));
return((cust_set_brightness) (cust->data)) ((long)(level*CONFIG_LIGHTNESS_MAPPING_VALUE/255) );
//其实调用的是disp_bls_set_backlight函数,cust_leds.c里定义
分析disp_bls_set_backlight
disp_bls_set_backlight
disp_pwm_set_backlight
disp_pwm_set_backlight_cmdq
disp_pwm_set_backlight_cmdq
level_1024= disp_pwm_level_remap(id, level_1024);
//这里可以设置上层和底层之间的映射
DISP_REG_MASK(cmdq,reg_base + DISP_PWM_CON_1_OFF, level_1024 << 16, 0x1fff << 16);
//设置背光,PWM寄存器配置
alps\kernel-3.10\drivers\misc\mediatek\dispsys\mt6735\ddp_pwm.c