日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

android系统平台显示驱动开发简要:LCD驱动调试篇『四』

發布時間:2023/12/15 综合教程 37 生活家
生活随笔 收集整理的這篇文章主要介紹了 android系统平台显示驱动开发简要:LCD驱动调试篇『四』 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

平臺信息:

內核:linux3.4.39
系統:android4.4
平臺:S5P4418(cortex a9)

作者:瘋耔(歡迎轉載,請注明作者)

歡迎指正錯誤,共同學習、共同進步!!

關注博主新浪博客:http://weibo.com/cpjphone



以下是Samsung Exynos4412搭配TTL轉LVDS芯片SN75LVDS83B、LVDS接口LCD為例說明。從硬件接口、驅動配置、背光PWM調節三部分說明。

一、LCD接口原理以及硬件電路
Samsung Exynos4412、SN75LVDS83B、LVDS接口LCD(24bit)為例說明,三者的關系如下:

如上圖所示,我們在應用中我,主控(Exynos4412)輸出RGB信號到TFT-LCD大體經過三部分:
(1)、標號1部分,主控(Exynos4412)輸出TTL信號;
(2)、標號2部分,TTL(RGB)-LVDS轉換芯片SN75LVDS83B,把TTL信號轉換成LVDS信號,傳輸到顯示器的LVDS接收端;這部分有SN75LVDS83B編碼芯片自動完成,所以我們不需要程序控制;
(3)、標號3部分,分兩個小部分,LVDS轉換成TTL,TFT-LCD顯示部分;我們前面說過,TFT-LCD其實只識別TTL信號,所以要有一個轉換的過程,先把LVDS信號轉換、解碼成TTL信號,在TFT-LCD上顯示。
有上面的過程,其實我們關心調試的部分只有標號1部分到標號2部分,后面標號2到標號3的部分是自動完成的,不需要我們程序上控制,把標號2部分、標號3部分合并:

標號二部分可以理解為一個TTL(RGB)接口的LCD,如下圖所示,標號一部分就是主控信號輸出端,簡化圖如下所示:


其實最簡單的做法就是找個TTL接口的TFT-LCD,這樣直接接上就可以。下面我們看下硬件上的電路連接:這個和我們上篇用的相同。

有上面圖可以看出:硬件連接

網絡標號

說明

管腳

XvVD[0:23]

XvVDEN

XvVSYNC

XvHSYNC

XvVCLK

RGB數據、使能、行場同步、時鐘信號

這是TTL信號輸出

LCD_PWM

調節背光

XpwmTOUT1/LCD_PWM/GPD0_1

LCD_LED_EN

LCD電壓(TFT電壓)使能

GPC1_2

LED_BL_EN

LED背光使能

GPL2_4

上面可分為幾部分,電路連接部分分析:

(1)、TTL數據部分
這張圖有木有爛掉呀,哈哈,就是這些數據了。還有有木有想起來攝像頭的數據(ITU接口)也是這樣的??其實視頻這種信號的原理是通用的,所以LCD通了,攝像頭也就知道怎么回事了。

(2)、PWM背光調節
PWM其實也是芯片的一個功能模塊,看到他的管腳就是一個復用腳XpwmTOUT1/LCD_PWM/GPD0_1。上一篇我們粗略的了解了PWM,就是用到這里。但是有一個疑問,PWM是調節背光電壓的,背光電壓一般都是12V以上的,我們PWM只有0-3V的樣子,Exynos4412的IO只有1.8V。怎么調節電壓???

其實這個PWM只是給LCD上PWM控制部分,真正的電壓還是通過LCD控制板上的電路實現。

3)、LED背光、LCD電壓控制
a、背光:LED+
我們可以看到這個升壓電路,通過SY7208把VBATT升壓到18V,供給LED背光。SY7208最大升壓26V。這個電壓是提供給我們前面講的背光的,也就是CCFL燈管或者LED背光組的電壓。

b、LCD電壓
這個電壓也就是給你我們TFT陣列組用的,控制LCD液晶元素。
這部分電路分析完成,我們就有比較清晰的思路出,要一個LCD工作,要完成兩部分內容:LCD上電控制,背光、LCD電壓;信號輸出。

▊對于4418來說主控部分集成了LVDS信號輸出,下面做電路介紹:

--

--

與TFT屏連接部分,功能:

①顯示數據傳遞

②觸摸數據傳遞

本章只講述顯示部分

