|
Prev: [Linux-fbdev-devel] [PATCH 0/9] viafb: VIA Frame Buffer Device Driver
Next: [PATCH 1/9] viafb: VIA Frame Buffer Device Driver
From: JosephChan on 7 May 2008 07:00 Signed-off-by: Joseph Chan <josephchan(a)via.com.tw> diff -Nur a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt --- a/Documentation/fb/viafb.txt 1969-12-31 19:00:00.000000000 -0500 +++ b/Documentation/fb/viafb.txt 2008-05-06 06:46:26.000000000 -0400 @@ -0,0 +1,197 @@ + + VIA Integration Graphic Chip Console Framebuffer Driver + +[Platform] +----------------------- + The console framebuffer driver is for Graphics chips of + VIA UniChrome (Pro) Family: + CLE266, PM800 / CN400,P4M800CE / P4M800Pro / CN700 / VN800, + CX700 / VX700, P4M890 + VIA Chrome9 Family: + K8M890, CN896 / P4M900, VX800) + +[Driver features] +------------------------ + Device:CRT, LCD, DVI + + Support Mode: + CRT: + 640 x480(60, 75, 85, 100, 120 Hz), 720 x480(60 Hz), + 720 x576(60 Hz), 800 x600(60, 75, 85, 100, 120 Hz), + 848 x480(60 Hz), 856 x480(60 Hz), 1024 x512(60 Hz), + 1024 x768(60, 75, 85, 100 Hz), 1152 x864(75 Hz), + 1280 x768(60 Hz), 1280 x960(60 Hz), 1280 x1024(60, 75, 85 Hz), + 1440 x1050(60 Hz), 1600 x1200(60, 75 Hz), 1280 x720(60 Hz), + 1920 x1080(60 Hz), 1400 x1050(60 Hz), 800 x480(60 Hz) + + color depth:8 bpp, 16 bpp, 32 bpp + + Support 2 D hardware accelerator for kernel 2.6.xx + +[Using the viafb module] +-- -- -------------------- + Start viafb with default settings, + #modprobe viafb + + Start viafb with with user options, + #modprobe viafb mode=800x600 via_fb_bpp=16 refresh=60 + active_dev=CRT+DVI dvi_port = DVP1 mode1 = 1024 x768 + via_fb_bpp1 = 16 refresh1 = 60 SAMM_ON = 1 + + mode: + 640 x480(default) + 720 x480 + 800 x600 + 1024 x768 + ...... + + via_fb_bpp: + 8, 16, 32(default:32) + + refresh: + 60, 75, 85, 100, 120(default:60) + + lcd_dsp_method: + 0 : expandsion(default) + 1 : centering + + lcd_mode: + 0 : OPEN LDI(default) + 1 : SPWG + + lcd_panel_id: + 0 : Resolution: 640 x480, Channel: single, Dithering: Enable + 1 : Resolution: 800 x600, Channel: single, Dithering: Enable + 2 : Resolution: 1024 x768, Channel: single, Dithering:Enable (default) + 3 : Resolution: 1280 x768, Channel: single, Dithering: Enable + 4 : Resolution: 1280 x1024, Channel: dual, Dithering: Enable + 5 : Resolution: 1400 x1050, Channel: dual, Dithering: Enable + 6 : Resolution: 1600 x1200, Channel: dual, Dithering: Enable + + 8 : Resolution: 800 x480, Channel: single, Dithering: Enable + 9 : Resolution: 1024 x768, Channel: dual, Dithering: Enable + 10: Resolution: 1024 x768, Channel: single, Dithering: Disable + 11: Resolution: 1024 x768, Channel: dual, Dithering: Disable + 12: Resolution: 1280 x768, Channel: single, Dithering: Disable + 13: Resolution: 1280 x1024, Channel: dual, Dithering: Disable + 14: Resolution: 1400 x1050, Channel: dual, Dithering: Disable + 15: Resolution: 1600 x1200, Channel: dual, Dithering: Disable + 16: Resolution: 1366 x768, Channel: single, Dithering: Disable + 17: Resolution: 1024 x600, Channel: single, Dithering: Enable + 18: Resolution: 1280 x768, Channel: dual, Dithering: Enable + 19: Resolution: 1280 x800, Channel: single, Dithering: Enable + + via_fb_accel: + 0 : No 2 D Hardware Acceleration(default) + 1 : 2 D Hardware Acceleration + + SAMM_ON: + 0 : SAMM_ON disable(default) + 1 : SAMM_ON enable + + mode1:(secondary display device) + 640 x480(default) + 720 x480 + 800 x600 + 1024 x768 + ... ... + + via_fb_bpp1:(secondary display device) + 8, 16, 32(default:32) + + refresh1:(secondary display device) + 60, 75, 85, 100, 120(default:60) + + active_dev: + This option is used to specify active devices.(CRT, DVI, LCD, CRT + LCD, CRT + DVI,...) + DVI stand for DVI or HDMI, Ex.If you want to enable HDMI, set active_dev = DVI + In SAMM case, the previous of active_dev is primary device, and the following is secondary device. + + For example: + To enable one device, such as DVI only, we should use: + modprobe viafb active_dev = DVI...To enable two devices, such as CRT + DVI: + + For DuoView case, we can use: + modprobe viafb active_dev = CRT + DVI...OR modprobe viafb active_dev = DVI + CRT... + + For SAMM case: + If CRT is primary and DVI is secondary, we should use: + modprobe viafb active_dev = CRT + DVI SAMM_ON = 1... + If DVI is primary and CRT is secondary, we should use: + modprobe viafb active_dev = DVI + CRT SAMM_ON = 1... + + display_hardware_layout: + This option is uesed to specify display hardware layout for CX700 chip. + 1 : LCD only + 2 : DVI only + 3 : LCD + DVI(default) + 4 : LCD1 + LCD2(internal + internal) + 16: LCD1 + ExternalLCD2(internal + external) + + second_size: + This option is used to set second device memory size(MB) in SAMM case. + The minimal size is 16. + + EPIA_DVI: + This option is used to enable DVI on EPIA - M + 0 : No DVI on EPIA - M(default) + 1 : DVI on EPIA - M + + BusWidth: + When using 24 - Bit Bus Width Digital Interface, this option should be set. + 12: 12-Bit LVDS or 12-Bit TMDS(default) + 24: 24-Bit LVDS or 24-Bit TMDS + + LCDDualEdge: + When using Dual Edge Panel, this option should be set. + 0 : No Dual Edge Panel(default) + 1 : Dual Edge Panel + + video_dev: + This option is used to specify video output devices(CRT, DVI, LCD) for duoview case. + For example: + To output video on DVI, we should use: + modprobe viafb video_dev = DVI... + + lcd_port: + This option is used to specify lcd output port, + available values are "DVP0" "DVP1" "DFP_HIGHLOW" "DFP_HIGH" + "DFP_LOW", for external LCD + external DVI on CX700(External LCD is on DVP0), + we should use: + modprobe viafb lcd_port = DVP0... + +Note: + 1. CRT may not display properly for DuoView CRT & DVI display at + the "640x480" PAL mode with DVI overscan enabled. + 2. When SAMM is enable, mode and mode1, via_fb_bpp and via_fb_bpp1, + refresh and refresh1 can be different. + 3. When console is depend on viafbinfo1, dynamically change resolution and bpp, + need call VIAFB specified ioctl interface VIAFB_SET_DEVICE. + Call common ioctl function FBIOPUT_VSCREENINFO will cause sreen crush. + +[Configure viafb with "fbset" tool] +----------------------------------- + "fbset" is an inbox utility of Linux. + 1. Inquire current viafb information, type, + # fbset -i + + 2. Set various resolutions and refresh rates, + # fbset <resolution-vertical_sync> + + example, + # fbset "1024x768-75" + or + # fbset -g 1024 768 1024 768 32 + Check the file "/etc/fb.modes" to find display modes available. + + 3. Set the color depth, + # fbset -depth <value> + + example, + # fbset -depth 16 + +[Bootup with viafb]: +-------------------- + Add the following line to your lilo.conf: + append = "video=viafb:mode:1024x768,via_fb_bpp:32,refresh:85" + diff -Nur a/drivers/video/Kconfig b/drivers/video/Kconfig --- a/drivers/video/Kconfig 2008-05-06 07:05:59.000000000 -0400 +++ b/drivers/video/Kconfig 2008-05-06 07:06:37.000000000 -0400 @@ -1501,6 +1501,24 @@ (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well as XGI V3XT, V5, V8 and Z7. +config FB_VIA + tristate "VIA UniChrome (Pro) and Chrome9 display support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_SOFT_CURSOR + help + This is the frame buffer device driver for Graphics chips of VIA + UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ + CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896 + /P4M900,VX800) + + Say Y if you have a VIA UniChrome graphics board. + + To compile this driver as a module, choose M here: the + module will be called viafb. + config FB_NEOMAGIC tristate "NeoMagic display support" depends on FB && PCI diff -Nur a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile 2008-05-06 07:05:49.000000000 -0400 +++ b/drivers/video/Makefile 2008-05-06 07:06:44.000000000 -0400 @@ -43,6 +43,7 @@ obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o obj-$(CONFIG_FB_RADEON) += aty/ obj-$(CONFIG_FB_SIS) += sis/ +obj-$(CONFIG_FB_VIA) += via/ obj-$(CONFIG_FB_KYRO) += kyro/ obj-$(CONFIG_FB_SAVAGE) += savage/ obj-$(CONFIG_FB_GEODE) += geode/ diff -Nur a/drivers/video/via/accel.c b/drivers/video/via/accel.c --- a/drivers/video/via/accel.c 1969-12-31 19:00:00.000000000 -0500 +++ b/drivers/video/via/accel.c 2008-04-29 02:51:13.000000000 -0400 @@ -0,0 +1,245 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + option) + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include "global.h" + +void init_accel(void) +{ + parinfo.cursor_start = parinfo.fbmem_free - CURSOR_SIZE; + parinfo.fbmem_free -= CURSOR_SIZE; + parinfo.fbmem_used += CURSOR_SIZE; + + /* Reverse 8*1024 memory space for cursor image of the XServer */ + parinfo.VQ_start = parinfo.fbmem_free - CURSOR_SIZE - VQ_SIZE; + parinfo.VQ_end = parinfo.VQ_start + VQ_SIZE - 1; + parinfo.fbmem_free -= (CURSOR_SIZE + VQ_SIZE); + parinfo.fbmem_used += (CURSOR_SIZE + VQ_SIZE); } + +void init_2d_engine(void) +{ + u32 dwVQStartAddr, dwVQEndAddr; + u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; + + /* init 2D engine regs to reset 2D engine */ + MMIO_OUT32(VIA_REG_GEMODE, 0x0); + MMIO_OUT32(VIA_REG_SRCPOS, 0x0); + MMIO_OUT32(VIA_REG_DSTPOS, 0x0); + MMIO_OUT32(VIA_REG_DIMENSION, 0x0); + MMIO_OUT32(VIA_REG_PATADDR, 0x0); + MMIO_OUT32(VIA_REG_FGCOLOR, 0x0); + MMIO_OUT32(VIA_REG_BGCOLOR, 0x0); + MMIO_OUT32(VIA_REG_CLIPTL, 0x0); + MMIO_OUT32(VIA_REG_CLIPBR, 0x0); + MMIO_OUT32(VIA_REG_OFFSET, 0x0); + MMIO_OUT32(VIA_REG_KEYCONTROL, 0x0); + MMIO_OUT32(VIA_REG_SRCBASE, 0x0); + MMIO_OUT32(VIA_REG_DSTBASE, 0x0); + MMIO_OUT32(VIA_REG_PITCH, 0x0); + MMIO_OUT32(VIA_REG_MONOPAT1, 0x0); + + /* Init AGP and VQ regs */ + switch (chip_info.gfx_chip_name) { + case UNICHROME_K8M890: + case UNICHROME_P4M900: + MMIO_OUT32(0x41c, 0x00100000); + MMIO_OUT32(0x420, 0x680A0000); + MMIO_OUT32(0x420, 0x02000000); + break; + + default: + MMIO_OUT32(VIA_REG_TRANSET, 0x00100000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x00333004); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x60000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x61000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x62000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x63000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x64000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x7D000000); + + MMIO_OUT32(VIA_REG_TRANSET, 0xFE020000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000000); + break; + } + if (parinfo.VQ_start != 0) { + /* Enable VQ */ + dwVQStartAddr = parinfo.VQ_start; + dwVQEndAddr = parinfo.VQ_end; + switch (chip_info.gfx_chip_name) { + case UNICHROME_K8M890: + case UNICHROME_P4M900: + dwVQStartL = 0x70000000 | (dwVQStartAddr & 0xFFFFFF); + dwVQEndL = 0x71000000 | (dwVQEndAddr & 0xFFFFFF); + dwVQStartEndH = + 0x72000000 | ((dwVQStartAddr & 0xFF000000) >> + 24) | ((dwVQEndAddr & 0xFF000000) + >> 16); + dwVQLen = 0x73000000 | (VQ_SIZE >> 3); + break; + default: + dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF); + dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF); + dwVQStartEndH = + 0x52000000 | ((dwVQStartAddr & 0xFF000000) >> + 24) | ((dwVQEndAddr & 0xFF000000) + >> 16); + dwVQLen = 0x53000000 | (VQ_SIZE >> 3); + break; + } + + switch (chip_info.gfx_chip_name) { + case UNICHROME_K8M890: + case UNICHROME_P4M900: + MMIO_OUT32(0x41c, 0x00100000); + MMIO_OUT32(0x420, dwVQStartEndH); + MMIO_OUT32(0x420, dwVQStartL); + MMIO_OUT32(0x420, dwVQEndL); + MMIO_OUT32(0x420, dwVQLen); + MMIO_OUT32(0x420, 0x74301001); + MMIO_OUT32(0x420, 0x00000000); + break; + default: + MMIO_OUT32(VIA_REG_TRANSET, 0x00FE0000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x080003FE); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x0A00027C); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x0B000260); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x0C000274); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x0D000264); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x0E000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x0F000020); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x1000027E); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x110002FE); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x200F0060); + + MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000006); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x40008C0F); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x44000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x45080C04); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x46800408); + + MMIO_OUT32(VIA_REG_TRANSPACE, dwVQStartEndH); + MMIO_OUT32(VIA_REG_TRANSPACE, dwVQStartL); + MMIO_OUT32(VIA_REG_TRANSPACE, dwVQEndL); + MMIO_OUT32(VIA_REG_TRANSPACE, dwVQLen); + break; + } + } else { + /* Diable VQ */ + switch (chip_info.gfx_chip_name) { + case UNICHROME_K8M890: + case UNICHROME_P4M900: + MMIO_OUT32(0x41c, 0x00100000); + MMIO_OUT32(0x420, 0x74301000); + break; + default: + MMIO_OUT32(VIA_REG_TRANSET, 0x00FE0000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000004); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x40008C0F); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x44000000); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x45080C04); + MMIO_OUT32(VIA_REG_TRANSPACE, 0x46800408); + break; + } + } + + set_2d_color_depth(parinfo.bpp); + + MMIO_OUT32(VIA_REG_SRCBASE, 0x0); + MMIO_OUT32(VIA_REG_DSTBASE, 0x0); + + MMIO_OUT32(VIA_REG_PITCH, + VIA_PITCH_ENABLE | + (((parinfo.hres * + parinfo.bpp >> 3) >> 3) | (((parinfo.hres * + parinfo. + bpp >> 3) >> 3) << 16))); +} + +void set_2d_color_depth(int bpp) +{ + u32 dwGEMode; + + dwGEMode = MMIO_IN32(0x04) & 0xFFFFFCFF; + + switch (bpp) { + case 16: + dwGEMode |= VIA_GEM_16bpp; + break; + case 32: + dwGEMode |= VIA_GEM_32bpp; + break; + default: + dwGEMode |= VIA_GEM_8bpp; + break; + } + + /* Set BPP and Pitch */ + MMIO_OUT32(VIA_REG_GEMODE, dwGEMode); +} + +void hw_cursor_init(void) +{ + /* Set Cursor Image Base Address */ + MMIO_OUT32(VIA_REG_CURSOR_MODE, parinfo.cursor_start); + MMIO_OUT32(VIA_REG_CURSOR_POS, 0x0); + MMIO_OUT32(VIA_REG_CURSOR_ORG, 0x0); + MMIO_OUT32(VIA_REG_CURSOR_BG, 0x0); + MMIO_OUT32(VIA_REG_CURSOR_FG, 0x0); +} + +void show_hw_cursor(struct fb_info *info, int Status) { + u32 temp; + u32 iga_path = ((struct viafb_par *)(info->par))->iga_path; + + temp = MMIO_IN32(VIA_REG_CURSOR_MODE); + switch (Status) { + case HW_Cursor_ON: + temp |= 0x1; + break; + case HW_Cursor_OFF: + temp &= 0xFFFFFFFE; + break; + } + switch (iga_path) { + case IGA2: + temp |= 0x80000000; + break; + case IGA1: + default: + temp &= 0x7FFFFFFF; + } + MMIO_OUT32(VIA_REG_CURSOR_MODE, temp); } + +int wait_engine_idle(void) +{ + int loop = 0; + + while (!(MMIO_IN32(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) + && (loop++ < MAXLOOP)) ; + + while ((MMIO_IN32(VIA_REG_STATUS) & + (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && + (loop++ < MAXLOOP)) ; + + return loop >= MAXLOOP; +} diff -Nur a/drivers/video/via/accel.h b/drivers/video/via/accel.h --- a/drivers/video/via/accel.h 1969-12-31 19:00:00.000000000 -0500 +++ b/drivers/video/via/accel.h 2008-04-29 02:51:14.000000000 -0400 @@ -0,0 +1,190 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + option) + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ACCEL_H__ +#define __ACCEL_H__ + +#ifndef FB_ACCEL_VIA_UNICHROME +#define FB_ACCEL_VIA_UNICHROME 50 +#endif + +/* MMIO Base Address Definition */ +#define MMIO_VGABASE 0x8000 +#define MMIO_CR_READ MMIO_VGABASE + 0x3D4 +#define MMIO_CR_WRITE MMIO_VGABASE + 0x3D5 +#define MMIO_SR_READ MMIO_VGABASE + 0x3C4 +#define MMIO_SR_WRITE MMIO_VGABASE + 0x3C5 + +#ifndef VIA_MMIO +#define VIA_MMIO 1 +#endif + +#if VIA_MMIO +#define MMIO_OUT8(reg, val) writeb(val, parinfo.io_virt + reg) #define +MMIO_OUT16(reg, val) writew(val, parinfo.io_virt + reg) #define +MMIO_OUT32(reg, val) writel(val, parinfo.io_virt + reg) +#define MMIO_IN8(reg) readb(parinfo.io_virt + reg) +#define MMIO_IN16(reg) readw(parinfo.io_virt + reg) +#define MMIO_IN32(reg) readl(parinfo.io_virt + reg) + +#else +#define MMIO_OUT8(reg, val) outb(val, reg) #define MMIO_OUT16(reg, +val) outw(val, reg) #define MMIO_OUT32(reg, val) outl(val, reg) +#define MMIO_IN8(reg) inb(reg) +#define MMIO_IN16(reg) inw(reg) +#define MMIO_IN32(reg) inl(reg) +#endif + +/* HW Cursor Status Define */ +#define HW_Cursor_ON 0 +#define HW_Cursor_OFF 1 + +#define CURSOR_SIZE (8 * 1024) +#define VQ_SIZE (256 * 1024) + +#define VIA_MMIO_BLTBASE 0x200000 +#define VIA_MMIO_BLTSIZE 0x200000 + +/* Defines for 2D registers */ +#define VIA_REG_GECMD 0x000 +#define VIA_REG_GEMODE 0x004 +#define VIA_REG_SRCPOS 0x008 +#define VIA_REG_DSTPOS 0x00C +/* width and height */ +#define VIA_REG_DIMENSION 0x010 +#define VIA_REG_PATADDR 0x014 +#define VIA_REG_FGCOLOR 0x018 +#define VIA_REG_BGCOLOR 0x01C +/* top and left of clipping */ +#define VIA_REG_CLIPTL 0x020 +/* bottom and right of clipping */ +#define VIA_REG_CLIPBR 0x024 +#define VIA_REG_OFFSET 0x028 +/* color key control */ +#define VIA_REG_KEYCONTROL 0x02C +#define VIA_REG_SRCBASE 0x030 +#define VIA_REG_DSTBASE 0x034 +/* pitch of src and dst */ +#define VIA_REG_PITCH 0x038 +#define VIA_REG_MONOPAT0 0x03C +#define VIA_REG_MONOPAT1 0x040 +/* from 0x100 to 0x1ff */ +#define VIA_REG_COLORPAT 0x100 + +/* VIA_REG_PITCH(0x38): Pitch Setting */ +#define VIA_PITCH_ENABLE 0x80000000 + +/* defines for VIA HW cursor registers */ +#define VIA_REG_CURSOR_MODE 0x2D0 +#define VIA_REG_CURSOR_POS 0x2D4 +#define VIA_REG_CURSOR_ORG 0x2D8 +#define VIA_REG_CURSOR_BG 0x2DC +#define VIA_REG_CURSOR_FG 0x2E0 + +/* VIA_REG_GEMODE(0x04): GE mode */ +#define VIA_GEM_8bpp 0x00000000 +#define VIA_GEM_16bpp 0x00000100 +#define VIA_GEM_32bpp 0x00000300 + +/* VIA_REG_GECMD(0x00): 2D Engine Command */ +#define VIA_GEC_NOOP 0x00000000 +#define VIA_GEC_BLT 0x00000001 +#define VIA_GEC_LINE 0x00000005 + +/* Rotate Command */ +#define VIA_GEC_ROT 0x00000008 + +#define VIA_GEC_SRC_XY 0x00000000 +#define VIA_GEC_SRC_LINEAR 0x00000010 +#define VIA_GEC_DST_XY 0x00000000 +#define VIA_GEC_DST_LINRAT 0x00000020 + +#define VIA_GEC_SRC_FB 0x00000000 +#define VIA_GEC_SRC_SYS 0x00000040 +#define VIA_GEC_DST_FB 0x00000000 +#define VIA_GEC_DST_SYS 0x00000080 + +/* source is mono */ +#define VIA_GEC_SRC_MONO 0x00000100 +/* pattern is mono */ +#define VIA_GEC_PAT_MONO 0x00000200 +/* mono src is opaque */ +#define VIA_GEC_MSRC_OPAQUE 0x00000000 +/* mono src is transparent */ +#define VIA_GEC_MSRC_TRANS 0x00000400 +/* pattern is in frame buffer */ +#define VIA_GEC_PAT_FB 0x00000000 +/* pattern is from reg setting */ +#define VIA_GEC_PAT_REG 0x00000800 + +#define VIA_GEC_CLIP_DISABLE 0x00000000 +#define VIA_GEC_CLIP_ENABLE 0x00001000 + +#define VIA_GEC_FIXCOLOR_PAT 0x00002000 + +#define VIA_GEC_INCX 0x00000000 +#define VIA_GEC_DECY 0x00004000 +#define VIA_GEC_INCY 0x00000000 +#define VIA_GEC_DECX 0x00008000 +/* mono pattern is opaque */ +#define VIA_GEC_MPAT_OPAQUE 0x00000000 +/* mono pattern is transparent */ +#define VIA_GEC_MPAT_TRANS 0x00010000 + +#define VIA_GEC_MONO_UNPACK 0x00000000 +#define VIA_GEC_MONO_PACK 0x00020000 +#define VIA_GEC_MONO_DWORD 0x00000000 +#define VIA_GEC_MONO_WORD 0x00040000 +#define VIA_GEC_MONO_BYTE 0x00080000 + +#define VIA_GEC_LASTPIXEL_ON 0x00000000 +#define VIA_GEC_LASTPIXEL_OFF 0x00100000 +#define VIA_GEC_X_MAJOR 0x00000000 +#define VIA_GEC_Y_MAJOR 0x00200000 +#define VIA_GEC_QUICK_START 0x00800000 + +/* defines for VIA 3D registers */ +#define VIA_REG_STATUS 0x400 +#define VIA_REG_TRANSET 0x43C +#define VIA_REG_TRANSPACE 0x440 + +/* VIA_REG_STATUS(0x400): Engine Status */ + +/* Command Regulator is busy */ +#define VIA_CMD_RGTR_BUSY 0x00000080 +/* 2D Engine is busy */ +#define VIA_2D_ENG_BUSY 0x00000002 +/* 3D Engine is busy */ +#define VIA_3D_ENG_BUSY 0x00000001 +/* Virtual Queue is busy */ +#define VIA_VR_QUEUE_BUSY 0x00020000 + +#define MAXLOOP 0xFFFFFF + +void init_accel(void); +void init_2d_engine(void); +void set_2d_color_depth(int); +void hw_cursor_init(void); +void show_hw_cursor(struct fb_info *info, int Status); int +wait_engine_idle(void); + +#endif /* __ACCEL_H__ */ diff -Nur a/drivers/video/via/chip.h b/drivers/video/via/chip.h --- a/drivers/video/via/chip.h 1969-12-31 19:00:00.000000000 -0500 +++ b/drivers/video/via/chip.h 2008-04-29 02:51:15.000000000 -0400 @@ -0,0 +1,189 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + option) + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef __CHIP_H__ +#define __CHIP_H__ + +#include "global.h" + +/***************************************/ +/* Definition Graphic Chip Information */ +/***************************************/ + +#define PCI_VIA_VENDOR_ID 0x1106 + +/* Define VIA Graphic Chip Name */ +#define UNICHROME_CLE266 1 +#define UNICHROME_CLE266_DID 0x3122 +#define CLE266_REVISION_AX 0x0A +#define CLE266_REVISION_CX 0x0C + +#define UNICHROME_K400 2 +#define UNICHROME_K400_DID 0x7205 + +#define UNICHROME_K800 3 +#define UNICHROME_K800_DID 0x3108 + +#define UNICHROME_PM800 4 +#define UNICHROME_PM800_DID 0x3118 + +#define UNICHROME_CN700 5 +#define UNICHROME_CN700_DID 0x3344 + +#define UNICHROME_CX700 6 +#define UNICHROME_CX700_DID 0x3157 +#define CX700_REVISION_700 0x0 +#define CX700_REVISION_700M 0x1 +#define CX700_REVISION_700M2 0x2 + +#define UNICHROME_CN750 7 +#define UNICHROME_CN750_DID 0x3225 + +#define UNICHROME_K8M890 8 +#define UNICHROME_K8M890_DID 0x3230 + +#define UNICHROME_P4M890 9 +#define UNICHROME_P4M890_DID 0x3343 + +#define UNICHROME_P4M900 10 +#define UNICHROME_P4M900_DID 0x3371 + +#define UNICHROME_VX800 11 +#define UNICHROME_VX800_DID 0x1122 +/**************************************************/ +/* Definition TMDS Trasmitter Information */ +/**************************************************/ + +/* Definition TMDS Trasmitter Index */ +#define NON_TMDS_TRANSMITTER 0x00 +#define VT1632_TMDS 0x01 +#define INTEGRATED_TMDS 0x42 + +/* Definition TMDS Trasmitter I2C Slave Address */ +#define VT1632_TMDS_I2C_ADDR 0x10 + +/**************************************************/ +/* Definition LVDS Trasmitter Information */ +/**************************************************/ + +/* Definition LVDS Trasmitter Index */ +#define NON_LVDS_TRANSMITTER 0x00 +#define VT1631_LVDS 0x01 +#define VT1636_LVDS 0x0E +#define INTEGRATED_LVDS 0x41 + +/* Definition Digital Transmitter Mode */ +#define TX_DATA_12_BITS 0x01 +#define TX_DATA_24_BITS 0x02 +#define TX_DATA_DDR_MODE 0x04 +#define TX_DATA_SDR_MODE 0x08 + +/* Definition LVDS Trasmitter I2C Slave Address */ +#define VT1631_LVDS_I2C_ADDR 0x70 +#define VT3271_LVDS_I2C_ADDR 0x80 +#define VT1636_LVDS_I2C_ADDR 0x80 + +struct tmds_chip_information { + int tmds_chip_name; + int tmds_chip_slave_addr; + int dvi_panel_id; + int data_mode; + int output_interface; + int i2c_port; + int device_type; +}; + +struct lvds_chip_information { + int lvds_chip_name; + int lvds_chip_slave_addr; + int data_mode; + int output_interface; + int i2c_port; +}; + +struct chip_information { + int gfx_chip_name; + int gfx_chip_revision; + int chip_on_slot; + struct tmds_chip_information tmds_chip_info; + struct lvds_chip_information lvds_chip_info; + struct lvds_chip_information lvds_chip_info2; }; + +struct crt_setting_information { + int iga_path; + int h_active; + int v_active; + int bpp; + int refresh_rate; +}; + +struct tmds_setting_information { + int iga_path; + int h_active; + int v_active; + int bpp; + int refresh_rate; + int get_dvi_size_method; + int max_pixel_clock; + int dvi_panel_size; + int dvi_panel_hres; + int dvi_panel_vres; + int native_size; +}; + +struct lvds_setting_information { + int iga_path; + int h_active; + int v_active; + int bpp; + int refresh_rate; + int get_lcd_size_method; + int lcd_panel_id; + int lcd_panel_size; + int lcd_panel_hres; + int lcd_panel_vres; + int display_method; + int device_lcd_dualedge; + int LCDDithering; + int lcd_mode; + u32 vclk; /*panel mode clock value */ +}; + +struct GFX_DPA_SETTING { + int ClkRangeIndex; + u8 DVP0; /* CR96[3:0] */ + u8 DVP0DataDri_S1; /* SR2A[5] */ + u8 DVP0DataDri_S; /* SR1B[1] */ + u8 DVP0ClockDri_S1; /* SR2A[4] */ + u8 DVP0ClockDri_S; /* SR1E[2] */ + u8 DVP1; /* CR9B[3:0] */ + u8 DVP1Driving; /* SR65[3:0], Data and Clock driving */ + u8 DFPHigh; /* CR97[3:0] */ + u8 DFPLow; /* CR99[3:0] */ + +}; + +struct VT1636_DPA_SETTING { + int PanelSizeID; + u8 CLK_SEL_ST1; + u8 CLK_SEL_ST2; +}; +#endif /* __CHIP_H__ */ diff -Nur a/drivers/video/via/debug.h b/drivers/video/via/debug.h --- a/drivers/video/via/debug.h 1969-12-31 19:00:00.000000000 -0500 +++ b/drivers/video/via/debug.h 2008-05-04 06:42:33.000000000 -0400 @@ -0,0 +1,41 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + option) + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#ifndef VIAFB_DEBUG +#define VIAFB_DEBUG 0 +#endif + +#if VIAFB_DEBUG +#define DEBUG_MSG(f, a...) printk(f, ## a) +#else +#define DEBUG_MSG(f, a...) +#endif + +#define VIAFB_WARN 0 +#if VIAFB_WARN +#define WARN_MSG(f, a...) printk(f, ## a) +#else +#define WARN_MSG(f, a...) +#endif + +#endif /* __DEBUG_H__ */ diff -Nur a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c --- a/drivers/video/via/dvi.c 1969-12-31 19:00:00.000000000 -0500 +++ b/drivers/video/via/dvi.c 2008-05-04 07:28:49.000000000 -0400 @@ -0,0 +1,721 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + option) + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include "global.h" + +int check_tmds_chip(int device_id_subaddr, int device_id) { + if (tmds_register_read(device_id_subaddr) == device_id) + return (OK); + else + return (FAIL); +} + +void init_dvi_size(void) +{ + DEBUG_MSG(KERN_INFO "init_dvi_size()\n"); + DEBUG_MSG(KERN_INFO "tmds_setting_info.get_dvi_size_method %d\n", + tmds_setting_info.get_dvi_size_method); + + switch (tmds_setting_info.get_dvi_size_method) { + case GET_DVI_SIZE_BY_SYSTEM_BIOS: + break; + case GET_DVI_SZIE_BY_HW_STRAPPING: + break; + case GET_DVI_SIZE_BY_VGA_BIOS: + default: + dvi_get_panel_info(); + break; + } + return; +} + +int tmds_trasmitter_identify(void) +{ + unsigned char sr2a = 0, sr1e = 0, sr3e = 0; + + /* Turn on ouputting pad */ + switch (chip_info.gfx_chip_name) { + case UNICHROME_K8M890: + /*=* DFP Low Pad on *=*/ + sr2a = read_reg(VIASR, SR2A); + write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); + break; + + case UNICHROME_P4M900: + case UNICHROME_P4M890: + /* DFP Low Pad on */ + sr2a = read_reg(VIASR, SR2A); + write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); + /* DVP0 Pad on */ + sr1e = read_reg(VIASR, SR1E); + write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7); + break; + + default: + /* DVP0/DVP1 Pad on */ + sr1e = read_reg(VIASR, SR1E); + write_reg_mask(SR1E, VIASR, 0xF0, BIT4 + BIT5 + BIT6 + BIT7); + /* SR3E[1]Multi-function selection: + 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ + sr3e = read_reg(VIASR, SR3E); + write_reg_mask(SR3E, VIASR, 0x0, BIT5); + break; + } + + /* Check for VT1632: */ + chip_info.tmds_chip_info.tmds_chip_name = VT1632_TMDS; + chip_info.tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; + chip_info.tmds_chip_info.i2c_port = I2CPORTINDEX; + if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { + /*Currently only support 12bits,dual edge,add 24bits mode later */ + tmds_register_write(0x08, 0x3b); + + DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); + DEBUG_MSG(KERN_INFO "\n %2d", + chip_info.tmds_chip_info.tmds_chip_name); + DEBUG_MSG(KERN_INFO "\n %2d", + chip_info.tmds_chip_info.i2c_port); + return (OK); + } else { + chip_info.tmds_chip_info.i2c_port = GPIOPORTINDEX; + if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) + != FAIL) { + tmds_register_write(0x08, 0x3b); + DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); + DEBUG_MSG(KERN_INFO "\n %2d", + chip_info.tmds_chip_info.tmds_chip_name); + DEBUG_MSG(KERN_INFO "\n %2d", + chip_info.tmds_chip_info.i2c_port); + return (OK); + } + } + + chip_info.tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS; + + if ((chip_info.gfx_chip_name == UNICHROME_CX700) && + ((display_hardware_layout == HW_LAYOUT_DVI_ONLY) || + (display_hardware_layout == HW_LAYOUT_LCD_DVI))) { + DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n"); + return (OK); + } + + switch (chip_info.gfx_chip_name) { + case UNICHROME_K8M890: + write_reg(SR2A, VIASR, sr2a); + break; + + case UNICHROME_P4M900: + case UNICHROME_P4M890: + write_reg(SR2A, VIASR, sr2a); + write_reg(SR1E, VIASR, sr1e); + break; + + default: + write_reg(SR1E, VIASR, sr1e); + write_reg(SR3E, VIASR, sr3e); + break; + } + + chip_info.tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER; + chip_info.tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; + return (FAIL); +} + +void tmds_register_write(int index, u8 data) { + u8 tmp; + + tmp = chip_info.chip_on_slot; + switch (chip_info.tmds_chip_info.i2c_port) { + case I2CPORTINDEX: + chip_info.chip_on_slot = PORT_ON_AMR; + break; + + case GPIOPORTINDEX: + default: + chip_info.chip_on_slot = PORT_ON_AGP; + break; + } + + i2cWriteByte(chip_info.tmds_chip_info.tmds_chip_slave_addr, index, + data); + + chip_info.chip_on_slot = tmp; + +} + +int tmds_register_read(int index) +{ + u8 data; + int status; + u8 tmp; + + tmp = chip_info.chip_on_slot; + switch (chip_info.tmds_chip_info.i2c_port) { + case I2CPORTINDEX: + chip_info.chip_on_slot = PORT_ON_AMR; + break; + + case GPIOPORTINDEX: + default: + chip_info.chip_on_slot = PORT_ON_AGP; + break; + } + + status = + i2cReadByte((u8) chip_info.tmds_chip_info.tmds_chip_slave_addr, + (u8) index, &data); + chip_info.chip_on_slot = tmp; + return (data); +} + +int tmds_register_read_bytes(int index, u8 *buff, int buff_len) { + int status; + u8 tmp; + + tmp = chip_info.chip_on_slot; + switch (chip_info.tmds_chip_info.i2c_port) { + case I2CPORTINDEX: + chip_info.chip_on_slot = PORT_ON_AMR; + break; + + case GPIOPORTINDEX: + default: + chip_info.chip_on_slot = PORT_ON_AGP; + break; + } + + status = + i2cReadBytes((u8) chip_info.tmds_chip_info. + tmds_chip_slave_addr, (u8) index, buff, buff_len); + chip_info.chip_on_slot = tmp; + return (status); +} + +int check_reduce_blanking_mode(int mode_index, int refresh_rate) { + if (refresh_rate != 60) + return (FALSE); + + switch (mode_index) { + /* Following modes have reduce blanking mode. */ + case VIA_RES_1360X768: + case VIA_RES_1400X1050: + case VIA_RES_1440X900: + case VIA_RES_1600X900: + case VIA_RES_1680X1050: + case VIA_RES_1920X1080: + case VIA_RES_1920X1200: + break; + + default: + DEBUG_MSG(KERN_INFO + "This dvi mode %d have no reduce blanking mode!\n", + mode_index); + return (FALSE); + } + + return (TRUE); +} + +/* DVI Set Mode */ +void dvi_set_mode(int video_index, int mode_bpp, int set_iga) { + struct VideoModeTable *videoMode = NULL; + struct crt_mode_table *pDviTiming; + unsigned long desirePixelClock, maxPixelClock; + int status = 0; + videoMode = get_modetbl_pointer(video_index); + pDviTiming = videoMode->crtc; + desirePixelClock = pDviTiming->clk / 1000000; + maxPixelClock = (unsigned long)tmds_setting_info.max_pixel_clock; + + DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); + + if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { + /*Check if reduce-blanking mode is exist */ + status = + check_reduce_blanking_mode(video_index, + pDviTiming->refresh_rate); + if (status) { + video_index += 100; /*Use reduce-blanking mode */ + videoMode = get_modetbl_pointer(video_index); + pDviTiming = videoMode->crtc; + DEBUG_MSG(KERN_INFO + "DVI use reduce blanking mode %d!!\n", + video_index); + } + } + fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga); + set_output_path(DEVICE_DVI, set_iga, + chip_info.tmds_chip_info.output_interface); +} + +/* Sense DVI Connector */ +int dvi_sense(void) +{ + u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0, RegCR93 = + 0, RegCR9B = 0, data; + int ret = FALSE; + + DEBUG_MSG(KERN_INFO "dvi_sense!!\n"); + + if (chip_info.gfx_chip_name == UNICHROME_CLE266) { + /* DI1 Pad on */ + RegSR1E = read_reg(VIASR, SR1E); + write_reg(SR1E, VIASR, RegSR1E | 0x30); + + /* CR6B[0]VCK Input Selection: 1 = External clock. */ + RegCR6B = read_reg(VIACR, CR6B); + write_reg(CR6B, VIACR, RegCR6B | 0x08); + + /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off + [0] Software Control Power Sequence */ + RegCR91 = read_reg(VIACR, CR91); + write_reg(CR91, VIACR, 0x1D); + + /* CR93[7] DI1 Data Source Selection: 1 = DSP2. + CR93[5] DI1 Clock Source: 1 = internal. + CR93[4] DI1 Clock Polarity. + CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */ + RegCR93 = read_reg(VIACR, CR93); + write_reg(CR93, VIACR, 0x01); + } else { + /* DVP0/DVP1 Pad on */ + RegSR1E = read_reg(VIASR, SR1E); + write_reg(SR1E, VIASR, RegSR1E | 0xF0); + + /* SR3E[1]Multi-function selection: + 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ + RegSR3E = read_reg(VIASR, SR3E); + write_reg(SR3E, VIASR, RegSR3E & (~0x20)); + + /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off + [0] Software Control Power Sequence */ + RegCR91 = read_reg(VIACR, CR91); + write_reg(CR91, VIACR, 0x1D); + + /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary + display.CR9B[2:0] DVP1 Clock Adjust */ + RegCR9B = read_reg(VIACR, CR9B); + write_reg(CR9B, VIACR, 0x01); + } + + data = (u8) tmds_register_read(0x09); + if (data & 0x04) + ret = TRUE; + + if (ret == FALSE) { + if (dvi_query_EDID()) + ret = TRUE; + } + + /* Restore status */ + if (chip_info.gfx_chip_name == UNICHROME_CLE266) { + write_reg(SR1E, VIASR, RegSR1E); + write_reg(CR6B, VIACR, RegCR6B); + write_reg(CR91, VIACR, RegCR91); + write_reg(CR93, VIACR, RegCR93); + } else { + write_reg(SR1E, VIASR, RegSR1E); + write_reg(SR3E, VIASR, RegSR3E); + write_reg(CR91, VIACR, RegCR91); + write_reg(CR9B, VIACR, RegCR9B); + } + + return ret; +} + +/* Query Flat Panel's EDID Table Version Through DVI Connector */ int +dvi_query_EDID(void) { + u8 data0, data1; + int restore; + + DEBUG_MSG(KERN_INFO "dvi_query_EDID!!\n"); + + restore = chip_info.tmds_chip_info.tmds_chip_slave_addr; + chip_info.tmds_chip_info.tmds_chip_slave_addr = 0xA0; + + data0 = (u8) tmds_register_read(0x00); + data1 = (u8) tmds_register_read(0x01); + if ((data0 == 0) && (data1 == 0xFF)) { + chip_info.tmds_chip_info.tmds_chip_slave_addr = restore; + return (EDID_VERSION_1); /* Found EDID1 Table */ + } + + data0 = (u8) tmds_register_read(0x00); + chip_info.tmds_chip_info.tmds_chip_slave_addr = restore; + if (data0 == 0x20) + return (EDID_VERSION_2); /* Found EDID2 Table */ + else + return (FALSE); +} + +/* + * + * int dvi_get_panel_size_from_DDCv1(void) + * + * - Get Panel Size Using EDID1 Table + * + * Return Type: int + * + */ +int dvi_get_panel_size_from_DDCv1(void) +{ + int i, max_h = 0, max_v = 0, tmp, restore; + unsigned char rData; + unsigned char EDID_DATA[18]; + + DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); + + restore = chip_info.tmds_chip_info.tmds_chip_slave_addr; + chip_info.tmds_chip_info.tmds_chip_slave_addr = 0xA0; + + for (i = 0x23; i < 0x6D; i++) { + switch (i) { + case 0x23: + rData = tmds_register_read(0x23); + if (rData & 0x3C) + max_h = 640; + if (rData & 0xC0) + max_h = 720; + if (rData & 0x03) + max_h = 800; + break; + case 0x24: + rData = tmds_register_read(0x24); + if (rData & 0xC0) + max_h = 800; + if (rData & 0x1E) + max_h = 1024; + if (rData & 0x01) + max_h = 1280; + break; + case 0x26: + case 0x28: + case 0x2A: + case 0x2C: + case 0x2E: + case 0x30: + case 0x32: + case 0x34: + rData = tmds_register_read(i); + if (rData == 1) + break; + /* data = (data + 31) * 8 */ + tmp = (rData + 31) << 3; + if (tmp > max_h) + max_h = tmp; + break; + + case 0x36: + case 0x48: + case 0x5A: + case 0x6C: + tmds_register_read_bytes(i, EDID_DATA, 10); + if (!(EDID_DATA[0] || EDID_DATA[1])) { + /* The first two byte must be zero. */ + if (EDID_DATA[3] == 0xFD) { + /* To get max pixel clock. */ + tmds_setting_info.max_pixel_clock = + EDID_DATA[9] * 10; + } + } + break; + + default: + break; + } + } + + switch (max_h) { + case 640: + tmds_setting_info.dvi_panel_size = VIA_RES_640X480; + break; + case 800: + tmds_setting_info.dvi_panel_size = VIA_RES_800X600; + break; + case 1024: + tmds_setting_info.dvi_panel_size = VIA_RES_1024X768; + break; + case 1280: + tmds_setting_info.dvi_panel_size = VIA_RES_1280X1024; + break; + case 1400: + tmds_setting_info.dvi_panel_size = VIA_RES_1400X1050; + break; + case 1440: + tmds_setting_info.dvi_panel_size = VIA_RES_1440X1050; + break; + case 1600: + tmds_setting_info.dvi_panel_size = VIA_RES_1600X1200; + break; + case 1920: + if (max_v == 1200) + tmds_setting_info.dvi_panel_size = VIA_RES_1920X1200; + else + tmds_setting_info.dvi_panel_size = VIA_RES_1920X1080; + break; + default: + tmds_setting_info.dvi_panel_size = VIA_RES_1024X768; + DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\ + set default panel size.\n", max_h); + break; + } + + DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", + tmds_setting_info.max_pixel_clock); + chip_info.tmds_chip_info.tmds_chip_slave_addr = restore; + return tmds_setting_info.dvi_panel_size; } + +/* + * + * int dvi_get_panel_size_from_DDCv2(void) + * + * - Get Panel Size Using EDID2 Table + * + * Return Type: int + * + */ +int dvi_get_panel_size_from_DDCv2(void) +{ + int HSize = 0, restore; + unsigned char R_Buffer[2]; + + DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); + + restore = chip_info.tmds_chip_info.tmds_chip_slave_addr; + chip_info.tmds_chip_info.tmds_chip_slave_addr = 0xA2; + + /* Horizontal: 0x76, 0x77 */ + tmds_register_read_bytes(0x76, R_Buffer, 2); + HSize = R_Buffer[0]; + HSize += R_Buffer[1] << 8; + + switch (HSize) { + case 640: + tmds_setting_info.dvi_panel_size = VIA_RES_640X480; + break; + case 800: + tmds_setting_info.dvi_panel_size = VIA_RES_800X600; + break; + case 1024: + tmds_setting_info.dvi_panel_size = VIA_RES_1024X768; + break; + case 1280: + tmds_setting_info.dvi_panel_size = VIA_RES_1280X1024; + break; + case 1400: + tmds_setting_info.dvi_panel_size = VIA_RES_1400X1050; + break; + case 1440: + tmds_setting_info.dvi_panel_size = VIA_RES_1440X1050; + break; + case 1600: + tmds_setting_info.dvi_panel_size = VIA_RES_1600X1200; + break; + default: + tmds_setting_info.dvi_panel_size = VIA_RES_1024X768; + DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\ + set default panel size.\n", HSize); + break; + } + + chip_info.tmds_chip_info.tmds_chip_slave_addr = restore; + return tmds_setting_info.dvi_panel_size; } + +/* + * + * unsigned char dvi_get_panel_info(void) + * + * - Get Panel Size + * + * Return Type: unsigned char + */ +unsigned char dvi_get_panel_info(void) +{ + DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n"); + + dvi_sense(); + switch (dvi_query_EDID()) { + case 1: + dvi_get_panel_size_from_DDCv1(); + break; + case 2: + dvi_get_panel_size_from_DDCv2(); + break; + default: + break; + } + + DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n", + tmds_setting_info.dvi_panel_size); + return (unsigned char)(tmds_setting_info.dvi_panel_size); +} + +/* If Disable DVI, turn off pad */ +void dvi_disable(void) +{ + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DVP0) + write_reg(SR1E, VIASR, read_reg(VIASR, SR1E) & (~0xC0)); + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DVP1) + write_reg(SR1E, VIASR, read_reg(VIASR, SR1E) & (~0x30)); + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) + write_reg(SR2A, VIASR, read_reg(VIASR, SR2A) & (~0x0C)); + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DFP_LOW) + write_reg(SR2A, VIASR, read_reg(VIASR, SR2A) & (~0x03)); + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_TMDS) + /* Turn off TMDS power. */ + write_reg(CRD2, VIACR, read_reg(VIACR, CRD2) | 0x08); } + +/* If Enable DVI, turn off pad */ +void dvi_enable(void) +{ + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DVP0) { + write_reg(SR1E, VIASR, read_reg(VIASR, SR1E) | 0xC0); + if (chip_info.gfx_chip_name == UNICHROME_CLE266) + tmds_register_write(0x88, 0x3b); + else + /*clear CR91[5] to direct on display period + in the secondary diplay path */ + write_reg(CR91, VIACR, read_reg(VIACR, CR91) & 0xDF); + } + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DVP1) { + write_reg(SR1E, VIASR, read_reg(VIASR, SR1E) | 0x30); + + /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */ + if (chip_info.gfx_chip_name == UNICHROME_CLE266) { + tmds_register_write(0x88, 0x3b); + } else { + /*clear CR91[5] to direct on display period + in the secondary diplay path */ + write_reg(CR91, VIACR, read_reg(VIACR, CR91) & 0xDF); + } + + /*fix DVI cannot enable on EPIA-M board */ + if (platform_epia_dvi == 1) { + write_reg_mask(CR91, VIACR, 0x1f, 0x1f); + write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0); + if (via_bus_width == 24) { + if (device_lcd_dualedge == 1) + i2cWriteByte(chip_info. + tmds_chip_info. + tmds_chip_slave_addr, + 0x08, 0x3F); + else + i2cWriteByte(chip_info. + tmds_chip_info. + tmds_chip_slave_addr, + 0x08, 0x37); + } + } + } + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) { + write_reg(SR2A, VIASR, read_reg(VIASR, SR2A) | 0x0C); + write_reg(CR91, VIACR, read_reg(VIACR, CR91) & 0xDF); + } + + if (chip_info.tmds_chip_info.output_interface == INTERFACE_DFP_LOW) { + write_reg(SR2A, VIASR, read_reg(VIASR, SR2A) | 0x03); + write_reg(CR91, VIACR, read_reg(VIACR, CR91) & 0xDF); + } + if (chip_info.tmds_chip_info.output_interface == INTERFACE_TMDS) { + /* Turn on Display period in the panel path. */ + write_reg_mask(CR91, VIACR, 0, BIT7); + + /* Turn on TMDS power. */ + write_reg_mask(CRD2, VIACR, 0, BIT3); + } +} + +int check_hdmi_connected_device(void) +{ + int bEdidExist = FALSE; + u8 byTemp = 0, byTemp1 = 0, byTemp2 = 0; + u8 byVendorDataBlock; + int restore, result = DEV_CONNECT_DVI; + + restore = chip_info.tmds_chip_info.tmds_chip_slave_addr; + chip_info.tmds_chip_info.tmds_chip_slave_addr = 0xA0; + byTemp = (u8) tmds_register_read(0x00); + + if (byTemp == 0x00) { + byTemp = (u8) tmds_register_read(0x01); + if (byTemp == 0xFF) + bEdidExist = TRUE; + } + + if (bEdidExist) { + byTemp = (u8) tmds_register_read(0x80); + byTemp1 = (u8) tmds_register_read(0x81); + + if (byTemp == 0x02 && byTemp1 == 0x03) { + byTemp = (u8) tmds_register_read(0x82); + + if (!(byTemp == 0 || byTemp == 4)) { + byVendorDataBlock = 0x82 + 2; + + byTemp1 = (u8) + tmds_register_read(byVendorDataBlock); + while ((byTemp1 & 0xE0) != 0x60 + && byVendorDataBlock < (byTemp + 0x82)) { + byTemp1 &= 0x1F; + + byVendorDataBlock += (byTemp1 + 1); + + byTemp1 = (u8) + tmds_register_read + (byVendorDataBlock); + } + if ((byTemp1 & 0xE0) == 0x60) { + byTemp = (u8) + tmds_register_read + (byVendorDataBlock + 1); + byTemp1 = (u8) + tmds_register_read + (byVendorDataBlock + 2); + byTemp2 = (u8) + tmds_register_read + (byVendorDataBlock + 3); + + if (byTemp == 0x03 + && byTemp1 == 0x0C + && byTemp2 == 0x00) + result = DEV_CONNECT_HDMI; + } + } + } + } + + chip_info.tmds_chip_info.tmds_chip_slave_addr = restore; + return result; +} -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |