如何添加一个新的LCD驱动

平台:mt65852 + Android 4.4 屏:HX8389B


那么首先来看的是如何配置lcd屏(在mtk中叫做lcm)。
1. ProjectConfig.mk中配置

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. CUSTOM_LK_LCM = hx8389b_qhd_dsi_vdo  
  2. CUSTOM_KERNEL_LCM = hx8389b_qhd_dsi_vdo  
  3.   
  4. LCM_HEIGHT = 960  
  5. LCM_WIDTH = 540  
那么相应的开机logo也要做相应的修改:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. BOOT_LOGO = cu_qhd  

2. 修改mt65xx_lcm_list.c
那么先在mediatek/custom/common/kernel/lcm目录中创建一个目录hx8389b_qhd_dsi_vdo(注意,目录的名字要和ProjectConfig.mk中的lcm配置相对应),然后在该目录下创建一个文件hx8389b_qhd_dsi_vdo.c,至于这个文件里面应该填些什么内容,我们稍后来看。

然后修改mt65xx_lcm_list.c,依照已有的格式在lcm_driver_list这个数组里面添加下面的内容:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #if defined(HX8389B_QHD_DSI_VDO)  
  2.     &hx8389b_qhd_dsi_vdo_drv,  
  3. #endif  
那么在这个数组的上面肯定还需要声明一下hx8389b_qhd_dsi_vdo_drv。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. extern LCM_DRIVER hx8389b_qhd_dsi_vdo_drv;  

3. 编写hx8389b_qhd_dsi_vdo.c
根据前面步骤可以看到,肯定需要一个hx8389b_qhd_dsi_vdo_drv这个结构,它的类型是LCM_DRIVER,来看一下应该怎么定义:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. LCM_DRIVER hx8389b_qhd_dsi_vdo_drv = {  
  2.     .name       = "hx8389b_qhd_dsi_vdo",  
  3.     .set_util_funcs = lcm_set_util_funcs,  
  4.     .get_params = lcm_get_params,  
  5.     .init       = lcm_init,  
  6.     .suspend    = lcm_suspend,  
  7.     .resume     = lcm_resume,  
  8.     .compare_id = lcm_compare_id,  
  9. };  

那么hx8389b_qhd_dsi_vdo_drv这个结构是定义好了,那么接下来是要实现结构体中定义的接口函数了。

先来看lcm_set_util_funcs这个函数:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static LCM_UTIL_FUNCS lcm_util;  
  2.   
  3. static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)  
  4. {  
  5.     memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));  
  6. }  
在lcm_set_util_funcs这个函数中将util的内容复制给了lcm_util。那么在LCM_UTIL_FUNCS这个类型中,主要定义了一些接口函数,这些接口函数是mtk提供给lcm驱动开发者使用的,所以说不管是哪一款lcm驱动,都需要这么一个接口,而且需要实现set_util_funcs接口,然后在mtk lcm核心部分自然会调用这个接口函数,这样我们就可以使用其中的接口函数了。

再来看lcm_get_params。
lcm_get_params函数中主要是一些参数定义,例如屏的分辨率,屏的接口类型等等:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #define FRAME_WIDTH 540  
  2. #define FRAME_HEIGHT    960  
  3.   
  4. static void lcm_get_params(LCM_PARAMS *params)  
  5. {  
  6.     memset(params, 0, sizeof(LCM_PARAMS));  
  7.       
  8.     params->type             = LCM_TYPE_DSI;         /* lcm的接口类型 */  
  9.     params->width                = FRAME_WIDTH;          /* lcm分辨率 */  
  10.     params->height               = FRAME_HEIGHT;  
  11.       
  12.     params->dsi.mode         = SYNC_PULSE_VDO_MODE;      /* video mode */  
  13.       
  14.     params->dsi.LANE_NUM         = LCM_THREE_LANE;       /* lanes */  
  15.     params->dsi.data_format.format       = LCM_DSI_FORMAT_RGB888;    /* 数据格式 */  
  16.       
  17.     params->dsi.PS               = LCM_PACKED_PS_24BIT_RGB888;  
  18.       
  19.     params->dsi.vertical_sync_active = 0x02;             /* video mode需要配置的一些参数 */  
  20.     params->dsi.vertical_backporch       = 0x0e;  
  21.     params->dsi.vertical_frontporch      = 0x09;  
  22.     params->dsi.vertical_active_line = FRAME_HEIGHT;  
  23.       
  24.     params->dsi.horizontal_sync_active   = 0x21;  
  25.     params->dsi.horizontal_backporch = 0x21;  
  26.     params->dsi.horizontal_frontporch    = 0x15;  
  27.     params->dsi.horizontal_active_pixel  = FRAME_WIDTH;  
  28.       
  29.     params->dsi.PLL_CLOCK            = 180;              /* clock(MHz) */  
  30. }  