二、LCD 驅動部分調試
LCD這部分,像上篇我們說的frambuffer這些部分一般平臺都是可以用的,除非你是芯片廠的要寫這部分。一般公司拿到的demo板子這部分都是通的,只是針對自己的lCD換一些參數。
下面我們針對三星平臺我們調試LCD的時時候程序方面的改動:
1、屏參數的配置
/kernel/drivers/video/Samsung/s3cfb_wa101s.c(4412)

static struct s3cfb_lcd wa101 = {  
      
    .width  = 1280,//LCD 分辨率寬1280  
    .height = 800, //LCD 分辨率高 800  
    .bpp    = 24,//CLD 數據位 24bit  
    .freq   = 60,//LCD 像素時鐘 60MHz  
    .timing = {//LCD porch無效值  
        .h_fp   = 70,  
        .h_bp   = 70,  
        .h_sw   = 20,  
      
        .v_fp   = 10,  
        .v_fpe  = 0,  
        .v_bp   = 10,  
        .v_bpe  = 0,  
        .v_sw   = 3,  
    },  
  
    .polarity = {//時鐘、行場的極性;  
        .rise_vclk  = 1,  
        .inv_hsync  = 1,  
        .inv_vsync  = 1,  
        .inv_vden   = 0,  
    },  
};  
/* name should be fixed as 's3cfb_set_lcd_info' */  
void s3cfb_set_lcd_info(struct s3cfb_global *ctrl)//初始化結構體  
{  
    wa101.init_ldi = NULL;  
    ctrl->lcd = &wa101;  
#endif  
}  

還能想起上一篇的如何閱讀規格書中的那些參數不,把這些填入就可以。
2、數據管腳初始化


kernel/arch/arm/mach-exynos/setup-fb-s5p.c(4412)

void s3cfb_cfg_gpio(struct platform_device *pdev)  
{  
    s3cfb_gpio_setup_24bpp(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2), S5P_GPIO_DRVSTR_LV4);  
    s3cfb_gpio_setup_24bpp(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2), S5P_GPIO_DRVSTR_LV4);  
    s3cfb_gpio_setup_24bpp(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2), S5P_GPIO_DRVSTR_LV4);  
    s3cfb_gpio_setup_24bpp(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2), S5P_GPIO_DRVSTR_LV4);  
}  

LCD數據腳初始化,驅動能力設為最高S5P_GPIO_DRVSTR_LV4;管腳驅動能力,S5P_GPIO_DRVSTR_LV1-4四個等級選擇。
3、時鐘控制部分
kernel/arch/arm/mach-exynos/setup-fb-s5p.c

