1. 程式人生 > >iTOP-4412開發板驅動lcd顯卡以及linux開機log的修改方法

iTOP-4412開發板驅動lcd顯卡以及linux開機log的修改方法

b- form 以及 選擇 arc pos cti ref ola

iTOP-4412 開發板 LCD 的屏幕驅動,iTOP-4412 開發板支持 4.3寸,7 寸,9.7 寸的 lcd 顯示屏。其中 4.3 寸屏是用的 cpu 直接出來的 RGB 信號,7 寸屏和 9.7寸屏是用的 LVDS 信號,硬件上使用了一個 RGB 轉 LVDS 的芯片實現的。我們來看下顯示驅動,顯示驅動在內核的“drivers/video/samsung”目錄下面,這個驅動是三星提供好的,我們這支只講下我們需要修改的幾個文件。
首先是關於屏幕的分辨率的修改, 因為不同的屏幕分辨率, 頻率以及其他一些硬件參數是不同的,所以我們需要根據這些參數去配置 cpu 的顯示控制器,關於這些參數是在“driversvideo/samsung/s3cfb_wa101s.c”這個文件,打開這個文件我們可以看到這個文件主要就是定義了一個類型是 s3cfb_lcd 的變量 wa101,屏幕的硬件參數(分辨率,時鐘頻率以及其它)就是保存在這個變量裏面,現在我們來看下這個變量結構類型的定義:
struct s3cfb_lcd {
int width;
int height;
int bpp;
int freq;
struct s3cfb_lcd_timing timing;
struct s3cfb_lcd_polarity polarity;
void (*init_ldi)(void);
void (*deinit_ldi)(void);
};
其中的 width 和 height 指屏幕的分辨率,freq 是時鐘頻率,bpp 是數據位。timing 是屏幕的其他一些參數,timing 的類型定義如下:
struct s3cfb_lcd_timing {
int h_fp;
int h_bp;
int h_sw;
int v_fp;
int v_fpe;
int v_bp;
int v_bpe;
int v_sw;
};
這個結構代表屏幕的左間距,右間距,水平同步信號寬度,垂直同步信號的有效行數等屏幕的硬件參數,這些參數可以通過查看屏幕的數據手冊獲得。
下面是 polarity 變量,他的定義如下:
struct s3cfb_lcd_polarity {
int rise_vclk;
int inv_hsync;
int inv_vsync;
int inv_vden;
};
這個變量代表時鐘行場的極性。
通過修改這個文件裏面的這些參數就可以設置 cpu 的顯示控制器來支持我們使用的 lcd屏幕了。
iTIO-4412 開 發 板 內 核 啟 動 時 LCD 會 顯 示 logo , 關 於 這 個 logo 是 保 存 在“drivers/video/samsung/ iTop-4412.h”文件,打開這個文件,會看到裏面指示定義了一個數組 iBitmapData_q,這個數組的內容就是要顯示的 logo。我們修改 logo,就需要準備一張480x640 的 bmp 圖片然後使用 Image2LCD 軟件轉換成數組,把 iBitmapData_q 裏面的內容用新生成的數組替換掉。
有可能我們自己制作的 logo 沒有顯示在屏幕的最中央,那我們需要修改下文件“drivers/video/samsung/ s3cfb_ops.c” ,在這個文件找到函數:s3cfb_draw_logo
int s3cfb_draw_logo(struct fb_info *fb)
{
#ifdef CONFIG_FB_S5P_SPLASH_SCREEN
struct fb_fix_screeninfo *fix = &fb->fix;
struct fb_var_screeninfo *var = &fb->var;
#if 0
struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
memcpy(fbdev->fb[pdata->default_win]->screen_base,
LOGO_RGB24, fix->line_length * var->yres);
#else
//u32 height = var->yres / 3;
u32 line = fix->line_length;
u32 i, j;
u32 index;
u32 top,left;
const unsigned char *pLog =NULL;
memset(fb->screen_base, 0x00, var->yres * line);
printk("\n CPU type: \n");
if(soc_is_exynos4412()){
printk(" Exynos 4412\n");
pLog = iBitmapData_q;
}else{
printk("Exynos 4212\n");
pLog = iBitmapData;
}
top = 170;
left = 230;
index = 0;
for (i = 0; i < 480; i++) {
for (j = 0; j < 640; j++) {
memset(fb->screen_base + (i + top) * line + (j + left) * 4 + 0, pLog[index], 1);//B
memset(fb->screen_base + (i + top) * line + (j + left) * 4 + 1, pLog[index+1], 1);//G
memset(fb->screen_base + (i + top) * line + (j + left) * 4 + 2, pLog[index+2], 1);//R
memset(fb->screen_base + (i + top) * line + (j + left) * 4 + 3, 0x00, 1);
index += 3;
}
}
#endif
#endif
return 0;
}
修改這個函數裏面的 top 和 left 就可以控制圖片在屏幕顯示的位置了。下面我們來看一下 lcd 的控制文件:arch/arm/mach-exynos/setup-fb-s5p.c在這個文件的 s3cfb_cfg_gpio 函數完成 LCD 數據引腳初始化,驅動能力設為最高S5P_GPIO_DRVSTR_LV4;管腳驅動能力,S5P_GPIO_DRVSTR_LV1-4 四個等級選擇,並且設置 LVDS 芯片的使能引腳輸出高:
void s3cfb_cfg_gpio(struct platform_device *pdev)
{
int err;
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);
#if 1 // TC4
//LVDS_PWDN
err = gpio_request(EXYNOS4_GPL1(0), "GPL1_0");
if (err) {
printk(KERN_ERR "failed to request GPL1 for "
"lcd power control\n");
return err;
}
gpio_direction_output(EXYNOS4_GPL1(0), 1);
s3c_gpio_cfgpin(EXYNOS4_GPL1(0), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPL1(0));
#endif
}
然後是時鐘控制函數,完成時鐘的使能和關閉:
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\n");
goto err_clk0;
}
ret = clk_enable(lcd_clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to clk_enable of lcd clk for fimd\n");
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\n");
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\n");
goto err_clk2;
}
ret = clk_set_parent(sclk, mout_mpll);
if (ret < 0) {
dev_err(&pdev->dev, "failed to clk_set_parent for fimd\n");
goto err_clk2;
}
ret = clk_set_rate(sclk, 800000000);
if (ret < 0) {
dev_err(&pdev->dev, "failed to clk_set_rate of sclk for fimd\n");
goto err_clk2;
}
dev_dbg(&pdev->dev, "set fimd sclk rate to %d\n", rate);
clk_put(mout_mpll);
ret = clk_enable(sclk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to clk_enable of sclk for fimd\n");
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\n");
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");
}
然後是 s3cfb_backlight_on 函數,這個是使能屏幕顯示,s3cfb_backlight_off 關閉屏幕顯示。

詳情了解:http://topeetboard.com/ 更多了解:https://arm-board.taobao.com/

技術分享圖片

iTOP-4412開發板驅動lcd顯卡以及linux開機log的修改方法