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

📄 hw.c

📁 VIA Framebuffer driver
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * 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 + -