int s3cfb_clk_on(struct platform_device *pdev, struct clk **s3cfb_clk)  
{  
    struct clk *sclk = NULL;  
    struct clk *mout_mpll = NULL;  
    struct clk *lcd_clk = NULL;  
  
    u32 rate = 0;  
    int ret = 0;  
  
    lcd_clk = clk_get(&pdev->dev, "lcd");  
    if (IS_ERR(lcd_clk)) {  
        dev_err(&pdev->dev, "failed to get operation clk for fimd
");  
        goto err_clk0;  
    }  
  
    ret = clk_enable(lcd_clk);  
    if (ret < 0) {  
        dev_err(&pdev->dev, "failed to clk_enable of lcd clk for fimd
");  
        goto err_clk0;  
    }  
    clk_put(lcd_clk);  
  
    sclk = clk_get(&pdev->dev, "sclk_fimd");  
    if (IS_ERR(sclk)) {  
        dev_err(&pdev->dev, "failed to get sclk for fimd
");  
        goto err_clk1;  
    }  
  
    if (soc_is_exynos4210())  
        mout_mpll = clk_get(&pdev->dev, "mout_mpll");  
    else  
        mout_mpll = clk_get(&pdev->dev, "mout_mpll_user");  
  
    if (IS_ERR(mout_mpll)) {  
        dev_err(&pdev->dev, "failed to get mout_mpll for fimd
");  
        goto err_clk2;  
    }  
  
    ret = clk_set_parent(sclk, mout_mpll);  
    if (ret < 0) {  
        dev_err(&pdev->dev, "failed to clk_set_parent for fimd
");  
        goto err_clk2;  
    }  
  
    if ((soc_is_exynos4412()) && (samsung_rev() >= EXYNOS4412_REV_2_0))  
        ret = clk_set_rate(sclk, 880000000);  
    else  
        ret = clk_set_rate(sclk, 800000000);  
    if (ret < 0) {  
        dev_err(&pdev->dev, "failed to clk_set_rate of sclk for fimd
");  
        goto err_clk2;  
    }  
    dev_dbg(&pdev->dev, "set fimd sclk rate to %d
", rate);  
  
    clk_put(mout_mpll);  
  
    ret = clk_enable(sclk);  
    if (ret < 0) {  
        dev_err(&pdev->dev, "failed to clk_enable of sclk for fimd
");  
        goto err_clk2;  
    }  
  
    *s3cfb_clk = sclk;  
  
    return 0;  
  
err_clk2:  
    clk_put(mout_mpll);  
err_clk1:  
    clk_put(sclk);  
err_clk0:  
    clk_put(lcd_clk);  
  
    return -EINVAL;  
}  
int s3cfb_clk_off(struct platform_device *pdev, struct clk **clk)  
{  
    struct clk *lcd_clk = NULL;  
  
    lcd_clk = clk_get(&pdev->dev, "lcd");  
    if (IS_ERR(lcd_clk)) {  
        printk(KERN_ERR "failed to get ip clk for fimd0
");  
        goto err_clk0;  
    }  
  
    clk_disable(lcd_clk);  
    clk_put(lcd_clk);  
  
    clk_disable(*clk);  
    clk_put(*clk);  
  
    *clk = NULL;  
  
    return 0;  
  
err_clk0:  
    clk_put(lcd_clk);  
  
    return -EINVAL;  
}  
  
void s3cfb_get_clk_name(char *clk_name)  
{  
    strcpy(clk_name, "sclk_fimd");  
}  

4、背光、LCD電壓的控制

LCD_LED_EN

LCD電壓(TFT電壓)使能

GPC1_2

LED_BL_EN

LED背光使能

GPL2_4

int s3cfb_backlight_on(struct platform_device *pdev)  
{  
        int err;  
        pwm_set();  
    err = gpio_request_one(EXYNOS4_GPL2(4), GPIOF_OUT_INIT_HIGH, "GPL2_4");  
    if (err) {  
        printk(KERN_ERR "failed to request GPL2 for "  
            "lcd backlight control
");  
        return err;  
    }  
    s3c_gpio_setpull(EXYNOS4_GPL2(4),S3C_GPIO_PULL_NONE);  
    gpio_direction_output(EXYNOS4_GPL2(4), 1);  
    gpio_free(EXYNOS4_GPL2(4));  
    mdelay(20);  
    err = gpio_request_one(EXYNOS4_GPC1(2), GPIOF_OUT_INIT_HIGH, "GPC1_2");  
    if (err) {  
        printk(KERN_ERR "failed to request GPC1 for "  
            "lcd backlight control
");  
        return err;  
    }  
    s3c_gpio_setpull(EXYNOS4_GPC1(2),S3C_GPIO_PULL_NONE);  
    gpio_direction_output(EXYNOS4_GPC1(2), 0);  
    gpio_free(EXYNOS4_GPC1(2));  
  
    mdelay(20);  
    err = gpio_request(EXYNOS4_GPD0(1), "GPD0_1");  
  
    if (err) {  
        printk(KERN_ERR "failed to request GPD0_1 for "  
            "lcd pwm control
");  
        return err;  
    }  
    s3c_gpio_setpull(EXYNOS4_GPD0(1),S3C_GPIO_PULL_NONE);  
    s5p_gpio_set_drvstr(EXYNOS4_GPD0(1), S5P_GPIO_DRVSTR_LV4);    
    gpio_direction_output(EXYNOS4_GPD0(1), 1);  
    s3c_gpio_cfgpin(EXYNOS4_GPD0(1), EXYNOS4_GPD_0_1_TOUT_1);  
      
    gpio_free(EXYNOS4_GPD0(1));  
    mdelay(20);  
    return 0;  
  
    return 0;  
}  
  
int s3cfb_backlight_off(struct platform_device *pdev)  
{  
    int err;  
    err = gpio_request_one(EXYNOS4_GPL2(4), GPIOF_OUT_INIT_LOW, "GPL2_4");  
    if (err) {  
        printk(KERN_ERR "failed to request GPL2 for "  
            "lcd backlight control
");  
        return err;  
    }  
    s3c_gpio_setpull(EXYNOS4_GPL2(4),S3C_GPIO_PULL_NONE);  
    gpio_direction_output(EXYNOS4_GPL2(4), 0);  
    gpio_free(EXYNOS4_GPL2(4));  
  
    err = gpio_request_one(EXYNOS4_GPC1(2), GPIOF_OUT_INIT_HIGH, "GPC1_2");  
    if (err) {  
        printk(KERN_ERR "failed to request GPC1 for "  
            "lcd backlight control
");  
        return err;  
    }  
    gpio_free(EXYNOS4_GPC1(2));  
  
    return 0;  
}  

5、PWM的設置

arch/arm/mach-exynos/mach-smdk4x12.c

Arch/arm/mach-exynos/mach-smdk4x12.c  
/* LCD Backlight data */  
static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {  
    .no = EXYNOS4_GPD0(1),//PWM管腳XpwmTOUT1/LCD_PWM/GPD0_1  
    .func = S3C_GPIO_SFN(2),  
};  
static struct platform_pwm_backlight_data smdk4x12_bl_data = {  
    .pwm_id = 1,//PWM ID PWM編號為1號;  
    .pwm_period_ns  = 90000,  //22k  
};  
static void __init smdk4x12_machine_init(void)  
{     
………………  
samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);//在初始化的時候把對應的結構體初始化  
………………  
}  

samsung_bl_set看下這個函數的實現:

kernel/arch/arm/palt-samsung/dev-backlight.c

void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,  
    struct platform_pwm_backlight_data *bl_data)  
{  
    int ret = 0;  
    struct platform_device *samsung_bl_device;  
    struct platform_pwm_backlight_data *samsung_bl_data;  
  
    samsung_bl_device = kmemdup(&samsung_dfl_bl_device,  
            sizeof(struct platform_device), GFP_KERNEL);//(1)、分配內存空間;  
    if (!samsung_bl_device) {  
        printk(KERN_ERR "%s: no memory for platform dev
", __func__);  
        return;  
    }  
  
    samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data,  
        sizeof(struct platform_pwm_backlight_data), samsung_bl_device);//(2)、  
    if (!samsung_bl_data) {  
        printk(KERN_ERR "%s: no memory for platform dev
", __func__);  
        goto err_data;  
    }  
  
    /* Copy board specific data provided by user */  
    samsung_bl_data->pwm_id = bl_data->pwm_id;//(3)、把具體配置的數據給samsung_bl_data  
    samsung_bl_device->dev.parent =  
            &s3c_device_timer[samsung_bl_data->pwm_id].dev;  
  
    if (bl_data->max_brightness)//(4)、對bl_data的結構體檢查,如果沒有復制則用default的值  
        samsung_bl_data->max_brightness = bl_data->max_brightness;  
    if (bl_data->dft_brightness)  
        samsung_bl_data->dft_brightness = bl_data->dft_brightness;  
    if (bl_data->lth_brightness)  
        samsung_bl_data->lth_brightness = bl_data->lth_brightness;  
    if (bl_data->pwm_period_ns)  
        samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;  
    if (bl_data->init)  
        samsung_bl_data->init = bl_data->init;  
    if (bl_data->notify)  
        samsung_bl_data->notify = bl_data->notify;  
    if (bl_data->exit)  
        samsung_bl_data->exit = bl_data->exit;  
    if (bl_data->check_fb)  
        samsung_bl_data->check_fb = bl_data->check_fb;  
  
    /* Keep the GPIO info for future use */  
    s3c_device_timer[samsung_bl_data->pwm_id].dev.platform_data = gpio_info;  
  
    /* Register the specific PWM timer dev for Backlight control */  
    ret = platform_device_register(//(5)、注冊PWM設備驅動;  
            &s3c_device_timer[samsung_bl_data->pwm_id]);  
    if (ret) {  
        printk(KERN_ERR "failed to register pwm timer for backlight: %d
", ret);  
        goto err_plat_reg1;  
    }  
  
    /* Register the Backlight dev */  
    ret = platform_device_register(samsung_bl_device);//(6)、注冊背光設備驅動;  
    if (ret) {  
        printk(KERN_ERR "failed to register backlight device: %d
", ret);  
        goto err_plat_reg2;  
    }  
  
    return;  
  
err_plat_reg2://(7)、如果有異常的情況下退出;  
    platform_device_unregister(&s3c_device_timer[samsung_bl_data->pwm_id]);  
err_plat_reg1:  
    kfree(samsung_bl_data);  
err_data:  
    kfree(samsung_bl_device);  
    return;  
}  

(1)、分配內存空間

   samsung_bl_device = kmemdup(&samsung_dfl_bl_device,  
            sizeof(struct platform_device), GFP_KERNEL);  
其中:  
static struct platform_pwm_backlight_data samsung_dfl_bl_data = {  
    .max_brightness = 255,  
    .dft_brightness = 140,   
    .pwm_period_ns  = 78770,  
    .init           = samsung_bl_init,  
    .exit           = samsung_bl_exit,  
};  
  
static struct platform_device samsung_dfl_bl_device = {  
    .name       = "pwm-backlight",  
};  

(3)、把具體配置的數據給samsung_bl_data

arch/arm/mach-exynos/mach-smdk4x12.c  
static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {  
    .no = EXYNOS4_GPD0(1),//PWM管腳XpwmTOUT1/LCD_PWM/GPD0_1  
    .func = S3C_GPIO_SFN(2),  
};  
static struct platform_pwm_backlight_data smdk4x12_bl_data = {  
    .pwm_id = 1,//PWM ID PWM編號為1號;  
    .pwm_period_ns  = 90000,  //22k  
};  

(4)、對bl_data的結構體檢查,如果沒有復制則用default的值

參考(1)中的那些值。

(5)、注冊PWM設備驅動;

ret = platform_device_register(  
        &s3c_device_timer[samsung_bl_data->pwm_id]); 

其中s3c_device_timer[]這個結構體如下:

struct platform_device s3c_device_timer[] = {  
    [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },  
    [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },  
    [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },  
    [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },  
    [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },  

我們餓samsung_bl_data->pwm_id=1;所以選擇[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },

(6)、注冊背光設備驅動;

ret =platform_device_register(samsung_bl_device);  

其中:samsung_bl_device

samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data,  
    sizeof(struct platform_pwm_backlight_data), samsung_bl_device);  

(7)、如果有異常的情況下退出;

6、PWM_BL背光驅動分析:

Kernel/drivers/video/backlight/pwm_bl.c

(1)、驅動注冊:

static struct platform_driver pwm_backlight_driver = {  
    .driver     = {  
        .name   = "pwm-backlight",  
        .owner  = THIS_MODULE,  
    },  
    .probe      = pwm_backlight_probe,  
    .remove     = pwm_backlight_remove,  
    .suspend    = pwm_backlight_suspend,  
    .resume     = pwm_backlight_resume,  
};  
  
static int __init pwm_backlight_init(void)  
{  
    return platform_driver_register(&pwm_backlight_driver);  
}  

(2)、probe函數分析

static int pwm_backlight_probe(struct platform_device *pdev)  
{  
    struct backlight_properties props;  
    struct platform_pwm_backlight_data *data = pdev->dev.platform_data;  
    struct backlight_device *bl;  
    struct pwm_bl_data *pb;  
    int ret;  
  
    if (!data) {  
        dev_err(&pdev->dev, "failed to find platform data
");  
        return -EINVAL;  
    }  
  
    if (data->init) {  
        ret = data->init(&pdev->dev);  
        if (ret < 0)  
            return ret;  
    }  
  
    pb = kzalloc(sizeof(*pb), GFP_KERNEL);  
    if (!pb) {  
        dev_err(&pdev->dev, "no memory for state
");  
        ret = -ENOMEM;  
        goto err_alloc;  
    }  
  
    global_pb=pb;  
    INIT_DELAYED_WORK_DEFERRABLE(&key_event, key_event_work);//1)、任務隊列初始化;  
  
    pb->period = data->pwm_period_ns;//2)、pb結構體初始化;  
    pb->notify = data->notify;  
    pb->check_fb = data->check_fb;  
    pb->lth_brightness = data->lth_brightness *  
        (data->pwm_period_ns / data->max_brightness);  
    pb->dev = &pdev->dev;  
  
    pb->pwm = pwm_request(data->pwm_id, "backlight");  
    if (IS_ERR(pb->pwm)) {  
        dev_err(&pdev->dev, "unable to request PWM for backlight
");  
        ret = PTR_ERR(pb->pwm);  
        goto err_pwm;  
    } else  
        dev_dbg(&pdev->dev, "got pwm for backlight
");  
  
    memset(&props, 0, sizeof(struct backlight_properties));  
    props.type = BACKLIGHT_RAW;  
    props.max_brightness = data->max_brightness;  
    bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,  
                       &pwm_backlight_ops, &props);  
    if (IS_ERR(bl)) {  
        dev_err(&pdev->dev, "failed to register backlight
");  
        ret = PTR_ERR(bl);  
        goto err_bl;  
    }  
    global_bl=bl;  
    bl->props.brightness = data->dft_brightness;  
    backlight_update_status(bl);//3)、更新背光狀態;  
  
    platform_set_drvdata(pdev, bl);  
    return 0;  
  
err_bl:  
    pwm_free(pb->pwm);  
err_pwm:  
    kfree(pb);  
err_alloc:  
    if (data->exit)  
        data->exit(&pdev->dev);  
    return ret;  
}  

1)、任務隊列初始化;

把key_event_work加入key_event隊列,

INIT_DELAYED_WORK_DEFERRABLE(&key_event, key_event_work);  

隊列調度函數:

static void key_event_work(struct work_struct *work)  
{  
    global_pb->period=90000;  
    global_bl->props.brightness=global_brightness;  
    backlight_update_status(global_bl);  
    return ;  
}  

backlight_update_status

static inline void backlight_update_status(struct backlight_device *bd)  
{  
    mutex_lock(&bd->update_lock);  
    if (bd->ops && bd->ops->update_status)  
        bd->ops->update_status(bd);  
    mutex_unlock(&bd->update_lock);  
}  

update_status在pwm_backlight_ops結構體重指定:

static const struct backlight_ops pwm_backlight_ops = {  
    .update_status  = pwm_backlight_update_status,  
    …………}  

pwm_backlight_update_status我們后面分析,這個其實就是我們PWM設定實現的具體實施過程。

2)、pb結構體初始化;

pb->period = data->pwm_period_ns; pb->notify = data->notify;  
pb->check_fb = data->check_fb;  
pb->lth_brightness = data->lth_brightness *  
    (data->pwm_period_ns / data->max_brightness);  
pb->dev = &pdev->dev;  
pb->pwm = pwm_request(data->pwm_id, "backlight");  

3)、更新背光狀態

backlight_update_status(bl);  

(4)、PWM_SET

當UI設置PWM時,會調用到驅動中的pwm_set(void)這個函數。這個函數主要在開機時使用。

int pwm_set(void)  
{  
    int error;  
    struct backlight_device *bl = global_bl;  
    struct pwm_bl_data *pb = global_pb;  
    printk("%s__%d
",__func__,pb->period);  
    pb->period=410000;  
    backlight_update_status(bl);  
    schedule_delayed_work(&key_event, 600); //調用隊列,跟新亮度信息;  
      
    return 0;  
}  

(5)、pwm_backlight_update_status這個就是PWM變化的具體實現,當應用層調節時,會調用到這個函數,把改變的值填入寄存器。

static int pwm_backlight_update_status(struct backlight_device *bl)  
{  
    struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);  
    int brightness = bl->props.brightness;  
    int max = bl->props.max_brightness;  
    //if(brightness==0)  
    //  return 0;  
    //printk("#####%s#%d__%d
",__func__,pb->period,brightness);  
    global_brightness=brightness;  
    if (bl->props.power != FB_BLANK_UNBLANK)  
        brightness = 0;  
  
    if (bl->props.fb_blank != FB_BLANK_UNBLANK)  
        brightness = 0;  
  
    if (pb->notify)  
        brightness = pb->notify(pb->dev, brightness);  
      
    if (brightness == 0) {  
        pwm_config(pb->pwm, 0, pb->period);  
        pwm_disable(pb->pwm);  
    } else {  
    #if 1  
        brightness = pb->lth_brightness +  
            (brightness * (pb->period - pb->lth_brightness) / max);  
    #else  
     brightness = pb->lth_brightness +  
                        (((pb->period - pb->lth_brightness) / max) * brightness );  
    #endif  
          
        pwm_config(pb->pwm, brightness, pb->period);//這里對PWM寄存器的具體操作;  
        pwm_enable(pb->pwm);  
    }  
    return 0;  
}  

三、LCD UBOOT下的控制(待整理…………)
LCD在UBOOT下的控制,這部分我們沒做過,后面有機會做了再把這部分完善,或者找個機會把代碼詳細看看。

--------------------------------------------

總結

以上是生活随笔為你收集整理的android系统平台显示驱动开发简要:LCD驱动调试篇『四』的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。