看下面的代码,你会发现韦老师这种组织与内核框架的组织是一脉相承的。
led.c
1 #define LCD_NUM 10 2 3 static p_lcd_params p_array_lcd[LCD_NUM]; 4 static p_lcd_params g_p_lcd_selected; 5 6 int register_lcd(p_lcd_params plcd) 7 { 8 int i; 9 for (i = 0; i < LCD_NUM; i++) 10 { 11 if (!p_array_lcd[i]) 12 { 13 p_array_lcd[i] = plcd; 14 return i; 15 } 16 } 17 return -1; 18 } 19 20 int select_lcd(char *name) 21 { 22 int i; 23 for (i = 0; i < LCD_NUM; i++) 24 { 25 if (p_array_lcd[i] && !strcmp(p_array_lcd[i]->name, name)) 26 { 27 g_p_lcd_selected = p_array_lcd[i]; 28 return i; 29 } 30 } 31 return -1; 32 } 33 34 int lcd_init(void) 35 { 36 /* 注册LCD */ 37 lcd_4_3_add(); 38 39 /* 注册LCD控制器 */ 40 lcd_contoller_add(); 4142 /* 选择某款LCD */ 43 select_lcd("lcd_4.3"); 44 45 /* 选择某款LCD控制器 */ 46 select_lcd_controller("s3c2440"); 47 48 /* 使用LCD的参数, 初始化LCD控制器 */ 49 lcd_controller_init(g_p_lcd_selected); 50 }
led_4.3.c
1 #define LCD_FB_BASE 0x33c00000
2
3 lcd_params lcd_4_3_params = {
4 .name = "lcd_4.3"
5 .pins_polarity = {
6 .de = NORMAL, /* normal: 高电平时可以传输数据 */
7 .pwren = NORMAL, /* normal: 高电平有效 */
8 .vclk = NORMAL, /* normal: 在下降沿获取数据 */
9 .rgb = NORMAL, /* normal: 高电平表示1 */
10 .hsync = INVERT, /* normal: 高脉冲 */
11 .vsync = INVERT, /* normal: 高脉冲 */
12 },
13 .time_sequence = {
14 /* 垂直方向 */
15 .tvp= 10, /* vysnc脉冲宽度 */
16 .tvb= 2, /* 上边黑框, Vertical Back porch */
17 .tvf= 2, /* 下边黑框, Vertical Front porch */
18
19 /* 水平方向 */
20 .thp= 41, /* hsync脉冲宽度 */
21 .thb= 2, /* 左边黑框, Horizontal Back porch */
22 .thf= 2, /* 右边黑框, Horizontal Front porch */
23
24 .vclk= 9, /* MHz */
25 },
26 .xres = 480,
27 .yres = 272,
28 .bpp = 16,
29 .fb_base = LCD_FB_BASE,
30 };
31
32
33 void lcd_4_3_add(void)
34 {
35 register_lcd(&lcd_4_3_params);
36 }
led_controller.c
1 #define LCD_CONTROLLER_NUM 10
2
3 static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM];
4 static p_lcd_controller g_p_lcd_controller_selected;
5
6 int register_lcd_controller(p_lcd_controller plcdcon)
7 {
8 int i;
9 for (i = 0; i < LCD_CONTROLLER_NUM; i++)
10 {
11 if (!p_array_lcd_controller[i])
12 {
13 p_array_lcd_controller[i] = plcdcon;
14 return i;
15 }
16 }
17 return -1;
18 }
19
20 int select_lcd_controller(char *name)
21 {
22 int i;
23 for (i = 0; i < LCD_CONTROLLER_NUM; i++)
24 {
25 if (p_array_lcd_controller[i] && !strcmp(p_array_lcd_controller[i]->name, name))
26 {
27 g_p_lcd_controller_selected = p_array_lcd_controller[i];
28 return i;
29 }
30 }
31 return -1;
32 }
33
34
35 /* 向上: 接收不同LCD的参数
36 * 向下: 使用这些参数设置对应的LCD控制器
37 */
38
39 int lcd_controller_init(p_lcd_params plcdparams)
40 {
41 /* 调用所选择的LCD控制器的初始化函数 */
42 if (g_p_lcd_controller_selected)
43 {
44 g_p_lcd_controller_selected->init(plcdparams);
45 return 0;
46 }
47 return -1;
48 }
49
50 void lcd_contoller_add(void)
51 {
52 s3c2440_lcd_contoller_add();
53 }
s3c2440_lcd_controller.c
1 #define HCLK 100
2
3 void jz2440_lcd_pin_init(void)
4 {
5 /* 初始化引脚 : 背光引脚 */
6 GPBCON &= ~0x3;
7 GPBCON |= 0x01;
8
9 /* LCD专用引脚 */
10 GPCCON = 0xaaaaaaaa;
11 GPDCON = 0xaaaaaaaa;
12
13 /* PWREN */
14 GPGCON |= (3<<8);
15 }
16
17
18 /* 根据传入的LCD参数设置LCD控制器 */
19 void s3c2440_lcd_controller_init(p_lcd_params plcdparams)
20 {
21 int pixelplace;
22 unsigned int addr;
23
24 jz2440_lcd_pin_init();
25
26 /* [17:8]: clkval, vclk = HCLK / [(CLKVAL+1) x 2]
27 * 9 = 100M /[(CLKVAL+1) x 2], clkval = 4.5 = 5
28 * CLKVAL = 100/vclk/2-1
29 * [6:5]: 0b11, tft lcd
30 * [4:1]: bpp mode
31 * [0] : LCD video output and the logic enable/disable
32 */
33 int clkval = (double)HCLK/plcdparams->time_seq.vclk/2-1+0.5;
34 int bppmode = plcdparams->bpp == 8 ? 0xb :\
35 plcdparams->bpp == 16 ? 0xc :\
36 0xd; /* 0xd: 24bpp */
37 LCDCON1 = (clkval<<8) | (3<<5) | (bppmode<<1) ;
38
39 /* [31:24] : VBPD = tvb - 1
40 * [23:14] : LINEVAL = line - 1
41 * [13:6] : VFPD = tvf - 1
42 * [5:0] : VSPW = tvp - 1
43 */
44 LCDCON2 = ((plcdparams->time_seq.tvb - 1)<<24) | \
45 ((plcdparams->yres - 1)<<14) | \
46 ((plcdparams->time_seq.tvf - 1)<<6) | \
47 ((plcdparams->time_seq.tvp - 1)<<0);
48
49 /* [25:19] : HBPD = thb - 1
50 * [18:8] : HOZVAL = 列 - 1
51 * [7:0] : HFPD = thf - 1
52 */
53 LCDCON3 = ((plcdparams->time_seq.thb - 1)<<19) | \
54 ((plcdparams->xres - 1)<<8) | \
55 ((plcdparams->time_seq.thf - 1)<<0);
56
57 /*
58 * [7:0] : HSPW = thp - 1
59 */
60 LCDCON4 = ((plcdparams->time_seq.thp - 1)<<0);
61
62 /* 用来设置引脚极性, 设置16bpp, 设置内存中象素存放的格式
63 * [12] : BPP24BL
64 * [11] : FRM565, 1-565
65 * [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
66 * [9] : HSYNC是否反转
67 * [8] : VSYNC是否反转
68 * [7] : INVVD, rgb是否反转
69 * [6] : INVVDEN
70 * [5] : INVPWREN
71 * [4] : INVLEND
72 * [3] : PWREN, LCD_PWREN output signal enable/disable
73 * [2] : ENLEND
74 * [1] : BSWP
75 * [0] : HWSWP
76 */
77
78 pixelplace = plcdparams->bpp == 24 ? (0) : |\
79 plcdparams->bpp == 16 ? (1) : |\
80 (1<<1); /* 8bpp */
81 LCDCON5 = (plcdparams->pins_pol.vclk<<10) |\
82 (plcdparams->pins_pol.rgb<<7) |\
83 (plcdparams->pins_pol.hsync<<9) |\
84 (plcdparams->pins_pol.vsync<<8) |\
85 (plcdparams->pins_pol.de<<6) |\
86 (plcdparams->pins_pol.pwren<<5) |\
87 (1<<11) | pixelplace;
88
89 /* framebuffer地址 */
90 /*
91 * [29:21] : LCDBANK, A[30:22] of fb
92 * [20:0] : LCDBASEU, A[21:1] of fb
93 */
94 addr = plcdparams->fb_base & ~(1<<31);
95 LCDSADDR1 = (addr >> 1);
96
97 /*
98 * [20:0] : LCDBASEL, A[21:1] of end addr
99 */
100 addr = plcdparams->fb_base + plcdparams->xres*plcdparams->yres*plcdparams->bpp/8;
101 addr >>=1;
102 addr &= 0x1fffff;
103 LCDSADDR2 = addr;//
104 }
105
106 void s3c2440_lcd_controller_enalbe(void)
107 {
108 /* 背光引脚 : GPB0 */
109 GPBDAT |= (1<<0);
110
111 /* pwren : 给LCD提供AVDD */
112 LCDCON5 |= (1<<3);
113
114 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
115 LCDCON1 |= (1<<0);
116 }
117
118 void s3c2440_lcd_controller_disable(void)
119 {
120 /* 背光引脚 : GPB0 */
121 GPBDAT &= ~(1<<0);
122
123 /* pwren : 给LCD提供AVDD */
124 LCDCON5 &= ~(1<<3);
125
126 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
127 LCDCON1 &= ~(1<<0);
128 }
129
130 struct lcd_controller s3c2440_lcd_controller = {
131 .name = "s3c2440",
132 .init = s3c2440_lcd_controller_init,
133 .enalbe = s3c2440_lcd_controller_enalbe,
134 .disable = s3c2440_lcd_controller_disable,
135 };
136
137
138 void s3c2440_lcd_contoller_add(void)
139 {
140 register_lcd_controller(&s3c2440_lcd_controller);
141 }