在x210上编写lcd驱动

2023-10-31 12:10
文章标签 驱动 编写 lcd x210

本文主要是介绍在x210上编写lcd驱动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前提准备:

1、将video/samsung/s3cfb.c文件s3cfb_probe函数里的内容注释掉,目的是去掉原来的lcd驱动。

2、将/drivers/gpu/pvr的Makefile里的obj-$(CONFIG_ARCH_S5PV210) += s3c_bc.o 注释掉,在s3c_bc.c文件S3C_BC_Register函数里使用到registered_fb,但我们上一步将原来的lcd驱动去掉,所以不应该链接这个文件,否则会出现段错误。如下图。

3、重新编译内核

二、驱动编写流程

1、首先先把总线平台框架编写好、在probe函数里按下面顺序编写

1)、lcd电源设置.

2)、分配fb_info

3)、设置fb_info

4)、lcd io口映射、设置

5)、lcd 时钟设置

6)、lcd 控制器映射、设置

7)、打开lcd控制器&&背光

8)、注册

9)、测试

2、分析

2.1、lcd电源设置。

要使用lcd控制器,首先要设置lcd的电源,linux内核是通过Regulator管理电源。若不设置的话,无法操作lcd控制器的寄存器。这里涉及到三个函数,regulator_get()、regulator_is_enabled()、regulator_enable()。

struct regulator *regulator_get(struct device *dev, const char *id):获取该驱动对应的regulator

struct device *dev:驱动对应的设备指针

const char *id:电源id

如:regulator_get(&pdev->dev, "pd") 。  &pdev->dev:总线平台的驱动,驱动的init_name,要和power_domain.c的s5pv210_pd_lcd_supply的dev_name设置一样。 "pd":要和power_domain.c的s5pv210_pd_lcd_supply的supply匹配。如下图。

int regulator_is_enabled(struct regulator *regulator):通过此接口判断电源输出是否已被使能。返回值大于0时已使能。

int regulator_enable(struct regulator *regulator):使能电源

代码如下:

	/******************************************1、lcd电源设置********************************************/lcd_regulator = regulator_get(&pdev->dev, "pd");//获取该驱动对应的regulatorprintk("lcd_regulator = %p \n",lcd_regulator);if (!lcd_regulator) {printk("failed to get lcd_regulator\n");ret = -EINVAL;}ret = regulator_is_enabled(lcd_regulator);//通过此接口判断电源输出是否已被使能。返回值大于0时已使能。printk("ret = %d \n",ret);if(ret == 0){ret = regulator_enable(lcd_regulator);//使能lcd电源输出。if (ret < 0) {printk("failed to enable regulator\n");ret = -EINVAL;}}

2.2、分配fb_info

lcd_info = framebuffer_alloc(0,NULL);

2.3、设置fb_info

	strcpy(lcd_info->fix.id,"s5p-lcd");
//	lcd_info->fix.smem_start =  //显存物理地址lcd_info->fix.smem_len = 1024*600*4;//显存大小lcd_info->fix.type = FB_TYPE_PACKED_PIXELS;lcd_info->fix.visual = FB_VISUAL_TRUECOLOR;//真彩色lcd_info->fix.line_length = 1024*4;//每行的字节数lcd_info->var.xres = 1024;//lcd宽度lcd_info->var.yres = 600;//lcd高度lcd_info->var.xres_virtual = 1024;//虚拟屏幕的宽度lcd_info->var.yres_virtual = 600;//虚拟屏幕的高度lcd_info->var.bits_per_pixel = 32;//bpp, ALPHA0-R-G-Blcd_info->var.red.length = 8;//位宽lcd_info->var.red.offset = 16;//偏移lcd_info->var.green.length = 8;lcd_info->var.green.offset = 8;lcd_info->var.blue.length = 8;lcd_info->var.blue.offset = 0;lcd_info->var.transp.offset = 24;lcd_info->var.transp.length = 8;lcd_info->var.activate = FB_ACTIVATE_NOW;/*设置操作函数*/lcd_info->fbops = &s3cfb_ops;lcd_info->pseudo_palette = pseudo_palette;/* Fake palette of 16 colors */ //调试板//lcd_info->screen_base = //显存虚拟大小lcd_info->screen_size = 1024*600*4;//显存虚拟大小

2.4、lcd io口映射、设置。

背光引脚GPD0_0

设置显示模式RGB=FIMD

代码如下:

	/******************************************4、lcd io口映射、设置******************************************/// 配置引脚用于LCD功能GPF0_0-GPF3_5// 背光引脚	GPD0_0(PWMTOUT0)gpf0_con = ioremap(0xE0200120, 4);//GPF0_CONif (!gpf0_con) {printk(KERN_ERR "failed to request io GPF0_CON\n");ret = -EINVAL;return ret;}gpf1_con = ioremap(0xE0200140 , 4);//GPF1_CONif (!gpf1_con) {printk(KERN_ERR "failed to request io GPF1_CON\n");ret = -EINVAL;return ret;}gpf2_con = ioremap(0xE0200160 , 4);//GPF2_CONif (!gpf2_con) {printk(KERN_ERR "failed to request io GPF2_CON\n");ret = -EINVAL;return ret;}gpf3_con = ioremap(0xE0200180 , 4);//GPF3_CONif (!gpf3_con) {printk(KERN_ERR "failed to request io GPF3_CON\n");ret = -EINVAL;return ret;}gpd0_con = ioremap(0xE02000A0 , 8);//GPD0_CONif (!gpd0_con) {printk(KERN_ERR "failed to request io GPD0_CON\n");ret = -EINVAL;return ret;}gpd0_dat = gpd0_con + 1;//GPD0_DAT//配置lcd引脚*gpf0_con = 0x22222222;*gpf1_con = 0x22222222;*gpf2_con = 0x22222222;*gpf3_con = 0x22222222;//配置背光引脚*gpd0_con &= ~(0xf<<0);*gpd0_con |= (1<<0);	*gpd0_dat |= (1<<0);//关闭背光display_con = ioremap(0xE0107008, 4);if (!display_con) {printk(KERN_ERR  "failed to remap display_con\n");ret = -EINVAL;}/*DISPLAY_CONTROL  0xE010_7008* DISPLAY_PATH_SEL [1:0] --> 10: RGB=FIMD I80=FIMD ITU=FIMD //Display path selection*/*display_con = 2<<0;//显示模式RGB=FIMD

2.5、lcd 时钟设置。

lcd的时钟源可以选择HCLK或者SCLK_FIMD。这里选择SCLK_FIMD。

struct clk *clk_get(struct device *dev, const char *id):获取XXX时钟结构体

unsigned long clk_get_rate(struct clk *clk):获取时钟的频率

int clk_set_parent(struct clk *clk, struct clk *parent):设置XXX时钟的时钟源,也就是从哪里分频。

int clk_set_rate(struct clk *clk, unsigned long rate):设置时钟频率

int clk_enable(struct clk *clk):使能时钟

	/******************************************5、lcd 时钟设置******************************************/	lcd_clk = clk_get(NULL, "sclk_fimd"); //获取sclk_fimd域的时钟clk结构体if (!lcd_clk || IS_ERR(lcd_clk)) {  printk(KERN_INFO "failed to get lcd clock source\n");  }  new_rate = clk_get_rate(lcd_clk);//获取sclk_fimd域当前的时钟频率printk(KERN_INFO "old_rate = %d \n",new_rate);  clk_set_parent(lcd_clk, clk_get(NULL, "mout_mpll"));//设置sclk_fimd域的时钟源mout_mpllclk_set_rate(lcd_clk, 166750000);//设置sclk_fimd域的时钟频率为166MHZclk_enable(lcd_clk);//使能时钟

2.6、lcd 控制器映射、设置。

s5pv210有0-4屏幕选择,我选择的是屏幕2。

主要设置的寄存器有:VIDCON0、VIDCON1、VIDTCON0、VIDTCON1、VIDTCON2、WINCON2、VIDOSD2A、VIDOSD2B、VIDOSD2D、VIDW02ADD0、VIDW02ADD1、VIDW02ADD2

VIDCON0:设置lcd时钟源为SCLK_FIMD,CLKVAL_F = 1选择对lcd时钟进行分频,CLKVAL = 3,则VCLK = 166M/(1+3) = 41.5MHZ。

VIDCON1:IHSYNC和IVSYNC设为1,即 HSYNC 和 VSYNC极性翻转,看lcd屏幕的手册。

VIDTCON0:帧同步信号。VBPD、VFPD、VSPW值设置

VIDTCON1:行同步信号。HBPD、HFPD、HSPW值设置

VIDTCON2:LINEVAL、HOZVAL设置。具体的值如下面的图。

WINCON2:ALPHA_SEL_F = 1,24位到32位用来存放透明度值;BPPMODE_F =1101,Unpacked 25 bpp ( non-palletized A:1-R:8-G:8-B:8 );BLD_PIX_F = 1,透明度混合。WSWP_F = 1,Swap Enable,显存的低位放低字节。看下图。

VIDOSD2A:显存左上角的XY坐标。

VIDOSD2B:显存右下角的XY坐标。

VIDOSD2D:屏幕大小。

VIDW02ADD0:显存地址,一定是要映射后的,不能直接操作物理地址。用这个函数dma_alloc_writecombine映射。

VIDW02ADD1:显存长度, 字节单位

VIDW02ADD2:PAGEWIDTH_F:屏幕宽度(字节);OFFSIZE_F: 屏幕显示的位置在虚拟显存的位置。

                                                           这里我的lcd屏幕的时序参数表

