天天看點

背光驅動核心層及驅動層分析

一些重要的結構體:

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;

#define LED_SUSPENDED                  (1 << 0)

#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)

         void           (*brightness_set)(struct led_classdev*led_cdev,

                                                 enumled_brightness brightness);

         enumled_brightness (*brightness_get)(struct led_classdev *led_cdev);

         int              (*blink_set)(struct led_classdev*led_cdev,

                                          unsigned long *delay_on,

                                          unsigned long *delay_off);

         structdevice             *dev;

         structlist_head        node;                       

         constchar                  *default_trigger;    

         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

         structrw_semaphore      trigger_lock;

         structled_trigger    *trigger;

         structlist_head        trig_list;

         void                    *trigger_data;

         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