⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 voyager.c

📁 嵌入式linux下sm501芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				: FIELD_SET(0, CURRENT_POWER_CLOCK, V2XCLK_DIVIDER, 3))
			| FIELD_VALUE(0, CURRENT_POWER_CLOCK, V2XCLK_SHIFT, clock.shift);

		// Set control register value.
		register_table->control 
			= (mode->vertical_sync_polarity == POSITIVE
				? FIELD_SET(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, ACTIVE_HIGH)
				: FIELD_SET(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, ACTIVE_LOW))
			| (mode->horizontal_sync_polarity == POSITIVE
				? FIELD_SET(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, ACTIVE_HIGH)
				: FIELD_SET(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, ACTIVE_LOW))
			| FIELD_SET(0, CRT_DISPLAY_CTRL, SELECT, CRT)
			| FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)
			| FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE)
			| (bpp == 8
				? FIELD_SET(0, CRT_DISPLAY_CTRL, FORMAT, 8)
				: (bpp == 16
					? FIELD_SET(0, CRT_DISPLAY_CTRL, FORMAT, 16)
					: FIELD_SET(0, CRT_DISPLAY_CTRL, FORMAT, 32)));

		// Set timing registers.
		register_table->horizontal_total
			= FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, 
						  mode->horizontal_total - 1)
			| FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, 
						  mode->horizontal_display_end - 1);

		register_table->horizontal_sync  
			= FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, 
						  mode->horizontal_sync_width)
			| FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, 
						  mode->horizontal_sync_start - 1);

		register_table->vertical_total   
			= FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, 
						  mode->vertical_total - 1)
			| FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, 
						  mode->vertical_display_end - 1);
		register_table->vertical_sync    
			= FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, 
						  mode->vertical_sync_height)
			| FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, 
						  mode->vertical_sync_start - 1);
	}

	// Calculate frame buffer width and height.
	register_table->fb_width = mode->horizontal_display_end * (bpp / 8);
	register_table->width = mode->horizontal_display_end;
	register_table->height = mode->vertical_display_end;

	// Save display type.
	register_table->display = display;
}