再来看lcm_init:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))  
  2.   
  3. #define UDELAY(n) (lcm_util.udelay(n))  
  4. #define MDELAY(n) (lcm_util.mdelay(n))  
  5.   
  6. #define dsi_set_cmdq_V3(para_tbl, size, force_update)       lcm_util.dsi_set_cmdq_V3(para_tbl, size, force_update)  
  7. #define dsi_set_cmdq_V2(cmd, count ppara, force_update)     lcm_util.dsi_set_cmdq_V2(cmd, count, ppare, force_update)  
  8. #define dsi_set_cmdq(pdata, queue_size, force_update)       lcm_util.dsi_set_cmdq(pdata, queue_size, force_update)  
  9. #define write_cmd(cmd)                      lcm_util.dsi_write_cmd(cmd)  
  10. #define write_regs(addr, pdata, byte_nums)          lcm_util.dsi_write_regs(addr, pdata, bytes_nums)  
  11. #define read_reg(cmd)                       lcm_util.dsi_dcs_read_lcm_reg(cmd)  
  12. #define read_reg_v2(cmd, buffer, buffer_size)           lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size)  
  13.   
  14. static LCM_setting_table_V3 lcm_initialization_setting[] = {  
  15.     {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x03}},  
  16.     {0x39, 0x90, 9, {0x05, 0x14, 0x05, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00}},  
  17.     {0x39, 0x91, 9, {0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00}},  
  18.     {0x39, 0x92, 11, {0x40, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x54, 0x00, 0x00, 0x05, 0x08}},  
  19.     {0x39, 0x94, 8, {0x00, 0x08, 0x05, 0x03, 0xCE, 0x03, 0xD0, 0x0C}},  
  20.     {0x39, 0x95, 16, {0x40, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x10, 0x00, 0x54, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08}},  
  21.     {0x39, 0x99, 2, {0x00, 0x00}},  
  22.     {0x39, 0x9A, 11, {0x80, 0x0D, 0x03, 0xD2, 0x03, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x50}},  
  23.     {0x39, 0x9B, 6, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},  
  24.     {0x39, 0x9C, 2, {0x00, 0x00}},  
  25.     {0x39, 0x9D, 8, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}},  
  26.     {0x39, 0x9E, 2, {0x00, 0x00}},  
  27.     {0x39, 0xA0, 10, {0x95, 0x14, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0B, 0x1F}},  
  28.     {0x39, 0xA1, 10, {0x1F, 0x1F, 0x09, 0x1F, 0x1F, 0x1F, 0x0F, 0x1F, 0x1F, 0x1F}},  
  29.     {0x39, 0xA2, 10, {0x0D, 0x1F, 0x01, 0x1F, 0x03, 0x1F, 0x1F, 0x1F, 0x05, 0x1F}},  
  30.     {0x39, 0xA3, 10, {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}},  
  31.     {0x39, 0xA4, 10, {0x1F, 0x04, 0x1F, 0x1F, 0x1F, 0x02, 0x1F, 0x00, 0x1F, 0x0C}},  
  32.     {0x39, 0xA5, 10, {0x1F, 0x1F, 0x1F, 0x0E, 0x1F, 0x1F, 0x1F, 0x08, 0x1F, 0x1F}},  
  33.     {0x39, 0xA6, 10, {0x1F, 0x0A, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x14, 0x15}},  
  34.     {0x39, 0xA7, 10, {0x14, 0x15, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0C, 0x1F}},  
  35.     {0x39, 0xA8, 10, {0x1F, 0x1F, 0x0E, 0x1F, 0x1F, 0x1F, 0x08, 0x1F, 0x1F, 0x1F}},  
  36.     {0x39, 0xA9, 10, {0x0A, 0x1F, 0x02, 0x1F, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x04}},  
  37.     {0x39, 0xAA, 10, {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}},  
  38.     {0x39, 0xAB, 10, {0x1F, 0x05, 0x1F, 0x1F, 0x1F, 0x01, 0x1F, 0x03, 0x1F, 0x0B}},  
  39.     {0x39, 0xAC, 10, {0x1F, 0x1F, 0x1F, 0x09, 0x1F, 0x1F, 0x1F, 0x0F, 0x1F, 0x1F}},  
  40.     {0x39, 0xAD, 10, {0x1F, 0x0D, 0x1F, 0x1F, 0x1F, 0x02, 0x1F, 0x1F, 0x15, 0x14}},  
  41.     {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x00}},  
  42.     {0x15, 0xFC, 1, {0x00}},  
  43.     {0x39, 0xBC, 3, {0x00, 0x00, 0x00}},  
  44.     {0x39, 0xB8, 4, {0x01, 0x8F, 0xBF, 0x80}},  
  45.     {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x01}},  
  46.     {0x39, 0xD1, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}},  
  47.     {0x39, 0xD2, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}},  
  48.     {0x39, 0xD3, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}},  
  49.     {0x39, 0xD4, 4, {0x03, 0xEE, 0x03, 0xFF}},  
  50.     {0x39, 0xD5, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}},  
  51.     {0x39, 0xD6, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}},  
  52.     {0x39, 0xD7, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}},  
  53.     {0x39, 0xD8, 4, {0x03, 0xEE, 0x03, 0xFF}},  
  54.     {0x39, 0xD9, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}},  
  55.     {0x39, 0xDD, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}},  
  56.     {0x39, 0xDE, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}},  
  57.     {0x39, 0xDF, 4, {0x03, 0xEE, 0x03, 0xFF}},  
  58.     {0x39, 0xE0, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}},  
  59.     {0x39, 0xE1, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}},  
  60.     {0x39, 0xE2, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}},  
  61.     {0x39, 0xE3, 4, {0x03, 0xEE, 0x03, 0xFF}},  
  62.     {0x39, 0xE4, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}},  
  63.     {0x39, 0xE5, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}},  
  64.     {0x39, 0xE6, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}},  
  65.     {0x39, 0xE7, 4, {0x03, 0xEE, 0x03, 0xFF}},  
  66.     {0x39, 0xE8, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}},  
  67.     {0x39, 0xE9, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}},  
  68.     {0x39, 0xEA, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}},  
  69.     {0x39, 0xEB, 4, {0x03, 0xEE, 0x03, 0xFF}},  
  70.     {0x39, 0xB0, 3, {0x05, 0x05, 0x05}},  
  71.     {0x39, 0xB1, 3, {0x05, 0x05, 0x05}},  
  72.     {0x39, 0xB6, 3, {0x44, 0x44, 0x44}},  
  73.     {0x39, 0xB7, 3, {0x34, 0x34, 0x34}},  
  74.     {0x39, 0xB3, 3, {0x12, 0x12, 0x12}},  
  75.     {0x39, 0xB9, 3, {0x34, 0x34, 0x34}},  
  76.     {0x39, 0xB4, 3, {0x06, 0x06, 0x06}},  
  77.     {0x39, 0xBA, 3, {0x14, 0x14, 0x14}},  
  78.     {0x39, 0xBC, 3, {0x00, 0x98, 0x00}},  
  79.     {0x39, 0xBD, 3, {0x00, 0x98, 0x00}},  
  80.     {0x15, 0xBE, 1, {0x5A}},//60  
  81.     {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x02}},  
  82.     {0x39, 0xF6, 2, {0xCA, 0x69}},  
  83.     {0x39, 0xFB, 3, {0x09, 0x03, 0x08}},  
  84.     {0x39, 0xF1, 3, {0x22, 0x22, 0x32}},  
  85.     {0x15, 0x35, 1, {0x00}},  
  86.   
  87.     {0x05, 0x11,0,{0x00}},  
  88.     {REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 200, {}},  
  89.     {0x05, 0x29,0,{0x00}},  
  90.     {REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 10, {}},  
  91. };  
  92.   
  93. static void lcm_init(void)  
  94. {  
  95.     SET_RESET_PIN(0);  
  96.     MDELAY(20);  
  97.     SET_RESET_PIN(1);  
  98.     MDELAY(120);  
  99.     dsi_set_cmdq_V3(lcm_initialization_setting, sizeof(lcm_initialization_setting)/sizeof(lcm_initialization_setting[0]), 1);  
  100. }  