当WINCON2的WSWP_F置1后,低位放在显存的低字节里。PXXX表示RGB、ALPHA value表示透明度值。

	//lcd控制器res = request_mem_region(S5P_PA_LCD,S5P_SZ_LCD, "s5p-lcd");if (!res) {printk(KERN_ERR "failed to request io memory region\n");ret = -EINVAL;}lcd_regs = ioremap(S5P_PA_LCD, S5P_SZ_LCD);if (!lcd_regs) {printk(KERN_ERR  "failed to remap io region\n");ret = -EINVAL;}printk(KERN_INFO  "lcd_regs = %p \n",lcd_regs);lcd_debug();//当前寄存器值查看/*VIDCON0 * DSI_EN [30] 	   --> 0  = disable MIPI DSI. * VIDOUT [28:26]  --> 000  = RGB interface * RGSPSEL [18]    --> 0  = RGB parallel format * CLKVAL_F [13:6] --> 3  = VCLK = HCLK / (CLKVAL+1),即VCLK = 166M/(1+3) = 41.5MHZ* CLKDIR [4] 	   --> 1 = Divided by CLKVAL_F ,选择对lcd时钟进行分频,若为0则不分频* CLKSEL_F [2]    --> 1 = SCLK_FIMD   Selects the video clock source. 0 = HCLK * ENVID [1]       --> 1 = Enables the video output and display control signal. //使能lcd控制器* ENVID_F [0]     -->1 = Enables the video output and display control signal. //当前帧结束后使能lcd控制器	 *	NOTE: Display On: ENVID and ENVID_F are set to “1”. Direct Off: ENVID and ENVID_F are set to “0” simultaneously. Per Frame Off: ENVID_F is set to “0” and ENVID is set to “1”. */cfg = (1<<2) | (1<< 4)| (3<<6);writel(cfg, lcd_regs + S3C_VIDCON0);/*VIDCON1 *IVCLK  [7]  -->0 = Video data is fetched at VCLK falling edge *IHSYNC [6]  -->1 = Inverted   Specifies the HSYNC pulse polarity  HSYNC极性翻转,看lcd屏幕的手册*IVSYNC [5]  -->1 = Inverted   Specifies the VSYNC pulse polarity. VSYNC极性翻转,看lcd屏幕的手册*IVDEN  [4]  -->0 = Normal     Specifies the VDEN signal polarity. */cfg = (1<<5) | (1<< 6);writel(cfg, lcd_regs + S3C_VIDCON1);/*VIDCON2 * RGB_ORDER_E [21:19]	--> 000 = RGB Even line* RGB_ORDER_O [18:16]  --> 000 = RGB  Odd Line*//*VIDTCON0 看lcd屏幕的手册,关于时序部分帧同步信号* VBPD [23:16] --> 17-1 = 16* VFPD [15:8] --> 12-1=11* VSPW [7:0] --> 3-1=2*/cfg =  ( (16<<16) | (11<<8) | (2<<0) );writel(cfg, lcd_regs + S3C_VIDTCON0);/*VIDTCON1 看lcd屏幕的手册,关于时序部分行同步信号* HBPD [23:16] --> 120-1=119* HFPD [15:8] --> 160-1=159* HSPW [7:0] --> 20-1=19*/cfg = ( (119<<16) | (159<<8) | (19<<0));writel(cfg, lcd_regs + S3C_VIDTCON1);/*VIDTCON2 * LINEVAL [21:11] --> 600-1=599 * HOZVAL [10:0] --> 1024-1*1023*/cfg =  ( (599<<11) | (1023<<0) );writel(cfg, lcd_regs + S3C_VIDTCON2);/*WINCON2 * InRGB [13] --> 0 = RGB 						* WSWP_F [15] -->1 = Swap Enable //Specifies the Word swap control bit. 显存的低位放低字节* BLD_PIX_F [6]  --> 1 = Per pixel blending //混合 * BPPMODE_F [5:2] --> *1101 = Unpacked 25 bpp ( non-palletized A:1-R:8-G:8-B:8 )* ALPHA_SEL_F [1]  -->1 = Using DATA[31:24] data in word boundary (only when BPPMODE_F = 4’b1101) 24位到32位用来存放透明度* ENWIN_F [0] -->1 = Enables the video output and video control signal. //Enables/ disables video output and logic immediately*/cfg = (1<<1) | (13<<2) | (1<<6) | (1<<15);writel(cfg, lcd_regs + S3C_WINCON2);/*WINCHMAP2 * CH0FISEL [18:16] --> 001 = Window 0  //Selects Channel 0’s channel. * W0FISEL [2:0] --> 001 = Channel 0  //Selects Window 0’s channel. 001 *//*VIDOSD2A   显存左上角的XY坐标* OSD_LeftTopX_F [21:11] --> 0* OSD_LeftTopY_F [10:0] --> 0*/cfg = (0<<11) | (0 << 0);writel(cfg, lcd_regs + S3C_VIDOSD2A);/*VIDOSD2B  显存右下角的XY坐标* OSD_RightBotX_F [21:11]  --> 1024 - 1 = 1023* OSD_RightBotY_F [10:0] --> 600 - 1 = 599*/cfg = ( (1023<<11) | (599<<0) );writel(cfg, lcd_regs + S3C_VIDOSD2B);/*VIDOSD2D  屏幕大小 * OSDSIZE [23:0] --> (1024) * (600)  //Specifies the Window Size */cfg = 1024*600;writel(cfg, lcd_regs + S3C_VIDOSD2D);	/*分配显存(framebuffer), 并把地址告诉LCD控制器 */lcd_info->screen_base = dma_alloc_writecombine(NULL, lcd_info->fix.smem_len,&lcd_info->fix.smem_start, GFP_KERNEL);printk(KERN_INFO  "lcd_info->fix.smem_start = %x \n",lcd_info->fix.smem_start);printk(KERN_INFO  "lcd_info->screen_base = %p \n",lcd_info->screen_base);/*VIDW02ADD0 显存的映射后的地址* VBASEL_F [31:0] -->显存地址 Specifies A [31:0] of the start address for Video frame buffer. */cfg = lcd_info->fix.smem_start;writel(cfg, lcd_regs + S3C_VIDW02ADD0);/*VIDW02ADD1 显存长度 1024*600*4 字节单位* VBASEU_F [31:0] -->((((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff)); //Specifies A [31:0] of the start address for Video frame buffer.*/	 cfg = lcd_info->fix.smem_len;writel(cfg, lcd_regs + S3C_VIDW02ADD1);/*VIDW02ADD2,  *OFFSIZE_F [25:13] --> 0  屏幕显示的位置在虚拟显存的位置*PAGEWIDTH_F [12:0] --> 1024 * 4 屏幕宽度(字节)*/cfg = (1024*4 << 0);writel(cfg, lcd_regs + S3C_VIDW02ADD2);

