android系统平台显示驱动开发简要:LCD驱动调试篇『四』
平臺信息:
內(nèi)核:linux3.4.39
系統(tǒng):android4.4
平臺:S5P4418(cortex a9)
作者:瘋耔(歡迎轉(zhuǎn)載,請注明作者)
歡迎指正錯誤,共同學(xué)習(xí)、共同進步!!
關(guān)注博主新浪博客:http://weibo.com/cpjphone
以下是Samsung Exynos4412搭配TTL轉(zhuǎn)LVDS芯片SN75LVDS83B、LVDS接口LCD為例說明。從硬件接口、驅(qū)動配置、背光PWM調(diào)節(jié)三部分說明。
一、LCD接口原理以及硬件電路
Samsung Exynos4412、SN75LVDS83B、LVDS接口LCD(24bit)為例說明,三者的關(guān)系如下:
如上圖所示,我們在應(yīng)用中我,主控(Exynos4412)輸出RGB信號到TFT-LCD大體經(jīng)過三部分:
(1)、標(biāo)號1部分,主控(Exynos4412)輸出TTL信號;
(2)、標(biāo)號2部分,TTL(RGB)-LVDS轉(zhuǎn)換芯片SN75LVDS83B,把TTL信號轉(zhuǎn)換成LVDS信號,傳輸?shù)斤@示器的LVDS接收端;這部分有SN75LVDS83B編碼芯片自動完成,所以我們不需要程序控制;
(3)、標(biāo)號3部分,分兩個小部分,LVDS轉(zhuǎn)換成TTL,TFT-LCD顯示部分;我們前面說過,TFT-LCD其實只識別TTL信號,所以要有一個轉(zhuǎn)換的過程,先把LVDS信號轉(zhuǎn)換、解碼成TTL信號,在TFT-LCD上顯示。
有上面的過程,其實我們關(guān)心調(diào)試的部分只有標(biāo)號1部分到標(biāo)號2部分,后面標(biāo)號2到標(biāo)號3的部分是自動完成的,不需要我們程序上控制,把標(biāo)號2部分、標(biāo)號3部分合并:
標(biāo)號二部分可以理解為一個TTL(RGB)接口的LCD,如下圖所示,標(biāo)號一部分就是主控信號輸出端,簡化圖如下所示:
其實最簡單的做法就是找個TTL接口的TFT-LCD,這樣直接接上就可以。下面我們看下硬件上的電路連接:這個和我們上篇用的相同。
有上面圖可以看出:硬件連接
|
網(wǎng)絡(luò)標(biāo)號 |
說明 |
管腳 |
|
XvVD[0:23] XvVDEN XvVSYNC XvHSYNC XvVCLK |
RGB數(shù)據(jù)、使能、行場同步、時鐘信號 |
這是TTL信號輸出 |
|
LCD_PWM |
調(diào)節(jié)背光 |
XpwmTOUT1/LCD_PWM/GPD0_1 |
|
LCD_LED_EN |
LCD電壓(TFT電壓)使能 |
GPC1_2 |
|
LED_BL_EN |
LED背光使能 |
GPL2_4 |
上面可分為幾部分,電路連接部分分析:
(1)、TTL數(shù)據(jù)部分
這張圖有木有爛掉呀,哈哈,就是這些數(shù)據(jù)了。還有有木有想起來攝像頭的數(shù)據(jù)(ITU接口)也是這樣的??其實視頻這種信號的原理是通用的,所以LCD通了,攝像頭也就知道怎么回事了。
(2)、PWM背光調(diào)節(jié)
PWM其實也是芯片的一個功能模塊,看到他的管腳就是一個復(fù)用腳XpwmTOUT1/LCD_PWM/GPD0_1。上一篇我們粗略的了解了PWM,就是用到這里。但是有一個疑問,PWM是調(diào)節(jié)背光電壓的,背光電壓一般都是12V以上的,我們PWM只有0-3V的樣子,Exynos4412的IO只有1.8V。怎么調(diào)節(jié)電壓???
其實這個PWM只是給LCD上PWM控制部分,真正的電壓還是通過LCD控制板上的電路實現(xiàn)。
(3)、LED背光、LCD電壓控制
a、背光:LED+
我們可以看到這個升壓電路,通過SY7208把VBATT升壓到18V,供給LED背光。SY7208最大升壓26V。這個電壓是提供給我們前面講的背光的,也就是CCFL燈管或者LED背光組的電壓。
b、LCD電壓
這個電壓也就是給你我們TFT陣列組用的,控制LCD液晶元素。
這部分電路分析完成,我們就有比較清晰的思路出,要一個LCD工作,要完成兩部分內(nèi)容:LCD上電控制,背光、LCD電壓;信號輸出。
▊對于4418來說主控部分集成了LVDS信號輸出,下面做電路介紹:
--
--
與TFT屏連接部分,功能:
①顯示數(shù)據(jù)傳遞
②觸摸數(shù)據(jù)傳遞
本章只講述顯示部分
二、LCD 驅(qū)動部分調(diào)試
LCD這部分,像上篇我們說的frambuffer這些部分一般平臺都是可以用的,除非你是芯片廠的要寫這部分。一般公司拿到的demo板子這部分都是通的,只是針對自己的lCD換一些參數(shù)。
下面我們針對三星平臺我們調(diào)試LCD的時時候程序方面的改動:
1、屏參數(shù)的配置
/kernel/drivers/video/Samsung/s3cfb_wa101s.c(4412)
static struct s3cfb_lcd wa101 = {
.width = 1280,//LCD 分辨率寬1280
.height = 800, //LCD 分辨率高 800
.bpp = 24,//CLD 數(shù)據(jù)位 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)//初始化結(jié)構(gòu)體
{
wa101.init_ldi = NULL;
ctrl->lcd = &wa101;
#endif
}
還能想起上一篇的如何閱讀規(guī)格書中的那些參數(shù)不,把這些填入就可以。
2、數(shù)據(jù)管腳初始化
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數(shù)據(jù)腳初始化,驅(qū)動能力設(shè)為最高S5P_GPIO_DRVSTR_LV4;管腳驅(qū)動能力,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的設(shè)置
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);//在初始化的時候把對應(yīng)的結(jié)構(gòu)體初始化
………………
}
samsung_bl_set看下這個函數(shù)的實現(xiàn):
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)、分配內(nèi)存空間;
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)、把具體配置的數(shù)據(jù)給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的結(jié)構(gòu)體檢查,如果沒有復(fù)制則用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設(shè)備驅(qū)動;
&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)、注冊背光設(shè)備驅(qū)動;
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)、分配內(nèi)存空間
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)、把具體配置的數(shù)據(jù)給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的結(jié)構(gòu)體檢查,如果沒有復(fù)制則用default的值
參考(1)中的那些值。
(5)、注冊PWM設(shè)備驅(qū)動;
ret = platform_device_register(
&s3c_device_timer[samsung_bl_data->pwm_id]);
其中s3c_device_timer[]這個結(jié)構(gòu)體如下:
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)、注冊背光設(shè)備驅(qū)動;
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背光驅(qū)動分析:
Kernel/drivers/video/backlight/pwm_bl.c
(1)、驅(qū)動注冊:
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函數(shù)分析
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)、任務(wù)隊列初始化;
pb->period = data->pwm_period_ns;//2)、pb結(jié)構(gòu)體初始化;
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)、更新背光狀態(tài);
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)、任務(wù)隊列初始化;
把key_event_work加入key_event隊列,
INIT_DELAYED_WORK_DEFERRABLE(&key_event, key_event_work);
隊列調(diào)度函數(shù):
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結(jié)構(gòu)體重指定:
static const struct backlight_ops pwm_backlight_ops = {
.update_status = pwm_backlight_update_status,
…………}
pwm_backlight_update_status我們后面分析,這個其實就是我們PWM設(shè)定實現(xiàn)的具體實施過程。
2)、pb結(jié)構(gòu)體初始化;
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)、更新背光狀態(tài)
backlight_update_status(bl);
(4)、PWM_SET
當(dāng)UI設(shè)置PWM時,會調(diào)用到驅(qū)動中的pwm_set(void)這個函數(shù)。這個函數(shù)主要在開機時使用。
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); //調(diào)用隊列,跟新亮度信息;
return 0;
}
(5)、pwm_backlight_update_status這個就是PWM變化的具體實現(xiàn),當(dāng)應(yīng)用層調(diào)節(jié)時,會調(diào)用到這個函數(shù),把改變的值填入寄存器。
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下的控制,這部分我們沒做過,后面有機會做了再把這部分完善,或者找個機會把代碼詳細(xì)看看。
--------------------------------------------
總結(jié)
以上是生活随笔為你收集整理的android系统平台显示驱动开发简要:LCD驱动调试篇『四』的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 好调剂的计算机类工科学校,B区最好调剂的
- 下一篇: 丹佛机场行李处理系统分析