要理解这部分代码,需要稍微了解一下mipi dsi协议。
mipi dsi协议中主要有两种packet,long packet和short packet。short packet长度为固定的4个字节,而long packet长度为6~65541(4+(0~65535)+2)字节。
short packet格式如下:

long packet格式如下:


不管是long packet还是short packet,都有个DATA ID字段,高两位我们先忽略,而低六位为Data Type,mipi dsi协议中有专门定义,这里暂时用到的有:

0x05	Short WRITE,无参数
0x15	Short WRITE,带一个参数
0x39	Long WRITE

详细的Data Type可以参见mipi dsi手册。

我们看在lcm_initialization_setting数组中,第一个值就是这里的Data Type,而第二个值则是hx8389b寄存器的地址,而第三个参数则是参数的个数,而最后才是参数值。

hx8389b的datasheet也给出了两个例子,例如:

05h CMD 0   ECC		05h 29h 00  1Ch (display on(29h))
15h CMD Par ECC		15h 36h 08h 11h (MADCTL(36h)-BGR bit=1)

我们可以看出lcm_init同它的名字一样,主要是对屏做初始化操作。

再来看lcm_suspend和lcm_resume。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static void lcm_suspend(void)  
  2. {  
  3.     unsigned int data_array[16];  
  4.       
  5.     data_array[0] = 0x00100500;  
  6.     dsi_set_cmdq(data_array, 1, 1);  
  7.     MDELAY(120);  
  8.       
  9.     SET_RESET_PIN(1);  
  10.     SET_RESET_PIN(0);  
  11.     MDELAY(20);  
  12.       
  13.     SET_RESET_PIN(1);  
  14.     MDELAY(120);  
  15. }  
  16.   
  17. static void lcm_resume(void)  
  18. {  
  19.     lcm_init();  
  20. }  