// Program the mode with the registers specified.
void programMode(reg_table_t *register_table)
{
	unsigned long value, gate, clock;
	unsigned long palette_ram;
	unsigned long fb_size, offset;

	// Get current power configuration.
	gate = regRead32(CURRENT_POWER_GATE);
	clock = regRead32(CURRENT_POWER_CLOCK);

	// Program panel.
	if (register_table->display == PANEL)
	{
		// Program clock, enable display controller.
		gate = FIELD_SET(gate, CURRENT_POWER_GATE, DISPLAY, ENABLE);
		clock &= FIELD_CLEAR(CURRENT_POWER_CLOCK, P2XCLK_SELECT)
			  &  FIELD_CLEAR(CURRENT_POWER_CLOCK, P2XCLK_DIVIDER)
			  &  FIELD_CLEAR(CURRENT_POWER_CLOCK, P2XCLK_SHIFT);

        // Set engine clock to 72Mhz, memory clock to 144MHz
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SELECT, 288);    //MCLK=72MHz
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_DIVIDER, 1);
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SHIFT, 2);
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SELECT, 288);  //M2XCLK=144MHz
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_DIVIDER, 1);
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SHIFT, 1);

		setPower(gate, clock | register_table->clock);

		// Calculate frame buffer address.
		value = 0;
		fb_size = register_table->fb_width * register_table->height;
		if (FIELD_GET(regRead32(CRT_DISPLAY_CTRL),
					  CRT_DISPLAY_CTRL,
					  PLANE) == CRT_DISPLAY_CTRL_PLANE_ENABLE)
		{
			value = FIELD_GET(regRead32(CRT_FB_ADDRESS),
							  CRT_FB_ADDRESS, 
							  ADDRESS);
			if (fb_size < value)
			{
				value = 0;
			}
			else
			{
				value += FIELD_GET(regRead32(CRT_FB_WIDTH),
								   CRT_FB_WIDTH,
								   OFFSET)
					  *  (FIELD_GET(regRead32(CRT_VERTICAL_TOTAL),
								   CRT_VERTICAL_TOTAL,
								   DISPLAY_END) + 1);
			}
		}

		// Program panel registers.
		regWrite32(PANEL_FB_ADDRESS,
						  FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, PENDING)	|
						  FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)		|
			              FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, value)	);

		regWrite32(PANEL_FB_WIDTH,
						  FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH,
									  register_table->fb_width)				|
						  FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET,
									  register_table->fb_width)				);

		regWrite32(PANEL_WINDOW_WIDTH,
						  FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH,
									  register_table->width)				|
						  FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, 0)			);

		regWrite32(PANEL_WINDOW_HEIGHT,
						  FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, 
									  register_table->height)				|
						  FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, 0)			);

		regWrite32(PANEL_PLANE_TL,
						  FIELD_VALUE(0, PANEL_PLANE_TL, TOP, 0)			|
						  FIELD_VALUE(0, PANEL_PLANE_TL, LEFT, 0)			);

		regWrite32(PANEL_PLANE_BR, 
						  FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM,
									  register_table->height - 1)			|
						  FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT,
									  register_table->width - 1)			);

		regWrite32(PANEL_HORIZONTAL_TOTAL,
						  register_table->horizontal_total);
		regWrite32(PANEL_HORIZONTAL_SYNC,
						  register_table->horizontal_sync);
		regWrite32(PANEL_VERTICAL_TOTAL,
						  register_table->vertical_total);
		regWrite32(PANEL_VERTICAL_SYNC,
						  register_table->vertical_sync);

		// Program panel display control register.
		value = regRead32(PANEL_DISPLAY_CTRL)
			  & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
			  & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
			  & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
			  & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE)
			  & FIELD_CLEAR(PANEL_DISPLAY_CTRL, FORMAT);

		regWrite32(PANEL_DISPLAY_CTRL,
						  value | register_table->control);

		// Palette RAM.
		palette_ram = PANEL_PALETTE_RAM;

		// Turn on panel.
		panelPowerSequence(PANEL_ON, 4);
	}

	// Program CRT.
	else
	{
		// Program clock, enable display controller.
		gate = FIELD_SET(gate, CURRENT_POWER_GATE, DISPLAY, ENABLE);
		clock &= FIELD_CLEAR(CURRENT_POWER_CLOCK, V2XCLK_SELECT)
			  &  FIELD_CLEAR(CURRENT_POWER_CLOCK, V2XCLK_DIVIDER)
			  &  FIELD_CLEAR(CURRENT_POWER_CLOCK, V2XCLK_SHIFT);
        
        // Set engine clock to 72Mhz, memory clock to 144MHz
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SELECT, 288);    //MCLK=72MHz
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_DIVIDER, 1);
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SHIFT, 2);
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SELECT, 288);  //M2XCLK=144MHz
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_DIVIDER, 1);
        clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SHIFT, 1);
        
		setPower(gate, clock | register_table->clock);

		// Turn on DAC.
		regWrite32(MISC_CTRL, FIELD_SET(regRead32(MISC_CTRL),
											   MISC_CTRL,
											   DAC_POWER,
											   ENABLE));

		// Calculate frame buffer address.
		value = 0;
		fb_size = register_table->fb_width * register_table->height;
		if (FIELD_GET(regRead32(PANEL_DISPLAY_CTRL),
					  PANEL_DISPLAY_CTRL,
					  PLANE) == PANEL_DISPLAY_CTRL_PLANE_ENABLE)
		{
			value = FIELD_GET(regRead32(PANEL_FB_ADDRESS),
							  PANEL_FB_ADDRESS, 
							  ADDRESS);
			if (fb_size < value)
			{
				value = 0;
			}
			else
			{
				value += FIELD_GET(regRead32(PANEL_FB_WIDTH),
								   PANEL_FB_WIDTH,
								   OFFSET)
					  *  FIELD_GET(regRead32(PANEL_WINDOW_HEIGHT),
								   PANEL_WINDOW_HEIGHT,
								   HEIGHT);
			}
		}

		// Program CRT registers.
		regWrite32(CRT_FB_ADDRESS,
						  FIELD_SET(0, CRT_FB_ADDRESS, STATUS, PENDING)		|
						  FIELD_SET(0, CRT_FB_ADDRESS, EXT, LOCAL)			|
			              FIELD_VALUE(0, CRT_FB_ADDRESS, ADDRESS, value)	);

		regWrite32(CRT_FB_WIDTH,
						  FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH,
									  register_table->fb_width)				|
						  FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET,
									  register_table->fb_width)				);

		regWrite32(CRT_HORIZONTAL_TOTAL,
						  register_table->horizontal_total);
		regWrite32(CRT_HORIZONTAL_SYNC,
						  register_table->horizontal_sync);
		regWrite32(CRT_VERTICAL_TOTAL,
						  register_table->vertical_total);
		regWrite32(CRT_VERTICAL_SYNC,
						  register_table->vertical_sync);

		// Program CRT display control register.
		value = regRead32(CRT_DISPLAY_CTRL)
			  & FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE)
			  & FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE)
			  & FIELD_CLEAR(CRT_DISPLAY_CTRL, SELECT)
			  & FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING)
			  & FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE)
			  & FIELD_CLEAR(CRT_DISPLAY_CTRL, FORMAT);

		regWrite32(CRT_DISPLAY_CTRL,
						  value | register_table->control);

		// Palette RAM.
		palette_ram = CRT_PALETTE_RAM;

		// Turn on CRT.
		setDPMS(DPMS_ON);
	}

	// In case of 8-bpp, fill palette.
	if (FIELD_GET(register_table->control,
				  PANEL_DISPLAY_CTRL,
				  FORMAT) == PANEL_DISPLAY_CTRL_FORMAT_8)
	{
		// Start with RGB = 0,0,0.
		unsigned char red = 0, green = 0, blue = 0;
		unsigned long gray = 0;
		for (offset = 0; offset < 256 * 4; offset += 4)
		{
			// Store current RGB value.
			regWrite32(palette_ram + offset, gray
								? RGB((gray + 50) / 100,
									  (gray + 50) / 100,
									  (gray + 50) / 100)
								: RGB(red, green, blue));

			if (gray)
			{
				// Walk through grays (40 in total).
				gray += 654;
			}

			else
			{
				// Walk through colors (6 per base color).
				if (blue != 255)
				{
					blue += 51;
				}
				else if (green != 255)
				{
					blue = 0;
					green += 51;
				}
				else if (red != 255)
				{
					green = blue = 0;
					red += 51;
				}
				else
				{
					gray = 1;
				}
			}
		}
	}

	// For 16- and 32-bpp,  fill palette with gamma values.
	else
	{
		// Start with RGB = 0,0,0.
		value = 0x000000;
		for (offset = 0; offset < 256 * 4; offset += 4)
		{
			regWrite32(palette_ram + offset, value);

			// Advance RGB by 1,1,1.
			value += 0x010101;
		}
	}
}