2.7、打开lcd控制器&&背光。

	/******************************************7、打开lcd控制器&&背光***********************************/	*gpd0_dat &= ~(1<<0);//打开背光/*SHODOWCON * W0_SHADOW _PROTECT [10] --> 0 = Updates shadow register per frame * C0_EN_F [2] --> 1 = Enables  //Enables Channel 2. 使能通道2传输*/cfg |= (1<<2);writel(cfg, lcd_regs + S3C_WINSHMAP);cfg = readl(lcd_regs + S3C_WINCON2);cfg |= (1<<0);writel(cfg, lcd_regs + S3C_WINCON2);cfg = readl(lcd_regs + S3C_VIDCON0);cfg |= ((1<<0) | (1<< 1));writel(cfg, lcd_regs + S3C_VIDCON0);

2.8、注册。

	/******************************************7、注册***********************************/	ret = register_framebuffer(lcd_info);printk(KERN_INFO  "register_framebuffer\n");

2.9、测试。

测试效果为,在屏幕上显示分三块,分别显示红绿蓝。

	/******************************************8、测试***********************************/	LCD_Fill(0,0,1024,200,0x00ff0000);LCD_Fill(0,200,1024,400,0x0000ff00);LCD_Fill(0,400,1024,600,0x000000ff);

三、全部代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/irq.h>
#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/memory.h>
#include <linux/cpufreq.h>
#include <plat/clock.h>
#include <plat/cpu-freq.h>
#include <plat/media.h>#ifdef CONFIG_HAS_WAKELOCK
#include <linux/wakelock.h>
#include <linux/earlysuspend.h>
#include <linux/suspend.h>
#endif
#include <mach/map.h>
#include <plat/regs-fb.h>struct regulator* lcd_regulator;
struct device	lcd_dev;
struct clk *lcd_clk; void __iomem	*lcd_regs;
struct fb_info* lcd_info;
static u32 pseudo_palette[16];static volatile unsigned int* gpf0_con;
static volatile unsigned int* gpf1_con;
static volatile unsigned int* gpf2_con;
static volatile unsigned int* gpf3_con;
static volatile unsigned int* gpd0_con;
static volatile unsigned int* gpd0_dat;
static volatile unsigned int* display_con;static int s5pfb_setcolreg(unsigned int regno, unsigned int red,unsigned int green, unsigned int blue,unsigned int transp, struct fb_info *fb);struct fb_ops s3cfb_ops = {.owner = THIS_MODULE,.fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,.fb_setcolreg = s5pfb_setcolreg,
};static unsigned int __chan_to_field(unsigned int chan,struct fb_bitfield bf)
{chan &= 0xffff;chan >>= 16 - bf.length;return chan << bf.offset;
}static int s5pfb_setcolreg(unsigned int regno, unsigned int red,unsigned int green, unsigned int blue,unsigned int transp, struct fb_info *fb)
{unsigned int val = 0;if (regno < 16) {val |= __chan_to_field(red, fb->var.red);val |= __chan_to_field(green, fb->var.green);val |= __chan_to_field(blue, fb->var.blue);val |= __chan_to_field(transp, fb->var.transp);pseudo_palette[regno] = val;}return 0;
}void LCD_Set_Point(unsigned int X_Pos,unsigned int Y_Pos,unsigned int color)
{*((unsigned int*)lcd_info->screen_base + Y_Pos*1024+X_Pos) = color;	
}//在指定区域内填充单个颜色
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
//color:要填充的颜色
void LCD_Fill(unsigned int sx,unsigned int sy,unsigned int ex,unsigned int ey,unsigned int color)
{          unsigned int i,j;unsigned int xlen=0;xlen=ex-sx;	 for(i=sy;i<ey;i++){for(j=0;j<xlen;j++)LCD_Set_Point(j,i,color);	//显示颜色 	    }
}  //lcd寄存器调试
void lcd_debug(void)
{printk("S3C_VIDCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDCON0)));printk("S3C_VIDCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDCON1)));printk("S3C_VIDCON2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDCON2)));printk("S3C_PRTCON = %x \n ",*((unsigned int*)(lcd_regs + S3C_PRTCON)));printk("S3C_VIDTCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDTCON0)));printk("S3C_VIDTCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDTCON1)));printk("S3C_VIDTCON2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDTCON2)));printk("S3C_WINCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_WINCON0)));printk("S3C_WINCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_WINCON1)));printk("S3C_WINCON2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_WINCON2)));printk("S3C_WINCON3 = %x \n ",*((unsigned int*)(lcd_regs + S3C_WINCON3)));printk("S3C_WINCON4 = %x \n ",*((unsigned int*)(lcd_regs + S3C_WINCON4)));printk("S3C_WINSHMAP = %x \n ",*((unsigned int*)(lcd_regs + S3C_WINSHMAP)));printk("S3C_VIDOSD0A = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD0A)));printk("S3C_VIDOSD0B = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD0B)));printk("S3C_VIDOSD0C = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD0C)));printk("S3C_VIDOSD1A = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD1A)));printk("S3C_VIDOSD1B = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD1B)));printk("S3C_VIDOSD1C = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD1C)));printk("S3C_VIDOSD1D = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD1D)));printk("S3C_VIDOSD2A = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD2A)));printk("S3C_VIDOSD2B = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD2B)));printk("S3C_VIDOSD2C = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD2C)));printk("S3C_VIDOSD2D = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD2D)));printk("S3C_VIDOSD3A = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD3A)));printk("S3C_VIDOSD3B = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD3B)));printk("S3C_VIDOSD3C = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD3C)));printk("S3C_VIDOSD4A = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD4A)));printk("S3C_VIDOSD4B = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD4B)));printk("S3C_VIDOSD4C = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDOSD4C)));printk("S3C_VIDW00ADD0B0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW00ADD0B0)));printk("S3C_VIDW00ADD0B1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW00ADD0B1)));printk("S3C_VIDW01ADD0B0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW01ADD0B0)));printk("S3C_VIDW01ADD0B1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW01ADD0B1)));printk("S3C_VIDW02ADD0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW02ADD0)));printk("S3C_VIDW03ADD0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW03ADD0)));printk("S3C_VIDW04ADD0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW04ADD0)));printk("S3C_VIDW00ADD1B0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW00ADD1B0)));printk("S3C_VIDW00ADD1B1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW00ADD1B1)));printk("S3C_VIDW01ADD1B0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW01ADD1B0)));printk("S3C_VIDW01ADD1B1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW01ADD1B1)));printk("S3C_VIDW02ADD1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW02ADD1)));printk("S3C_VIDW03ADD1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW03ADD1)));printk("S3C_VIDW04ADD1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW04ADD1)));printk("S3C_VIDW00ADD2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW00ADD2)));printk("S3C_VIDW01ADD2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW01ADD2)));printk("S3C_VIDW02ADD2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW02ADD2)));printk("S3C_VIDW03ADD2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW03ADD2)));printk("S3C_VIDW04ADD2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW04ADD2)));printk("S3C_VP1TCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VP1TCON0)));printk("S3C_VP1TCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VP1TCON1)));printk("S3C_VIDINTCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDINTCON0)));printk("S3C_VIDINTCON1 = %x \n ",*(((unsigned int*)lcd_regs + S3C_VIDINTCON1)));printk("S3C_W1KEYCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W1KEYCON0)));printk("S3C_W1KEYCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W1KEYCON1)));printk("S3C_W2KEYCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W2KEYCON0)));printk("S3C_W2KEYCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W2KEYCON1)));printk("S3C_W3KEYCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W3KEYCON0)));printk("S3C_W3KEYCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W3KEYCON1)));printk("S3C_W4KEYCON0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W4KEYCON0)));printk("S3C_W4KEYCON1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_W4KEYCON1)));printk("S3C_W1KEYALPHA = %x \n ",*((unsigned int*)(lcd_regs + S3C_W1KEYALPHA)));printk("S3C_W2KEYALPHA = %x \n ",*((unsigned int*)(lcd_regs + S3C_W2KEYALPHA)));printk("S3C_W3KEYALPHA = %x \n ",*((unsigned int*)(lcd_regs + S3C_W3KEYALPHA)));printk("S3C_W4KEYALPHA = %x \n ",*((unsigned int*)(lcd_regs + S3C_W4KEYALPHA)));printk("S3C_DITHMODE = %x \n ",*((unsigned int*)(lcd_regs + S3C_DITHMODE)));printk("S3C_WIN0MAP = %x \n ",*((unsigned int*)(lcd_regs + S3C_WIN0MAP)));printk("S3C_WIN1MAP = %x \n ",*((unsigned int*)(lcd_regs + S3C_WIN1MAP)));printk("S3C_WIN2MAP = %x \n ",*((unsigned int*)(lcd_regs + S3C_WIN2MAP)));printk("S3C_WIN3MAP = %x \n ",*((unsigned int*)(lcd_regs + S3C_WIN3MAP)));printk("S3C_WIN4MAP = %x \n ",*((unsigned int*)(lcd_regs + S3C_WIN4MAP)));printk("S3C_WPALCON_H = %x \n ",*((unsigned int*)(lcd_regs + S3C_WPALCON_H)));printk("S3C_WPALCON_L = %x \n ",*((unsigned int*)(lcd_regs + S3C_WPALCON_L)));printk("S3C_VIDW0ALPHA0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW0ALPHA0)));printk("S3C_VIDW0ALPHA1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW0ALPHA1)));printk("S3C_VIDW1ALPHA0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW1ALPHA0)));printk("S3C_VIDW1ALPHA1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW1ALPHA1)));printk("S3C_VIDW2ALPHA0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW2ALPHA0)));printk("S3C_VIDW2ALPHA1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW2ALPHA1)));printk("S3C_VIDW3ALPHA0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW3ALPHA0)));printk("S3C_VIDW3ALPHA1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW3ALPHA1)));printk("S3C_VIDW4ALPHA0 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW4ALPHA0)));printk("S3C_VIDW4ALPHA1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_VIDW4ALPHA1)));printk("S3C_BLENDEQ1 = %x \n ",*((unsigned int*)(lcd_regs + S3C_BLENDEQ1)));printk("S3C_BLENDEQ2 = %x \n ",*((unsigned int*)(lcd_regs + S3C_BLENDEQ2)));printk("S3C_BLENDEQ3 = %x \n ",*((unsigned int*)(lcd_regs + S3C_BLENDEQ3)));printk("S3C_BLENDEQ4 = %x \n ",*((unsigned int*)(lcd_regs + S3C_BLENDEQ4)));printk("S3C_BLENDCON = %x \n ",*((unsigned int*)(lcd_regs + S3C_BLENDCON)));
}static int s5pfb_probe(struct platform_device *pdev)
{int ret;struct resource *res;u32 cfg;long new_rate = 0;/******************************************1、lcd电源设置********************************************/lcd_regulator = regulator_get(&pdev->dev, "pd");//获取该驱动对应的regulatorprintk("lcd_regulator = %p \n",lcd_regulator);if (!lcd_regulator) {printk("failed to get lcd_regulator\n");ret = -EINVAL;}ret = regulator_is_enabled(lcd_regulator);//通过此接口判断电源输出是否已被使能。返回值大于0时已使能。printk("ret = %d \n",ret);if(ret == 0){ret = regulator_enable(lcd_regulator);//使能lcd电源输出。if (ret < 0) {printk("failed to enable regulator\n");ret = -EINVAL;}}/******************************************2、分配fb_info********************************************/lcd_info = framebuffer_alloc(0,NULL);/******************************************3、设置***************************************************/strcpy(lcd_info->fix.id,"s5p-lcd");
//	lcd_info->fix.smem_start =  //显存物理地址lcd_info->fix.smem_len = 1024*600*4;//显存大小lcd_info->fix.type = FB_TYPE_PACKED_PIXELS;lcd_info->fix.visual = FB_VISUAL_TRUECOLOR;//真彩色lcd_info->fix.line_length = 1024*4;//每行的字节数lcd_info->var.xres = 1024;//lcd宽度lcd_info->var.yres = 600;//lcd高度lcd_info->var.xres_virtual = 1024;//虚拟屏幕的宽度lcd_info->var.yres_virtual = 600;//虚拟屏幕的高度lcd_info->var.bits_per_pixel = 32;//bpp, ALPHA0-R-G-Blcd_info->var.red.length = 8;//位宽lcd_info->var.red.offset = 16;//偏移lcd_info->var.green.length = 8;lcd_info->var.green.offset = 8;lcd_info->var.blue.length = 8;lcd_info->var.blue.offset = 0;lcd_info->var.transp.offset = 24;lcd_info->var.transp.length = 8;lcd_info->var.activate = FB_ACTIVATE_NOW;/*设置操作函数*/lcd_info->fbops = &s3cfb_ops;lcd_info->pseudo_palette = pseudo_palette;/* Fake palette of 16 colors */ //调试板//lcd_info->screen_base = //显存虚拟大小lcd_info->screen_size = 1024*600*4;//显存虚拟大小/******************************************4、lcd io口映射、设置******************************************/// 配置引脚用于LCD功能GPF0_0-GPF3_5// 背光引脚	GPD0_0(PWMTOUT0)gpf0_con = ioremap(0xE0200120, 4);//GPF0_CONif (!gpf0_con) {printk(KERN_ERR "failed to request io GPF0_CON\n");ret = -EINVAL;return ret;}gpf1_con = ioremap(0xE0200140 , 4);//GPF1_CONif (!gpf1_con) {printk(KERN_ERR "failed to request io GPF1_CON\n");ret = -EINVAL;return ret;}gpf2_con = ioremap(0xE0200160 , 4);//GPF2_CONif (!gpf2_con) {printk(KERN_ERR "failed to request io GPF2_CON\n");ret = -EINVAL;return ret;}gpf3_con = ioremap(0xE0200180 , 4);//GPF3_CONif (!gpf3_con) {printk(KERN_ERR "failed to request io GPF3_CON\n");ret = -EINVAL;return ret;}gpd0_con = ioremap(0xE02000A0 , 8);//GPD0_CONif (!gpd0_con) {printk(KERN_ERR "failed to request io GPD0_CON\n");ret = -EINVAL;return ret;}gpd0_dat = gpd0_con + 1;//GPD0_DAT//配置lcd引脚*gpf0_con = 0x22222222;*gpf1_con = 0x22222222;*gpf2_con = 0x22222222;*gpf3_con = 0x22222222;//配置背光引脚*gpd0_con &= ~(0xf<<0);*gpd0_con |= (1<<0);	*gpd0_dat |= (1<<0);//关闭背光display_con = ioremap(0xE0107008, 4);if (!display_con) {printk(KERN_ERR  "failed to remap display_con\n");ret = -EINVAL;}/*DISPLAY_CONTROL  0xE010_7008* DISPLAY_PATH_SEL [1:0] --> 10: RGB=FIMD I80=FIMD ITU=FIMD //Display path selection*/*display_con = 2<<0;//显示模式RGB=FIMD/******************************************5、lcd 时钟设置******************************************/	lcd_clk = clk_get(NULL, "sclk_fimd"); //获取sclk_fimd域的时钟clk结构体if (!lcd_clk || IS_ERR(lcd_clk)) {  printk(KERN_INFO "failed to get lcd clock source\n");  }  new_rate = clk_get_rate(lcd_clk);//获取sclk_fimd域当前的时钟频率printk(KERN_INFO "old_rate = %d \n",new_rate);  clk_set_parent(lcd_clk, clk_get(NULL, "mout_mpll"));//设置sclk_fimd域的时钟源mout_mpllclk_set_rate(lcd_clk, 166750000);//设置sclk_fimd域的时钟频率为166MHZclk_enable(lcd_clk);//使能时钟new_rate = clk_get_rate(lcd_clk);printk(KERN_INFO "new_rate = %d \n",new_rate);  /******************************************6、lcd 控制器映射、设置***********************************/	//lcd控制器res = request_mem_region(S5P_PA_LCD,S5P_SZ_LCD, "s5p-lcd");if (!res) {printk(KERN_ERR "failed to request io memory region\n");ret = -EINVAL;}lcd_regs = ioremap(S5P_PA_LCD, S5P_SZ_LCD);if (!lcd_regs) {printk(KERN_ERR  "failed to remap io region\n");ret = -EINVAL;}printk(KERN_INFO  "lcd_regs = %p \n",lcd_regs);//lcd_debug();//当前寄存器值查看/*VIDCON0 * DSI_EN [30] 	   --> 0  = disable MIPI DSI. * VIDOUT [28:26]  --> 000  = RGB interface * RGSPSEL [18]    --> 0  = RGB parallel format * CLKVAL_F [13:6] --> 3  = VCLK = HCLK / (CLKVAL+1),即VCLK = 166M/(1+3) = 41.5MHZ* CLKDIR [4] 	   --> 1 = Divided by CLKVAL_F ,选择对lcd时钟进行分频,若为0则不分频* CLKSEL_F [2]    --> 1 = SCLK_FIMD   Selects the video clock source. 0 = HCLK * ENVID [1]       --> 1 = Enables the video output and display control signal. //使能lcd控制器* ENVID_F [0]     --> 1 = Enables the video output and display control signal. //当前帧结束后使能lcd控制器	 *	NOTE: Display On: ENVID and ENVID_F are set to “1”. Direct Off: ENVID and ENVID_F are set to “0” simultaneously. Per Frame Off: ENVID_F is set to “0” and ENVID is set to “1”. */cfg = (1<<2) | (1<< 4)| (3<<6);writel(cfg, lcd_regs + S3C_VIDCON0);/*VIDCON1 *IVCLK  [7]  -->0 = Video data is fetched at VCLK falling edge *IHSYNC [6]  -->1 = Inverted   Specifies the HSYNC pulse polarity  HSYNC极性翻转,看lcd屏幕的手册*IVSYNC [5]  -->1 = Inverted   Specifies the VSYNC pulse polarity. VSYNC极性翻转,看lcd屏幕的手册*IVDEN  [4]  -->0 = Normal     Specifies the VDEN signal polarity. */cfg = (1<<5) | (1<< 6);writel(cfg, lcd_regs + S3C_VIDCON1);/*VIDCON2 * RGB_ORDER_E [21:19]	--> 000 = RGB Even line* RGB_ORDER_O [18:16]  --> 000 = RGB  Odd Line*//*VIDTCON0 看lcd屏幕的手册,关于时序部分帧同步信号* VBPD [23:16] --> 17-1 = 16* VFPD [15:8] --> 12-1=11* VSPW [7:0] --> 3-1=2*/cfg =  ( (16<<16) | (11<<8) | (2<<0) );writel(cfg, lcd_regs + S3C_VIDTCON0);/*VIDTCON1 看lcd屏幕的手册,关于时序部分行同步信号* HBPD [23:16] --> 120-1=119* HFPD [15:8] --> 160-1=159* HSPW [7:0] --> 20-1=19*/cfg = ( (119<<16) | (159<<8) | (19<<0));writel(cfg, lcd_regs + S3C_VIDTCON1);/*VIDTCON2 * LINEVAL [21:11] --> 600-1=599 * HOZVAL [10:0] --> 1024-1*1023*/cfg =  ( (599<<11) | (1023<<0) );writel(cfg, lcd_regs + S3C_VIDTCON2);/*WINCON2 * InRGB [13] --> 0 = RGB 						* WSWP_F [15] -->1 = Swap Enable //Specifies the Word swap control bit. 显存的低位放低字节* BLD_PIX_F [6]  --> 1 = Per pixel blending //混合 * BPPMODE_F [5:2] --> *1101 = Unpacked 25 bpp ( non-palletized A:1-R:8-G:8-B:8 )* ALPHA_SEL_F [1]  -->1 = Using DATA[31:24] data in word boundary (only when BPPMODE_F = 4’b1101) 24位到32位用来存放透明度* ENWIN_F [0] -->1 = Enables the video output and video control signal. //Enables/ disables video output and logic immediately*/cfg = (1<<1) | (13<<2) | (1<<6) | (1<<15);writel(cfg, lcd_regs + S3C_WINCON2);/*WINCHMAP2 * CH0FISEL [18:16] --> 001 = Window 0  //Selects Channel 0’s channel. * W0FISEL [2:0] --> 001 = Channel 0  //Selects Window 0’s channel. 001 *//*VIDOSD2A   显存左上角的XY坐标* OSD_LeftTopX_F [21:11] --> 0* OSD_LeftTopY_F [10:0] --> 0*/cfg = (0<<11) | (0 << 0);writel(cfg, lcd_regs + S3C_VIDOSD2A);/*VIDOSD2B  显存右下角的XY坐标* OSD_RightBotX_F [21:11]  --> 1024 - 1 = 1023* OSD_RightBotY_F [10:0] --> 600 - 1 = 599*/cfg = ( (1023<<11) | (599<<0) );writel(cfg, lcd_regs + S3C_VIDOSD2B);/*VIDOSD2D  屏幕大小 * OSDSIZE [23:0] --> (1024) * (600)  //Specifies the Window Size */cfg = 1024*600;writel(cfg, lcd_regs + S3C_VIDOSD2D);	/*分配显存(framebuffer), 并把地址告诉LCD控制器 */lcd_info->screen_base = dma_alloc_writecombine(NULL, lcd_info->fix.smem_len,&lcd_info->fix.smem_start, GFP_KERNEL);printk(KERN_INFO  "lcd_info->fix.smem_start = %x \n",lcd_info->fix.smem_start);printk(KERN_INFO  "lcd_info->screen_base = %p \n",lcd_info->screen_base);/*VIDW02ADD0 显存的映射后的地址* VBASEL_F [31:0] -->显存地址 Specifies A [31:0] of the start address for Video frame buffer. */cfg = lcd_info->fix.smem_start;writel(cfg, lcd_regs + S3C_VIDW02ADD0);/*VIDW02ADD1 显存长度 1024*600*4 字节单位* VBASEU_F [31:0] -->((((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff)); //Specifies A [31:0] of the start address for Video frame buffer.*/	 cfg = lcd_info->fix.smem_len;writel(cfg, lcd_regs + S3C_VIDW02ADD1);/*VIDW02ADD2,  *OFFSIZE_F [25:13] --> 0  屏幕显示的位置在虚拟显存的位置*PAGEWIDTH_F [12:0] --> 1024 * 4 屏幕宽度(字节)*/cfg = (1024*4 << 0);writel(cfg, lcd_regs + S3C_VIDW02ADD2);/******************************************7、打开lcd控制器&&背光***********************************/	*gpd0_dat &= ~(1<<0);//打开背光/*SHODOWCON * W0_SHADOW _PROTECT [10] --> 0 = Updates shadow register per frame * C0_EN_F [2] --> 1 = Enables  //Enables Channel 2. 使能通道2传输*/cfg = (1<<2);writel(cfg, lcd_regs + S3C_WINSHMAP);cfg = readl(lcd_regs + S3C_WINCON2);cfg |= (1<<0);writel(cfg, lcd_regs + S3C_WINCON2);cfg = readl(lcd_regs + S3C_VIDCON0);cfg |= ((1<<0) | (1<< 1));writel(cfg, lcd_regs + S3C_VIDCON0);/******************************************7、注册***********************************/	ret = register_framebuffer(lcd_info);printk(KERN_INFO  "register_framebuffer\n");/******************************************8、测试***********************************/	LCD_Fill(0,0,1024,200,0x00ff0000);LCD_Fill(0,200,1024,400,0x0000ff00);LCD_Fill(0,400,1024,600,0x000000ff);//lcd_debug();return 0;
}static int  s5pfb_remove(struct platform_device *pdev)
{unregister_framebuffer(lcd_info);dma_free_writecombine(NULL,lcd_info->fix.smem_len, lcd_info->screen_base, lcd_info->fix.smem_start);iounmap(display_con);iounmap(lcd_regs);release_mem_region(S5P_PA_LCD,S5P_SZ_LCD);		iounmap(gpf0_con);//GPF0_CONiounmap(gpf1_con);//GPF1_CONiounmap(gpf2_con);//GPF2_CONiounmap(gpf3_con);//GPF3_CONiounmap(gpd0_con);//GPD0_CONframebuffer_release(lcd_info);regulator_disable(lcd_regulator);regulator_put(lcd_regulator);
}static void s5p_lcd_release(struct device * dev)
{
}struct platform_device s5p_device_fb = {.name		= "s5p-lcd",//总线平台名称.id		  = -1,.dev		  = {.init_name		= "s5p-lcd",//设备init_name,用来获取电源管理pd的regulator。与power-domain.c文件的s5pv210_pd_lcd_supply里dev_name对应.release = s5p_lcd_release,}
};static struct platform_driver s5pfb_driver = {.probe =  s5pfb_probe,.remove = s5pfb_remove,.driver = {.name = "s5p-lcd", //总线平台名称.owner = THIS_MODULE,},
};static int __init s5pfb_register(void)
{platform_driver_register(&s5pfb_driver);platform_device_register(&s5p_device_fb);return 0;
}
static void __exit s5pfb_unregister(void)
{platform_driver_unregister(&s5pfb_driver);	platform_device_unregister(&s5p_device_fb);
}module_init(s5pfb_register);
module_exit(s5pfb_unregister);
MODULE_LICENSE("GPL");

 

这篇关于在x210上编写lcd驱动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/315260

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

Wondows dos下怎么编写bat批处理文件

最近搞php,在运行时,以Nginx+php-cgi.exe方式运行Wordpress项目 打开dos,先cd到php-cgi.exe文件当前目录下执行启动命令:php-cgi.exe -b 127.0.0.1:9001再打开一个dos,再cd到nginx.exe文件当前目录下执行启动命令:start nginx 大概过程要经过这些步骤,觉得很麻烦,就学下怎么编写一个bat文件,以双击运行代替

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

用Python编写倒计时程序:详细教程

目录 引言 环境准备 基本概念 代码实现 步骤一:导入必要的库 步骤二:获取用户输入 步骤三:实现倒计时逻辑 步骤四:整合代码 运行程序 高级功能 扩展功能示例:支持分钟和小时输入 扩展功能示例:图形用户界面 (GUI) 总结 引言 倒计时程序是一个非常常见的小工具,广泛用于各种应用场景中,例如考试时间提醒、烹饪计时器、会议倒计时等。Python 作为一种

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件

麒麟系统安装GPU驱动

1.nvidia 1.1显卡驱动 本机显卡型号:nvidia rtx 3090 1.1.1下载驱动 打开 https://www.nvidia.cn/geforce/drivers/ 也可以直接使用下面这个地址下载 https://www.nvidia.com/download/driverResults.aspx/205464/en-us/ 1.1.3安装驱动 右击,

windows10 卸载网络驱动以及重新安装

右键桌面此电脑的图标,点击管理,设备管理器—网络适配器,找到下图中的驱动(不同的系统或者显卡会导致网卡驱动名称与下图不一样,多为Realtek开头),右键选择卸载设备,然后重启电脑,系统会自动重新安装驱动 新电脑首次安装驱动: 根据主板厂家,比如华硕,进入华硕官网,点击服务支持,点击下载中心,选择型号,点击右侧驱动程序和工具软件,选择windows版本,下载相应的驱动,下载完之后在对应文件中找