在lcm_suspend函数中,我们主要来看dsi_set_cmdq这部分。
如果是short packet,那么数组的第一个元素定义如下:
bits	8~15	16~23	24~31
	DATA_ID	DATA_0	DATA_1

所以,前面data_array[0] = 0x00100500对应的是一个不带参数的short packet,寄存器地址是0x10,下发的指令意思是进入sleep模式(可以参见hx8389b的数据手册)。

如果是long packet,那么数组的第一个元素定义如下:

bits	8~15	16~23
	DATA_ID	DATA_0

注意,在long packet中,DATA_0表示的是Word Count的低8位。

最后来看那个lcm_compare_id函数。
compare_id函数对于lcm驱动来说不是必须的,但最好加上。这个函数主要是用于兼容lcm时,lcm核心会调用该函数来匹配lcm驱动和屏。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #define LCM_ID_HX8389B 0x89  
  2.   
  3. static unsigned int lcm_compare_id(void)  
  4. {  
  5.     unsigned int id = 0;  
  6.     unsigned char buffer[2];  
  7.     unsigned int array[16];  
  8.       
  9.     SET_RESET_PIN(1);  
  10.     SET_RESET_PIN(0);  
  11.     MDELAY(1);  
  12.     SET_RESET_PIN(1);  
  13.     MDELAY(10);  
  14.       
  15.     array[0] = 0x00023700;  
  16.     dsi_set_cmdq(array, 1, 1);  
  17.     MDELAY(10);  
  18.       
  19.     read_reg_v2(0x04, buffer, 2);  
  20.     id = buffer[1];  
  21.       
  22.     return (id == LCM_ID_HX8389B) ? 1 : 0;  
  23. }  
这里也涉及到了mipi dsi协议:

0x37	Set Maximum Return Packet Size
0x06	DCS READ, no parameters

read_reg_v2第一个参数为读寄存器的地址。


参考文档:
1. MIPI_DSI_Specification_V1.02.00.pdf
2. HX8389-B_DS_Temporary_General_v00_20120109.pdf
3. MT6582_LCM_Porting_Guide_DSI_V1.0.pptx.pdf


// 2016-03-17 add

Command and Video Modes

兼容MIPI DSI协议的外设都支持Command Mode和Video Mode两种操作模式,具体使用哪一种操作模式由具体的外设架构决定,那么这两种操作模式它们有什么区别呢。

Video Mode:
这种操作模式同传统的RGB接口类似,主控制器需要实时的往显示屏上刷新像素数据,因为数据流一般比较大,这种模式只能工作在高速率模式下。这种模式是不需要带有显存的。

Video Mode同样也包含一些简单的命令操作,例如屏的初始化、屏的打开、关闭等等,这个时候是工作在低速模式下的。

Video Mode主要又有三种模式:
1. Non-burst Mode Sync pulses
2. Non-burst Mode Sync event
3. Burst mode

Command Mode:
MIPI主控制器通过命令集往显示器发送像素数据流,所以这种模式必须要有一个显存(frame buffer)用来存储像素数据。

参考:MIPI_DSI_Specification_V1.02.00.pdf
http://www.electronicproducts.com/Analog_Mixed_Signal_ICs/Communications_Interface/MIPI_display_standards_for_mobile_Internet_devices.aspx


附:HX8389B Datasheet下载地址:http://download.csdn.net/detail/mcgrady_tracy/8327585

2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值