📄 hw.c
字号:
/*
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sub license,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <linux/config.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <asm/io.h>
#include "hw.h"
#include "share.h"
#include "debug.h"
#include "chip.h"
#include "viamode.h"
// External Function
extern int tmds_trasmitter_identify(void);
extern void init_dvi_size(void);
extern int lvds_trasmitter_identify(void);
extern void init_lcd_size(void);
extern void tv_set_mode(int video_index);
extern void lcd_set_mode(struct crt_mode_table *lcd_crt_timing, int video_index, int mode_bpp, int set_iga);
extern void dvi_set_mode(struct crt_mode_table *dvi_crt_timing, int video_index, int mode_bpp, int set_iga);
// External struct
extern struct chip_information chip_info;
extern struct crt_setting_information crt_setting_info;
extern struct tv_setting_information tv_setting_info;
extern struct tmds_setting_information tmds_setting_info;
extern struct lvds_setting_information lvds_setting_info;
extern int refresh;
extern int tv_level;
extern int tv_system;
extern int tv_out_signal;
extern int tv_dedotcrawl;
extern int CRT_ON, TV_ON, DVI_ON, LCD_ON;
/* Access I/O Function */
inline void write_reg(u8 index, u16 io_port, u8 data);
void write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
inline u8 read_reg(int io_port, u8 index);
inline void lock_crt(void);
inline void unlock_crt(void);
void set_crt_output_path(int set_iga);
void set_tv_output_path(int set_iga, int output_interface);
void set_dvi_output_path(int set_iga, int output_interface);
void set_lcd_output_path(int set_iga, int output_interface);
void SetVCLK( u32 CLK, int set_iga );
void init_gfx_chip_info(void);
void init_tv_chip_info(void);
void init_tmds_chip_info(void);
void init_lvds_chip_info(void);
void load_reg(int timing_value, int load_reg_num, struct io_register *reg, int io_type);
inline void write_reg(u8 index, u16 io_port, u8 data)
{
outb(index, io_port);
outb(data, io_port+1);
//DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data);
}
void write_reg_mask(u8 index, int io_port, u8 data, u8 mask)
{
u8 tmp;
outb(index, io_port);
tmp = inb(io_port+1);
outb((data & mask) | (tmp & (~mask)), io_port+1);
//DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp);
}
void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
{
outb(index, LUT_INDEX_WRITE);
outb(r, LUT_DATA);
outb(g, LUT_DATA);
outb(b, LUT_DATA);
}
inline u8 read_reg(int io_port, u8 index)
{
outb(index, io_port);
return(inb(io_port+1));
}
inline void lock_crt(void)
{
write_reg_mask(CR11, VIACR, BIT7, BIT7);
}
inline void unlock_crt(void)
{
write_reg_mask(CR11, VIACR, 0, BIT7);
write_reg_mask(CR47, VIACR, 0, BIT0);
}
void set_output_path(int device, int set_iga, int output_interface)
{
switch(device) {
case DEVICE_CRT:
set_crt_output_path(set_iga);
break;
case DEVICE_TV:
set_tv_output_path(set_iga, output_interface);
break;
case DEVICE_DVI:
set_dvi_output_path(set_iga, output_interface);
break;
case DEVICE_LCD:
set_lcd_output_path(set_iga, output_interface);
break;
}
}
void set_crt_output_path(int set_iga)
{
write_reg_mask(CR36, VIACR, 0x00, BIT4+BIT5);
switch(set_iga) {
case IGA1:
write_reg_mask(SR16, VIASR, 0x00, BIT6);
break;
case IGA2:
case IGA1_IGA2:
write_reg_mask(CR6A, VIACR, 0xC0, BIT6+BIT7);
write_reg_mask(SR16, VIASR, 0x40, BIT6);
if (set_iga == IGA1_IGA2)
write_reg_mask(CR6B, VIACR, 0x08, BIT3);
break;
}
}
void set_tv_output_path(int set_iga, int output_interface)
{
switch(set_iga)
{
case IGA1:
// Set IGA1 display channel to normal case beside CLE266.AX chip
// and disable simultaneous display.
if ((chip_info.gfx_chip_name == UNICHROME_CLE266) && (chip_info.gfx_chip_revision == CLE266_REVISION_AX))
{
SetVCLK(0x471c, IGA1);
write_reg_mask(CR6B, VIACR, 0xC0, BIT3+BIT6+BIT7);
}
else
write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
break;
case IGA2:
// Set IGA2 display channel to normal case beside CLE266.AX chip
// and disable simultaneous display.
write_reg_mask(CR6A, VIACR, 0xC0, BIT6+BIT7);
if (chip_info.gfx_chip_name == UNICHROME_CLE266 && chip_info.gfx_chip_revision == CLE266_REVISION_AX)
write_reg_mask(CR6B, VIACR, 0x30, BIT3+BIT4+BIT5);
else
write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
// Disable LCD Scaling
write_reg_mask(CR79, VIACR, 0x00, BIT0);
break;
case IGA1_IGA2:
// Set IGA1_IGA2 display channel to normal case beside CLE266.AX chip
// and enable simultaneous display.
write_reg_mask(CR6A, VIACR, 0xC0, BIT6+BIT7);
if (chip_info.gfx_chip_name == UNICHROME_CLE266 && chip_info.gfx_chip_revision == CLE266_REVISION_AX)
write_reg_mask(CR6B, VIACR, 0xC0, BIT3+BIT6+BIT7);
else
write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
break;
}
switch(output_interface)
{
case INTERFACE_DVP0:
if (set_iga== IGA1)
write_reg_mask(CR6C, VIACR, 0x00, BIT7);
else
write_reg_mask(CR6C, VIACR, 0x80, BIT7);
if (chip_info.gfx_chip_name == UNICHROME_CLE266 && chip_info.gfx_chip_revision == CLE266_REVISION_AX)
{
write_reg_mask(CR6B, VIACR, 0x01, BIT0);
write_reg_mask(CR6C, VIACR, 0x01, BIT0);
}
else
{
write_reg_mask(CR6B, VIACR, 0x00, BIT0);
write_reg_mask(CR6C, VIACR, 0x21, BIT0+BIT5);
}
write_reg_mask(SR1E, VIASR, 0xC0, BIT6+BIT7);
break;
case INTERFACE_DVP1:
if (set_iga== IGA1)
{
write_reg_mask(CR6C, VIACR, 0x00, BIT7);
write_reg_mask(CR9B, VIACR, 0x00, BIT4);
}
else
{
write_reg_mask(CR6C, VIACR, 0x80, BIT7);
write_reg_mask(CR9B, VIACR, 0x10, BIT4);
}
write_reg_mask(CR6C, VIACR, 0x21, BIT0+BIT5);
write_reg_mask(SR1E, VIASR, 0x30, BIT4+BIT5);
break;
case INTERFACE_DFP_HIGH:
if (set_iga== IGA1)
{
write_reg_mask(CR6C, VIACR, 0x00, BIT7);
write_reg_mask(CR96, VIACR, 0x00, BIT4);
write_reg_mask(CR97, VIACR, 0x00, BIT4);
}
else
{
write_reg_mask(CR6C, VIACR, 0x80, BIT7);
write_reg_mask(CR96, VIACR, 0x10, BIT4);
write_reg_mask(CR97, VIACR, 0x10, BIT4);
}
write_reg_mask(CR6C, VIACR, 0x21, BIT0+BIT5);
break;
case INTERFACE_DFP_LOW:
if (set_iga== IGA1)
{
write_reg_mask(CR6C, VIACR, 0x00, BIT7);
write_reg_mask(CR9B, VIACR, 0x00, BIT4);
write_reg_mask(CR99, VIACR, 0x00, BIT4);
}
else
{
write_reg_mask(CR6C, VIACR, 0x80, BIT7);
write_reg_mask(CR9B, VIACR, 0x10, BIT4);
write_reg_mask(CR99, VIACR, 0x10, BIT4);
}
write_reg_mask(CR6C, VIACR, 0x21, BIT0+BIT5);
break;
}
}
void set_dvi_output_path(int set_iga, int output_interface)
{
switch(output_interface)
{
case INTERFACE_DVP0:
break;
case INTERFACE_DVP1:
if (chip_info.gfx_chip_name == UNICHROME_CLE266)
{
if (set_iga== IGA1)
write_reg_mask(CR93, VIACR, 0x21, BIT0+BIT5+BIT7);
else
write_reg_mask(CR93, VIACR, 0xA1, BIT0+BIT5+BIT7);
}
else
{
if (set_iga== IGA1)
write_reg_mask(CR9B, VIACR, 0x00, BIT4);
else
write_reg_mask(CR9B, VIACR, 0x10, BIT4);
}
write_reg_mask(SR1E, VIASR, 0x30, BIT4+BIT5);
break;
case INTERFACE_DFP_HIGH:
break;
case INTERFACE_DFP_LOW:
break;
}
}
void set_lcd_output_path(int set_iga, int output_interface)
{
switch(set_iga)
{
case IGA1:
write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
break;
case IGA2:
write_reg_mask(CR6A, VIACR, 0xC0, BIT6+BIT7);
break;
case IGA1_IGA2:
write_reg_mask(CR6B, VIACR, 0x00, BIT3+BIT6+BIT7);
break;
}
switch(output_interface)
{
case INTERFACE_DVP0:
break;
case INTERFACE_DVP1:
if (set_iga== IGA1)
write_reg_mask(CR9B, VIACR, 0x00, BIT4);
else
write_reg_mask(CR9B, VIACR, 0x10, BIT4);
write_reg_mask(CR6A, VIACR, 0x01, BIT0);
break;
case INTERFACE_DFP_HIGH:
if (set_iga== IGA1)
write_reg_mask(CR97, VIACR, 0x00, BIT4);
else
write_reg_mask(CR97, VIACR, 0x10, BIT4);
write_reg_mask(CR6A, VIACR, 0x01, BIT0);
break;
case INTERFACE_DFP_LOW:
if (set_iga== IGA1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -