mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 07:04:10 +08:00
Merge branch 'viafb-next' of git://git.lwn.net/linux-2.6
* 'viafb-next' of git://git.lwn.net/linux-2.6: (35 commits) viafb: move some include files to include/linux viafb: Eliminate some global.h references viafb: get rid of i2c debug cruft viafb: fold via_io.h into via-core.h viafb: Fix initialization error paths viafb: Do not remove gpiochip under spinlock viafb: make procfs entries optional viafb: fix proc entry removal viafb: improve misc register handling viafb: replace inb/outb viafb: move some modesetting functions to a seperate file viafb: unify modesetting functions viafb: Reserve framebuffer memory for the upcoming camera driver viafb: Add a simple VX855 DMA engine driver viafb: Add a simple interrupt management infrastructure via: Rationalize vt1636 detection viafb: Introduce viafb_find_i2c_adapter() via: Do not attempt I/O on inactive I2C adapters viafb: Turn GPIO and i2c into proper platform devices viafb: Convert GPIO and i2c to the new indexed port ops ...
This commit is contained in:
commit
7c6d87ac84
@ -1511,6 +1511,7 @@ config FB_VIA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
select I2C_ALGOBIT
|
||||
select I2C
|
||||
select GPIOLIB
|
||||
help
|
||||
This is the frame buffer device driver for Graphics chips of VIA
|
||||
UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
|
||||
@ -1520,6 +1521,21 @@ config FB_VIA
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called viafb.
|
||||
|
||||
if FB_VIA
|
||||
|
||||
config FB_VIA_DIRECT_PROCFS
|
||||
bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
|
||||
depends on FB_VIA
|
||||
default n
|
||||
help
|
||||
Allow direct hardware access to some output registers via procfs.
|
||||
This is dangerous but may provide the only chance to get the
|
||||
correct output device configuration.
|
||||
Its use is strongly discouraged.
|
||||
|
||||
endif
|
||||
|
||||
config FB_NEOMAGIC
|
||||
tristate "NeoMagic display support"
|
||||
depends on FB && PCI
|
||||
|
@ -4,4 +4,6 @@
|
||||
|
||||
obj-$(CONFIG_FB_VIA) += viafb.o
|
||||
|
||||
viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
|
||||
viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
|
||||
via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o \
|
||||
via-core.o via-gpio.o via_modesetting.o
|
||||
|
@ -18,14 +18,45 @@
|
||||
* Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <linux/via-core.h>
|
||||
#include "global.h"
|
||||
|
||||
/*
|
||||
* Figure out an appropriate bytes-per-pixel setting.
|
||||
*/
|
||||
static int viafb_set_bpp(void __iomem *engine, u8 bpp)
|
||||
{
|
||||
u32 gemode;
|
||||
|
||||
/* Preserve the reserved bits */
|
||||
/* Lowest 2 bits to zero gives us no rotation */
|
||||
gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
gemode |= VIA_GEM_8bpp;
|
||||
break;
|
||||
case 16:
|
||||
gemode |= VIA_GEM_16bpp;
|
||||
break;
|
||||
case 32:
|
||||
gemode |= VIA_GEM_32bpp;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
|
||||
return -EINVAL;
|
||||
}
|
||||
writel(gemode, engine + VIA_REG_GEMODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
|
||||
u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
|
||||
u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
|
||||
u32 fg_color, u32 bg_color, u8 fill_rop)
|
||||
{
|
||||
u32 ge_cmd = 0, tmp, i;
|
||||
int ret;
|
||||
|
||||
if (!op || op > 3) {
|
||||
printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
|
||||
@ -59,22 +90,9 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
|
||||
}
|
||||
}
|
||||
|
||||
switch (dst_bpp) {
|
||||
case 8:
|
||||
tmp = 0x00000000;
|
||||
break;
|
||||
case 16:
|
||||
tmp = 0x00000100;
|
||||
break;
|
||||
case 32:
|
||||
tmp = 0x00000300;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n",
|
||||
dst_bpp);
|
||||
return -EINVAL;
|
||||
}
|
||||
writel(tmp, engine + 0x04);
|
||||
ret = viafb_set_bpp(engine, dst_bpp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (op != VIA_BITBLT_FILL) {
|
||||
if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
|
||||
@ -171,6 +189,7 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
|
||||
u32 fg_color, u32 bg_color, u8 fill_rop)
|
||||
{
|
||||
u32 ge_cmd = 0, tmp, i;
|
||||
int ret;
|
||||
|
||||
if (!op || op > 3) {
|
||||
printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
|
||||
@ -204,22 +223,9 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
|
||||
}
|
||||
}
|
||||
|
||||
switch (dst_bpp) {
|
||||
case 8:
|
||||
tmp = 0x00000000;
|
||||
break;
|
||||
case 16:
|
||||
tmp = 0x00000100;
|
||||
break;
|
||||
case 32:
|
||||
tmp = 0x00000300;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n",
|
||||
dst_bpp);
|
||||
return -EINVAL;
|
||||
}
|
||||
writel(tmp, engine + 0x04);
|
||||
ret = viafb_set_bpp(engine, dst_bpp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (op == VIA_BITBLT_FILL)
|
||||
tmp = 0;
|
||||
@ -312,17 +318,29 @@ int viafb_init_engine(struct fb_info *info)
|
||||
{
|
||||
struct viafb_par *viapar = info->par;
|
||||
void __iomem *engine;
|
||||
int highest_reg, i;
|
||||
u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
|
||||
vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
|
||||
|
||||
engine = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
|
||||
viapar->shared->engine_mmio = engine;
|
||||
engine = viapar->shared->vdev->engine_mmio;
|
||||
if (!engine) {
|
||||
printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
|
||||
"hardware acceleration disabled\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize registers to reset the 2D engine */
|
||||
switch (viapar->shared->chip_info.twod_engine) {
|
||||
case VIA_2D_ENG_M1:
|
||||
highest_reg = 0x5c;
|
||||
break;
|
||||
default:
|
||||
highest_reg = 0x40;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i <= highest_reg; i += 4)
|
||||
writel(0x0, engine + i);
|
||||
|
||||
switch (chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
case UNICHROME_K400:
|
||||
@ -352,13 +370,28 @@ int viafb_init_engine(struct fb_info *info)
|
||||
viapar->shared->vq_vram_addr = viapar->fbmem_free;
|
||||
viapar->fbmem_used += VQ_SIZE;
|
||||
|
||||
/* Init 2D engine reg to reset 2D engine */
|
||||
writel(0x0, engine + VIA_REG_KEYCONTROL);
|
||||
#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE)
|
||||
/*
|
||||
* Set aside a chunk of framebuffer memory for the camera
|
||||
* driver. Someday this driver probably needs a proper allocator
|
||||
* for fbmem; for now, we just have to do this before the
|
||||
* framebuffer initializes itself.
|
||||
*
|
||||
* As for the size: the engine can handle three frames,
|
||||
* 16 bits deep, up to VGA resolution.
|
||||
*/
|
||||
viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2;
|
||||
viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size;
|
||||
viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size;
|
||||
viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
|
||||
#endif
|
||||
|
||||
/* Init AGP and VQ regs */
|
||||
switch (chip_name) {
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
writel(0x00100000, engine + VIA_REG_CR_TRANSET);
|
||||
writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
|
||||
writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
|
||||
@ -393,6 +426,8 @@ int viafb_init_engine(struct fb_info *info)
|
||||
switch (chip_name) {
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
vq_start_low |= 0x20000000;
|
||||
vq_end_low |= 0x20000000;
|
||||
vq_high |= 0x20000000;
|
||||
@ -446,7 +481,7 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status)
|
||||
struct viafb_par *viapar = info->par;
|
||||
u32 temp, iga_path = viapar->iga_path;
|
||||
|
||||
temp = readl(viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE);
|
||||
temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
|
||||
switch (Status) {
|
||||
case HW_Cursor_ON:
|
||||
temp |= 0x1;
|
||||
@ -463,23 +498,33 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status)
|
||||
default:
|
||||
temp &= 0x7FFFFFFF;
|
||||
}
|
||||
writel(temp, viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE);
|
||||
writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
|
||||
}
|
||||
|
||||
void viafb_wait_engine_idle(struct fb_info *info)
|
||||
{
|
||||
struct viafb_par *viapar = info->par;
|
||||
int loop = 0;
|
||||
u32 mask;
|
||||
void __iomem *engine = viapar->shared->vdev->engine_mmio;
|
||||
|
||||
while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) &
|
||||
VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
|
||||
loop++;
|
||||
cpu_relax();
|
||||
switch (viapar->shared->chip_info.twod_engine) {
|
||||
case VIA_2D_ENG_H5:
|
||||
case VIA_2D_ENG_M1:
|
||||
mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 |
|
||||
VIA_3D_ENG_BUSY_M1;
|
||||
break;
|
||||
default:
|
||||
while (!(readl(engine + VIA_REG_STATUS) &
|
||||
VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
|
||||
loop++;
|
||||
cpu_relax();
|
||||
}
|
||||
mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) &
|
||||
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
|
||||
(loop < MAXLOOP)) {
|
||||
while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) {
|
||||
loop++;
|
||||
cpu_relax();
|
||||
}
|
||||
|
@ -67,6 +67,34 @@
|
||||
/* from 0x100 to 0x1ff */
|
||||
#define VIA_REG_COLORPAT 0x100
|
||||
|
||||
/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/
|
||||
#define VIA_REG_GECMD_M1 0x000
|
||||
#define VIA_REG_GEMODE_M1 0x004
|
||||
#define VIA_REG_GESTATUS_M1 0x004 /* as same as VIA_REG_GEMODE */
|
||||
#define VIA_REG_PITCH_M1 0x008 /* pitch of src and dst */
|
||||
#define VIA_REG_DIMENSION_M1 0x00C /* width and height */
|
||||
#define VIA_REG_DSTPOS_M1 0x010
|
||||
#define VIA_REG_LINE_XY_M1 0x010
|
||||
#define VIA_REG_DSTBASE_M1 0x014
|
||||
#define VIA_REG_SRCPOS_M1 0x018
|
||||
#define VIA_REG_LINE_K1K2_M1 0x018
|
||||
#define VIA_REG_SRCBASE_M1 0x01C
|
||||
#define VIA_REG_PATADDR_M1 0x020
|
||||
#define VIA_REG_MONOPAT0_M1 0x024
|
||||
#define VIA_REG_MONOPAT1_M1 0x028
|
||||
#define VIA_REG_OFFSET_M1 0x02C
|
||||
#define VIA_REG_LINE_ERROR_M1 0x02C
|
||||
#define VIA_REG_CLIPTL_M1 0x040 /* top and left of clipping */
|
||||
#define VIA_REG_CLIPBR_M1 0x044 /* bottom and right of clipping */
|
||||
#define VIA_REG_KEYCONTROL_M1 0x048 /* color key control */
|
||||
#define VIA_REG_FGCOLOR_M1 0x04C
|
||||
#define VIA_REG_DSTCOLORKEY_M1 0x04C /* as same as VIA_REG_FG */
|
||||
#define VIA_REG_BGCOLOR_M1 0x050
|
||||
#define VIA_REG_SRCCOLORKEY_M1 0x050 /* as same as VIA_REG_BG */
|
||||
#define VIA_REG_MONOPATFGC_M1 0x058 /* Add BG color of Pattern. */
|
||||
#define VIA_REG_MONOPATBGC_M1 0x05C /* Add FG color of Pattern. */
|
||||
#define VIA_REG_COLORPAT_M1 0x100 /* from 0x100 to 0x1ff */
|
||||
|
||||
/* VIA_REG_PITCH(0x38): Pitch Setting */
|
||||
#define VIA_PITCH_ENABLE 0x80000000
|
||||
|
||||
@ -157,6 +185,18 @@
|
||||
/* Virtual Queue is busy */
|
||||
#define VIA_VR_QUEUE_BUSY 0x00020000
|
||||
|
||||
/* VIA_REG_STATUS(0x400): Engine Status for H5 */
|
||||
#define VIA_CMD_RGTR_BUSY_H5 0x00000010 /* Command Regulator is busy */
|
||||
#define VIA_2D_ENG_BUSY_H5 0x00000002 /* 2D Engine is busy */
|
||||
#define VIA_3D_ENG_BUSY_H5 0x00001FE1 /* 3D Engine is busy */
|
||||
#define VIA_VR_QUEUE_BUSY_H5 0x00000004 /* Virtual Queue is busy */
|
||||
|
||||
/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */
|
||||
#define VIA_CMD_RGTR_BUSY_M1 0x00000010 /* Command Regulator is busy */
|
||||
#define VIA_2D_ENG_BUSY_M1 0x00000002 /* 2D Engine is busy */
|
||||
#define VIA_3D_ENG_BUSY_M1 0x00001FE1 /* 3D Engine is busy */
|
||||
#define VIA_VR_QUEUE_BUSY_M1 0x00000004 /* Virtual Queue is busy */
|
||||
|
||||
#define MAXLOOP 0xFFFFFF
|
||||
|
||||
#define VIA_BITBLT_COLOR 1
|
||||
|
@ -121,9 +121,17 @@ struct lvds_chip_information {
|
||||
int i2c_port;
|
||||
};
|
||||
|
||||
/* The type of 2D engine */
|
||||
enum via_2d_engine {
|
||||
VIA_2D_ENG_H2,
|
||||
VIA_2D_ENG_H5,
|
||||
VIA_2D_ENG_M1,
|
||||
};
|
||||
|
||||
struct chip_information {
|
||||
int gfx_chip_name;
|
||||
int gfx_chip_revision;
|
||||
enum via_2d_engine twod_engine;
|
||||
struct tmds_chip_information tmds_chip_info;
|
||||
struct lvds_chip_information lvds_chip_info;
|
||||
struct lvds_chip_information lvds_chip_info2;
|
||||
|
@ -18,6 +18,8 @@
|
||||
* Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <linux/via-core.h>
|
||||
#include <linux/via_i2c.h>
|
||||
#include "global.h"
|
||||
|
||||
static void tmds_register_write(int index, u8 data);
|
||||
@ -96,7 +98,7 @@ int viafb_tmds_trasmitter_identify(void)
|
||||
viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
|
||||
viaparinfo->chip_info->
|
||||
tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX;
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
|
||||
if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) {
|
||||
/*
|
||||
* Currently only support 12bits,dual edge,add 24bits mode later
|
||||
@ -110,7 +112,7 @@ int viafb_tmds_trasmitter_identify(void)
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port);
|
||||
return OK;
|
||||
} else {
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX;
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
|
||||
if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)
|
||||
!= FAIL) {
|
||||
tmds_register_write(0x08, 0x3b);
|
||||
@ -160,32 +162,26 @@ int viafb_tmds_trasmitter_identify(void)
|
||||
|
||||
static void tmds_register_write(int index, u8 data)
|
||||
{
|
||||
viaparinfo->shared->i2c_stuff.i2c_port =
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port;
|
||||
|
||||
viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.
|
||||
tmds_chip_slave_addr, index,
|
||||
data);
|
||||
viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
|
||||
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
|
||||
index, data);
|
||||
}
|
||||
|
||||
static int tmds_register_read(int index)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
viaparinfo->shared->i2c_stuff.i2c_port =
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port;
|
||||
viafb_i2c_readbyte((u8) viaparinfo->chip_info->
|
||||
tmds_chip_info.tmds_chip_slave_addr,
|
||||
(u8) index, &data);
|
||||
viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
|
||||
(u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
|
||||
(u8) index, &data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
|
||||
{
|
||||
viaparinfo->shared->i2c_stuff.i2c_port =
|
||||
viaparinfo->chip_info->tmds_chip_info.i2c_port;
|
||||
viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info.
|
||||
tmds_chip_slave_addr, (u8) index, buff, buff_len);
|
||||
viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,
|
||||
(u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
|
||||
(u8) index, buff, buff_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -541,9 +537,10 @@ void viafb_dvi_enable(void)
|
||||
else
|
||||
data = 0x37;
|
||||
viafb_i2c_writebyte(viaparinfo->chip_info->
|
||||
tmds_chip_info.
|
||||
tmds_chip_slave_addr,
|
||||
0x08, data);
|
||||
tmds_chip_info.i2c_port,
|
||||
viaparinfo->chip_info->
|
||||
tmds_chip_info.tmds_chip_slave_addr,
|
||||
0x08, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "share.h"
|
||||
#include "dvi.h"
|
||||
#include "viamode.h"
|
||||
#include "via_i2c.h"
|
||||
#include "hw.h"
|
||||
|
||||
#include "lcd.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/via-core.h>
|
||||
#include "global.h"
|
||||
|
||||
static struct pll_map pll_value[] = {
|
||||
@ -62,6 +63,7 @@ static struct pll_map pll_value[] = {
|
||||
CX700_52_977M, VX855_52_977M},
|
||||
{CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M,
|
||||
CX700_56_250M, VX855_56_250M},
|
||||
{CLK_57_275M, 0, 0, 0, VX855_57_275M},
|
||||
{CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M,
|
||||
CX700_60_466M, VX855_60_466M},
|
||||
{CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M,
|
||||
@ -525,8 +527,7 @@ static void dvi_patch_skew_dvp_low(void);
|
||||
static void set_dvi_output_path(int set_iga, int output_interface);
|
||||
static void set_lcd_output_path(int set_iga, int output_interface);
|
||||
static void load_fix_bit_crtc_reg(void);
|
||||
static void init_gfx_chip_info(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pdi);
|
||||
static void init_gfx_chip_info(int chip_type);
|
||||
static void init_tmds_chip_info(void);
|
||||
static void init_lvds_chip_info(void);
|
||||
static void device_screen_off(void);
|
||||
@ -537,18 +538,6 @@ static void device_on(void);
|
||||
static void enable_second_display_channel(void);
|
||||
static void disable_second_display_channel(void);
|
||||
|
||||
void viafb_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); */
|
||||
}
|
||||
u8 viafb_read_reg(int io_port, u8 index)
|
||||
{
|
||||
outb(index, io_port);
|
||||
return inb(io_port + 1);
|
||||
}
|
||||
|
||||
void viafb_lock_crt(void)
|
||||
{
|
||||
viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
|
||||
@ -560,16 +549,6 @@ void viafb_unlock_crt(void)
|
||||
viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
|
||||
}
|
||||
|
||||
void viafb_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);
|
||||
@ -646,102 +625,6 @@ void viafb_set_iga_path(void)
|
||||
}
|
||||
}
|
||||
|
||||
void viafb_set_primary_address(u32 addr)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_set_primary_address(0x%08X)\n", addr);
|
||||
viafb_write_reg(CR0D, VIACR, addr & 0xFF);
|
||||
viafb_write_reg(CR0C, VIACR, (addr >> 8) & 0xFF);
|
||||
viafb_write_reg(CR34, VIACR, (addr >> 16) & 0xFF);
|
||||
viafb_write_reg_mask(CR48, VIACR, (addr >> 24) & 0x1F, 0x1F);
|
||||
}
|
||||
|
||||
void viafb_set_secondary_address(u32 addr)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_address(0x%08X)\n", addr);
|
||||
/* secondary display supports only quadword aligned memory */
|
||||
viafb_write_reg_mask(CR62, VIACR, (addr >> 2) & 0xFE, 0xFE);
|
||||
viafb_write_reg(CR63, VIACR, (addr >> 10) & 0xFF);
|
||||
viafb_write_reg(CR64, VIACR, (addr >> 18) & 0xFF);
|
||||
viafb_write_reg_mask(CRA3, VIACR, (addr >> 26) & 0x07, 0x07);
|
||||
}
|
||||
|
||||
void viafb_set_primary_pitch(u32 pitch)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_set_primary_pitch(0x%08X)\n", pitch);
|
||||
/* spec does not say that first adapter skips 3 bits but old
|
||||
* code did it and seems to be reasonable in analogy to 2nd adapter
|
||||
*/
|
||||
pitch = pitch >> 3;
|
||||
viafb_write_reg(0x13, VIACR, pitch & 0xFF);
|
||||
viafb_write_reg_mask(0x35, VIACR, (pitch >> (8 - 5)) & 0xE0, 0xE0);
|
||||
}
|
||||
|
||||
void viafb_set_secondary_pitch(u32 pitch)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_pitch(0x%08X)\n", pitch);
|
||||
pitch = pitch >> 3;
|
||||
viafb_write_reg(0x66, VIACR, pitch & 0xFF);
|
||||
viafb_write_reg_mask(0x67, VIACR, (pitch >> 8) & 0x03, 0x03);
|
||||
viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80);
|
||||
}
|
||||
|
||||
void viafb_set_primary_color_depth(u8 depth)
|
||||
{
|
||||
u8 value;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth);
|
||||
switch (depth) {
|
||||
case 8:
|
||||
value = 0x00;
|
||||
break;
|
||||
case 15:
|
||||
value = 0x04;
|
||||
break;
|
||||
case 16:
|
||||
value = 0x14;
|
||||
break;
|
||||
case 24:
|
||||
value = 0x0C;
|
||||
break;
|
||||
case 30:
|
||||
value = 0x08;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "viafb_set_primary_color_depth: "
|
||||
"Unsupported depth: %d\n", depth);
|
||||
return;
|
||||
}
|
||||
|
||||
viafb_write_reg_mask(0x15, VIASR, value, 0x1C);
|
||||
}
|
||||
|
||||
void viafb_set_secondary_color_depth(u8 depth)
|
||||
{
|
||||
u8 value;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth);
|
||||
switch (depth) {
|
||||
case 8:
|
||||
value = 0x00;
|
||||
break;
|
||||
case 16:
|
||||
value = 0x40;
|
||||
break;
|
||||
case 24:
|
||||
value = 0xC0;
|
||||
break;
|
||||
case 30:
|
||||
value = 0x80;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "viafb_set_secondary_color_depth: "
|
||||
"Unsupported depth: %d\n", depth);
|
||||
return;
|
||||
}
|
||||
|
||||
viafb_write_reg_mask(0x67, VIACR, value, 0xC0);
|
||||
}
|
||||
|
||||
static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
|
||||
{
|
||||
outb(0xFF, 0x3C6); /* bit mask of palette */
|
||||
@ -1126,16 +1009,12 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num,
|
||||
void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
|
||||
{
|
||||
int i;
|
||||
unsigned char RegTemp;
|
||||
|
||||
/*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
|
||||
|
||||
for (i = 0; i < ItemNum; i++) {
|
||||
outb(RegTable[i].index, RegTable[i].port);
|
||||
RegTemp = inb(RegTable[i].port + 1);
|
||||
RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value;
|
||||
outb(RegTemp, RegTable[i].port + 1);
|
||||
}
|
||||
for (i = 0; i < ItemNum; i++)
|
||||
via_write_reg_mask(RegTable[i].port, RegTable[i].index,
|
||||
RegTable[i].value, RegTable[i].mask);
|
||||
}
|
||||
|
||||
void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
|
||||
@ -1516,8 +1395,6 @@ u32 viafb_get_clk_value(int clk)
|
||||
/* Set VCLK*/
|
||||
void viafb_set_vclock(u32 CLK, int set_iga)
|
||||
{
|
||||
unsigned char RegTemp;
|
||||
|
||||
/* H.W. Reset : ON */
|
||||
viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
|
||||
|
||||
@ -1590,8 +1467,7 @@ void viafb_set_vclock(u32 CLK, int set_iga)
|
||||
}
|
||||
|
||||
/* Fire! */
|
||||
RegTemp = inb(VIARMisc);
|
||||
outb(RegTemp | (BIT2 + BIT3), VIAWMisc);
|
||||
via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
|
||||
}
|
||||
|
||||
void viafb_load_crtc_timing(struct display_timing device_timing,
|
||||
@ -1835,6 +1711,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
|
||||
int index = 0;
|
||||
int h_addr, v_addr;
|
||||
u32 pll_D_N;
|
||||
u8 polarity = 0;
|
||||
|
||||
for (i = 0; i < video_mode->mode_array; i++) {
|
||||
index = i;
|
||||
@ -1863,20 +1740,11 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
|
||||
v_addr = crt_reg.ver_addr;
|
||||
|
||||
/* update polarity for CRT timing */
|
||||
if (crt_table[index].h_sync_polarity == NEGATIVE) {
|
||||
if (crt_table[index].v_sync_polarity == NEGATIVE)
|
||||
outb((inb(VIARMisc) & (~(BIT6 + BIT7))) |
|
||||
(BIT6 + BIT7), VIAWMisc);
|
||||
else
|
||||
outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6),
|
||||
VIAWMisc);
|
||||
} else {
|
||||
if (crt_table[index].v_sync_polarity == NEGATIVE)
|
||||
outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7),
|
||||
VIAWMisc);
|
||||
else
|
||||
outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc);
|
||||
}
|
||||
if (crt_table[index].h_sync_polarity == NEGATIVE)
|
||||
polarity |= BIT6;
|
||||
if (crt_table[index].v_sync_polarity == NEGATIVE)
|
||||
polarity |= BIT7;
|
||||
via_write_misc_reg_mask(polarity, BIT6 | BIT7);
|
||||
|
||||
if (set_iga == IGA1) {
|
||||
viafb_unlock_crt();
|
||||
@ -1910,10 +1778,9 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
|
||||
|
||||
}
|
||||
|
||||
void viafb_init_chip_info(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pdi)
|
||||
void viafb_init_chip_info(int chip_type)
|
||||
{
|
||||
init_gfx_chip_info(pdev, pdi);
|
||||
init_gfx_chip_info(chip_type);
|
||||
init_tmds_chip_info();
|
||||
init_lvds_chip_info();
|
||||
|
||||
@ -1980,12 +1847,11 @@ void viafb_update_device_setting(int hres, int vres,
|
||||
}
|
||||
}
|
||||
|
||||
static void init_gfx_chip_info(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pdi)
|
||||
static void init_gfx_chip_info(int chip_type)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
viaparinfo->chip_info->gfx_chip_name = pdi->driver_data;
|
||||
viaparinfo->chip_info->gfx_chip_name = chip_type;
|
||||
|
||||
/* Check revision of CLE266 Chip */
|
||||
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
|
||||
@ -2016,6 +1882,21 @@ static void init_gfx_chip_info(struct pci_dev *pdev,
|
||||
CX700_REVISION_700;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine which 2D engine we have */
|
||||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
|
||||
break;
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M900:
|
||||
viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
|
||||
break;
|
||||
default:
|
||||
viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_tmds_chip_info(void)
|
||||
@ -2232,13 +2113,11 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
|
||||
|
||||
/* Fill VPIT Parameters */
|
||||
/* Write Misc Register */
|
||||
outb(VPIT.Misc, VIAWMisc);
|
||||
outb(VPIT.Misc, VIA_MISC_REG_WRITE);
|
||||
|
||||
/* Write Sequencer */
|
||||
for (i = 1; i <= StdSR; i++) {
|
||||
outb(i, VIASR);
|
||||
outb(VPIT.SR[i - 1], VIASR + 1);
|
||||
}
|
||||
for (i = 1; i <= StdSR; i++)
|
||||
via_write_reg(VIASR, i, VPIT.SR[i - 1]);
|
||||
|
||||
viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
|
||||
viafb_set_iga_path();
|
||||
@ -2247,10 +2126,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
|
||||
viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1);
|
||||
|
||||
/* Write Graphic Controller */
|
||||
for (i = 0; i < StdGR; i++) {
|
||||
outb(i, VIAGR);
|
||||
outb(VPIT.GR[i], VIAGR + 1);
|
||||
}
|
||||
for (i = 0; i < StdGR; i++)
|
||||
via_write_reg(VIAGR, i, VPIT.GR[i]);
|
||||
|
||||
/* Write Attribute Controller */
|
||||
for (i = 0; i < StdAR; i++) {
|
||||
@ -2277,11 +2154,11 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
|
||||
}
|
||||
}
|
||||
|
||||
viafb_set_primary_pitch(viafbinfo->fix.line_length);
|
||||
viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
|
||||
via_set_primary_pitch(viafbinfo->fix.line_length);
|
||||
via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
|
||||
: viafbinfo->fix.line_length);
|
||||
viafb_set_primary_color_depth(viaparinfo->depth);
|
||||
viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
|
||||
via_set_primary_color_depth(viaparinfo->depth);
|
||||
via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
|
||||
: viaparinfo->depth);
|
||||
/* Update Refresh Rate Setting */
|
||||
|
||||
@ -2473,108 +2350,6 @@ static void disable_second_display_channel(void)
|
||||
viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
|
||||
}
|
||||
|
||||
int viafb_get_fb_size_from_pci(void)
|
||||
{
|
||||
unsigned long configid, deviceid, FBSize = 0;
|
||||
int VideoMemSize;
|
||||
int DeviceFound = false;
|
||||
|
||||
for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) {
|
||||
outl(configid, (unsigned long)0xCF8);
|
||||
deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff;
|
||||
|
||||
switch (deviceid) {
|
||||
case CLE266:
|
||||
case KM400:
|
||||
outl(configid + 0xE0, (unsigned long)0xCF8);
|
||||
FBSize = inl((unsigned long)0xCFC);
|
||||
DeviceFound = true; /* Found device id */
|
||||
break;
|
||||
|
||||
case CN400_FUNCTION3:
|
||||
case CN700_FUNCTION3:
|
||||
case CX700_FUNCTION3:
|
||||
case KM800_FUNCTION3:
|
||||
case KM890_FUNCTION3:
|
||||
case P4M890_FUNCTION3:
|
||||
case P4M900_FUNCTION3:
|
||||
case VX800_FUNCTION3:
|
||||
case VX855_FUNCTION3:
|
||||
/*case CN750_FUNCTION3: */
|
||||
outl(configid + 0xA0, (unsigned long)0xCF8);
|
||||
FBSize = inl((unsigned long)0xCFC);
|
||||
DeviceFound = true; /* Found device id */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (DeviceFound)
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid);
|
||||
|
||||
FBSize = FBSize & 0x00007000;
|
||||
DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
|
||||
|
||||
if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) {
|
||||
switch (FBSize) {
|
||||
case 0x00004000:
|
||||
VideoMemSize = (16 << 20); /*16M */
|
||||
break;
|
||||
|
||||
case 0x00005000:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
|
||||
case 0x00006000:
|
||||
VideoMemSize = (64 << 20); /*64M */
|
||||
break;
|
||||
|
||||
default:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (FBSize) {
|
||||
case 0x00001000:
|
||||
VideoMemSize = (8 << 20); /*8M */
|
||||
break;
|
||||
|
||||
case 0x00002000:
|
||||
VideoMemSize = (16 << 20); /*16M */
|
||||
break;
|
||||
|
||||
case 0x00003000:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
|
||||
case 0x00004000:
|
||||
VideoMemSize = (64 << 20); /*64M */
|
||||
break;
|
||||
|
||||
case 0x00005000:
|
||||
VideoMemSize = (128 << 20); /*128M */
|
||||
break;
|
||||
|
||||
case 0x00006000:
|
||||
VideoMemSize = (256 << 20); /*256M */
|
||||
break;
|
||||
|
||||
case 0x00007000: /* Only on VX855/875 */
|
||||
VideoMemSize = (512 << 20); /*512M */
|
||||
break;
|
||||
|
||||
default:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return VideoMemSize;
|
||||
}
|
||||
|
||||
void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
|
||||
*p_gfx_dpa_setting)
|
||||
|
@ -24,6 +24,11 @@
|
||||
|
||||
#include "viamode.h"
|
||||
#include "global.h"
|
||||
#include "via_modesetting.h"
|
||||
|
||||
#define viafb_read_reg(p, i) via_read_reg(p, i)
|
||||
#define viafb_write_reg(i, p, d) via_write_reg(p, i, d)
|
||||
#define viafb_write_reg_mask(i, p, d, m) via_write_reg_mask(p, i, d, m)
|
||||
|
||||
/***************************************************
|
||||
* Definition IGA1 Design Method of CRTC Registers *
|
||||
@ -823,8 +828,8 @@ struct iga2_crtc_timing {
|
||||
};
|
||||
|
||||
/* device ID */
|
||||
#define CLE266 0x3123
|
||||
#define KM400 0x3205
|
||||
#define CLE266_FUNCTION3 0x3123
|
||||
#define KM400_FUNCTION3 0x3205
|
||||
#define CN400_FUNCTION2 0x2259
|
||||
#define CN400_FUNCTION3 0x3259
|
||||
/* support VT3314 chipset */
|
||||
@ -870,7 +875,6 @@ extern int viafb_LCD_ON;
|
||||
extern int viafb_DVI_ON;
|
||||
extern int viafb_hotplug;
|
||||
|
||||
void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
|
||||
void viafb_set_output_path(int device, int set_iga,
|
||||
int output_interface);
|
||||
|
||||
@ -885,8 +889,6 @@ void viafb_crt_disable(void);
|
||||
void viafb_crt_enable(void);
|
||||
void init_ad9389(void);
|
||||
/* Access I/O Function */
|
||||
void viafb_write_reg(u8 index, u16 io_port, u8 data);
|
||||
u8 viafb_read_reg(int io_port, u8 index);
|
||||
void viafb_lock_crt(void);
|
||||
void viafb_unlock_crt(void);
|
||||
void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
|
||||
@ -900,20 +902,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
|
||||
struct VideoModeTable *vmode_tbl1, int video_bpp1);
|
||||
void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
|
||||
struct VideoModeTable *vmode_tbl);
|
||||
void viafb_init_chip_info(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pdi);
|
||||
void viafb_init_chip_info(int chip_type);
|
||||
void viafb_init_dac(int set_iga);
|
||||
int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
|
||||
int viafb_get_refresh(int hres, int vres, u32 float_refresh);
|
||||
void viafb_update_device_setting(int hres, int vres, int bpp,
|
||||
int vmode_refresh, int flag);
|
||||
|
||||
int viafb_get_fb_size_from_pci(void);
|
||||
void viafb_set_iga_path(void);
|
||||
void viafb_set_primary_address(u32 addr);
|
||||
void viafb_set_secondary_address(u32 addr);
|
||||
void viafb_set_primary_pitch(u32 pitch);
|
||||
void viafb_set_secondary_pitch(u32 pitch);
|
||||
void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
|
||||
void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
|
||||
void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
|
||||
|
@ -75,7 +75,7 @@
|
||||
/*SAMM operation flag*/
|
||||
#define OP_SAMM 0x80
|
||||
|
||||
#define LCD_PANEL_ID_MAXIMUM 22
|
||||
#define LCD_PANEL_ID_MAXIMUM 23
|
||||
|
||||
#define STATE_ON 0x1
|
||||
#define STATE_OFF 0x0
|
||||
|
@ -18,7 +18,8 @@
|
||||
* Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/via-core.h>
|
||||
#include <linux/via_i2c.h>
|
||||
#include "global.h"
|
||||
#include "lcdtbl.h"
|
||||
|
||||
@ -172,18 +173,16 @@ static bool lvds_identify_integratedlvds(void)
|
||||
|
||||
int viafb_lvds_trasmitter_identify(void)
|
||||
{
|
||||
viaparinfo->shared->i2c_stuff.i2c_port = I2CPORTINDEX;
|
||||
if (viafb_lvds_identify_vt1636()) {
|
||||
viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
|
||||
if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
|
||||
viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
|
||||
DEBUG_MSG(KERN_INFO
|
||||
"Found VIA VT1636 LVDS on port i2c 0x31 \n");
|
||||
"Found VIA VT1636 LVDS on port i2c 0x31\n");
|
||||
} else {
|
||||
viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX;
|
||||
if (viafb_lvds_identify_vt1636()) {
|
||||
if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
|
||||
viaparinfo->chip_info->lvds_chip_info.i2c_port =
|
||||
GPIOPORTINDEX;
|
||||
VIA_PORT_2C;
|
||||
DEBUG_MSG(KERN_INFO
|
||||
"Found VIA VT1636 LVDS on port gpio 0x2c \n");
|
||||
"Found VIA VT1636 LVDS on port gpio 0x2c\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,6 +397,15 @@ static void fp_id_to_vindex(int panel_id)
|
||||
viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
|
||||
viaparinfo->lvds_setting_info->LCDDithering = 1;
|
||||
break;
|
||||
case 0x17:
|
||||
/* OLPC XO-1.5 panel */
|
||||
viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
|
||||
viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
|
||||
viaparinfo->lvds_setting_info->lcd_panel_id =
|
||||
LCD_PANEL_IDD_1200X900;
|
||||
viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
|
||||
viaparinfo->lvds_setting_info->LCDDithering = 0;
|
||||
break;
|
||||
default:
|
||||
viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
|
||||
viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
|
||||
@ -412,9 +420,8 @@ static int lvds_register_read(int index)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX;
|
||||
viafb_i2c_readbyte((u8) viaparinfo->chip_info->
|
||||
lvds_chip_info.lvds_chip_slave_addr,
|
||||
viafb_i2c_readbyte(VIA_PORT_2C,
|
||||
(u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
|
||||
(u8) index, &data);
|
||||
return data;
|
||||
}
|
||||
|
@ -60,6 +60,8 @@
|
||||
#define LCD_PANEL_IDB_1360X768 0x0B
|
||||
/* Resolution: 480x640, Channel: single, Dithering: Enable */
|
||||
#define LCD_PANEL_IDC_480X640 0x0C
|
||||
/* Resolution: 1200x900, Channel: single, Dithering: Disable */
|
||||
#define LCD_PANEL_IDD_1200X900 0x0D
|
||||
|
||||
|
||||
extern int viafb_LCD2_ON;
|
||||
|
@ -43,16 +43,9 @@
|
||||
/* Video Memory Size */
|
||||
#define VIDEO_MEMORY_SIZE_16M 0x1000000
|
||||
|
||||
/* standard VGA IO port
|
||||
*/
|
||||
#define VIARMisc 0x3CC
|
||||
#define VIAWMisc 0x3C2
|
||||
#define VIAStatus 0x3DA
|
||||
#define VIACR 0x3D4
|
||||
#define VIASR 0x3C4
|
||||
#define VIAGR 0x3CE
|
||||
#define VIAAR 0x3C0
|
||||
|
||||
/*
|
||||
* Lengths of the VPIT structure arrays.
|
||||
*/
|
||||
#define StdCR 0x19
|
||||
#define StdSR 0x04
|
||||
#define StdGR 0x09
|
||||
@ -570,6 +563,10 @@
|
||||
#define M1200X720_R60_HSP NEGATIVE
|
||||
#define M1200X720_R60_VSP POSITIVE
|
||||
|
||||
/* 1200x900@60 Sync Polarity (DCON) */
|
||||
#define M1200X900_R60_HSP NEGATIVE
|
||||
#define M1200X900_R60_VSP NEGATIVE
|
||||
|
||||
/* 1280x600@60 Sync Polarity (GTF Mode) */
|
||||
#define M1280x600_R60_HSP NEGATIVE
|
||||
#define M1280x600_R60_VSP POSITIVE
|
||||
@ -651,6 +648,7 @@
|
||||
#define CLK_52_406M 52406000
|
||||
#define CLK_52_977M 52977000
|
||||
#define CLK_56_250M 56250000
|
||||
#define CLK_57_275M 57275000
|
||||
#define CLK_60_466M 60466000
|
||||
#define CLK_61_500M 61500000
|
||||
#define CLK_65_000M 65000000
|
||||
@ -939,6 +937,7 @@
|
||||
#define VX855_52_406M 0x00580C03
|
||||
#define VX855_52_977M 0x00940C05
|
||||
#define VX855_56_250M 0x009D0C05
|
||||
#define VX855_57_275M 0x009D8C85 /* Used by XO panel */
|
||||
#define VX855_60_466M 0x00A90C05
|
||||
#define VX855_61_500M 0x00AC0C05
|
||||
#define VX855_65_000M 0x006D0C03
|
||||
@ -1065,6 +1064,7 @@
|
||||
#define RES_1600X1200_60HZ_PIXCLOCK 6172
|
||||
#define RES_1600X1200_75HZ_PIXCLOCK 4938
|
||||
#define RES_1280X720_60HZ_PIXCLOCK 13426
|
||||
#define RES_1200X900_60HZ_PIXCLOCK 17459
|
||||
#define RES_1920X1080_60HZ_PIXCLOCK 5787
|
||||
#define RES_1400X1050_60HZ_PIXCLOCK 8214
|
||||
#define RES_1400X1050_75HZ_PIXCLOCK 6410
|
||||
|
668
drivers/video/via/via-core.c
Normal file
668
drivers/video/via/via-core.c
Normal file
@ -0,0 +1,668 @@
|
||||
/*
|
||||
* Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
|
||||
* Copyright 2009 Jonathan Corbet <corbet@lwn.net>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Core code for the Via multifunction framebuffer device.
|
||||
*/
|
||||
#include <linux/via-core.h>
|
||||
#include <linux/via_i2c.h>
|
||||
#include <linux/via-gpio.h>
|
||||
#include "global.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/*
|
||||
* The default port config.
|
||||
*/
|
||||
static struct via_port_cfg adap_configs[] = {
|
||||
[VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_OFF, VIASR, 0x26 },
|
||||
[VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
|
||||
[VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
|
||||
[VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
|
||||
[VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* We currently only support one viafb device (will there ever be
|
||||
* more than one?), so just declare it globally here.
|
||||
*/
|
||||
static struct viafb_dev global_dev;
|
||||
|
||||
|
||||
/*
|
||||
* Basic register access; spinlock required.
|
||||
*/
|
||||
static inline void viafb_mmio_write(int reg, u32 v)
|
||||
{
|
||||
iowrite32(v, global_dev.engine_mmio + reg);
|
||||
}
|
||||
|
||||
static inline int viafb_mmio_read(int reg)
|
||||
{
|
||||
return ioread32(global_dev.engine_mmio + reg);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/*
|
||||
* Interrupt management. We have a single IRQ line for a lot of
|
||||
* different functions, so we need to share it. The design here
|
||||
* is that we don't want to reimplement the shared IRQ code here;
|
||||
* we also want to avoid having contention for a single handler thread.
|
||||
* So each subdev driver which needs interrupts just requests
|
||||
* them directly from the kernel. We just have what's needed for
|
||||
* overall access to the interrupt control register.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Which interrupts are enabled now?
|
||||
*/
|
||||
static u32 viafb_enabled_ints;
|
||||
|
||||
static void viafb_int_init(void)
|
||||
{
|
||||
viafb_enabled_ints = 0;
|
||||
|
||||
viafb_mmio_write(VDE_INTERRUPT, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow subdevs to ask for specific interrupts to be enabled. These
|
||||
* functions must be called with reg_lock held
|
||||
*/
|
||||
void viafb_irq_enable(u32 mask)
|
||||
{
|
||||
viafb_enabled_ints |= mask;
|
||||
viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_irq_enable);
|
||||
|
||||
void viafb_irq_disable(u32 mask)
|
||||
{
|
||||
viafb_enabled_ints &= ~mask;
|
||||
if (viafb_enabled_ints == 0)
|
||||
viafb_mmio_write(VDE_INTERRUPT, 0); /* Disable entirely */
|
||||
else
|
||||
viafb_mmio_write(VDE_INTERRUPT,
|
||||
viafb_enabled_ints | VDE_I_ENABLE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_irq_disable);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/*
|
||||
* Access to the DMA engine. This currently provides what the camera
|
||||
* driver needs (i.e. outgoing only) but is easily expandable if need
|
||||
* be.
|
||||
*/
|
||||
|
||||
/*
|
||||
* There are four DMA channels in the vx855. For now, we only
|
||||
* use one of them, though. Most of the time, the DMA channel
|
||||
* will be idle, so we keep the IRQ handler unregistered except
|
||||
* when some subsystem has indicated an interest.
|
||||
*/
|
||||
static int viafb_dma_users;
|
||||
static DECLARE_COMPLETION(viafb_dma_completion);
|
||||
/*
|
||||
* This mutex protects viafb_dma_users and our global interrupt
|
||||
* registration state; it also serializes access to the DMA
|
||||
* engine.
|
||||
*/
|
||||
static DEFINE_MUTEX(viafb_dma_lock);
|
||||
|
||||
/*
|
||||
* The VX855 DMA descriptor (used for s/g transfers) looks
|
||||
* like this.
|
||||
*/
|
||||
struct viafb_vx855_dma_descr {
|
||||
u32 addr_low; /* Low part of phys addr */
|
||||
u32 addr_high; /* High 12 bits of addr */
|
||||
u32 fb_offset; /* Offset into FB memory */
|
||||
u32 seg_size; /* Size, 16-byte units */
|
||||
u32 tile_mode; /* "tile mode" setting */
|
||||
u32 next_desc_low; /* Next descriptor addr */
|
||||
u32 next_desc_high;
|
||||
u32 pad; /* Fill out to 64 bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags added to the "next descriptor low" pointers
|
||||
*/
|
||||
#define VIAFB_DMA_MAGIC 0x01 /* ??? Just has to be there */
|
||||
#define VIAFB_DMA_FINAL_SEGMENT 0x02 /* Final segment */
|
||||
|
||||
/*
|
||||
* The completion IRQ handler.
|
||||
*/
|
||||
static irqreturn_t viafb_dma_irq(int irq, void *data)
|
||||
{
|
||||
int csr;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
spin_lock(&global_dev.reg_lock);
|
||||
csr = viafb_mmio_read(VDMA_CSR0);
|
||||
if (csr & VDMA_C_DONE) {
|
||||
viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
|
||||
complete(&viafb_dma_completion);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
spin_unlock(&global_dev.reg_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate a need for DMA functionality.
|
||||
*/
|
||||
int viafb_request_dma(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Only VX855 is supported currently.
|
||||
*/
|
||||
if (global_dev.chip_type != UNICHROME_VX855)
|
||||
return -ENODEV;
|
||||
/*
|
||||
* Note the new user and set up our interrupt handler
|
||||
* if need be.
|
||||
*/
|
||||
mutex_lock(&viafb_dma_lock);
|
||||
viafb_dma_users++;
|
||||
if (viafb_dma_users == 1) {
|
||||
ret = request_irq(global_dev.pdev->irq, viafb_dma_irq,
|
||||
IRQF_SHARED, "via-dma", &viafb_dma_users);
|
||||
if (ret)
|
||||
viafb_dma_users--;
|
||||
else
|
||||
viafb_irq_enable(VDE_I_DMA0TDEN);
|
||||
}
|
||||
mutex_unlock(&viafb_dma_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_request_dma);
|
||||
|
||||
void viafb_release_dma(void)
|
||||
{
|
||||
mutex_lock(&viafb_dma_lock);
|
||||
viafb_dma_users--;
|
||||
if (viafb_dma_users == 0) {
|
||||
viafb_irq_disable(VDE_I_DMA0TDEN);
|
||||
free_irq(global_dev.pdev->irq, &viafb_dma_users);
|
||||
}
|
||||
mutex_unlock(&viafb_dma_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_release_dma);
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Copy a single buffer from FB memory, synchronously. This code works
|
||||
* but is not currently used.
|
||||
*/
|
||||
void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len)
|
||||
{
|
||||
unsigned long flags;
|
||||
int csr;
|
||||
|
||||
mutex_lock(&viafb_dma_lock);
|
||||
init_completion(&viafb_dma_completion);
|
||||
/*
|
||||
* Program the controller.
|
||||
*/
|
||||
spin_lock_irqsave(&global_dev.reg_lock, flags);
|
||||
viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
|
||||
/* Enable ints; must happen after CSR0 write! */
|
||||
viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE);
|
||||
viafb_mmio_write(VDMA_MARL0, (int) (paddr & 0xfffffff0));
|
||||
viafb_mmio_write(VDMA_MARH0, (int) ((paddr >> 28) & 0xfff));
|
||||
/* Data sheet suggests DAR0 should be <<4, but it lies */
|
||||
viafb_mmio_write(VDMA_DAR0, offset);
|
||||
viafb_mmio_write(VDMA_DQWCR0, len >> 4);
|
||||
viafb_mmio_write(VDMA_TMR0, 0);
|
||||
viafb_mmio_write(VDMA_DPRL0, 0);
|
||||
viafb_mmio_write(VDMA_DPRH0, 0);
|
||||
viafb_mmio_write(VDMA_PMR0, 0);
|
||||
csr = viafb_mmio_read(VDMA_CSR0);
|
||||
viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
|
||||
spin_unlock_irqrestore(&global_dev.reg_lock, flags);
|
||||
/*
|
||||
* Now we just wait until the interrupt handler says
|
||||
* we're done.
|
||||
*/
|
||||
wait_for_completion_interruptible(&viafb_dma_completion);
|
||||
viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
|
||||
mutex_unlock(&viafb_dma_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_dma_copy_out);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do a scatter/gather DMA copy from FB memory. You must have done
|
||||
* a successful call to viafb_request_dma() first.
|
||||
*/
|
||||
int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
|
||||
{
|
||||
struct viafb_vx855_dma_descr *descr;
|
||||
void *descrpages;
|
||||
dma_addr_t descr_handle;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
struct scatterlist *sgentry;
|
||||
dma_addr_t nextdesc;
|
||||
|
||||
/*
|
||||
* Get a place to put the descriptors.
|
||||
*/
|
||||
descrpages = dma_alloc_coherent(&global_dev.pdev->dev,
|
||||
nsg*sizeof(struct viafb_vx855_dma_descr),
|
||||
&descr_handle, GFP_KERNEL);
|
||||
if (descrpages == NULL) {
|
||||
dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
mutex_lock(&viafb_dma_lock);
|
||||
/*
|
||||
* Fill them in.
|
||||
*/
|
||||
descr = descrpages;
|
||||
nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr);
|
||||
for_each_sg(sg, sgentry, nsg, i) {
|
||||
dma_addr_t paddr = sg_dma_address(sgentry);
|
||||
descr->addr_low = paddr & 0xfffffff0;
|
||||
descr->addr_high = ((u64) paddr >> 32) & 0x0fff;
|
||||
descr->fb_offset = offset;
|
||||
descr->seg_size = sg_dma_len(sgentry) >> 4;
|
||||
descr->tile_mode = 0;
|
||||
descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC;
|
||||
descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff;
|
||||
descr->pad = 0xffffffff; /* VIA driver does this */
|
||||
offset += sg_dma_len(sgentry);
|
||||
nextdesc += sizeof(struct viafb_vx855_dma_descr);
|
||||
descr++;
|
||||
}
|
||||
descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC;
|
||||
/*
|
||||
* Program the engine.
|
||||
*/
|
||||
spin_lock_irqsave(&global_dev.reg_lock, flags);
|
||||
init_completion(&viafb_dma_completion);
|
||||
viafb_mmio_write(VDMA_DQWCR0, 0);
|
||||
viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
|
||||
viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN);
|
||||
viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC);
|
||||
viafb_mmio_write(VDMA_DPRH0,
|
||||
(((u64)descr_handle >> 32) & 0x0fff) | 0xf0000);
|
||||
(void) viafb_mmio_read(VDMA_CSR0);
|
||||
viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
|
||||
spin_unlock_irqrestore(&global_dev.reg_lock, flags);
|
||||
/*
|
||||
* Now we just wait until the interrupt handler says
|
||||
* we're done. Except that, actually, we need to wait a little
|
||||
* longer: the interrupts seem to jump the gun a little and we
|
||||
* get corrupted frames sometimes.
|
||||
*/
|
||||
wait_for_completion_timeout(&viafb_dma_completion, 1);
|
||||
msleep(1);
|
||||
if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0)
|
||||
printk(KERN_ERR "VIA DMA timeout!\n");
|
||||
/*
|
||||
* Clean up and we're done.
|
||||
*/
|
||||
viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
|
||||
viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
|
||||
mutex_unlock(&viafb_dma_lock);
|
||||
dma_free_coherent(&global_dev.pdev->dev,
|
||||
nsg*sizeof(struct viafb_vx855_dma_descr), descrpages,
|
||||
descr_handle);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/*
|
||||
* Figure out how big our framebuffer memory is. Kind of ugly,
|
||||
* but evidently we can't trust the information found in the
|
||||
* fbdev configuration area.
|
||||
*/
|
||||
static u16 via_function3[] = {
|
||||
CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
|
||||
CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
|
||||
P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3,
|
||||
};
|
||||
|
||||
/* Get the BIOS-configured framebuffer size from PCI configuration space
|
||||
* of function 3 in the respective chipset */
|
||||
static int viafb_get_fb_size_from_pci(int chip_type)
|
||||
{
|
||||
int i;
|
||||
u8 offset = 0;
|
||||
u32 FBSize;
|
||||
u32 VideoMemSize;
|
||||
|
||||
/* search for the "FUNCTION3" device in this chipset */
|
||||
for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
|
||||
struct pci_dev *pdev;
|
||||
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
|
||||
NULL);
|
||||
if (!pdev)
|
||||
continue;
|
||||
|
||||
DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
|
||||
|
||||
switch (pdev->device) {
|
||||
case CLE266_FUNCTION3:
|
||||
case KM400_FUNCTION3:
|
||||
offset = 0xE0;
|
||||
break;
|
||||
case CN400_FUNCTION3:
|
||||
case CN700_FUNCTION3:
|
||||
case CX700_FUNCTION3:
|
||||
case KM800_FUNCTION3:
|
||||
case KM890_FUNCTION3:
|
||||
case P4M890_FUNCTION3:
|
||||
case P4M900_FUNCTION3:
|
||||
case VX800_FUNCTION3:
|
||||
case VX855_FUNCTION3:
|
||||
/*case CN750_FUNCTION3: */
|
||||
offset = 0xA0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!offset)
|
||||
break;
|
||||
|
||||
pci_read_config_dword(pdev, offset, &FBSize);
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
||||
if (!offset) {
|
||||
printk(KERN_ERR "cannot determine framebuffer size\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
FBSize = FBSize & 0x00007000;
|
||||
DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
|
||||
|
||||
if (chip_type < UNICHROME_CX700) {
|
||||
switch (FBSize) {
|
||||
case 0x00004000:
|
||||
VideoMemSize = (16 << 20); /*16M */
|
||||
break;
|
||||
|
||||
case 0x00005000:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
|
||||
case 0x00006000:
|
||||
VideoMemSize = (64 << 20); /*64M */
|
||||
break;
|
||||
|
||||
default:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (FBSize) {
|
||||
case 0x00001000:
|
||||
VideoMemSize = (8 << 20); /*8M */
|
||||
break;
|
||||
|
||||
case 0x00002000:
|
||||
VideoMemSize = (16 << 20); /*16M */
|
||||
break;
|
||||
|
||||
case 0x00003000:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
|
||||
case 0x00004000:
|
||||
VideoMemSize = (64 << 20); /*64M */
|
||||
break;
|
||||
|
||||
case 0x00005000:
|
||||
VideoMemSize = (128 << 20); /*128M */
|
||||
break;
|
||||
|
||||
case 0x00006000:
|
||||
VideoMemSize = (256 << 20); /*256M */
|
||||
break;
|
||||
|
||||
case 0x00007000: /* Only on VX855/875 */
|
||||
VideoMemSize = (512 << 20); /*512M */
|
||||
break;
|
||||
|
||||
default:
|
||||
VideoMemSize = (32 << 20); /*32M */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return VideoMemSize;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Figure out and map our MMIO regions.
|
||||
*/
|
||||
static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
|
||||
{
|
||||
int ret;
|
||||
/*
|
||||
* Hook up to the device registers. Note that we soldier
|
||||
* on if it fails; the framebuffer can operate (without
|
||||
* acceleration) without this region.
|
||||
*/
|
||||
vdev->engine_start = pci_resource_start(vdev->pdev, 1);
|
||||
vdev->engine_len = pci_resource_len(vdev->pdev, 1);
|
||||
vdev->engine_mmio = ioremap_nocache(vdev->engine_start,
|
||||
vdev->engine_len);
|
||||
if (vdev->engine_mmio == NULL)
|
||||
dev_err(&vdev->pdev->dev,
|
||||
"Unable to map engine MMIO; operation will be "
|
||||
"slow and crippled.\n");
|
||||
/*
|
||||
* Map in framebuffer memory. For now, failure here is
|
||||
* fatal. Unfortunately, in the absence of significant
|
||||
* vmalloc space, failure here is also entirely plausible.
|
||||
* Eventually we want to move away from mapping this
|
||||
* entire region.
|
||||
*/
|
||||
vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
|
||||
ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
|
||||
if (ret < 0)
|
||||
goto out_unmap;
|
||||
vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len);
|
||||
if (vdev->fbmem == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unmap;
|
||||
}
|
||||
return 0;
|
||||
out_unmap:
|
||||
iounmap(vdev->engine_mmio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev)
|
||||
{
|
||||
iounmap(vdev->fbmem);
|
||||
iounmap(vdev->engine_mmio);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create our subsidiary devices.
|
||||
*/
|
||||
static struct viafb_subdev_info {
|
||||
char *name;
|
||||
struct platform_device *platdev;
|
||||
} viafb_subdevs[] = {
|
||||
{
|
||||
.name = "viafb-gpio",
|
||||
},
|
||||
{
|
||||
.name = "viafb-i2c",
|
||||
}
|
||||
};
|
||||
#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
|
||||
|
||||
static int __devinit via_create_subdev(struct viafb_dev *vdev,
|
||||
struct viafb_subdev_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
info->platdev = platform_device_alloc(info->name, -1);
|
||||
if (!info->platdev) {
|
||||
dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
|
||||
info->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->platdev->dev.parent = &vdev->pdev->dev;
|
||||
info->platdev->dev.platform_data = vdev;
|
||||
ret = platform_device_add(info->platdev);
|
||||
if (ret) {
|
||||
dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
|
||||
info->name);
|
||||
platform_device_put(info->platdev);
|
||||
info->platdev = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit via_setup_subdevs(struct viafb_dev *vdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Ignore return values. Even if some of the devices
|
||||
* fail to be created, we'll still be able to use some
|
||||
* of the rest.
|
||||
*/
|
||||
for (i = 0; i < N_SUBDEVS; i++)
|
||||
via_create_subdev(vdev, viafb_subdevs + i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit via_teardown_subdevs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N_SUBDEVS; i++)
|
||||
if (viafb_subdevs[i].platdev) {
|
||||
viafb_subdevs[i].platdev->dev.platform_data = NULL;
|
||||
platform_device_unregister(viafb_subdevs[i].platdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int __devinit via_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* Global device initialization.
|
||||
*/
|
||||
memset(&global_dev, 0, sizeof(global_dev));
|
||||
global_dev.pdev = pdev;
|
||||
global_dev.chip_type = ent->driver_data;
|
||||
global_dev.port_cfg = adap_configs;
|
||||
spin_lock_init(&global_dev.reg_lock);
|
||||
ret = via_pci_setup_mmio(&global_dev);
|
||||
if (ret)
|
||||
goto out_disable;
|
||||
/*
|
||||
* Set up interrupts and create our subdevices. Continue even if
|
||||
* some things fail.
|
||||
*/
|
||||
viafb_int_init();
|
||||
via_setup_subdevs(&global_dev);
|
||||
/*
|
||||
* Set up the framebuffer device
|
||||
*/
|
||||
ret = via_fb_pci_probe(&global_dev);
|
||||
if (ret)
|
||||
goto out_subdevs;
|
||||
return 0;
|
||||
|
||||
out_subdevs:
|
||||
via_teardown_subdevs();
|
||||
via_pci_teardown_mmio(&global_dev);
|
||||
out_disable:
|
||||
pci_disable_device(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit via_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
via_teardown_subdevs();
|
||||
via_fb_pci_remove(pdev);
|
||||
via_pci_teardown_mmio(&global_dev);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
|
||||
static struct pci_device_id via_pci_table[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
|
||||
.driver_data = UNICHROME_CLE266 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
|
||||
.driver_data = UNICHROME_PM800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
|
||||
.driver_data = UNICHROME_K400 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
|
||||
.driver_data = UNICHROME_K800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
|
||||
.driver_data = UNICHROME_CN700 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
|
||||
.driver_data = UNICHROME_K8M890 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
|
||||
.driver_data = UNICHROME_CX700 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
|
||||
.driver_data = UNICHROME_P4M900 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
|
||||
.driver_data = UNICHROME_CN750 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
|
||||
.driver_data = UNICHROME_VX800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
|
||||
.driver_data = UNICHROME_VX855 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, via_pci_table);
|
||||
|
||||
static struct pci_driver via_driver = {
|
||||
.name = "viafb",
|
||||
.id_table = via_pci_table,
|
||||
.probe = via_pci_probe,
|
||||
.remove = __devexit_p(via_pci_remove),
|
||||
};
|
||||
|
||||
static int __init via_core_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = viafb_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
viafb_i2c_init();
|
||||
viafb_gpio_init();
|
||||
return pci_register_driver(&via_driver);
|
||||
}
|
||||
|
||||
static void __exit via_core_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&via_driver);
|
||||
viafb_gpio_exit();
|
||||
viafb_i2c_exit();
|
||||
viafb_exit();
|
||||
}
|
||||
|
||||
module_init(via_core_init);
|
||||
module_exit(via_core_exit);
|
285
drivers/video/via/via-gpio.c
Normal file
285
drivers/video/via/via-gpio.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Support for viafb GPIO ports.
|
||||
*
|
||||
* Copyright 2009 Jonathan Corbet <corbet@lwn.net>
|
||||
* Distributable under version 2 of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/via-core.h>
|
||||
#include <linux/via-gpio.h>
|
||||
|
||||
/*
|
||||
* The ports we know about. Note that the port-25 gpios are not
|
||||
* mentioned in the datasheet.
|
||||
*/
|
||||
|
||||
struct viafb_gpio {
|
||||
char *vg_name; /* Data sheet name */
|
||||
u16 vg_io_port;
|
||||
u8 vg_port_index;
|
||||
int vg_mask_shift;
|
||||
};
|
||||
|
||||
static struct viafb_gpio viafb_all_gpios[] = {
|
||||
{
|
||||
.vg_name = "VGPIO0", /* Guess - not in datasheet */
|
||||
.vg_io_port = VIASR,
|
||||
.vg_port_index = 0x25,
|
||||
.vg_mask_shift = 1
|
||||
},
|
||||
{
|
||||
.vg_name = "VGPIO1",
|
||||
.vg_io_port = VIASR,
|
||||
.vg_port_index = 0x25,
|
||||
.vg_mask_shift = 0
|
||||
},
|
||||
{
|
||||
.vg_name = "VGPIO2", /* aka DISPCLKI0 */
|
||||
.vg_io_port = VIASR,
|
||||
.vg_port_index = 0x2c,
|
||||
.vg_mask_shift = 1
|
||||
},
|
||||
{
|
||||
.vg_name = "VGPIO3", /* aka DISPCLKO0 */
|
||||
.vg_io_port = VIASR,
|
||||
.vg_port_index = 0x2c,
|
||||
.vg_mask_shift = 0
|
||||
},
|
||||
{
|
||||
.vg_name = "VGPIO4", /* DISPCLKI1 */
|
||||
.vg_io_port = VIASR,
|
||||
.vg_port_index = 0x3d,
|
||||
.vg_mask_shift = 1
|
||||
},
|
||||
{
|
||||
.vg_name = "VGPIO5", /* DISPCLKO1 */
|
||||
.vg_io_port = VIASR,
|
||||
.vg_port_index = 0x3d,
|
||||
.vg_mask_shift = 0
|
||||
},
|
||||
};
|
||||
|
||||
#define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios)
|
||||
|
||||
/*
|
||||
* This structure controls the active GPIOs, which may be a subset
|
||||
* of those which are known.
|
||||
*/
|
||||
|
||||
struct viafb_gpio_cfg {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct viafb_dev *vdev;
|
||||
struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS];
|
||||
char *gpio_names[VIAFB_NUM_GPIOS];
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO access functions
|
||||
*/
|
||||
static void via_gpio_set(struct gpio_chip *chip, unsigned int nr,
|
||||
int value)
|
||||
{
|
||||
struct viafb_gpio_cfg *cfg = container_of(chip,
|
||||
struct viafb_gpio_cfg,
|
||||
gpio_chip);
|
||||
u8 reg;
|
||||
struct viafb_gpio *gpio;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
|
||||
gpio = cfg->active_gpios[nr];
|
||||
reg = via_read_reg(VIASR, gpio->vg_port_index);
|
||||
reg |= 0x40 << gpio->vg_mask_shift; /* output enable */
|
||||
if (value)
|
||||
reg |= 0x10 << gpio->vg_mask_shift;
|
||||
else
|
||||
reg &= ~(0x10 << gpio->vg_mask_shift);
|
||||
via_write_reg(VIASR, gpio->vg_port_index, reg);
|
||||
spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
|
||||
}
|
||||
|
||||
static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr,
|
||||
int value)
|
||||
{
|
||||
via_gpio_set(chip, nr, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the input direction. I'm not sure this is right; we should
|
||||
* be able to do input without disabling output.
|
||||
*/
|
||||
static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr)
|
||||
{
|
||||
struct viafb_gpio_cfg *cfg = container_of(chip,
|
||||
struct viafb_gpio_cfg,
|
||||
gpio_chip);
|
||||
struct viafb_gpio *gpio;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
|
||||
gpio = cfg->active_gpios[nr];
|
||||
via_write_reg_mask(VIASR, gpio->vg_port_index, 0,
|
||||
0x40 << gpio->vg_mask_shift);
|
||||
spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int via_gpio_get(struct gpio_chip *chip, unsigned int nr)
|
||||
{
|
||||
struct viafb_gpio_cfg *cfg = container_of(chip,
|
||||
struct viafb_gpio_cfg,
|
||||
gpio_chip);
|
||||
u8 reg;
|
||||
struct viafb_gpio *gpio;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
|
||||
gpio = cfg->active_gpios[nr];
|
||||
reg = via_read_reg(VIASR, gpio->vg_port_index);
|
||||
spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
|
||||
return reg & (0x04 << gpio->vg_mask_shift);
|
||||
}
|
||||
|
||||
|
||||
static struct viafb_gpio_cfg gpio_config = {
|
||||
.gpio_chip = {
|
||||
.label = "VIAFB onboard GPIO",
|
||||
.owner = THIS_MODULE,
|
||||
.direction_output = via_gpio_dir_out,
|
||||
.set = via_gpio_set,
|
||||
.direction_input = via_gpio_dir_input,
|
||||
.get = via_gpio_get,
|
||||
.base = -1,
|
||||
.ngpio = 0,
|
||||
.can_sleep = 0
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Manage the software enable bit.
|
||||
*/
|
||||
static void viafb_gpio_enable(struct viafb_gpio *gpio)
|
||||
{
|
||||
via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02);
|
||||
}
|
||||
|
||||
static void viafb_gpio_disable(struct viafb_gpio *gpio)
|
||||
{
|
||||
via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a specific gpio and return the number it was assigned.
|
||||
*/
|
||||
int viafb_gpio_lookup(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gpio_config.gpio_chip.ngpio; i++)
|
||||
if (!strcmp(name, gpio_config.active_gpios[i]->vg_name))
|
||||
return gpio_config.gpio_chip.base + i;
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
|
||||
|
||||
/*
|
||||
* Platform device stuff.
|
||||
*/
|
||||
static __devinit int viafb_gpio_probe(struct platform_device *platdev)
|
||||
{
|
||||
struct viafb_dev *vdev = platdev->dev.platform_data;
|
||||
struct via_port_cfg *port_cfg = vdev->port_cfg;
|
||||
int i, ngpio = 0, ret;
|
||||
struct viafb_gpio *gpio;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Set up entries for all GPIOs which have been configured to
|
||||
* operate as such (as opposed to as i2c ports).
|
||||
*/
|
||||
for (i = 0; i < VIAFB_NUM_PORTS; i++) {
|
||||
if (port_cfg[i].mode != VIA_MODE_GPIO)
|
||||
continue;
|
||||
for (gpio = viafb_all_gpios;
|
||||
gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++)
|
||||
if (gpio->vg_port_index == port_cfg[i].ioport_index) {
|
||||
gpio_config.active_gpios[ngpio] = gpio;
|
||||
gpio_config.gpio_names[ngpio] = gpio->vg_name;
|
||||
ngpio++;
|
||||
}
|
||||
}
|
||||
gpio_config.gpio_chip.ngpio = ngpio;
|
||||
gpio_config.gpio_chip.names = gpio_config.gpio_names;
|
||||
gpio_config.vdev = vdev;
|
||||
if (ngpio == 0) {
|
||||
printk(KERN_INFO "viafb: no GPIOs configured\n");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Enable the ports. They come in pairs, with a single
|
||||
* enable bit for both.
|
||||
*/
|
||||
spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags);
|
||||
for (i = 0; i < ngpio; i += 2)
|
||||
viafb_gpio_enable(gpio_config.active_gpios[i]);
|
||||
spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags);
|
||||
/*
|
||||
* Get registered.
|
||||
*/
|
||||
gpio_config.gpio_chip.base = -1; /* Dynamic */
|
||||
ret = gpiochip_add(&gpio_config.gpio_chip);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
|
||||
gpio_config.gpio_chip.ngpio = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int viafb_gpio_remove(struct platform_device *platdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0, i;
|
||||
|
||||
/*
|
||||
* Get unregistered.
|
||||
*/
|
||||
if (gpio_config.gpio_chip.ngpio > 0) {
|
||||
ret = gpiochip_remove(&gpio_config.gpio_chip);
|
||||
if (ret) { /* Somebody still using it? */
|
||||
printk(KERN_ERR "Viafb: GPIO remove failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Disable the ports.
|
||||
*/
|
||||
spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags);
|
||||
for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2)
|
||||
viafb_gpio_disable(gpio_config.active_gpios[i]);
|
||||
gpio_config.gpio_chip.ngpio = 0;
|
||||
spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver via_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "viafb-gpio",
|
||||
},
|
||||
.probe = viafb_gpio_probe,
|
||||
.remove = viafb_gpio_remove,
|
||||
};
|
||||
|
||||
int viafb_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&via_gpio_driver);
|
||||
}
|
||||
|
||||
void viafb_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&via_gpio_driver);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 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
|
||||
@ -19,77 +19,106 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/via-core.h>
|
||||
#include <linux/via_i2c.h>
|
||||
|
||||
/*
|
||||
* There can only be one set of these, so there's no point in having
|
||||
* them be dynamically allocated...
|
||||
*/
|
||||
#define VIAFB_NUM_I2C 5
|
||||
static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
|
||||
struct viafb_dev *i2c_vdev; /* Passed in from core */
|
||||
|
||||
static void via_i2c_setscl(void *data, int state)
|
||||
{
|
||||
u8 val;
|
||||
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
|
||||
struct via_port_cfg *adap_data = data;
|
||||
unsigned long flags;
|
||||
|
||||
val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
|
||||
spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
|
||||
val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
|
||||
if (state)
|
||||
val |= 0x20;
|
||||
else
|
||||
val &= ~0x20;
|
||||
switch (via_i2c_chan->i2c_port) {
|
||||
case I2CPORTINDEX:
|
||||
switch (adap_data->type) {
|
||||
case VIA_PORT_I2C:
|
||||
val |= 0x01;
|
||||
break;
|
||||
case GPIOPORTINDEX:
|
||||
case VIA_PORT_GPIO:
|
||||
val |= 0x80;
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
|
||||
printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
|
||||
}
|
||||
viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
|
||||
via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
|
||||
spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
|
||||
}
|
||||
|
||||
static int via_i2c_getscl(void *data)
|
||||
{
|
||||
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
|
||||
struct via_port_cfg *adap_data = data;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08)
|
||||
return 1;
|
||||
return 0;
|
||||
spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
|
||||
if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
|
||||
ret = 1;
|
||||
spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int via_i2c_getsda(void *data)
|
||||
{
|
||||
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
|
||||
struct via_port_cfg *adap_data = data;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04)
|
||||
return 1;
|
||||
return 0;
|
||||
spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
|
||||
if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
|
||||
ret = 1;
|
||||
spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void via_i2c_setsda(void *data, int state)
|
||||
{
|
||||
u8 val;
|
||||
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
|
||||
struct via_port_cfg *adap_data = data;
|
||||
unsigned long flags;
|
||||
|
||||
val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
|
||||
spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
|
||||
val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
|
||||
if (state)
|
||||
val |= 0x10;
|
||||
else
|
||||
val &= ~0x10;
|
||||
switch (via_i2c_chan->i2c_port) {
|
||||
case I2CPORTINDEX:
|
||||
switch (adap_data->type) {
|
||||
case VIA_PORT_I2C:
|
||||
val |= 0x01;
|
||||
break;
|
||||
case GPIOPORTINDEX:
|
||||
case VIA_PORT_GPIO:
|
||||
val |= 0x40;
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
|
||||
printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
|
||||
}
|
||||
viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
|
||||
via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
|
||||
spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
|
||||
}
|
||||
|
||||
int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
|
||||
int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
|
||||
{
|
||||
u8 mm1[] = {0x00};
|
||||
struct i2c_msg msgs[2];
|
||||
|
||||
if (!via_i2c_par[adap].is_active)
|
||||
return -ENODEV;
|
||||
*pdata = 0;
|
||||
msgs[0].flags = 0;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
@ -97,81 +126,144 @@ int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
|
||||
mm1[0] = index;
|
||||
msgs[0].len = 1; msgs[1].len = 1;
|
||||
msgs[0].buf = mm1; msgs[1].buf = pdata;
|
||||
i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2);
|
||||
|
||||
return 0;
|
||||
return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
|
||||
}
|
||||
|
||||
int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data)
|
||||
int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
|
||||
{
|
||||
u8 msg[2] = { index, data };
|
||||
struct i2c_msg msgs;
|
||||
|
||||
if (!via_i2c_par[adap].is_active)
|
||||
return -ENODEV;
|
||||
msgs.flags = 0;
|
||||
msgs.addr = slave_addr / 2;
|
||||
msgs.len = 2;
|
||||
msgs.buf = msg;
|
||||
return i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, &msgs, 1);
|
||||
return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
|
||||
}
|
||||
|
||||
int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
|
||||
int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
|
||||
{
|
||||
u8 mm1[] = {0x00};
|
||||
struct i2c_msg msgs[2];
|
||||
|
||||
if (!via_i2c_par[adap].is_active)
|
||||
return -ENODEV;
|
||||
msgs[0].flags = 0;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[0].addr = msgs[1].addr = slave_addr / 2;
|
||||
mm1[0] = index;
|
||||
msgs[0].len = 1; msgs[1].len = buff_len;
|
||||
msgs[0].buf = mm1; msgs[1].buf = buff;
|
||||
i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2);
|
||||
return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow other viafb subdevices to look up a specific adapter
|
||||
* by port name.
|
||||
*/
|
||||
struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which)
|
||||
{
|
||||
struct via_i2c_stuff *stuff = &via_i2c_par[which];
|
||||
|
||||
return &stuff->adapter;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter);
|
||||
|
||||
|
||||
static int create_i2c_bus(struct i2c_adapter *adapter,
|
||||
struct i2c_algo_bit_data *algo,
|
||||
struct via_port_cfg *adap_cfg,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
algo->setsda = via_i2c_setsda;
|
||||
algo->setscl = via_i2c_setscl;
|
||||
algo->getsda = via_i2c_getsda;
|
||||
algo->getscl = via_i2c_getscl;
|
||||
algo->udelay = 40;
|
||||
algo->timeout = 20;
|
||||
algo->data = adap_cfg;
|
||||
|
||||
sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
|
||||
adap_cfg->ioport_index);
|
||||
adapter->owner = THIS_MODULE;
|
||||
adapter->id = 0x01FFFF;
|
||||
adapter->class = I2C_CLASS_DDC;
|
||||
adapter->algo_data = algo;
|
||||
if (pdev)
|
||||
adapter->dev.parent = &pdev->dev;
|
||||
else
|
||||
adapter->dev.parent = NULL;
|
||||
/* i2c_set_adapdata(adapter, adap_cfg); */
|
||||
|
||||
/* Raise SCL and SDA */
|
||||
via_i2c_setsda(adap_cfg, 1);
|
||||
via_i2c_setscl(adap_cfg, 1);
|
||||
udelay(20);
|
||||
|
||||
return i2c_bit_add_bus(adapter);
|
||||
}
|
||||
|
||||
static int viafb_i2c_probe(struct platform_device *platdev)
|
||||
{
|
||||
int i, ret;
|
||||
struct via_port_cfg *configs;
|
||||
|
||||
i2c_vdev = platdev->dev.platform_data;
|
||||
configs = i2c_vdev->port_cfg;
|
||||
|
||||
for (i = 0; i < VIAFB_NUM_PORTS; i++) {
|
||||
struct via_port_cfg *adap_cfg = configs++;
|
||||
struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
|
||||
|
||||
i2c_stuff->is_active = 0;
|
||||
if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C)
|
||||
continue;
|
||||
ret = create_i2c_bus(&i2c_stuff->adapter,
|
||||
&i2c_stuff->algo, adap_cfg,
|
||||
NULL); /* FIXME: PCIDEV */
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n",
|
||||
i, ret);
|
||||
continue; /* Still try to make the rest */
|
||||
}
|
||||
i2c_stuff->is_active = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int viafb_create_i2c_bus(void *viapar)
|
||||
static int viafb_i2c_remove(struct platform_device *platdev)
|
||||
{
|
||||
int ret;
|
||||
struct via_i2c_stuff *i2c_stuff =
|
||||
&((struct viafb_par *)viapar)->shared->i2c_stuff;
|
||||
int i;
|
||||
|
||||
strcpy(i2c_stuff->adapter.name, "via_i2c");
|
||||
i2c_stuff->i2c_port = 0x0;
|
||||
i2c_stuff->adapter.owner = THIS_MODULE;
|
||||
i2c_stuff->adapter.id = 0x01FFFF;
|
||||
i2c_stuff->adapter.class = 0;
|
||||
i2c_stuff->adapter.algo_data = &i2c_stuff->algo;
|
||||
i2c_stuff->adapter.dev.parent = NULL;
|
||||
i2c_stuff->algo.setsda = via_i2c_setsda;
|
||||
i2c_stuff->algo.setscl = via_i2c_setscl;
|
||||
i2c_stuff->algo.getsda = via_i2c_getsda;
|
||||
i2c_stuff->algo.getscl = via_i2c_getscl;
|
||||
i2c_stuff->algo.udelay = 40;
|
||||
i2c_stuff->algo.timeout = 20;
|
||||
i2c_stuff->algo.data = i2c_stuff;
|
||||
|
||||
i2c_set_adapdata(&i2c_stuff->adapter, i2c_stuff);
|
||||
|
||||
/* Raise SCL and SDA */
|
||||
i2c_stuff->i2c_port = I2CPORTINDEX;
|
||||
via_i2c_setsda(i2c_stuff, 1);
|
||||
via_i2c_setscl(i2c_stuff, 1);
|
||||
|
||||
i2c_stuff->i2c_port = GPIOPORTINDEX;
|
||||
via_i2c_setsda(i2c_stuff, 1);
|
||||
via_i2c_setscl(i2c_stuff, 1);
|
||||
udelay(20);
|
||||
|
||||
ret = i2c_bit_add_bus(&i2c_stuff->adapter);
|
||||
if (ret == 0)
|
||||
DEBUG_MSG("I2C bus %s registered.\n", i2c_stuff->adapter.name);
|
||||
else
|
||||
DEBUG_MSG("Failed to register I2C bus %s.\n",
|
||||
i2c_stuff->adapter.name);
|
||||
return ret;
|
||||
for (i = 0; i < VIAFB_NUM_PORTS; i++) {
|
||||
struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
|
||||
/*
|
||||
* Only remove those entries in the array that we've
|
||||
* actually used (and thus initialized algo_data)
|
||||
*/
|
||||
if (i2c_stuff->is_active)
|
||||
i2c_del_adapter(&i2c_stuff->adapter);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void viafb_delete_i2c_buss(void *par)
|
||||
static struct platform_driver via_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "viafb-i2c",
|
||||
},
|
||||
.probe = viafb_i2c_probe,
|
||||
.remove = viafb_i2c_remove,
|
||||
};
|
||||
|
||||
int viafb_i2c_init(void)
|
||||
{
|
||||
i2c_del_adapter(&((struct viafb_par *)par)->shared->i2c_stuff.adapter);
|
||||
return platform_driver_register(&via_i2c_driver);
|
||||
}
|
||||
|
||||
void viafb_i2c_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&via_i2c_driver);
|
||||
}
|
||||
|
126
drivers/video/via/via_modesetting.c
Normal file
126
drivers/video/via/via_modesetting.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
|
||||
* Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* basic modesetting functions
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/via-core.h>
|
||||
#include "via_modesetting.h"
|
||||
#include "share.h"
|
||||
#include "debug.h"
|
||||
|
||||
void via_set_primary_address(u32 addr)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
|
||||
via_write_reg(VIACR, 0x0D, addr & 0xFF);
|
||||
via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF);
|
||||
via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF);
|
||||
via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F);
|
||||
}
|
||||
|
||||
void via_set_secondary_address(u32 addr)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr);
|
||||
/* secondary display supports only quadword aligned memory */
|
||||
via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE);
|
||||
via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF);
|
||||
via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF);
|
||||
via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07);
|
||||
}
|
||||
|
||||
void via_set_primary_pitch(u32 pitch)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch);
|
||||
/* spec does not say that first adapter skips 3 bits but old
|
||||
* code did it and seems to be reasonable in analogy to 2nd adapter
|
||||
*/
|
||||
pitch = pitch >> 3;
|
||||
via_write_reg(VIACR, 0x13, pitch & 0xFF);
|
||||
via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0);
|
||||
}
|
||||
|
||||
void via_set_secondary_pitch(u32 pitch)
|
||||
{
|
||||
DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch);
|
||||
pitch = pitch >> 3;
|
||||
via_write_reg(VIACR, 0x66, pitch & 0xFF);
|
||||
via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03);
|
||||
via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80);
|
||||
}
|
||||
|
||||
void via_set_primary_color_depth(u8 depth)
|
||||
{
|
||||
u8 value;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth);
|
||||
switch (depth) {
|
||||
case 8:
|
||||
value = 0x00;
|
||||
break;
|
||||
case 15:
|
||||
value = 0x04;
|
||||
break;
|
||||
case 16:
|
||||
value = 0x14;
|
||||
break;
|
||||
case 24:
|
||||
value = 0x0C;
|
||||
break;
|
||||
case 30:
|
||||
value = 0x08;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "via_set_primary_color_depth: "
|
||||
"Unsupported depth: %d\n", depth);
|
||||
return;
|
||||
}
|
||||
|
||||
via_write_reg_mask(VIASR, 0x15, value, 0x1C);
|
||||
}
|
||||
|
||||
void via_set_secondary_color_depth(u8 depth)
|
||||
{
|
||||
u8 value;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth);
|
||||
switch (depth) {
|
||||
case 8:
|
||||
value = 0x00;
|
||||
break;
|
||||
case 16:
|
||||
value = 0x40;
|
||||
break;
|
||||
case 24:
|
||||
value = 0xC0;
|
||||
break;
|
||||
case 30:
|
||||
value = 0x80;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "via_set_secondary_color_depth: "
|
||||
"Unsupported depth: %d\n", depth);
|
||||
return;
|
||||
}
|
||||
|
||||
via_write_reg_mask(VIACR, 0x67, value, 0xC0);
|
||||
}
|
38
drivers/video/via/via_modesetting.h
Normal file
38
drivers/video/via/via_modesetting.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
|
||||
* Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* basic modesetting functions
|
||||
*/
|
||||
|
||||
#ifndef __VIA_MODESETTING_H__
|
||||
#define __VIA_MODESETTING_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
void via_set_primary_address(u32 addr);
|
||||
void via_set_secondary_address(u32 addr);
|
||||
void via_set_primary_pitch(u32 pitch);
|
||||
void via_set_secondary_pitch(u32 pitch);
|
||||
void via_set_primary_color_depth(u8 depth);
|
||||
void via_set_secondary_color_depth(u8 depth);
|
||||
|
||||
#endif /* __VIA_MODESETTING_H__ */
|
@ -19,6 +19,7 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/via-core.h>
|
||||
#include "global.h"
|
||||
|
||||
void viafb_get_device_support_state(u32 *support_state)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 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
|
||||
@ -23,8 +23,9 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#define _MASTER_FILE
|
||||
#include <linux/via-core.h>
|
||||
|
||||
#define _MASTER_FILE
|
||||
#include "global.h"
|
||||
|
||||
static char *viafb_name = "Via";
|
||||
@ -221,7 +222,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
|
||||
/* Adjust var according to our driver's own table */
|
||||
viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry);
|
||||
if (info->var.accel_flags & FB_ACCELF_TEXT &&
|
||||
!ppar->shared->engine_mmio)
|
||||
!ppar->shared->vdev->engine_mmio)
|
||||
info->var.accel_flags = 0;
|
||||
|
||||
return 0;
|
||||
@ -317,12 +318,12 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
|
||||
if (!viafb_dual_fb) {
|
||||
viafb_set_primary_address(vram_addr);
|
||||
viafb_set_secondary_address(vram_addr);
|
||||
via_set_primary_address(vram_addr);
|
||||
via_set_secondary_address(vram_addr);
|
||||
} else if (viapar->iga_path == IGA1)
|
||||
viafb_set_primary_address(vram_addr);
|
||||
via_set_primary_address(vram_addr);
|
||||
else
|
||||
viafb_set_secondary_address(vram_addr);
|
||||
via_set_secondary_address(vram_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -696,7 +697,7 @@ static void viafb_fillrect(struct fb_info *info,
|
||||
rop = 0xF0;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
|
||||
if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_FILL,
|
||||
if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL,
|
||||
rect->width, rect->height, info->var.bits_per_pixel,
|
||||
viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
|
||||
NULL, 0, 0, 0, 0, fg_color, 0, rop))
|
||||
@ -718,7 +719,7 @@ static void viafb_copyarea(struct fb_info *info,
|
||||
return;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
|
||||
if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_COLOR,
|
||||
if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR,
|
||||
area->width, area->height, info->var.bits_per_pixel,
|
||||
viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
|
||||
NULL, viapar->vram_addr, info->fix.line_length,
|
||||
@ -755,7 +756,7 @@ static void viafb_imageblit(struct fb_info *info,
|
||||
op = VIA_BITBLT_COLOR;
|
||||
|
||||
DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
|
||||
if (shared->hw_bitblt(shared->engine_mmio, op,
|
||||
if (shared->hw_bitblt(shared->vdev->engine_mmio, op,
|
||||
image->width, image->height, info->var.bits_per_pixel,
|
||||
viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
|
||||
(u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
|
||||
@ -765,7 +766,7 @@ static void viafb_imageblit(struct fb_info *info,
|
||||
static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
|
||||
{
|
||||
struct viafb_par *viapar = info->par;
|
||||
void __iomem *engine = viapar->shared->engine_mmio;
|
||||
void __iomem *engine = viapar->shared->vdev->engine_mmio;
|
||||
u32 temp, xx, yy, bg_color = 0, fg_color = 0,
|
||||
chip_name = viapar->shared->chip_info.gfx_chip_name;
|
||||
int i, j = 0, cur_size = 64;
|
||||
@ -1018,8 +1019,8 @@ static void viafb_set_device(struct device_t active_dev)
|
||||
viafb_SAMM_ON = active_dev.samm;
|
||||
viafb_primary_dev = active_dev.primary_dev;
|
||||
|
||||
viafb_set_primary_address(0);
|
||||
viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
|
||||
via_set_primary_address(0);
|
||||
via_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
|
||||
viafb_set_iga_path();
|
||||
}
|
||||
|
||||
@ -1165,8 +1166,9 @@ static int apply_device_setting(struct viafb_ioctl_setting setting_info,
|
||||
if (viafb_SAMM_ON)
|
||||
viafb_primary_dev = setting_info.primary_device;
|
||||
|
||||
viafb_set_primary_address(0);
|
||||
viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
|
||||
via_set_primary_address(0);
|
||||
via_set_secondary_address(viafb_SAMM_ON ?
|
||||
viafb_second_offset : 0);
|
||||
viafb_set_iga_path();
|
||||
}
|
||||
need_set_mode = 1;
|
||||
@ -1325,6 +1327,8 @@ static void parse_dvi_port(void)
|
||||
output_interface);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
|
||||
|
||||
/*
|
||||
* The proc filesystem read/write function, a simple proc implement to
|
||||
* get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
|
||||
@ -1701,16 +1705,21 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
|
||||
}
|
||||
static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
|
||||
{
|
||||
/* no problem if it was not registered */
|
||||
struct chip_information *chip_info = &viaparinfo->shared->chip_info;
|
||||
|
||||
remove_proc_entry("dvp0", viafb_entry);/* parent dir */
|
||||
remove_proc_entry("dvp1", viafb_entry);
|
||||
remove_proc_entry("dfph", viafb_entry);
|
||||
remove_proc_entry("dfpl", viafb_entry);
|
||||
remove_proc_entry("vt1636", viafb_entry);
|
||||
remove_proc_entry("vt1625", viafb_entry);
|
||||
if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS
|
||||
|| chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS)
|
||||
remove_proc_entry("vt1636", viafb_entry);
|
||||
|
||||
remove_proc_entry("viafb", NULL);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
|
||||
|
||||
static int parse_mode(const char *str, u32 *xres, u32 *yres)
|
||||
{
|
||||
char *ptr;
|
||||
@ -1732,12 +1741,13 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit via_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
|
||||
int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
|
||||
{
|
||||
u32 default_xres, default_yres;
|
||||
struct VideoModeTable *vmode_entry;
|
||||
struct fb_var_screeninfo default_var;
|
||||
int rc;
|
||||
u32 viafb_par_length;
|
||||
|
||||
DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
|
||||
@ -1749,14 +1759,15 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
||||
*/
|
||||
viafbinfo = framebuffer_alloc(viafb_par_length +
|
||||
ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
|
||||
&pdev->dev);
|
||||
&vdev->pdev->dev);
|
||||
if (!viafbinfo) {
|
||||
printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
|
||||
return -ENODEV;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
viaparinfo = (struct viafb_par *)viafbinfo->par;
|
||||
viaparinfo->shared = viafbinfo->par + viafb_par_length;
|
||||
viaparinfo->shared->vdev = vdev;
|
||||
viaparinfo->vram_addr = 0;
|
||||
viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
|
||||
viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
|
||||
@ -1774,23 +1785,20 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
||||
if (!viafb_SAMM_ON)
|
||||
viafb_dual_fb = 0;
|
||||
|
||||
/* Set up I2C bus stuff */
|
||||
viafb_create_i2c_bus(viaparinfo);
|
||||
|
||||
viafb_init_chip_info(pdev, ent);
|
||||
viaparinfo->fbmem = pci_resource_start(pdev, 0);
|
||||
viaparinfo->memsize = viafb_get_fb_size_from_pci();
|
||||
viafb_init_chip_info(vdev->chip_type);
|
||||
/*
|
||||
* The framebuffer will have been successfully mapped by
|
||||
* the core (or we'd not be here), but we still need to
|
||||
* set up our own accounting.
|
||||
*/
|
||||
viaparinfo->fbmem = vdev->fbmem_start;
|
||||
viaparinfo->memsize = vdev->fbmem_len;
|
||||
viaparinfo->fbmem_free = viaparinfo->memsize;
|
||||
viaparinfo->fbmem_used = 0;
|
||||
viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem,
|
||||
viaparinfo->memsize);
|
||||
if (!viafbinfo->screen_base) {
|
||||
printk(KERN_INFO "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
viafbinfo->screen_base = vdev->fbmem;
|
||||
|
||||
viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1);
|
||||
viafbinfo->fix.mmio_len = pci_resource_len(pdev, 1);
|
||||
viafbinfo->fix.mmio_start = vdev->engine_start;
|
||||
viafbinfo->fix.mmio_len = vdev->engine_len;
|
||||
viafbinfo->node = 0;
|
||||
viafbinfo->fbops = &viafb_ops;
|
||||
viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
||||
@ -1858,12 +1866,13 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
||||
viafbinfo->var = default_var;
|
||||
|
||||
if (viafb_dual_fb) {
|
||||
viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev);
|
||||
viafbinfo1 = framebuffer_alloc(viafb_par_length,
|
||||
&vdev->pdev->dev);
|
||||
if (!viafbinfo1) {
|
||||
printk(KERN_ERR
|
||||
"allocate the second framebuffer struct error\n");
|
||||
framebuffer_release(viafbinfo);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto out_fb_release;
|
||||
}
|
||||
viaparinfo1 = viafbinfo1->par;
|
||||
memcpy(viaparinfo1, viaparinfo, viafb_par_length);
|
||||
@ -1914,48 +1923,66 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
||||
viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
|
||||
&viafbinfo->fix);
|
||||
default_var.activate = FB_ACTIVATE_NOW;
|
||||
fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
|
||||
rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
|
||||
if (rc)
|
||||
goto out_fb1_release;
|
||||
|
||||
if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
|
||||
&& (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
|
||||
if (register_framebuffer(viafbinfo1) < 0)
|
||||
return -EINVAL;
|
||||
rc = register_framebuffer(viafbinfo1);
|
||||
if (rc)
|
||||
goto out_dealloc_cmap;
|
||||
}
|
||||
if (register_framebuffer(viafbinfo) < 0)
|
||||
return -EINVAL;
|
||||
rc = register_framebuffer(viafbinfo);
|
||||
if (rc)
|
||||
goto out_fb1_unreg_lcd_cle266;
|
||||
|
||||
if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
|
||||
|| (viaparinfo->chip_info->gfx_chip_name !=
|
||||
UNICHROME_CLE266))) {
|
||||
if (register_framebuffer(viafbinfo1) < 0)
|
||||
return -EINVAL;
|
||||
rc = register_framebuffer(viafbinfo1);
|
||||
if (rc)
|
||||
goto out_fb_unreg;
|
||||
}
|
||||
DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
|
||||
viafbinfo->node, viafbinfo->fix.id, default_var.xres,
|
||||
default_var.yres, default_var.bits_per_pixel);
|
||||
|
||||
#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
|
||||
viafb_init_proc(&viaparinfo->shared->proc_entry);
|
||||
#endif
|
||||
viafb_init_dac(IGA2);
|
||||
return 0;
|
||||
|
||||
out_fb_unreg:
|
||||
unregister_framebuffer(viafbinfo);
|
||||
out_fb1_unreg_lcd_cle266:
|
||||
if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
|
||||
&& (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
|
||||
unregister_framebuffer(viafbinfo1);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&viafbinfo->cmap);
|
||||
out_fb1_release:
|
||||
if (viafbinfo1)
|
||||
framebuffer_release(viafbinfo1);
|
||||
out_fb_release:
|
||||
framebuffer_release(viafbinfo);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __devexit via_pci_remove(struct pci_dev *pdev)
|
||||
void __devexit via_fb_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
|
||||
fb_dealloc_cmap(&viafbinfo->cmap);
|
||||
unregister_framebuffer(viafbinfo);
|
||||
if (viafb_dual_fb)
|
||||
unregister_framebuffer(viafbinfo1);
|
||||
iounmap((void *)viafbinfo->screen_base);
|
||||
iounmap(viaparinfo->shared->engine_mmio);
|
||||
|
||||
viafb_delete_i2c_buss(viaparinfo);
|
||||
|
||||
#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
|
||||
viafb_remove_proc(viaparinfo->shared->proc_entry);
|
||||
#endif
|
||||
framebuffer_release(viafbinfo);
|
||||
if (viafb_dual_fb)
|
||||
framebuffer_release(viafbinfo1);
|
||||
|
||||
viafb_remove_proc(viaparinfo->shared->proc_entry);
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
@ -2031,41 +2058,10 @@ static int __init viafb_setup(char *options)
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pci_device_id viafb_pci_table[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
|
||||
.driver_data = UNICHROME_CLE266 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
|
||||
.driver_data = UNICHROME_PM800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
|
||||
.driver_data = UNICHROME_K400 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
|
||||
.driver_data = UNICHROME_K800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
|
||||
.driver_data = UNICHROME_CN700 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
|
||||
.driver_data = UNICHROME_K8M890 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
|
||||
.driver_data = UNICHROME_CX700 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
|
||||
.driver_data = UNICHROME_P4M900 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
|
||||
.driver_data = UNICHROME_CN750 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
|
||||
.driver_data = UNICHROME_VX800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
|
||||
.driver_data = UNICHROME_VX855 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, viafb_pci_table);
|
||||
|
||||
static struct pci_driver viafb_driver = {
|
||||
.name = "viafb",
|
||||
.id_table = viafb_pci_table,
|
||||
.probe = via_pci_probe,
|
||||
.remove = __devexit_p(via_pci_remove),
|
||||
};
|
||||
|
||||
static int __init viafb_init(void)
|
||||
/*
|
||||
* These are called out of via-core for now.
|
||||
*/
|
||||
int __init viafb_init(void)
|
||||
{
|
||||
u32 dummy;
|
||||
#ifndef MODULE
|
||||
@ -2084,13 +2080,12 @@ static int __init viafb_init(void)
|
||||
printk(KERN_INFO
|
||||
"VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
|
||||
VERSION_MAJOR, VERSION_MINOR);
|
||||
return pci_register_driver(&viafb_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit viafb_exit(void)
|
||||
void __exit viafb_exit(void)
|
||||
{
|
||||
DEBUG_MSG(KERN_INFO "viafb_exit!\n");
|
||||
pci_unregister_driver(&viafb_driver);
|
||||
}
|
||||
|
||||
static struct fb_ops viafb_ops = {
|
||||
@ -2110,8 +2105,6 @@ static struct fb_ops viafb_ops = {
|
||||
.fb_sync = viafb_sync,
|
||||
};
|
||||
|
||||
module_init(viafb_init);
|
||||
module_exit(viafb_exit);
|
||||
|
||||
#ifdef MODULE
|
||||
module_param(viafb_mode, charp, S_IRUSR);
|
||||
|
@ -24,12 +24,12 @@
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "ioctl.h"
|
||||
#include "share.h"
|
||||
#include "chip.h"
|
||||
#include "hw.h"
|
||||
#include "via_i2c.h"
|
||||
|
||||
#define VERSION_MAJOR 2
|
||||
#define VERSION_KERNEL 6 /* For kernel 2.6 */
|
||||
@ -37,11 +37,11 @@
|
||||
#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */
|
||||
#define VERSION_MINOR 4
|
||||
|
||||
#define VIAFB_NUM_I2C 5
|
||||
|
||||
struct viafb_shared {
|
||||
struct proc_dir_entry *proc_entry; /*viafb proc entry */
|
||||
|
||||
/* I2C stuff */
|
||||
struct via_i2c_stuff i2c_stuff;
|
||||
struct viafb_dev *vdev; /* Global dev info */
|
||||
|
||||
/* All the information will be needed to set engine */
|
||||
struct tmds_setting_information tmds_setting_info;
|
||||
@ -51,7 +51,6 @@ struct viafb_shared {
|
||||
struct chip_information chip_info;
|
||||
|
||||
/* hardware acceleration stuff */
|
||||
void __iomem *engine_mmio;
|
||||
u32 cursor_vram_addr;
|
||||
u32 vq_vram_addr; /* virtual queue address in video ram */
|
||||
int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height,
|
||||
@ -99,4 +98,9 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
|
||||
void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
|
||||
*plvds_setting_info, struct lvds_chip_information
|
||||
*plvds_chip_info, struct IODATA io_data);
|
||||
int via_fb_pci_probe(struct viafb_dev *vdev);
|
||||
void via_fb_pci_remove(struct pci_dev *pdev);
|
||||
/* Temporary */
|
||||
int viafb_init(void);
|
||||
void viafb_exit(void);
|
||||
#endif /* __VIAFBDEV_H__ */
|
||||
|
@ -19,6 +19,7 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/via-core.h>
|
||||
#include "global.h"
|
||||
struct res_map_refresh res_map_refresh_tbl[] = {
|
||||
/*hres, vres, vclock, vmode_refresh*/
|
||||
@ -66,6 +67,7 @@ struct res_map_refresh res_map_refresh_tbl[] = {
|
||||
{1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60},
|
||||
{1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60},
|
||||
{1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60},
|
||||
{1200, 900, RES_1200X900_60HZ_PIXCLOCK, 60},
|
||||
{1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60},
|
||||
{1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50},
|
||||
{1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50},
|
||||
@ -759,6 +761,16 @@ struct crt_mode_table CRTM1200x720[] = {
|
||||
{1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
|
||||
};
|
||||
|
||||
/* 1200x900 (DCON) */
|
||||
struct crt_mode_table DCON1200x900[] = {
|
||||
/* r_rate, vclk, hsp, vsp */
|
||||
{REFRESH_60, CLK_57_275M, M1200X900_R60_HSP, M1200X900_R60_VSP,
|
||||
/* The correct htotal is 1240, but this doesn't raster on VX855. */
|
||||
/* Via suggested changing to a multiple of 16, hence 1264. */
|
||||
/* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
|
||||
{1264, 1200, 1200, 64, 1211, 32, 912, 900, 900, 12, 901, 10} }
|
||||
};
|
||||
|
||||
/* 1280x600 (GTF) */
|
||||
struct crt_mode_table CRTM1280x600[] = {
|
||||
/* r_rate, vclk, hsp, vsp */
|
||||
@ -937,6 +949,9 @@ struct VideoModeTable viafb_modes[] = {
|
||||
/* Display : 1200x720 (GTF) */
|
||||
{CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
|
||||
|
||||
/* Display : 1200x900 (DCON) */
|
||||
{DCON1200x900, ARRAY_SIZE(DCON1200x900)},
|
||||
|
||||
/* Display : 1280x600 (GTF) */
|
||||
{CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/via-core.h>
|
||||
#include <linux/via_i2c.h>
|
||||
#include "global.h"
|
||||
|
||||
u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
|
||||
@ -27,9 +29,8 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
|
||||
{
|
||||
u8 data;
|
||||
|
||||
viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
|
||||
viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data);
|
||||
|
||||
viafb_i2c_readbyte(plvds_chip_info->i2c_port,
|
||||
plvds_chip_info->lvds_chip_slave_addr, index, &data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -39,14 +40,13 @@ void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
|
||||
{
|
||||
int index, data;
|
||||
|
||||
viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
|
||||
|
||||
index = io_data.Index;
|
||||
data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
|
||||
index);
|
||||
data = (data & (~io_data.Mask)) | io_data.Data;
|
||||
|
||||
viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data);
|
||||
viafb_i2c_writebyte(plvds_chip_info->i2c_port,
|
||||
plvds_chip_info->lvds_chip_slave_addr, index, data);
|
||||
}
|
||||
|
||||
void viafb_init_lvds_vt1636(struct lvds_setting_information
|
||||
@ -159,7 +159,7 @@ void viafb_disable_lvds_vt1636(struct lvds_setting_information
|
||||
}
|
||||
}
|
||||
|
||||
bool viafb_lvds_identify_vt1636(void)
|
||||
bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
|
||||
{
|
||||
u8 Buffer[2];
|
||||
|
||||
@ -167,26 +167,20 @@ bool viafb_lvds_identify_vt1636(void)
|
||||
|
||||
/* Sense VT1636 LVDS Transmiter */
|
||||
viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
|
||||
VT1636_LVDS_I2C_ADDR;
|
||||
VT1636_LVDS_I2C_ADDR;
|
||||
|
||||
/* Check vendor ID first: */
|
||||
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
|
||||
lvds_chip_slave_addr,
|
||||
0x00, &Buffer[0]);
|
||||
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
|
||||
lvds_chip_slave_addr,
|
||||
0x01, &Buffer[1]);
|
||||
if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
|
||||
0x00, &Buffer[0]))
|
||||
return false;
|
||||
viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
|
||||
|
||||
if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
|
||||
return false;
|
||||
|
||||
/* Check Chip ID: */
|
||||
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
|
||||
lvds_chip_slave_addr,
|
||||
0x02, &Buffer[0]);
|
||||
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
|
||||
lvds_chip_slave_addr,
|
||||
0x03, &Buffer[1]);
|
||||
viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
|
||||
viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
|
||||
if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
|
||||
viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
|
||||
VT1636_LVDS;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef _VT1636_H_
|
||||
#define _VT1636_H_
|
||||
#include "chip.h"
|
||||
bool viafb_lvds_identify_vt1636(void);
|
||||
bool viafb_lvds_identify_vt1636(u8 i2c_adapter);
|
||||
void viafb_init_lvds_vt1636(struct lvds_setting_information
|
||||
*plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
|
||||
void viafb_enable_lvds_vt1636(struct lvds_setting_information
|
||||
|
219
include/linux/via-core.h
Normal file
219
include/linux/via-core.h
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
|
||||
* Copyright 2009-2010 Jonathan Corbet <corbet@lwn.net>
|
||||
* Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
|
||||
*
|
||||
* 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 __VIA_CORE_H__
|
||||
#define __VIA_CORE_H__
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
/*
|
||||
* A description of each known serial I2C/GPIO port.
|
||||
*/
|
||||
enum via_port_type {
|
||||
VIA_PORT_NONE = 0,
|
||||
VIA_PORT_I2C,
|
||||
VIA_PORT_GPIO,
|
||||
};
|
||||
|
||||
enum via_port_mode {
|
||||
VIA_MODE_OFF = 0,
|
||||
VIA_MODE_I2C, /* Used as I2C port */
|
||||
VIA_MODE_GPIO, /* Two GPIO ports */
|
||||
};
|
||||
|
||||
enum viafb_i2c_adap {
|
||||
VIA_PORT_26 = 0,
|
||||
VIA_PORT_31,
|
||||
VIA_PORT_25,
|
||||
VIA_PORT_2C,
|
||||
VIA_PORT_3D,
|
||||
};
|
||||
#define VIAFB_NUM_PORTS 5
|
||||
|
||||
struct via_port_cfg {
|
||||
enum via_port_type type;
|
||||
enum via_port_mode mode;
|
||||
u16 io_port;
|
||||
u8 ioport_index;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the global viafb "device" containing stuff needed by
|
||||
* all subdevs.
|
||||
*/
|
||||
struct viafb_dev {
|
||||
struct pci_dev *pdev;
|
||||
int chip_type;
|
||||
struct via_port_cfg *port_cfg;
|
||||
/*
|
||||
* Spinlock for access to device registers. Not yet
|
||||
* globally used.
|
||||
*/
|
||||
spinlock_t reg_lock;
|
||||
/*
|
||||
* The framebuffer MMIO region. Little, if anything, touches
|
||||
* this memory directly, and certainly nothing outside of the
|
||||
* framebuffer device itself. We *do* have to be able to allocate
|
||||
* chunks of this memory for other devices, though.
|
||||
*/
|
||||
unsigned long fbmem_start;
|
||||
long fbmem_len;
|
||||
void __iomem *fbmem;
|
||||
#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE)
|
||||
long camera_fbmem_offset;
|
||||
long camera_fbmem_size;
|
||||
#endif
|
||||
/*
|
||||
* The MMIO region for device registers.
|
||||
*/
|
||||
unsigned long engine_start;
|
||||
unsigned long engine_len;
|
||||
void __iomem *engine_mmio;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Interrupt management.
|
||||
*/
|
||||
|
||||
void viafb_irq_enable(u32 mask);
|
||||
void viafb_irq_disable(u32 mask);
|
||||
|
||||
/*
|
||||
* The global interrupt control register and its bits.
|
||||
*/
|
||||
#define VDE_INTERRUPT 0x200 /* Video interrupt flags/masks */
|
||||
#define VDE_I_DVISENSE 0x00000001 /* DVI sense int status */
|
||||
#define VDE_I_VBLANK 0x00000002 /* Vertical blank status */
|
||||
#define VDE_I_MCCFI 0x00000004 /* MCE compl. frame int status */
|
||||
#define VDE_I_VSYNC 0x00000008 /* VGA VSYNC int status */
|
||||
#define VDE_I_DMA0DDONE 0x00000010 /* DMA 0 descr done */
|
||||
#define VDE_I_DMA0TDONE 0x00000020 /* DMA 0 transfer done */
|
||||
#define VDE_I_DMA1DDONE 0x00000040 /* DMA 1 descr done */
|
||||
#define VDE_I_DMA1TDONE 0x00000080 /* DMA 1 transfer done */
|
||||
#define VDE_I_C1AV 0x00000100 /* Cap Eng 1 act vid end */
|
||||
#define VDE_I_HQV0 0x00000200 /* First HQV engine */
|
||||
#define VDE_I_HQV1 0x00000400 /* Second HQV engine */
|
||||
#define VDE_I_HQV1EN 0x00000800 /* Second HQV engine enable */
|
||||
#define VDE_I_C0AV 0x00001000 /* Cap Eng 0 act vid end */
|
||||
#define VDE_I_C0VBI 0x00002000 /* Cap Eng 0 VBI end */
|
||||
#define VDE_I_C1VBI 0x00004000 /* Cap Eng 1 VBI end */
|
||||
#define VDE_I_VSYNC2 0x00008000 /* Sec. Disp. VSYNC */
|
||||
#define VDE_I_DVISNSEN 0x00010000 /* DVI sense enable */
|
||||
#define VDE_I_VSYNC2EN 0x00020000 /* Sec Disp VSYNC enable */
|
||||
#define VDE_I_MCCFIEN 0x00040000 /* MC comp frame int mask enable */
|
||||
#define VDE_I_VSYNCEN 0x00080000 /* VSYNC enable */
|
||||
#define VDE_I_DMA0DDEN 0x00100000 /* DMA 0 descr done enable */
|
||||
#define VDE_I_DMA0TDEN 0x00200000 /* DMA 0 trans done enable */
|
||||
#define VDE_I_DMA1DDEN 0x00400000 /* DMA 1 descr done enable */
|
||||
#define VDE_I_DMA1TDEN 0x00800000 /* DMA 1 trans done enable */
|
||||
#define VDE_I_C1AVEN 0x01000000 /* cap 1 act vid end enable */
|
||||
#define VDE_I_HQV0EN 0x02000000 /* First hqv engine enable */
|
||||
#define VDE_I_C1VBIEN 0x04000000 /* Cap 1 VBI end enable */
|
||||
#define VDE_I_LVDSSI 0x08000000 /* LVDS sense interrupt */
|
||||
#define VDE_I_C0AVEN 0x10000000 /* Cap 0 act vid end enable */
|
||||
#define VDE_I_C0VBIEN 0x20000000 /* Cap 0 VBI end enable */
|
||||
#define VDE_I_LVDSSIEN 0x40000000 /* LVDS Sense enable */
|
||||
#define VDE_I_ENABLE 0x80000000 /* Global interrupt enable */
|
||||
|
||||
/*
|
||||
* DMA management.
|
||||
*/
|
||||
int viafb_request_dma(void);
|
||||
void viafb_release_dma(void);
|
||||
/* void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len); */
|
||||
int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg);
|
||||
|
||||
/*
|
||||
* DMA Controller registers.
|
||||
*/
|
||||
#define VDMA_MR0 0xe00 /* Mod reg 0 */
|
||||
#define VDMA_MR_CHAIN 0x01 /* Chaining mode */
|
||||
#define VDMA_MR_TDIE 0x02 /* Transfer done int enable */
|
||||
#define VDMA_CSR0 0xe04 /* Control/status */
|
||||
#define VDMA_C_ENABLE 0x01 /* DMA Enable */
|
||||
#define VDMA_C_START 0x02 /* Start a transfer */
|
||||
#define VDMA_C_ABORT 0x04 /* Abort a transfer */
|
||||
#define VDMA_C_DONE 0x08 /* Transfer is done */
|
||||
#define VDMA_MARL0 0xe20 /* Mem addr low */
|
||||
#define VDMA_MARH0 0xe24 /* Mem addr high */
|
||||
#define VDMA_DAR0 0xe28 /* Device address */
|
||||
#define VDMA_DQWCR0 0xe2c /* Count (16-byte) */
|
||||
#define VDMA_TMR0 0xe30 /* Tile mode reg */
|
||||
#define VDMA_DPRL0 0xe34 /* Not sure */
|
||||
#define VDMA_DPR_IN 0x08 /* Inbound transfer to FB */
|
||||
#define VDMA_DPRH0 0xe38
|
||||
#define VDMA_PMR0 (0xe00 + 0x134) /* Pitch mode */
|
||||
|
||||
/*
|
||||
* Useful stuff that probably belongs somewhere global.
|
||||
*/
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
||||
|
||||
/*
|
||||
* Indexed port operations. Note that these are all multi-op
|
||||
* functions; every invocation will be racy if you're not holding
|
||||
* reg_lock.
|
||||
*/
|
||||
|
||||
#define VIAStatus 0x3DA /* Non-indexed port */
|
||||
#define VIACR 0x3D4
|
||||
#define VIASR 0x3C4
|
||||
#define VIAGR 0x3CE
|
||||
#define VIAAR 0x3C0
|
||||
|
||||
static inline u8 via_read_reg(u16 port, u8 index)
|
||||
{
|
||||
outb(index, port);
|
||||
return inb(port + 1);
|
||||
}
|
||||
|
||||
static inline void via_write_reg(u16 port, u8 index, u8 data)
|
||||
{
|
||||
outb(index, port);
|
||||
outb(data, port + 1);
|
||||
}
|
||||
|
||||
static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask)
|
||||
{
|
||||
u8 old;
|
||||
|
||||
outb(index, port);
|
||||
old = inb(port + 1);
|
||||
outb((data & mask) | (old & ~mask), port + 1);
|
||||
}
|
||||
|
||||
#define VIA_MISC_REG_READ 0x03CC
|
||||
#define VIA_MISC_REG_WRITE 0x03C2
|
||||
|
||||
static inline void via_write_misc_reg_mask(u8 data, u8 mask)
|
||||
{
|
||||
u8 old = inb(VIA_MISC_REG_READ);
|
||||
outb((data & mask) | (old & ~mask), VIA_MISC_REG_WRITE);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __VIA_CORE_H__ */
|
14
include/linux/via-gpio.h
Normal file
14
include/linux/via-gpio.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Support for viafb GPIO ports.
|
||||
*
|
||||
* Copyright 2009 Jonathan Corbet <corbet@lwn.net>
|
||||
* Distributable under version 2 of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef __VIA_GPIO_H__
|
||||
#define __VIA_GPIO_H__
|
||||
|
||||
extern int viafb_gpio_lookup(const char *name);
|
||||
extern int viafb_gpio_init(void);
|
||||
extern void viafb_gpio_exit(void);
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 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
|
||||
@ -26,21 +26,17 @@
|
||||
|
||||
struct via_i2c_stuff {
|
||||
u16 i2c_port; /* GPIO or I2C port */
|
||||
u16 is_active; /* Being used as I2C? */
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_bit_data algo;
|
||||
};
|
||||
|
||||
#define I2CPORT 0x3c4
|
||||
#define I2CPORTINDEX 0x31
|
||||
#define GPIOPORT 0x3C4
|
||||
#define GPIOPORTINDEX 0x2C
|
||||
#define I2C_BUS 1
|
||||
#define GPIO_BUS 2
|
||||
#define DELAYPORT 0x3C3
|
||||
|
||||
int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata);
|
||||
int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data);
|
||||
int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len);
|
||||
int viafb_create_i2c_bus(void *par);
|
||||
void viafb_delete_i2c_buss(void *par);
|
||||
int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata);
|
||||
int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data);
|
||||
int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len);
|
||||
struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which);
|
||||
|
||||
extern int viafb_i2c_init(void);
|
||||
extern void viafb_i2c_exit(void);
|
||||
#endif /* __VIA_I2C_H__ */
|
Loading…
Reference in New Issue
Block a user