void SetMode(unsigned long dst_width, unsigned long dst_height, unsigned long fMode, unsigned long nHertz, display_t display, int bpp)
{
	mode_table_t mode;
	pmode_table_t vesaMode;
	reg_table_t register_table;

	// Locate the mode
	vesaMode = findMode(mode_table, dst_width, dst_height, nHertz);
	if (vesaMode != NULL)
	{
		// Convert VESA timing into Voyager timing
		adjustMode(vesaMode, &mode, display);

		// Fill the register structure
		setModeRegisters(&register_table, &mode, display, bpp);

		// Program the registers
		programMode(&register_table);
	}
}

void panelSetMode(unsigned long dst_width, unsigned long dst_height, unsigned long fMode, unsigned long nHertz, int bpp)
{
	SetMode(dst_width, dst_height, fMode, nHertz, PANEL, bpp);
}

void crtSetMode(unsigned long dst_width, unsigned long dst_height, unsigned long fMode, unsigned long nHertz, int bpp)
{
	SetMode(dst_width, dst_height, fMode, nHertz, CRT, bpp);
}


static void smi_set_timing(struct smifb_info *sfb,struct par_info *hw)
{
    panelSetMode(hw->width, hw->height, 0, hw->hz, sfb->fb.var.bits_per_pixel); 

    // Turn on CRT DAC. for simultanous display
    regWrite32(MISC_CTRL, FIELD_SET(regRead32(MISC_CTRL),  MISC_CTRL,  DAC_POWER, ENABLE));
}

static void sm501_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
{
    red   >>= 8;
    green >>= 8;
    blue  >>= 8;
    
    regWrite32(PANEL_PALETTE_RAM+regno*4, red<<16 | green<<8 | blue);
    regWrite32(CRT_PALETTE_RAM+regno*4, red<<16 | green<<8 | blue); //for dual display only
}

#ifdef CONFIG_FB_SM501_KERNEL_2_4_X
static void fbcon_SMI8_bmove(struct display *p, int sy, int sx, int dy,
                             int dx, int height, int width)
{
    sx *= 8; dx *= 8; width *= 8;
    deCopy(0, 0, 8,  
        dx, dy*fontheight(p), width, height*fontheight(p), 
        0, 0, sx, sy*fontheight(p), 0, 0xC);
}

static void fbcon_SMI8_clear(struct vc_data *conp, struct display *p, int sy,
			       int sx, int height, int width)
{
        unsigned char color;

        color = attr_bgcol_ec(p,conp);

        deFillRect(0, 0, sx*8, sy*fontheight(p), width*8, height*fontheight(p), color);
}

static void fbcon_SMI8_putc(struct vc_data *conp, struct display *p, int c, int yy,
                              int xx)
{
	if (SMI_de_busy)
		deWaitForNotBusy();
	fbcon_cfb8_putc(conp, p, c, yy, xx);
}

static void fbcon_SMI8_putcs(struct vc_data *conp, struct display *p,
                      const unsigned short *s, int count, int yy, int xx)
{
	if (SMI_de_busy)
		deWaitForNotBusy();
	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
}

static void fbcon_SMI8_revc(struct display *p, int xx, int yy)
{
	if (SMI_de_busy)
		deWaitForNotBusy();
	fbcon_cfb8_revc(p, xx, yy);
}

static void fbcon_SMI8_clear_margins(struct vc_data *conp, struct display *p,
                              int bottom_only)
{
	if (SMI_de_busy)
		deWaitForNotBusy();
	fbcon_cfb8_clear_margins(conp, p, bottom_only);
}

static struct display_switch fbcon_SMI8 = {
	setup:		fbcon_cfb8_setup,
	bmove:		fbcon_SMI8_bmove,
	clear:		fbcon_SMI8_clear,
	putc:		fbcon_SMI8_putc,
	putcs:		fbcon_SMI8_putcs,
	revc:		fbcon_SMI8_revc,
	clear_margins:	fbcon_SMI8_clear_margins,
	fontwidthmask:	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};

static void fbcon_SMI16_bmove(struct display *p, int sy, int sx, int dy,
                              int dx, int height, int width)
{
    sx *= 8; dx *= 8; width *= 8;

    deCopy(0, 0, 16,  
        dx, dy*fontheight(p), width, height*fontheight(p), 
        0, 0, sx, sy*fontheight(p), 0, 0xC);
}

static void fbcon_SMI16_clear(struct vc_data *conp, struct display *p, int sy,
                               int sx, int height, int width)
{
        unsigned long color;

        color = attr_bgcol_ec(p,conp);

        deFillRect(0, 0, sx*8, sy*fontheight(p), width*8, height*fontheight(p), color);
}

static void fbcon_SMI16_putc(struct vc_data *conp, struct display *p, int c, int yy,
                              int xx)
{
	if (SMI_de_busy)
		deWaitForNotBusy();
	fbcon_cfb16_putc(conp, p, c, yy, xx);
}

static void fbcon_SMI16_putcs(struct vc_data *conp, struct display *p,
                      const unsigned short *s, int count, int yy, int xx)
{
	if (SMI_de_busy)
		deWaitForNotBusy();
	fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
}

static void fbcon_SMI16_revc(struct display *p, int xx, int yy)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -