Merge branch 'modesetting' into crestline
This works for analog, but SDVO output appears to not work yet. Conflicts: src/i830_driver.c
This commit is contained in:
commit
15ff17c756
|
|
@ -4,6 +4,7 @@ Makefile
|
|||
Makefile.in
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
|
|
@ -20,3 +21,4 @@ libtool
|
|||
ltmain.sh
|
||||
missing
|
||||
stamp-h1
|
||||
i810.4
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
- licensing of new files
|
||||
- Figure out what exactly doublescan, interlace mean, and see if we support them.
|
||||
- Remove VbeModeInfoData
|
||||
|
|
@ -118,8 +118,6 @@ if test "x$GCC" = "xyes"; then
|
|||
-Wnested-externs -fno-strict-aliasing"
|
||||
fi
|
||||
|
||||
CFLAGS="$CFLAGS $WARN_CFLAGS"
|
||||
|
||||
AM_CONDITIONAL(DRI, test x$DRI = xyes)
|
||||
if test "$DRI" = yes; then
|
||||
PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto])
|
||||
|
|
@ -134,6 +132,7 @@ fi
|
|||
|
||||
AC_SUBST([DRI_CFLAGS])
|
||||
AC_SUBST([XORG_CFLAGS])
|
||||
AC_SUBST([WARN_CFLAGS])
|
||||
AC_SUBST([moduledir])
|
||||
|
||||
DRIVER_NAME=i810
|
||||
|
|
@ -148,5 +147,8 @@ AC_OUTPUT([
|
|||
Makefile
|
||||
src/Makefile
|
||||
src/xvmc/Makefile
|
||||
src/bios_reader/Makefile
|
||||
src/ch7xxx/Makefile
|
||||
src/sil164/Makefile
|
||||
man/Makefile
|
||||
])
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
20
man/i810.man
20
man/i810.man
|
|
@ -116,13 +116,6 @@ The following driver
|
|||
.B Options
|
||||
are supported for the 830M and later chipsets:
|
||||
.TP
|
||||
.BI "Option \*qVBERestore\*q \*q" boolean \*q
|
||||
Enable or disable the use of VBE save/restore for saving and restoring
|
||||
the initial text mode. This is disabled by default because it causes
|
||||
lockups on some platforms. However, there are some cases where it must
|
||||
enabled for the correct restoration of the initial video mode. If you are
|
||||
having a problem with that, try enabling this option. Default: Disabled.
|
||||
.TP
|
||||
.BI "Option \*qVideoKey\*q \*q" integer \*q
|
||||
This is the same as the
|
||||
.B \*qColorKey\*q
|
||||
|
|
@ -178,19 +171,6 @@ NOTE: Using this option may cause text mode to be restored incorrectly,
|
|||
and thus should be used with caution.
|
||||
Default: disabled.
|
||||
.TP
|
||||
.BI "Option \*qDisplayInfo\*q \*q" boolean \*q
|
||||
It has been found that a certain BIOS call can lockup the Xserver because
|
||||
of a problem in the Video BIOS. The log file will identify if you are
|
||||
suffering from this problem and tell you to turn this option off.
|
||||
Default: enabled
|
||||
.TP
|
||||
.BI "Option \*qDevicePresence\*q \*q" boolean \*q
|
||||
Tell the driver to perform an active detect of the currently connected
|
||||
monitors. This option is useful if the monitor was not connected when
|
||||
the machine has booted, but unfortunately it doesn't always work and
|
||||
is extremely dependent upon the Video BIOS.
|
||||
Default: disabled
|
||||
.TP
|
||||
.BI "Option \*qRotate\*q \*q90\*q"
|
||||
Rotate the desktop 90 degrees counterclockwise. Other valid options are
|
||||
0, 90, 180 and 270 degrees. The RandR extension is used for rotation
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
SUBDIRS = xvmc
|
||||
SUBDIRS = xvmc bios_reader ch7xxx sil164
|
||||
# this is obnoxious:
|
||||
# -module lets us name the module exactly how we want
|
||||
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
|
||||
# _ladir passes a dummy rpath to libtool so the thing will actually link
|
||||
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
|
||||
AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
|
||||
AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
|
||||
|
||||
i810_drv_la_LTLIBRARIES = i810_drv.la
|
||||
i810_drv_la_LDFLAGS = -module -avoid-version
|
||||
|
|
@ -36,6 +36,7 @@ i810_drv_la_SOURCES = \
|
|||
sf_prog.h \
|
||||
wm_prog.h \
|
||||
common.h \
|
||||
i2c_vid.h \
|
||||
i810_accel.c \
|
||||
i810_common.h \
|
||||
i810_cursor.c \
|
||||
|
|
@ -47,21 +48,38 @@ i810_drv_la_SOURCES = \
|
|||
i810_reg.h \
|
||||
i810_video.c \
|
||||
i810_wmark.c \
|
||||
i830_3d.c \
|
||||
i830_accel.c \
|
||||
i830_bios.c \
|
||||
i830_bios.h \
|
||||
i830_common.h \
|
||||
i830_crt.c \
|
||||
i830_cursor.c \
|
||||
i830_debug.c \
|
||||
i830_debug.h \
|
||||
i830_dga.c \
|
||||
i830_display.c \
|
||||
i830_display.h \
|
||||
i830_driver.c \
|
||||
i830_dvo.c \
|
||||
i830.h \
|
||||
i830_gtf.c \
|
||||
i830_i2c.c \
|
||||
i830_io.c \
|
||||
i830_lvds.c \
|
||||
i830_memory.c \
|
||||
i830_modes.c \
|
||||
i830_video.c \
|
||||
i830_video.h \
|
||||
i830_reg.h \
|
||||
i830_rotate.c \
|
||||
i830_randr.c \
|
||||
i830_3d.c \
|
||||
i830_reg.h \
|
||||
i830_sdvo.c \
|
||||
i830_sdvo.h \
|
||||
i830_sdvo_regs.h \
|
||||
i830_tv.c \
|
||||
i830_xf86Modes.h \
|
||||
i830_xf86Modes.c \
|
||||
i915_3d.c \
|
||||
i915_3d.h \
|
||||
i915_reg.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
bios_reader
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
AM_CFLAGS = @XORG_CFLAGS@
|
||||
|
||||
noinst_PROGRAMS = bios_reader
|
||||
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define _PARSE_EDID_
|
||||
#include "edid.h"
|
||||
|
||||
/* Define some types so we can reuse i830_bios.h */
|
||||
typedef void *ScrnInfoPtr;
|
||||
typedef int Bool;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#include "../i830_bios.h"
|
||||
|
||||
|
||||
/* Make a fake pI830 so we can easily pull i830_bios.c code in here. */
|
||||
struct _fake_i830 {
|
||||
CARD8 *VBIOS;
|
||||
};
|
||||
struct _fake_i830 I830;
|
||||
struct _fake_i830 *pI830 = &I830;
|
||||
|
||||
#define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr])
|
||||
#define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \
|
||||
(pI830->VBIOS[_addr + 1] << 8))
|
||||
#define INTEL_BIOS_32(_addr) (pI830->VBIOS[_addr] | \
|
||||
(pI830->VBIOS[_addr + 1] << 8) \
|
||||
(pI830->VBIOS[_addr + 2] << 16) \
|
||||
(pI830->VBIOS[_addr + 3] << 24))
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
int bios_size = 65536;
|
||||
struct vbt_header *vbt;
|
||||
struct bdb_header *bdb;
|
||||
int vbt_off, bdb_off, bdb_block_off, block_size;
|
||||
int panel_type = -1, i;
|
||||
char *filename = "bios";
|
||||
|
||||
if (argc == 2)
|
||||
filename = argv[1];
|
||||
|
||||
f = fopen(filename, "r");
|
||||
if (!f) {
|
||||
printf("Couldn't open %s\n", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pI830->VBIOS = calloc(1, bios_size);
|
||||
if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size)
|
||||
return 1;
|
||||
|
||||
vbt_off = INTEL_BIOS_16(0x1a);
|
||||
printf("VBT offset: %08x\n", vbt_off);
|
||||
vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
|
||||
printf("VBT sig: %20s\n", vbt->signature);
|
||||
printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
|
||||
|
||||
bdb_off = vbt_off + vbt->bdb_offset;
|
||||
bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
|
||||
printf("BDB sig: %16s\n", bdb->signature);
|
||||
printf("BDB vers: %d.%d\n", bdb->version / 100, bdb->version % 100);
|
||||
for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
|
||||
bdb_block_off += block_size)
|
||||
{
|
||||
int start = bdb_off + bdb_block_off;
|
||||
int id;
|
||||
struct lvds_bdb_1 *lvds1;
|
||||
struct lvds_bdb_2 *lvds2;
|
||||
struct lvds_bdb_2_fp_params *fpparam;
|
||||
struct lvds_bdb_2_fp_edid_dtd *fptiming;
|
||||
CARD8 *timing_ptr;
|
||||
|
||||
id = INTEL_BIOS_8(start);
|
||||
block_size = INTEL_BIOS_16(start + 1) + 3;
|
||||
printf("BDB block type %03d size %d\n", id, block_size);
|
||||
switch (id) {
|
||||
case 40:
|
||||
lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
|
||||
panel_type = lvds1->panel_type;
|
||||
printf("Panel type: %d, caps %04x\n", panel_type, lvds1->caps);
|
||||
break;
|
||||
case 41:
|
||||
if (panel_type == -1) {
|
||||
printf("Found panel block with no panel type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
|
||||
|
||||
printf("Entries per table: %d\n", lvds2->table_size);
|
||||
for (i = 0; i < 16; i++) {
|
||||
char marker;
|
||||
fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
|
||||
bdb_off + lvds2->panels[i].fp_params_offset);
|
||||
fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
|
||||
bdb_off + lvds2->panels[i].fp_edid_dtd_offset);
|
||||
timing_ptr = pI830->VBIOS + bdb_off +
|
||||
lvds2->panels[i].fp_edid_dtd_offset;
|
||||
if (fpparam->terminator != 0xffff) {
|
||||
/* Apparently the offsets are wrong for some BIOSes, so we
|
||||
* try the other offsets if we find a bad terminator.
|
||||
*/
|
||||
fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
|
||||
bdb_off + lvds2->panels[i].fp_params_offset + 8);
|
||||
fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
|
||||
bdb_off + lvds2->panels[i].fp_edid_dtd_offset + 8);
|
||||
timing_ptr = pI830->VBIOS + bdb_off +
|
||||
lvds2->panels[i].fp_edid_dtd_offset + 8;
|
||||
|
||||
if (fpparam->terminator != 0xffff)
|
||||
continue;
|
||||
}
|
||||
if (i == panel_type)
|
||||
marker = '*';
|
||||
else
|
||||
marker = ' ';
|
||||
printf("%c Panel index %02i xres %d yres %d clock %d\n", marker,
|
||||
i, fpparam->x_res, fpparam->y_res,
|
||||
_PIXEL_CLOCK(timing_ptr));
|
||||
printf(" %d %d %d %d %d %d %d %d\n",
|
||||
_H_ACTIVE(timing_ptr), _H_BLANK(timing_ptr),
|
||||
_H_SYNC_OFF(timing_ptr), _H_SYNC_WIDTH(timing_ptr),
|
||||
_V_ACTIVE(timing_ptr), _V_BLANK(timing_ptr),
|
||||
_V_SYNC_OFF(timing_ptr), _V_SYNC_WIDTH(timing_ptr));
|
||||
}
|
||||
|
||||
printf("Panel of size %dx%d\n", fpparam->x_res, fpparam->y_res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# this is obnoxious:
|
||||
# -module lets us name the module exactly how we want
|
||||
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
|
||||
# _ladir passes a dummy rpath to libtool so the thing will actually link
|
||||
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
|
||||
AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
|
||||
|
||||
ch7xxx_la_LTLIBRARIES = ch7xxx.la
|
||||
ch7xxx_la_LDFLAGS = -module -avoid-version
|
||||
ch7xxx_ladir = @moduledir@/drivers
|
||||
|
||||
ch7xxx_la_SOURCES = \
|
||||
ch7xxx.c \
|
||||
ch7xxx_module.c \
|
||||
ch7xxx.h \
|
||||
ch7xxx_reg.h
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright © 2006 Dave Airlie
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sub license, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the
|
||||
next paragraph) shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
#include <string.h>
|
||||
#include "xf86.h"
|
||||
#include "xf86_OSproc.h"
|
||||
#include "xf86Resources.h"
|
||||
#include "compiler.h"
|
||||
#include "miscstruct.h"
|
||||
#include "xf86i2c.h"
|
||||
|
||||
|
||||
#include "../i2c_vid.h"
|
||||
#include "ch7xxx.h"
|
||||
#include "ch7xxx_reg.h"
|
||||
|
||||
static void ch7xxxSaveRegs(I2CDevPtr d);
|
||||
|
||||
static CARD8 ch7xxxFreqRegs[][7] =
|
||||
{ { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 },
|
||||
{ 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 },
|
||||
{ 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } };
|
||||
|
||||
|
||||
static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch)
|
||||
{
|
||||
if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch)
|
||||
{
|
||||
if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Ch7xxxicon Image 164 driver for chip on i2c bus */
|
||||
static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr)
|
||||
{
|
||||
/* this will detect the CH7xxx chip on the specified i2c bus */
|
||||
CH7xxxPtr ch7xxx;
|
||||
unsigned char ch;
|
||||
|
||||
xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
|
||||
|
||||
ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
|
||||
if (ch7xxx == NULL)
|
||||
return NULL;
|
||||
|
||||
ch7xxx->d.DevName = "CH7xxx TMDS Controller";
|
||||
ch7xxx->d.SlaveAddr = addr;
|
||||
ch7xxx->d.pI2CBus = b;
|
||||
ch7xxx->d.StartTimeout = b->StartTimeout;
|
||||
ch7xxx->d.BitTimeout = b->BitTimeout;
|
||||
ch7xxx->d.AcknTimeout = b->AcknTimeout;
|
||||
ch7xxx->d.ByteTimeout = b->ByteTimeout;
|
||||
ch7xxx->d.DriverPrivate.ptr = ch7xxx;
|
||||
|
||||
if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
|
||||
goto out;
|
||||
|
||||
ErrorF("VID is %02X", ch);
|
||||
if (ch!=(CH7xxx_VID & 0xFF))
|
||||
{
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
|
||||
goto out;
|
||||
|
||||
ErrorF("DID is %02X", ch);
|
||||
if (ch!=(CH7xxx_DID & 0xFF))
|
||||
{
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (!xf86I2CDevInit(&(ch7xxx->d)))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
return ch7xxx;
|
||||
|
||||
out:
|
||||
xfree(ch7xxx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static Bool ch7xxxInit(I2CDevPtr d)
|
||||
{
|
||||
CH7xxxPtr ch7xxx = CH7PTR(d);
|
||||
|
||||
/* not much to do */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode)
|
||||
{
|
||||
CH7xxxPtr ch7xxx = CH7PTR(d);
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode)
|
||||
{
|
||||
CH7xxxPtr ch7xxx = CH7PTR(d);
|
||||
int ret;
|
||||
unsigned char pm, idf;
|
||||
unsigned char tpcp, tpd, tpf, cm;
|
||||
CARD8 *freq_regs;
|
||||
int i;
|
||||
ErrorF("Clock is %d\n", mode->Clock);
|
||||
|
||||
if (mode->Clock < 75000)
|
||||
freq_regs = ch7xxxFreqRegs[0];
|
||||
else if (mode->Clock < 125000)
|
||||
freq_regs = ch7xxxFreqRegs[1];
|
||||
else
|
||||
freq_regs = ch7xxxFreqRegs[2];
|
||||
|
||||
for (i = 0x31; i < 0x37; i++) {
|
||||
ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
|
||||
ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", idf, tpcp, tpd, tpf);
|
||||
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", pm);
|
||||
|
||||
if (mode->Clock < 65000) {
|
||||
tpcp = 0x08;
|
||||
tpd = 0x16;
|
||||
tpf = 0x60;
|
||||
} else {
|
||||
tpcp = 0x06;
|
||||
tpd = 0x26;
|
||||
tpf = 0xa0;
|
||||
}
|
||||
|
||||
idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
|
||||
if (mode->Flags & V_PHSYNC)
|
||||
idf |= CH7xxx_IDF_HSP;
|
||||
|
||||
if (mode->Flags & V_PVSYNC)
|
||||
idf |= CH7xxx_IDF_HSP;
|
||||
|
||||
/* setup PM Registers */
|
||||
pm &= ~CH7xxx_PM_FPD;
|
||||
pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
|
||||
|
||||
// cm |= 1;
|
||||
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
|
||||
|
||||
#endif
|
||||
/* don't do much */
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the CH7xxx power state */
|
||||
static void ch7xxxPower(I2CDevPtr d, Bool On)
|
||||
{
|
||||
CH7xxxPtr ch7xxx = CH7PTR(d);
|
||||
int ret;
|
||||
unsigned char ch;
|
||||
|
||||
|
||||
ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
|
||||
if (ret == FALSE)
|
||||
return;
|
||||
|
||||
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", ch);
|
||||
|
||||
#if 0
|
||||
ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (On)
|
||||
ch |= CH7xxx_8_PD;
|
||||
else
|
||||
ch &= ~CH7xxx_8_PD;
|
||||
|
||||
ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static void ch7xxxPrintRegs(I2CDevPtr d)
|
||||
{
|
||||
CH7xxxPtr ch7xxx = CH7PTR(d);
|
||||
int i;
|
||||
|
||||
ch7xxxSaveRegs(d);
|
||||
|
||||
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
|
||||
if (( i % 8 ) == 0 )
|
||||
ErrorF("\n %02X: ", i);
|
||||
ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void ch7xxxSaveRegs(I2CDevPtr d)
|
||||
{
|
||||
CH7xxxPtr ch7xxx = CH7PTR(d);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
|
||||
ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
|
||||
if (ret == FALSE)
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
I830I2CVidOutputRec CH7xxxVidOutput = {
|
||||
ch7xxxDetect,
|
||||
ch7xxxInit,
|
||||
ch7xxxModeValid,
|
||||
ch7xxxMode,
|
||||
ch7xxxPower,
|
||||
ch7xxxPrintRegs,
|
||||
ch7xxxSaveRegs,
|
||||
NULL,
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CH7xxx_H
|
||||
#define CH7xxx_H
|
||||
|
||||
#define CH7xxx_ADDR_1 0x76
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86Module.h"
|
||||
|
||||
static MODULESETUPPROTO(ch7xxxSetup);
|
||||
|
||||
static XF86ModuleVersionInfo ch7xxxVersRec =
|
||||
{
|
||||
"ch7xxx",
|
||||
MODULEVENDORSTRING,
|
||||
MODINFOSTRING1,
|
||||
MODINFOSTRING2,
|
||||
XORG_VERSION_CURRENT,
|
||||
1, 0, 0,
|
||||
ABI_CLASS_VIDEODRV,
|
||||
ABI_VIDEODRV_VERSION,
|
||||
MOD_CLASS_NONE,
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
_X_EXPORT XF86ModuleData ch7xxxModuleData = {
|
||||
&ch7xxxVersRec,
|
||||
ch7xxxSetup,
|
||||
NULL
|
||||
};
|
||||
|
||||
static pointer
|
||||
ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
|
||||
return (pointer)1;
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CH7xxx_REG_H
|
||||
#define CH7xxx_REG_H
|
||||
|
||||
#define CH7xxx_REG_VID 0x4a
|
||||
#define CH7xxx_REG_DID 0x4b
|
||||
|
||||
|
||||
#define CH7011_VID 0x83
|
||||
#define CH7009A_VID 0x84
|
||||
#define CH7009B_VID 0x85
|
||||
#define CH7301_VID 0x95
|
||||
|
||||
#define CH7xxx_VID 0x84
|
||||
#define CH7xxx_DID 0x17
|
||||
|
||||
#define CH7xxx_NUM_REGS 0x4c
|
||||
|
||||
typedef struct _CH7xxxSaveRec {
|
||||
CARD8 regs[CH7xxx_NUM_REGS];
|
||||
} CH7xxxSaveRec;
|
||||
|
||||
typedef struct {
|
||||
I2CDevRec d;
|
||||
CH7xxxSaveRec SavedReg;
|
||||
CH7xxxSaveRec ModeReg;
|
||||
} CH7xxxRec, *CH7xxxPtr;
|
||||
|
||||
#define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr))
|
||||
|
||||
#define CH7xxx_CM 0x1C
|
||||
#define CH7xxx_CM_XCM (1<<0)
|
||||
#define CH7xxx_CM_MCP (1<<2)
|
||||
#define CH7xxx_INPUT_CLOCK 0x1D
|
||||
#define CH7xxx_GPIO 0x1E
|
||||
#define CH7xxx_IDF 0x1F
|
||||
|
||||
#define CH7xxx_IDF_HSP (1<<3)
|
||||
#define CH7xxx_IDF_VSP (1<<4)
|
||||
|
||||
#define CH7301_CONNECTION_DETECT 0x20
|
||||
#define CH7301_DAC_CNTL 0x21
|
||||
#define CH7301_HOTPLUG 0x23
|
||||
#define CH7xxx_TCTL 0x31
|
||||
#define CH7xxx_TPCP 0x33
|
||||
#define CH7xxx_TPD 0x34
|
||||
#define CH7xxx_TPVT 0x35
|
||||
#define CH7xxx_TPF 0x36
|
||||
#define CH7301_TCT 0x37
|
||||
#define CH7301_TEST_PATTERN 0x48
|
||||
#define CH7xxx_PM 0x49
|
||||
|
||||
#define CH7xxx_PM_FPD (1<<0)
|
||||
#define CH7301_PM_DACPD0 (1<<1)
|
||||
#define CH7301_PM_DACPD1 (1<<2)
|
||||
#define CH7301_PM_DACPD2 (1<<3)
|
||||
#define CH7xxx_PM_DVIL (1<<6)
|
||||
#define CH7xxx_PM_DVIP (1<<7)
|
||||
|
||||
#define CH7301_SYNC_POLARITY 0x56
|
||||
|
||||
#define CH7301_SYNC_RGB_YUV (1<<0)
|
||||
#define CH7301_SYNC_POL_DVI (1<<5)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -73,7 +73,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#endif
|
||||
|
||||
/* I830 hooks for the I810 driver setup/probe. */
|
||||
extern const OptionInfoRec *I830BIOSAvailableOptions(int chipid, int busid);
|
||||
extern const OptionInfoRec *I830AvailableOptions(int chipid, int busid);
|
||||
extern void I830InitpScrn(ScrnInfoPtr pScrn);
|
||||
|
||||
/* Symbol lists shared by the i810 and i830 parts. */
|
||||
|
|
@ -90,6 +90,7 @@ extern const char *I810shadowSymbols[];
|
|||
extern const char *I810driSymbols[];
|
||||
extern const char *I810drmSymbols[];
|
||||
#endif
|
||||
extern const char *I810i2cSymbols[];
|
||||
|
||||
extern void I830DPRINTF_stub(const char *filename, int line,
|
||||
const char *function, const char *fmt, ...);
|
||||
|
|
@ -106,8 +107,8 @@ extern void I830DPRINTF_stub(const char *filename, int line,
|
|||
|
||||
/* BIOS debug macro */
|
||||
#define xf86ExecX86int10_wrapper(pInt, pScrn) do { \
|
||||
ErrorF("Executing (ax == 0x%x) BIOS call at %s:%d\n", pInt->ax, __FILE__, __LINE__); \
|
||||
if (I810_DEBUG & DEBUG_VERBOSE_BIOS) { \
|
||||
ErrorF("\n\n\n\nExecuting (ax == 0x%x) BIOS call\n", pInt->ax); \
|
||||
ErrorF("Checking Error state before execution\n"); \
|
||||
PrintErrorState(pScrn); \
|
||||
} \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
/* this needs to go in the server */
|
||||
#ifndef I2C_VID_H
|
||||
#define I2C_VID_H
|
||||
|
||||
typedef struct _I830I2CVidOutputRec {
|
||||
void *(*Detect)(I2CBusPtr b, I2CSlaveAddr addr);
|
||||
Bool (*Init)(I2CDevPtr d);
|
||||
ModeStatus (*ModeValid)(I2CDevPtr d, DisplayModePtr mode);
|
||||
void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
|
||||
void (*Power)(I2CDevPtr d, Bool On);
|
||||
void (*PrintRegs)(I2CDevPtr d);
|
||||
void (*SaveRegs)(I2CDevPtr d);
|
||||
void (*RestoreRegs)(I2CDevPtr d);
|
||||
} I830I2CVidOutputRec, *I830I2CVidOutputPtr;
|
||||
|
||||
#endif
|
||||
|
|
@ -347,6 +347,14 @@ const char *I810shadowSymbols[] = {
|
|||
"shadowInit",
|
||||
"shadowSetup",
|
||||
"shadowAdd",
|
||||
"shadowRemove",
|
||||
"shadowUpdateRotatePacked",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *I810i2cSymbols[] = {
|
||||
"xf86CreateI2CBusRec",
|
||||
"xf86I2CBusInit",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -486,11 +494,11 @@ I810AvailableOptions(int chipid, int busid)
|
|||
#ifndef I830_ONLY
|
||||
const OptionInfoRec *pOptions;
|
||||
|
||||
if ((pOptions = I830BIOSAvailableOptions(chipid, busid)))
|
||||
if ((pOptions = I830AvailableOptions(chipid, busid)))
|
||||
return pOptions;
|
||||
return I810Options;
|
||||
#else
|
||||
return I830BIOSAvailableOptions(chipid, busid);
|
||||
return I830AvailableOptions(chipid, busid);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
843
src/i810_reg.h
843
src/i810_reg.h
|
|
@ -26,9 +26,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
**************************************************************************/
|
||||
|
||||
/** @file
|
||||
* Register names and fields for Intel graphics.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
* based on the i740 driver by
|
||||
* Kevin E. Martin <kevin@precisioninsight.com>
|
||||
|
|
@ -94,6 +99,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define LINEAR_MODE_ENABLE 0x02
|
||||
#define PAGE_MAPPING_ENABLE 0x01
|
||||
|
||||
#define HOTKEY_VBIOS_SWITCH_BLOCK 0x80
|
||||
#define HOTKEY_SWITCH 0x20
|
||||
#define HOTKEY_TOGGLE 0x10
|
||||
|
||||
/* Blitter control, p378
|
||||
*/
|
||||
#define BITBLT_CNTL 0x7000c
|
||||
|
|
@ -258,7 +267,26 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define HSYNC_ON 0x00
|
||||
#define HSYNC_OFF 0x02
|
||||
|
||||
|
||||
#define GPIOA 0x5010
|
||||
#define GPIOB 0x5014
|
||||
#define GPIOC 0x5018
|
||||
#define GPIOD 0x501c
|
||||
#define GPIOE 0x5020
|
||||
#define GPIOF 0x5024
|
||||
#define GPIOG 0x5028
|
||||
#define GPIOH 0x502c
|
||||
# define GPIO_CLOCK_DIR_MASK (1 << 0)
|
||||
# define GPIO_CLOCK_DIR_IN (0 << 1)
|
||||
# define GPIO_CLOCK_DIR_OUT (1 << 1)
|
||||
# define GPIO_CLOCK_VAL_MASK (1 << 2)
|
||||
# define GPIO_CLOCK_VAL_OUT (1 << 3)
|
||||
# define GPIO_CLOCK_VAL_IN (1 << 4)
|
||||
# define GPIO_DATA_DIR_MASK (1 << 8)
|
||||
# define GPIO_DATA_DIR_IN (0 << 9)
|
||||
# define GPIO_DATA_DIR_OUT (1 << 9)
|
||||
# define GPIO_DATA_VAL_MASK (1 << 10)
|
||||
# define GPIO_DATA_VAL_OUT (1 << 11)
|
||||
# define GPIO_DATA_VAL_IN (1 << 12)
|
||||
|
||||
/* p317, 319
|
||||
*/
|
||||
|
|
@ -713,6 +741,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define VSYNC_A 0x60014
|
||||
#define PIPEASRC 0x6001c
|
||||
#define BCLRPAT_A 0x60020
|
||||
#define VSYNCSHIFT_A 0x60028
|
||||
|
||||
#define HTOTAL_B 0x61000
|
||||
#define HBLANK_B 0x61004
|
||||
|
|
@ -722,11 +751,206 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define VSYNC_B 0x61014
|
||||
#define PIPEBSRC 0x6101c
|
||||
#define BCLRPAT_B 0x61020
|
||||
#define VSYNCSHIFT_B 0x61028
|
||||
|
||||
#define PP_STATUS 0x61200
|
||||
# define PP_ON (1 << 31)
|
||||
|
||||
#define PP_CONTROL 0x61204
|
||||
# define POWER_TARGET_ON (1 << 0)
|
||||
|
||||
#define LVDSPP_ON 0x61208
|
||||
#define LVDSPP_OFF 0x6120c
|
||||
#define PP_CYCLE 0x61210
|
||||
|
||||
#define PFIT_CONTROL 0x61230
|
||||
# define PFIT_ENABLE (1 << 31)
|
||||
# define VERT_INTERP_DISABLE (0 << 10)
|
||||
# define VERT_INTERP_BILINEAR (1 << 10)
|
||||
# define VERT_INTERP_MASK (3 << 10)
|
||||
# define VERT_AUTO_SCALE (1 << 9)
|
||||
# define HORIZ_INTERP_DISABLE (0 << 6)
|
||||
# define HORIZ_INTERP_BILINEAR (1 << 6)
|
||||
# define HORIZ_INTERP_MASK (3 << 6)
|
||||
# define HORIZ_AUTO_SCALE (1 << 5)
|
||||
# define PANEL_8TO6_DITHER_ENABLE (1 << 3)
|
||||
|
||||
#define PFIT_PGM_RATIOS 0x61234
|
||||
# define PFIT_VERT_SCALE_MASK 0xfff00000
|
||||
# define PFIT_HORIZ_SCALE_MASK 0x0000fff0
|
||||
|
||||
#define PFIT_AUTO_RATIOS 0x61238
|
||||
|
||||
#define DPLL_A 0x06014
|
||||
#define DPLL_B 0x06018
|
||||
# define DPLL_VCO_ENABLE (1 << 31)
|
||||
# define DPLL_DVO_HIGH_SPEED (1 << 30)
|
||||
# define DPLL_SYNCLOCK_ENABLE (1 << 29)
|
||||
# define DPLL_VGA_MODE_DIS (1 << 28)
|
||||
# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
|
||||
# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
|
||||
# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
|
||||
# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
|
||||
# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
|
||||
# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
|
||||
# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
|
||||
# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
|
||||
# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */
|
||||
# define DPLL_FPA01_P1_POS_DIV_MASK_I830 0x001f0000 /* i830 */
|
||||
# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
|
||||
# define PLL_REF_INPUT_DREFCLK (0 << 13)
|
||||
# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
|
||||
# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
|
||||
# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
|
||||
# define PLL_LOAD_PULSE_PHASE_SHIFT 9
|
||||
/*
|
||||
* Parallel to Serial Load Pulse phase selection.
|
||||
* Selects the phase for the 10X DPLL clock for the PCIe
|
||||
* digital display port. The range is 4 to 13; 10 or more
|
||||
* is just a flip delay. The default is 6
|
||||
*/
|
||||
# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
|
||||
# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
|
||||
/**
|
||||
* SDVO multiplier for 945G/GM. Not used on 965.
|
||||
*
|
||||
* \sa DPLL_MD_UDI_MULTIPLIER_MASK
|
||||
*/
|
||||
# define SDVO_MULTIPLIER_MASK 0x000000ff
|
||||
# define SDVO_MULTIPLIER_SHIFT_HIRES 4
|
||||
# define SDVO_MULTIPLIER_SHIFT_VGA 0
|
||||
|
||||
/** @defgroup DPLL_MD
|
||||
* @{
|
||||
*/
|
||||
/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
|
||||
#define DPLL_A_MD 0x0601c
|
||||
/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
|
||||
#define DPLL_B_MD 0x06020
|
||||
/**
|
||||
* UDI pixel divider, controlling how many pixels are stuffed into a packet.
|
||||
*
|
||||
* Value is pixels minus 1. Must be set to 1 pixel for SDVO.
|
||||
*/
|
||||
# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
|
||||
# define DPLL_MD_UDI_DIVIDER_SHIFT 24
|
||||
/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
|
||||
# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
|
||||
# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
|
||||
/**
|
||||
* SDVO/UDI pixel multiplier.
|
||||
*
|
||||
* SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
|
||||
* clock rate is 10 times the DPLL clock. At low resolution/refresh rate
|
||||
* modes, the bus rate would be below the limits, so SDVO allows for stuffing
|
||||
* dummy bytes in the datastream at an increased clock rate, with both sides of
|
||||
* the link knowing how many bytes are fill.
|
||||
*
|
||||
* So, for a mode with a dotclock of 65Mhz, we would want to double the clock
|
||||
* rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
|
||||
* set to 130Mhz, and the SDVO multiplier set to 2x in this register and
|
||||
* through an SDVO command.
|
||||
*
|
||||
* This register field has values of multiplication factor minus 1, with
|
||||
* a maximum multiplier of 5 for SDVO.
|
||||
*/
|
||||
# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
|
||||
# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
|
||||
/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
|
||||
* This best be set to the default value (3) or the CRT won't work. No,
|
||||
* I don't entirely understand what this does...
|
||||
*/
|
||||
# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
|
||||
# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
#define DPLL_TEST 0x606c
|
||||
|
||||
#define D_STATE 0x6104
|
||||
#define DSPCLK_GATE_D 0x6200
|
||||
#define RENCLK_GATE_D1 0x6204
|
||||
#define RENCLK_GATE_D2 0x6208
|
||||
#define RAMCLK_GATE_D 0x6210 /* CRL only */
|
||||
|
||||
#define BLC_PWM_CTL 0x61254
|
||||
#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
|
||||
#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
|
||||
#define BLM_LEGACY_MODE (1 << 16)
|
||||
#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
|
||||
#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
|
||||
|
||||
#define BLM_CTL 0x61260
|
||||
#define BLM_THRESHOLD_0 0x61270
|
||||
#define BLM_THRESHOLD_1 0x61274
|
||||
#define BLM_THRESHOLD_2 0x61278
|
||||
#define BLM_THRESHOLD_3 0x6127c
|
||||
#define BLM_THRESHOLD_4 0x61280
|
||||
#define BLM_THRESHOLD_5 0x61284
|
||||
|
||||
#define BLM_ACCUMULATOR_0 0x61290
|
||||
#define BLM_ACCUMULATOR_1 0x61294
|
||||
#define BLM_ACCUMULATOR_2 0x61298
|
||||
#define BLM_ACCUMULATOR_3 0x6129c
|
||||
#define BLM_ACCUMULATOR_4 0x612a0
|
||||
#define BLM_ACCUMULATOR_5 0x612a4
|
||||
|
||||
#define FPA0 0x06040
|
||||
#define FPA1 0x06044
|
||||
#define FPB0 0x06048
|
||||
#define FPB1 0x0604c
|
||||
# define FP_N_DIV_MASK 0x003f0000
|
||||
# define FP_M1_DIV_MASK 0x00003f00
|
||||
# define FP_M2_DIV_MASK 0x0000003f
|
||||
|
||||
#define PORT_HOTPLUG_EN 0x61110
|
||||
# define SDVOB_HOTPLUG_INT_EN (1 << 26)
|
||||
# define SDVOC_HOTPLUG_INT_EN (1 << 25)
|
||||
# define TV_HOTPLUG_INT_EN (1 << 18)
|
||||
# define CRT_HOTPLUG_INT_EN (1 << 9)
|
||||
# define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
|
||||
|
||||
#define PORT_HOTPLUG_STAT 0x61114
|
||||
# define CRT_HOTPLUG_INT_STATUS (1 << 11)
|
||||
# define TV_HOTPLUG_INT_STATUS (1 << 10)
|
||||
# define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
|
||||
# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
|
||||
# define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
|
||||
# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
|
||||
# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
|
||||
# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
|
||||
|
||||
#define SDVOB 0x61140
|
||||
#define SDVOC 0x61160
|
||||
#define SDVO_ENABLE (1 << 31)
|
||||
#define SDVO_PIPE_B_SELECT (1 << 30)
|
||||
#define SDVO_STALL_SELECT (1 << 29)
|
||||
#define SDVO_INTERRUPT_ENABLE (1 << 26)
|
||||
/**
|
||||
* 915G/GM SDVO pixel multiplier.
|
||||
*
|
||||
* Programmed value is multiplier - 1, up to 5x.
|
||||
*
|
||||
* \sa DPLL_MD_UDI_MULTIPLIER_MASK
|
||||
*/
|
||||
#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
|
||||
#define SDVO_PORT_MULTIPLY_SHIFT 23
|
||||
#define SDVO_PHASE_SELECT_MASK (15 << 19)
|
||||
#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
|
||||
#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
|
||||
#define SDVOC_GANG_MODE (1 << 16)
|
||||
#define SDVO_BORDER_ENABLE (1 << 7)
|
||||
#define SDVOB_PCIE_CONCURRENCY (1 << 3)
|
||||
#define SDVO_DETECTED (1 << 2)
|
||||
/* Bits to be preserved when writing */
|
||||
#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
|
||||
#define SDVOC_PRESERVE_MASK (1 << 17)
|
||||
|
||||
#define UDIB_SVB_SHB_CODES 0x61144
|
||||
#define UDIB_SHA_BLANK_CODES 0x61148
|
||||
#define UDIB_START_END_FILL_CODES 0x6114c
|
||||
|
||||
|
||||
#define SDVOUDI 0x61150
|
||||
|
||||
#define I830_HTOTAL_MASK 0xfff0000
|
||||
#define I830_HACTIVE_MASK 0x7ff
|
||||
|
|
@ -770,13 +994,599 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define DVOA 0x61120
|
||||
#define DVOB 0x61140
|
||||
#define DVOC 0x61160
|
||||
#define DVO_ENABLE (1<<31)
|
||||
#define DVO_ENABLE (1 << 31)
|
||||
#define DVO_PIPE_B_SELECT (1 << 30)
|
||||
#define DVO_PIPE_STALL_UNUSED (0 << 28)
|
||||
#define DVO_PIPE_STALL (1 << 28)
|
||||
#define DVO_PIPE_STALL_TV (2 << 28)
|
||||
#define DVO_USE_VGA_SYNC (1 << 15)
|
||||
#define DVO_DATA_ORDER_I740 (0 << 14)
|
||||
#define DVO_DATA_ORDER_FP (1 << 14)
|
||||
#define DVO_VSYNC_DISABLE (1 << 11)
|
||||
#define DVO_HSYNC_DISABLE (1 << 10)
|
||||
#define DVO_VSYNC_TRISTATE (1 << 9)
|
||||
#define DVO_HSYNC_TRISTATE (1 << 8)
|
||||
#define DVO_BORDER_ENABLE (1 << 7)
|
||||
#define DVO_DATA_ORDER_GBRG (1 << 6)
|
||||
#define DVO_DATA_ORDER_RGGB (0 << 6)
|
||||
#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6)
|
||||
#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6)
|
||||
#define DVO_VSYNC_ACTIVE_HIGH (1 << 4)
|
||||
#define DVO_HSYNC_ACTIVE_HIGH (1 << 3)
|
||||
#define DVO_BLANK_ACTIVE_HIGH (1 << 2)
|
||||
#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
|
||||
#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
|
||||
#define DVO_PRESERVE_MASK (0x7<<24)
|
||||
|
||||
#define DVOA_SRCDIM 0x61124
|
||||
#define DVOB_SRCDIM 0x61144
|
||||
#define DVOC_SRCDIM 0x61164
|
||||
#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
|
||||
#define DVO_SRCDIM_VERTICAL_SHIFT 0
|
||||
|
||||
#define LVDS 0x61180
|
||||
# define LVDS_PORT_EN (1 << 31)
|
||||
# define LVDS_PIPEB_SELECT (1 << 30)
|
||||
# define LVDS_CLKA_POWER_DOWN (0 << 8)
|
||||
# define LVDS_CLKA_POWER_UP (3 << 8)
|
||||
|
||||
/** @defgroup TV_CTL
|
||||
* @{
|
||||
*/
|
||||
#define TV_CTL 0x68000
|
||||
/** Enables the TV encoder */
|
||||
# define TV_ENC_ENABLE (1 << 31)
|
||||
/** Sources the TV encoder input from pipe B instead of A. */
|
||||
# define TV_ENC_PIPEB_SELECT (1 << 30)
|
||||
/** Outputs composite video (DAC A only) */
|
||||
# define TV_ENC_OUTPUT_COMPOSITE (0 << 28)
|
||||
/** Outputs SVideo video (DAC B/C) */
|
||||
# define TV_ENC_OUTPUT_SVIDEO (1 << 28)
|
||||
/** Outputs Component video (DAC A/B/C) */
|
||||
# define TV_ENC_OUTPUT_COMPONENT (2 << 28)
|
||||
# define TV_TRILEVEL_SYNC (1 << 21)
|
||||
/** Enables slow sync generation (945GM only) */
|
||||
# define TV_SLOW_SYNC (1 << 20)
|
||||
/** Selects 4x oversampling for 480i and 576p */
|
||||
# define TV_OVERSAMPLE_4X (0 << 18)
|
||||
/** Selects 2x oversampling for 720p and 1080i */
|
||||
# define TV_OVERSAMPLE_2X (1 << 18)
|
||||
/** Selects no oversampling for 1080p */
|
||||
# define TV_OVERSAMPLE_NONE (2 << 18)
|
||||
/** Selects 8x oversampling */
|
||||
# define TV_OVERSAMPLE_8X (3 << 18)
|
||||
/** Selects progressive mode rather than interlaced */
|
||||
# define TV_PROGRESSIVE (1 << 17)
|
||||
/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */
|
||||
# define TV_PAL_BURST (1 << 16)
|
||||
/** Field for setting delay of Y compared to C */
|
||||
# define TV_YC_SKEW_MASK (7 << 12)
|
||||
/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
|
||||
# define TV_ENC_SDP_FIX (1 << 11)
|
||||
/**
|
||||
* Enables a fix for the 915GM only.
|
||||
*
|
||||
* Not sure what it does.
|
||||
*/
|
||||
# define TV_ENC_C0_FIX (1 << 10)
|
||||
/** Bits that must be preserved by software */
|
||||
# define TV_CTL_SAVE ((3 << 8) | (3 << 6))
|
||||
# define TV_FUSE_STATE_MASK (3 << 4)
|
||||
/** Read-only state that reports all features enabled */
|
||||
# define TV_FUSE_STATE_ENABLED (0 << 4)
|
||||
/** Read-only state that reports that Macrovision is disabled in hardware*/
|
||||
# define TV_FUSE_STATE_NO_MACROVISION (1 << 4)
|
||||
/** Read-only state that reports that TV-out is disabled in hardware. */
|
||||
# define TV_FUSE_STATE_DISABLED (2 << 4)
|
||||
/**
|
||||
* This test mode forces the DACs to 50% of full output.
|
||||
*
|
||||
* This is used for load detection in combination with TVDAC_SENSE_MASK
|
||||
*/
|
||||
# define TV_TEST_MODE_MONITOR_DETECT (7 << 0)
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_DAC
|
||||
* @{
|
||||
*/
|
||||
#define TV_DAC 0x68004
|
||||
/**
|
||||
* Reports that DAC state change logic has reported change (RO).
|
||||
*
|
||||
* This gets cleared when TV_DAC_STATE_EN is cleared
|
||||
*/
|
||||
# define TVDAC_STATE_CHG (1 << 31)
|
||||
# define TVDAC_SENSE_MASK (7 << 28)
|
||||
/** Reports that DAC A voltage is above the detect threshold */
|
||||
# define TVDAC_A_SENSE (1 << 30)
|
||||
/** Reports that DAC B voltage is above the detect threshold */
|
||||
# define TVDAC_B_SENSE (1 << 29)
|
||||
/** Reports that DAC C voltage is above the detect threshold */
|
||||
# define TVDAC_C_SENSE (1 << 28)
|
||||
/**
|
||||
* Enables DAC state detection logic, for load-based TV detection.
|
||||
*
|
||||
* The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
|
||||
* to off, for load detection to work.
|
||||
*/
|
||||
# define TVDAC_STATE_CHG_EN (1 << 27)
|
||||
/** Sets the DAC A sense value to high */
|
||||
# define TVDAC_A_SENSE_CTL (1 << 26)
|
||||
/** Sets the DAC B sense value to high */
|
||||
# define TVDAC_B_SENSE_CTL (1 << 25)
|
||||
/** Sets the DAC C sense value to high */
|
||||
# define TVDAC_C_SENSE_CTL (1 << 24)
|
||||
/** Overrides the ENC_ENABLE and DAC voltage levels */
|
||||
# define DAC_CTL_OVERRIDE (1 << 7)
|
||||
/** Sets the slew rate. Must be preserved in software */
|
||||
# define ENC_TVDAC_SLEW_FAST (1 << 6)
|
||||
# define DAC_A_1_3_V (0 << 4)
|
||||
# define DAC_A_1_1_V (1 << 4)
|
||||
# define DAC_A_0_7_V (2 << 4)
|
||||
# define DAC_A_OFF (3 << 4)
|
||||
# define DAC_B_1_3_V (0 << 2)
|
||||
# define DAC_B_1_1_V (1 << 2)
|
||||
# define DAC_B_0_7_V (2 << 2)
|
||||
# define DAC_B_OFF (3 << 2)
|
||||
# define DAC_C_1_3_V (0 << 0)
|
||||
# define DAC_C_1_1_V (1 << 0)
|
||||
# define DAC_C_0_7_V (2 << 0)
|
||||
# define DAC_C_OFF (3 << 0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* CSC coefficients are stored in a floating point format with 9 bits of
|
||||
* mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n,
|
||||
* where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
|
||||
* -1 (0x3) being the only legal negative value.
|
||||
*/
|
||||
#define TV_CSC_Y 0x68010
|
||||
# define TV_RY_MASK 0x07ff0000
|
||||
# define TV_RY_SHIFT 16
|
||||
# define TV_GY_MASK 0x00000fff
|
||||
# define TV_GY_SHIFT 0
|
||||
|
||||
#define TV_CSC_Y2 0x68014
|
||||
# define TV_BY_MASK 0x07ff0000
|
||||
# define TV_BY_SHIFT 16
|
||||
/**
|
||||
* Y attenuation for component video.
|
||||
*
|
||||
* Stored in 1.9 fixed point.
|
||||
*/
|
||||
# define TV_AY_MASK 0x000003ff
|
||||
# define TV_AY_SHIFT 0
|
||||
|
||||
#define TV_CSC_U 0x68018
|
||||
# define TV_RU_MASK 0x07ff0000
|
||||
# define TV_RU_SHIFT 16
|
||||
# define TV_GU_MASK 0x000007ff
|
||||
# define TV_GU_SHIFT 0
|
||||
|
||||
#define TV_CSC_U2 0x6801c
|
||||
# define TV_BU_MASK 0x07ff0000
|
||||
# define TV_BU_SHIFT 16
|
||||
/**
|
||||
* U attenuation for component video.
|
||||
*
|
||||
* Stored in 1.9 fixed point.
|
||||
*/
|
||||
# define TV_AU_MASK 0x000003ff
|
||||
# define TV_AU_SHIFT 0
|
||||
|
||||
#define TV_CSC_V 0x68020
|
||||
# define TV_RV_MASK 0x0fff0000
|
||||
# define TV_RV_SHIFT 16
|
||||
# define TV_GV_MASK 0x000007ff
|
||||
# define TV_GV_SHIFT 0
|
||||
|
||||
#define TV_CSC_V2 0x68024
|
||||
# define TV_BV_MASK 0x07ff0000
|
||||
# define TV_BV_SHIFT 16
|
||||
/**
|
||||
* V attenuation for component video.
|
||||
*
|
||||
* Stored in 1.9 fixed point.
|
||||
*/
|
||||
# define TV_AV_MASK 0x000007ff
|
||||
# define TV_AV_SHIFT 0
|
||||
|
||||
/** @defgroup TV_CSC_KNOBS
|
||||
* @{
|
||||
*/
|
||||
#define TV_CLR_KNOBS 0x68028
|
||||
/** 2s-complement brightness adjustment */
|
||||
# define TV_BRIGHTNESS_MASK 0xff000000
|
||||
# define TV_BRIGHTNESS_SHIFT 24
|
||||
/** Contrast adjustment, as a 2.6 unsigned floating point number */
|
||||
# define TV_CONTRAST_MASK 0x00ff0000
|
||||
# define TV_CONTRAST_SHIFT 16
|
||||
/** Saturation adjustment, as a 2.6 unsigned floating point number */
|
||||
# define TV_SATURATION_MASK 0x0000ff00
|
||||
# define TV_SATURATION_SHIFT 8
|
||||
/** Hue adjustment, as an integer phase angle in degrees */
|
||||
# define TV_HUE_MASK 0x000000ff
|
||||
# define TV_HUE_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_CLR_LEVEL
|
||||
* @{
|
||||
*/
|
||||
#define TV_CLR_LEVEL 0x6802c
|
||||
/** Controls the DAC level for black */
|
||||
# define TV_BLACK_LEVEL_MASK 0x01ff0000
|
||||
# define TV_BLACK_LEVEL_SHIFT 16
|
||||
/** Controls the DAC level for blanking */
|
||||
# define TV_BLANK_LEVEL_MASK 0x000001ff
|
||||
# define TV_BLANK_LEVEL_SHIFT 0
|
||||
/* @} */
|
||||
|
||||
/** @defgroup TV_H_CTL_1
|
||||
* @{
|
||||
*/
|
||||
#define TV_H_CTL_1 0x68030
|
||||
/** Number of pixels in the hsync. */
|
||||
# define TV_HSYNC_END_MASK 0x1fff0000
|
||||
# define TV_HSYNC_END_SHIFT 16
|
||||
/** Total number of pixels minus one in the line (display and blanking). */
|
||||
# define TV_HTOTAL_MASK 0x00001fff
|
||||
# define TV_HTOTAL_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_H_CTL_2
|
||||
* @{
|
||||
*/
|
||||
#define TV_H_CTL_2 0x68034
|
||||
/** Enables the colorburst (needed for non-component color) */
|
||||
# define TV_BURST_ENA (1 << 31)
|
||||
/** Offset of the colorburst from the start of hsync, in pixels minus one. */
|
||||
# define TV_HBURST_START_SHIFT 16
|
||||
# define TV_HBURST_START_MASK 0x1fff0000
|
||||
/** Length of the colorburst */
|
||||
# define TV_HBURST_LEN_SHIFT 0
|
||||
# define TV_HBURST_LEN_MASK 0x0001fff
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_H_CTL_3
|
||||
* @{
|
||||
*/
|
||||
#define TV_H_CTL_3 0x68038
|
||||
/** End of hblank, measured in pixels minus one from start of hsync */
|
||||
# define TV_HBLANK_END_SHIFT 16
|
||||
# define TV_HBLANK_END_MASK 0x1fff0000
|
||||
/** Start of hblank, measured in pixels minus one from start of hsync */
|
||||
# define TV_HBLANK_START_SHIFT 0
|
||||
# define TV_HBLANK_START_MASK 0x0001fff
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_1
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_1 0x6803c
|
||||
/** XXX */
|
||||
# define TV_NBR_END_SHIFT 16
|
||||
# define TV_NBR_END_MASK 0x07ff0000
|
||||
/** XXX */
|
||||
# define TV_VI_END_F1_SHIFT 8
|
||||
# define TV_VI_END_F1_MASK 0x00003f00
|
||||
/** XXX */
|
||||
# define TV_VI_END_F2_SHIFT 0
|
||||
# define TV_VI_END_F2_MASK 0x0000003f
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_2
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_2 0x68040
|
||||
/** Length of vsync, in half lines */
|
||||
# define TV_VSYNC_LEN_MASK 0x07ff0000
|
||||
# define TV_VSYNC_LEN_SHIFT 16
|
||||
/** Offset of the start of vsync in field 1, measured in one less than the
|
||||
* number of half lines.
|
||||
*/
|
||||
# define TV_VSYNC_START_F1_MASK 0x00007f00
|
||||
# define TV_VSYNC_START_F1_SHIFT 8
|
||||
/**
|
||||
* Offset of the start of vsync in field 2, measured in one less than the
|
||||
* number of half lines.
|
||||
*/
|
||||
# define TV_VSYNC_START_F2_MASK 0x0000007f
|
||||
# define TV_VSYNC_START_F2_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_3
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_3 0x68044
|
||||
/** Enables generation of the equalization signal */
|
||||
# define TV_EQUAL_ENA (1 << 31)
|
||||
/** Length of vsync, in half lines */
|
||||
# define TV_VEQ_LEN_MASK 0x007f0000
|
||||
# define TV_VEQ_LEN_SHIFT 16
|
||||
/** Offset of the start of equalization in field 1, measured in one less than
|
||||
* the number of half lines.
|
||||
*/
|
||||
# define TV_VEQ_START_F1_MASK 0x0007f00
|
||||
# define TV_VEQ_START_F1_SHIFT 8
|
||||
/**
|
||||
* Offset of the start of equalization in field 2, measured in one less than
|
||||
* the number of half lines.
|
||||
*/
|
||||
# define TV_VEQ_START_F2_MASK 0x000007f
|
||||
# define TV_VEQ_START_F2_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_4
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_4 0x68048
|
||||
/**
|
||||
* Offset to start of vertical colorburst, measured in one less than the
|
||||
* number of lines from vertical start.
|
||||
*/
|
||||
# define TV_VBURST_START_F1_MASK 0x003f0000
|
||||
# define TV_VBURST_START_F1_SHIFT 16
|
||||
/**
|
||||
* Offset to the end of vertical colorburst, measured in one less than the
|
||||
* number of lines from the start of NBR.
|
||||
*/
|
||||
# define TV_VBURST_END_F1_MASK 0x000000ff
|
||||
# define TV_VBURST_END_F1_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_5
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_5 0x6804c
|
||||
/**
|
||||
* Offset to start of vertical colorburst, measured in one less than the
|
||||
* number of lines from vertical start.
|
||||
*/
|
||||
# define TV_VBURST_START_F2_MASK 0x003f0000
|
||||
# define TV_VBURST_START_F2_SHIFT 16
|
||||
/**
|
||||
* Offset to the end of vertical colorburst, measured in one less than the
|
||||
* number of lines from the start of NBR.
|
||||
*/
|
||||
# define TV_VBURST_END_F2_MASK 0x000000ff
|
||||
# define TV_VBURST_END_F2_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_6
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_6 0x68050
|
||||
/**
|
||||
* Offset to start of vertical colorburst, measured in one less than the
|
||||
* number of lines from vertical start.
|
||||
*/
|
||||
# define TV_VBURST_START_F3_MASK 0x003f0000
|
||||
# define TV_VBURST_START_F3_SHIFT 16
|
||||
/**
|
||||
* Offset to the end of vertical colorburst, measured in one less than the
|
||||
* number of lines from the start of NBR.
|
||||
*/
|
||||
# define TV_VBURST_END_F3_MASK 0x000000ff
|
||||
# define TV_VBURST_END_F3_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_V_CTL_7
|
||||
* @{
|
||||
*/
|
||||
#define TV_V_CTL_7 0x68054
|
||||
/**
|
||||
* Offset to start of vertical colorburst, measured in one less than the
|
||||
* number of lines from vertical start.
|
||||
*/
|
||||
# define TV_VBURST_START_F4_MASK 0x003f0000
|
||||
# define TV_VBURST_START_F4_SHIFT 16
|
||||
/**
|
||||
* Offset to the end of vertical colorburst, measured in one less than the
|
||||
* number of lines from the start of NBR.
|
||||
*/
|
||||
# define TV_VBURST_END_F4_MASK 0x000000ff
|
||||
# define TV_VBURST_END_F4_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_SC_CTL_1
|
||||
* @{
|
||||
*/
|
||||
#define TV_SC_CTL_1 0x68060
|
||||
/** Turns on the first subcarrier phase generation DDA */
|
||||
# define TV_SC_DDA1_EN (1 << 31)
|
||||
/** Turns on the first subcarrier phase generation DDA */
|
||||
# define TV_SC_DDA2_EN (2 << 31)
|
||||
/** Turns on the first subcarrier phase generation DDA */
|
||||
# define TV_SC_DDA3_EN (3 << 31)
|
||||
/** Sets the subcarrier DDA to reset frequency every other field */
|
||||
# define TV_SC_RESET_EVERY_2 (0 << 24)
|
||||
/** Sets the subcarrier DDA to reset frequency every fourth field */
|
||||
# define TV_SC_RESET_EVERY_4 (1 << 24)
|
||||
/** Sets the subcarrier DDA to reset frequency every eighth field */
|
||||
# define TV_SC_RESET_EVERY_8 (2 << 24)
|
||||
/** Sets the subcarrier DDA to never reset the frequency */
|
||||
# define TV_SC_RESET_NEVER (3 << 24)
|
||||
/** Sets the peak amplitude of the colorburst.*/
|
||||
# define TV_BURST_LEVEL_MASK 0x00ff0000
|
||||
# define TV_BURST_LEVEL_SHIFT 16
|
||||
/** Sets the increment of the first subcarrier phase generation DDA */
|
||||
# define TV_SCDDA1_INC_MASK 0x00000fff
|
||||
# define TV_SCDDA1_INC_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_SC_CTL_2
|
||||
* @{
|
||||
*/
|
||||
#define TV_SC_CTL_2 0x68068
|
||||
/** Sets the rollover for the second subcarrier phase generation DDA */
|
||||
# define TV_SCDDA2_SIZE_MASK 0x7fff0000
|
||||
# define TV_SCDDA2_SIZE_SHIFT 16
|
||||
/** Sets the increent of the second subcarrier phase generation DDA */
|
||||
# define TV_SCDDA2_INC_MASK 0x00007fff
|
||||
# define TV_SCDDA2_INC_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_SC_CTL_3
|
||||
* @{
|
||||
*/
|
||||
#define TV_SC_CTL_3 0x68068
|
||||
/** Sets the rollover for the third subcarrier phase generation DDA */
|
||||
# define TV_SCDDA3_SIZE_MASK 0x7fff0000
|
||||
# define TV_SCDDA3_SIZE_SHIFT 16
|
||||
/** Sets the increent of the third subcarrier phase generation DDA */
|
||||
# define TV_SCDDA3_INC_MASK 0x00007fff
|
||||
# define TV_SCDDA3_INC_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_WIN_POS
|
||||
* @{
|
||||
*/
|
||||
#define TV_WIN_POS 0x68070
|
||||
/** X coordinate of the display from the start of horizontal active */
|
||||
# define TV_XPOS_MASK 0x1fff0000
|
||||
# define TV_XPOS_SHIFT 16
|
||||
/** Y coordinate of the display from the start of vertical active (NBR) */
|
||||
# define TV_YPOS_MASK 0x00000fff
|
||||
# define TV_YPOS_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_WIN_SIZE
|
||||
* @{
|
||||
*/
|
||||
#define TV_WIN_SIZE 0x68074
|
||||
/** Horizontal size of the display window, measured in pixels*/
|
||||
# define TV_XSIZE_MASK 0x1fff0000
|
||||
# define TV_XSIZE_SHIFT 16
|
||||
/**
|
||||
* Vertical size of the display window, measured in pixels.
|
||||
*
|
||||
* Must be even for interlaced modes.
|
||||
*/
|
||||
# define TV_YSIZE_MASK 0x00000fff
|
||||
# define TV_YSIZE_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_FILTER_CTL_1
|
||||
* @{
|
||||
*/
|
||||
#define TV_FILTER_CTL_1 0x68080
|
||||
/**
|
||||
* Enables automatic scaling calculation.
|
||||
*
|
||||
* If set, the rest of the registers are ignored, and the calculated values can
|
||||
* be read back from the register.
|
||||
*/
|
||||
# define TV_AUTO_SCALE (1 << 31)
|
||||
/**
|
||||
* Disables the vertical filter.
|
||||
*
|
||||
* This is required on modes more than 1024 pixels wide */
|
||||
# define TV_V_FILTER_BYPASS (1 << 29)
|
||||
/** Enables adaptive vertical filtering */
|
||||
# define TV_VADAPT (1 << 28)
|
||||
# define TV_VADAPT_MODE_MASK (3 << 26)
|
||||
/** Selects the least adaptive vertical filtering mode */
|
||||
# define TV_VADAPT_MODE_LEAST (0 << 26)
|
||||
/** Selects the moderately adaptive vertical filtering mode */
|
||||
# define TV_VADAPT_MODE_MODERATE (1 << 26)
|
||||
/** Selects the most adaptive vertical filtering mode */
|
||||
# define TV_VADAPT_MODE_MOST (3 << 26)
|
||||
/**
|
||||
* Sets the horizontal scaling factor.
|
||||
*
|
||||
* This should be the fractional part of the horizontal scaling factor divided
|
||||
* by the oversampling rate. TV_HSCALE should be less than 1, and set to:
|
||||
*
|
||||
* (src width - 1) / ((oversample * dest width) - 1)
|
||||
*/
|
||||
# define TV_HSCALE_FRAC_MASK 0x00003fff
|
||||
# define TV_HSCALE_FRAC_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_FILTER_CTL_2
|
||||
* @{
|
||||
*/
|
||||
#define TV_FILTER_CTL_2 0x68084
|
||||
/**
|
||||
* Sets the integer part of the 3.15 fixed-point vertical scaling factor.
|
||||
*
|
||||
* TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
|
||||
*/
|
||||
# define TV_VSCALE_INT_MASK 0x00038000
|
||||
# define TV_VSCALE_INT_SHIFT 15
|
||||
/**
|
||||
* Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
|
||||
*
|
||||
* \sa TV_VSCALE_INT_MASK
|
||||
*/
|
||||
# define TV_VSCALE_FRAC_MASK 0x00007fff
|
||||
# define TV_VSCALE_FRAC_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_FILTER_CTL_3
|
||||
* @{
|
||||
*/
|
||||
#define TV_FILTER_CTL_3 0x68088
|
||||
/**
|
||||
* Sets the integer part of the 3.15 fixed-point vertical scaling factor.
|
||||
*
|
||||
* TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
|
||||
*
|
||||
* For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
|
||||
*/
|
||||
# define TV_VSCALE_IP_INT_MASK 0x00038000
|
||||
# define TV_VSCALE_IP_INT_SHIFT 15
|
||||
/**
|
||||
* Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
|
||||
*
|
||||
* For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
|
||||
*
|
||||
* \sa TV_VSCALE_IP_INT_MASK
|
||||
*/
|
||||
# define TV_VSCALE_IP_FRAC_MASK 0x00007fff
|
||||
# define TV_VSCALE_IP_FRAC_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_CC_CONTROL
|
||||
* @{
|
||||
*/
|
||||
#define TV_CC_CONTROL 0x68090
|
||||
# define TV_CC_ENABLE (1 << 31)
|
||||
/**
|
||||
* Specifies which field to send the CC data in.
|
||||
*
|
||||
* CC data is usually sent in field 0.
|
||||
*/
|
||||
# define TV_CC_FID_MASK (1 << 27)
|
||||
# define TV_CC_FID_SHIFT 27
|
||||
/** Sets the horizontal position of the CC data. Usually 135. */
|
||||
# define TV_CC_HOFF_MASK 0x03ff0000
|
||||
# define TV_CC_HOFF_SHIFT 16
|
||||
/** Sets the vertical position of the CC data. Usually 21 */
|
||||
# define TV_CC_LINE_MASK 0x0000003f
|
||||
# define TV_CC_LINE_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
/** @defgroup TV_CC_DATA
|
||||
* @{
|
||||
*/
|
||||
#define TV_CC_DATA 0x68094
|
||||
# define TV_CC_RDY (1 << 31)
|
||||
/** Second word of CC data to be transmitted. */
|
||||
# define TV_CC_DATA_2_MASK 0x007f0000
|
||||
# define TV_CC_DATA_2_SHIFT 16
|
||||
/** First word of CC data to be transmitted. */
|
||||
# define TV_CC_DATA_1_MASK 0x0000007f
|
||||
# define TV_CC_DATA_1_SHIFT 0
|
||||
/** @}
|
||||
*/
|
||||
|
||||
/** @{ */
|
||||
#define TV_H_LUMA_0 0x68100
|
||||
#define TV_H_LUMA_59 0x681ec
|
||||
#define TV_H_CHROMA_0 0x68200
|
||||
#define TV_H_CHROMA_59 0x682ec
|
||||
/** @} */
|
||||
|
||||
#define PIPEACONF 0x70008
|
||||
#define PIPEACONF_ENABLE (1<<31)
|
||||
|
|
@ -787,6 +1597,20 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define PIPEACONF_PIPE_LOCKED (1<<25)
|
||||
#define PIPEACONF_PALETTE 0
|
||||
#define PIPEACONF_GAMMA (1<<24)
|
||||
#define PIPECONF_FORCE_BORDER (1<<25)
|
||||
|
||||
#define PIPEAGCMAXRED 0x70010
|
||||
#define PIPEAGCMAXGREEN 0x70014
|
||||
#define PIPEAGCMAXBLUE 0x70018
|
||||
#define PIPEASTAT 0x70024
|
||||
|
||||
#define DSPARB 0x70030
|
||||
#define DSPFW1 0x70034
|
||||
#define DSPFW2 0x70038
|
||||
#define DSPFW3 0x7003c
|
||||
#define PIPEAFRAMEHIGH 0x70040
|
||||
#define PIPEAFRAMEPIXEL 0x70044
|
||||
|
||||
|
||||
#define PIPEBCONF 0x71008
|
||||
#define PIPEBCONF_ENABLE (1<<31)
|
||||
|
|
@ -796,6 +1620,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define PIPEBCONF_GAMMA (1<<24)
|
||||
#define PIPEBCONF_PALETTE 0
|
||||
|
||||
#define PIPEBGCMAXRED 0x71010
|
||||
#define PIPEBGCMAXGREEN 0x71014
|
||||
#define PIPEBGCMAXBLUE 0x71018
|
||||
#define PIPEBSTAT 0x71024
|
||||
#define PIPEBFRAMEHIGH 0x71040
|
||||
#define PIPEBFRAMEPIXEL 0x71044
|
||||
|
||||
#define DSPACNTR 0x70180
|
||||
#define DSPBCNTR 0x71180
|
||||
#define DISPLAY_PLANE_ENABLE (1<<31)
|
||||
|
|
@ -832,6 +1663,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define DSPBADDR DSPBBASE
|
||||
#define DSPBSTRIDE 0x71188
|
||||
|
||||
#define DSPAKEYVAL 0x70194
|
||||
#define DSPAKEYMASK 0x70198
|
||||
|
||||
#define DSPAPOS 0x7018C /* reserved */
|
||||
#define DSPASIZE 0x70190
|
||||
#define DSPBPOS 0x7118C
|
||||
|
|
@ -843,6 +1677,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define DSPBSURF 0x7119C
|
||||
#define DSPBTILEOFF 0x711A4
|
||||
|
||||
#define VGACNTRL 0x71400
|
||||
# define VGA_DISP_DISABLE (1 << 31)
|
||||
# define VGA_2X_MODE (1 << 30)
|
||||
# define VGA_PIPE_B_SELECT (1 << 29)
|
||||
|
||||
/* Various masks for reserved bits, etc. */
|
||||
#define I830_FWATER1_MASK (~((1<<11)|(1<<10)|(1<<9)| \
|
||||
(1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)| \
|
||||
|
|
|
|||
397
src/i830.h
397
src/i830.h
|
|
@ -57,7 +57,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include "xf86xv.h"
|
||||
#include "xf86int10.h"
|
||||
#include "vbe.h"
|
||||
#include "vbeModes.h"
|
||||
#include "vgaHW.h"
|
||||
#include "randrstr.h"
|
||||
|
||||
|
|
@ -70,43 +69,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include "i830_dri.h"
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr;
|
||||
|
||||
#include "common.h"
|
||||
#include "i830_sdvo.h"
|
||||
#include "i2c_vid.h"
|
||||
|
||||
/* I830 Video support */
|
||||
#define NEED_REPLIES /* ? */
|
||||
#define EXTENSION_PROC_ARGS void *
|
||||
#include "extnsionst.h" /* required */
|
||||
#include <X11/extensions/panoramiXproto.h> /* required */
|
||||
|
||||
/* I830 Video BIOS support */
|
||||
|
||||
/*
|
||||
* The mode handling is based upon the VESA driver written by
|
||||
* Paulo César Pereira de Andrade <pcpa@conectiva.com.br>.
|
||||
*/
|
||||
|
||||
#define PIPE_NONE 0<<0
|
||||
#define PIPE_CRT 1<<0
|
||||
#define PIPE_TV 1<<1
|
||||
#define PIPE_DFP 1<<2
|
||||
#define PIPE_LFP 1<<3
|
||||
#define PIPE_CRT2 1<<4
|
||||
#define PIPE_TV2 1<<5
|
||||
#define PIPE_DFP2 1<<6
|
||||
#define PIPE_LFP2 1<<7
|
||||
|
||||
typedef struct _VESARec {
|
||||
/* SVGA state */
|
||||
pointer state, pstate;
|
||||
int statePage, stateSize, stateMode, stateRefresh;
|
||||
CARD32 *savedPal;
|
||||
int savedScanlinePitch;
|
||||
/* Don't try to set the refresh rate for any modes. */
|
||||
Bool useDefaultRefresh;
|
||||
/* display start */
|
||||
int x, y;
|
||||
} VESARec, *VESAPtr;
|
||||
|
||||
|
||||
#ifdef XF86DRI
|
||||
#define I830_MM_MINPAGES 512
|
||||
#define I830_MM_MAXSIZE (32*1024)
|
||||
|
|
@ -168,43 +147,165 @@ typedef struct {
|
|||
#endif
|
||||
} I830EntRec, *I830EntPtr;
|
||||
|
||||
typedef struct _MergedDisplayModeRec {
|
||||
DisplayModePtr First;
|
||||
DisplayModePtr Second;
|
||||
int SecondPosition;
|
||||
} I830MergedDisplayModeRec, *I830MergedDisplayModePtr;
|
||||
/* store information about an Ixxx DVO */
|
||||
/* The i830->i865 use multiple DVOs with multiple i2cs */
|
||||
/* the i915, i945 have a single sDVO i2c bus - which is different */
|
||||
#define MAX_OUTPUTS 6
|
||||
|
||||
typedef struct _I830XineramaData {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
} I830XineramaData;
|
||||
#define I830_I2C_BUS_DVO 1
|
||||
#define I830_I2C_BUS_SDVO 2
|
||||
|
||||
typedef struct _ModePrivateRec {
|
||||
I830MergedDisplayModeRec merged;
|
||||
VbeModeInfoData vbeData;
|
||||
} I830ModePrivateRec, *I830ModePrivatePtr;
|
||||
/* these are outputs from the chip - integrated only
|
||||
external chips are via DVO or SDVO output */
|
||||
#define I830_OUTPUT_UNUSED 0
|
||||
#define I830_OUTPUT_ANALOG 1
|
||||
#define I830_OUTPUT_DVO 2
|
||||
#define I830_OUTPUT_SDVO 3
|
||||
#define I830_OUTPUT_LVDS 4
|
||||
#define I830_OUTPUT_TVOUT 5
|
||||
|
||||
typedef struct _region {
|
||||
int x0,x1,y0,y1;
|
||||
} region;
|
||||
#define I830_DVO_CHIP_NONE 0
|
||||
#define I830_DVO_CHIP_LVDS 1
|
||||
#define I830_DVO_CHIP_TMDS 2
|
||||
#define I830_DVO_CHIP_TVOUT 4
|
||||
|
||||
struct _I830DVODriver {
|
||||
int type;
|
||||
char *modulename;
|
||||
char *fntablename;
|
||||
int address;
|
||||
const char **symbols;
|
||||
I830I2CVidOutputRec *vid_rec;
|
||||
void *dev_priv;
|
||||
pointer modhandle;
|
||||
};
|
||||
|
||||
extern const char *i830_output_type_names[];
|
||||
|
||||
enum detect_status {
|
||||
OUTPUT_STATUS_CONNECTED,
|
||||
OUTPUT_STATUS_DISCONNECTED,
|
||||
OUTPUT_STATUS_UNKNOWN
|
||||
};
|
||||
|
||||
struct _I830OutputRec {
|
||||
int type;
|
||||
int pipe;
|
||||
Bool enabled;
|
||||
/**
|
||||
* Marks that the output and associated pipe is temporarily enabled for
|
||||
* load detection.
|
||||
*/
|
||||
Bool load_detect_temp;
|
||||
|
||||
/**
|
||||
* Turns the output on/off, or sets intermediate power levels if available.
|
||||
*
|
||||
* Unsupported intermediate modes drop to the lower power setting. If the
|
||||
* mode is DPMSModeOff, the output must be disabled, as the DPLL may be
|
||||
* disabled afterwards.
|
||||
*/
|
||||
void (*dpms)(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
|
||||
|
||||
/**
|
||||
* Saves the output's state for restoration on VT switch.
|
||||
*/
|
||||
void (*save)(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/**
|
||||
* Restore's the output's state at VT switch.
|
||||
*/
|
||||
void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/**
|
||||
* Callback for testing a video mode for a given output.
|
||||
*
|
||||
* This function should only check for cases where a mode can't be supported
|
||||
* on the pipe specifically, and not represent generic CRTC limitations.
|
||||
*
|
||||
* \return MODE_OK if the mode is valid, or another MODE_* otherwise.
|
||||
*/
|
||||
int (*mode_valid)(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode);
|
||||
|
||||
/**
|
||||
* Callback for setting up a video mode before any pipe/dpll changes.
|
||||
*
|
||||
* \param pMode the mode that will be set, or NULL if the mode to be set is
|
||||
* unknown (such as the restore path of VT switching).
|
||||
*/
|
||||
void (*pre_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode);
|
||||
|
||||
/**
|
||||
* Callback for setting up a video mode after the DPLL update but before
|
||||
* the plane is enabled.
|
||||
*/
|
||||
void (*post_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode);
|
||||
|
||||
/**
|
||||
* Probe for a connected output, and return detect_status.
|
||||
*/
|
||||
enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/**
|
||||
* Query the device for the modes it provides.
|
||||
*
|
||||
* This function may also update MonInfo, mm_width, and mm_height.
|
||||
*
|
||||
* \return singly-linked list of modes or NULL if no modes found.
|
||||
*/
|
||||
DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/**
|
||||
* List of available modes on this output.
|
||||
*
|
||||
* This should be the list from get_modes(), plus perhaps additional
|
||||
* compatible modes added later.
|
||||
*/
|
||||
DisplayModePtr probed_modes;
|
||||
|
||||
/** EDID monitor information */
|
||||
xf86MonPtr MonInfo;
|
||||
|
||||
/** Physical size of the output currently attached. */
|
||||
int mm_width, mm_height;
|
||||
|
||||
I2CBusPtr pI2CBus;
|
||||
I2CBusPtr pDDCBus;
|
||||
struct _I830DVODriver *i2c_drv;
|
||||
/** Output-private structure. Should replace i2c_drv */
|
||||
void *dev_priv;
|
||||
#ifdef RANDR_12_INTERFACE
|
||||
RROutputPtr randr_output;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _I830PipeRec {
|
||||
Bool enabled;
|
||||
Bool gammaEnabled;
|
||||
int x;
|
||||
int y;
|
||||
Bool cursorInRange;
|
||||
Bool cursorShown;
|
||||
DisplayModeRec curMode;
|
||||
DisplayModeRec desiredMode;
|
||||
#ifdef RANDR_12_INTERFACE
|
||||
RRCrtcPtr randr_crtc;
|
||||
#endif
|
||||
} I830PipeRec, *I830PipePtr;
|
||||
|
||||
typedef struct _I830Rec {
|
||||
unsigned char *MMIOBase;
|
||||
unsigned char *FbBase;
|
||||
int cpp;
|
||||
|
||||
unsigned int bios_version;
|
||||
|
||||
Bool newPipeSwitch;
|
||||
|
||||
Bool fakeSwitch;
|
||||
|
||||
int fixedPipe;
|
||||
|
||||
DisplayModePtr currentMode;
|
||||
/* Mode saved during randr reprobe, which will need to be freed at the point
|
||||
* of the next SwitchMode, when we lose this last reference to it.
|
||||
*/
|
||||
DisplayModePtr savedCurrentMode;
|
||||
|
||||
Bool Clone;
|
||||
int CloneRefresh;
|
||||
|
|
@ -212,7 +313,9 @@ typedef struct _I830Rec {
|
|||
int CloneVDisplay;
|
||||
|
||||
I830EntPtr entityPrivate;
|
||||
#if 0
|
||||
int pipe, origPipe;
|
||||
#endif
|
||||
int init;
|
||||
|
||||
unsigned int bufferOffset; /* for I830SelectBuffer */
|
||||
|
|
@ -224,8 +327,6 @@ typedef struct _I830Rec {
|
|||
long FbMapSize;
|
||||
long TotalVideoRam;
|
||||
I830MemRange StolenMemory; /* pre-allocated memory */
|
||||
long BIOSMemorySize; /* min stolen pool size */
|
||||
int BIOSMemSizeLoc;
|
||||
|
||||
/* These change according to what has been allocated. */
|
||||
long FreeMemory;
|
||||
|
|
@ -254,26 +355,7 @@ typedef struct _I830Rec {
|
|||
I830MemRange *OverlayMem;
|
||||
I830MemRange LinearMem;
|
||||
#endif
|
||||
int LinearAlloc;
|
||||
|
||||
Bool MergedFB;
|
||||
ScrnInfoPtr pScrn_2;
|
||||
char *SecondHSync;
|
||||
char *SecondVRefresh;
|
||||
char *MetaModes;
|
||||
int SecondPosition;
|
||||
int FirstXOffs, FirstYOffs, SecondXOffs, SecondYOffs;
|
||||
int FirstframeX0, FirstframeX1, FirstframeY0, FirstframeY1;
|
||||
int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX;
|
||||
Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions;
|
||||
int maxFirst_X1, maxFirst_X2, maxFirst_Y1, maxFirst_Y2;
|
||||
int maxSecond_X1, maxSecond_X2, maxSecond_Y1, maxSecond_Y2;
|
||||
region NonRectDead, OffDead1, OffDead2;
|
||||
Bool IntelXinerama;
|
||||
Bool SecondIsScrn0;
|
||||
ExtensionEntry *XineramaExtEntry;
|
||||
int I830XineramaVX, I830XineramaVY;
|
||||
|
||||
unsigned long LinearAlloc;
|
||||
XF86ModReqInfo shadowReq; /* to test for later libshadow */
|
||||
I830MemRange RotatedMem;
|
||||
I830MemRange RotatedMem2;
|
||||
|
|
@ -312,10 +394,6 @@ typedef struct _I830Rec {
|
|||
Bool CursorIsARGB;
|
||||
CursorPtr pCurs;
|
||||
|
||||
int MonType1;
|
||||
int MonType2;
|
||||
Bool specifiedMonitor;
|
||||
|
||||
DGAModePtr DGAModes;
|
||||
int numDGAModes;
|
||||
Bool DGAactive;
|
||||
|
|
@ -338,7 +416,6 @@ typedef struct _I830Rec {
|
|||
int NumScanlineColorExpandBuffers;
|
||||
int nextColorExpandBuf;
|
||||
|
||||
I830RegRec SavedReg;
|
||||
I830RegRec ModeReg;
|
||||
|
||||
Bool noAccel;
|
||||
|
|
@ -384,44 +461,17 @@ typedef struct _I830Rec {
|
|||
/* Stolen memory support */
|
||||
Bool StolenOnly;
|
||||
|
||||
/* Video BIOS support. */
|
||||
vbeInfoPtr pVbe;
|
||||
VbeInfoBlock *vbeInfo;
|
||||
VESAPtr vesa;
|
||||
|
||||
Bool overrideBIOSMemSize;
|
||||
int saveBIOSMemSize;
|
||||
int newBIOSMemSize;
|
||||
Bool useSWF1;
|
||||
int saveSWF1;
|
||||
|
||||
Bool swfSaved;
|
||||
CARD32 saveSWF0;
|
||||
CARD32 saveSWF4;
|
||||
|
||||
/* Use BIOS call 0x5f05 to set the refresh rate. */
|
||||
Bool useExtendedRefresh;
|
||||
|
||||
Bool checkDevices;
|
||||
int monitorSwitch;
|
||||
int operatingDevices;
|
||||
int toggleDevices;
|
||||
int savedDevices;
|
||||
int lastDevice0, lastDevice1, lastDevice2;
|
||||
|
||||
/* These are indexed by the display types */
|
||||
Bool displayAttached[NumDisplayTypes];
|
||||
Bool displayPresent[NumDisplayTypes];
|
||||
BoxRec displaySize[NumDisplayTypes];
|
||||
|
||||
/* [0] is Pipe A, [1] is Pipe B. */
|
||||
int availablePipes;
|
||||
int pipeDevices[MAX_DISPLAY_PIPES];
|
||||
int num_pipes;
|
||||
/* [0] is display plane A, [1] is display plane B. */
|
||||
Bool pipeEnabled[MAX_DISPLAY_PIPES];
|
||||
BoxRec pipeDisplaySize[MAX_DISPLAY_PIPES];
|
||||
int planeEnabled[MAX_DISPLAY_PIPES];
|
||||
|
||||
I830PipeRec pipes[MAX_DISPLAY_PIPES];
|
||||
|
||||
/* Driver phase/state information */
|
||||
Bool preinit;
|
||||
Bool starting;
|
||||
|
|
@ -434,14 +484,85 @@ typedef struct _I830Rec {
|
|||
int yoffset;
|
||||
|
||||
unsigned int SaveGeneration;
|
||||
Bool vbeRestoreWorkaround;
|
||||
Bool displayInfo;
|
||||
Bool devicePresence;
|
||||
|
||||
OsTimerPtr devicesTimer;
|
||||
|
||||
CARD32 savedAsurf;
|
||||
CARD32 savedBsurf;
|
||||
int ddc2;
|
||||
int num_outputs;
|
||||
struct _I830OutputRec output[MAX_OUTPUTS];
|
||||
|
||||
/* Panel size pulled from the BIOS */
|
||||
int PanelXRes, PanelYRes;
|
||||
|
||||
/* The BIOS's fixed timings for the LVDS */
|
||||
int panel_fixed_clock;
|
||||
int panel_fixed_hactive;
|
||||
int panel_fixed_hblank;
|
||||
int panel_fixed_hsyncoff;
|
||||
int panel_fixed_hsyncwidth;
|
||||
int panel_fixed_vactive;
|
||||
int panel_fixed_vblank;
|
||||
int panel_fixed_vsyncoff;
|
||||
int panel_fixed_vsyncwidth;
|
||||
|
||||
int backlight_duty_cycle; /* restore backlight to this value */
|
||||
|
||||
Bool panel_wants_dither;
|
||||
|
||||
CARD32 saveDSPACNTR;
|
||||
CARD32 saveDSPBCNTR;
|
||||
CARD32 savePIPEACONF;
|
||||
CARD32 savePIPEBCONF;
|
||||
CARD32 savePIPEASRC;
|
||||
CARD32 savePIPEBSRC;
|
||||
CARD32 saveFPA0;
|
||||
CARD32 saveFPA1;
|
||||
CARD32 saveDPLL_A;
|
||||
CARD32 saveDPLL_A_MD;
|
||||
CARD32 saveHTOTAL_A;
|
||||
CARD32 saveHBLANK_A;
|
||||
CARD32 saveHSYNC_A;
|
||||
CARD32 saveVTOTAL_A;
|
||||
CARD32 saveVBLANK_A;
|
||||
CARD32 saveVSYNC_A;
|
||||
CARD32 saveDSPASTRIDE;
|
||||
CARD32 saveDSPASIZE;
|
||||
CARD32 saveDSPAPOS;
|
||||
CARD32 saveDSPABASE;
|
||||
CARD32 saveDSPASURF;
|
||||
CARD32 saveFPB0;
|
||||
CARD32 saveFPB1;
|
||||
CARD32 saveDPLL_B;
|
||||
CARD32 saveDPLL_B_MD;
|
||||
CARD32 saveHTOTAL_B;
|
||||
CARD32 saveHBLANK_B;
|
||||
CARD32 saveHSYNC_B;
|
||||
CARD32 saveVTOTAL_B;
|
||||
CARD32 saveVBLANK_B;
|
||||
CARD32 saveVSYNC_B;
|
||||
CARD32 saveDSPBSTRIDE;
|
||||
CARD32 saveDSPBSIZE;
|
||||
CARD32 saveDSPBPOS;
|
||||
CARD32 saveDSPBBASE;
|
||||
CARD32 saveDSPBSURF;
|
||||
CARD32 saveVCLK_DIVISOR_VGA0;
|
||||
CARD32 saveVCLK_DIVISOR_VGA1;
|
||||
CARD32 saveVCLK_POST_DIV;
|
||||
CARD32 saveVGACNTRL;
|
||||
CARD32 saveADPA;
|
||||
CARD32 saveLVDS;
|
||||
CARD32 saveDVOA;
|
||||
CARD32 saveDVOB;
|
||||
CARD32 saveDVOC;
|
||||
CARD32 savePP_ON;
|
||||
CARD32 savePP_OFF;
|
||||
CARD32 savePP_CONTROL;
|
||||
CARD32 savePP_CYCLE;
|
||||
CARD32 savePFIT_CONTROL;
|
||||
CARD32 savePaletteA[256];
|
||||
CARD32 savePaletteB[256];
|
||||
CARD32 saveSWF[17];
|
||||
CARD32 saveBLC_PWM_CTL;
|
||||
} I830Rec;
|
||||
|
||||
#define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
|
||||
|
|
@ -459,6 +580,7 @@ extern void I830PrintErrorState(ScrnInfoPtr pScrn);
|
|||
extern void I965PrintErrorState(ScrnInfoPtr pScrn);
|
||||
extern void I830Sync(ScrnInfoPtr pScrn);
|
||||
extern void I830InitHWCursor(ScrnInfoPtr pScrn);
|
||||
extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force);
|
||||
extern Bool I830CursorInit(ScreenPtr pScreen);
|
||||
extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
|
||||
extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
|
||||
|
|
@ -530,25 +652,52 @@ extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg);
|
|||
extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
|
||||
extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
|
||||
|
||||
extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe,
|
||||
VbeInfoBlock *vbe);
|
||||
extern void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
|
||||
extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
|
||||
extern void I830PrintModes(ScrnInfoPtr pScrn);
|
||||
extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
|
||||
extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
|
||||
extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
|
||||
extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
|
||||
extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
|
||||
char *name);
|
||||
|
||||
/* i830_display.c */
|
||||
Bool
|
||||
i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type);
|
||||
|
||||
/* i830_crt.c */
|
||||
void i830_crt_init(ScrnInfoPtr pScrn);
|
||||
|
||||
/* i830_dvo.c */
|
||||
void i830_dvo_init(ScrnInfoPtr pScrn);
|
||||
|
||||
/* i830_lvds.c */
|
||||
void i830_lvds_init(ScrnInfoPtr pScrn);
|
||||
|
||||
/* i830_memory.c */
|
||||
Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
|
||||
Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
|
||||
|
||||
/* i830_gtf.c */
|
||||
DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
|
||||
int interlaced, int margins);
|
||||
|
||||
/* i830_modes.c */
|
||||
int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
|
||||
void i830_reprobe_output_modes(ScrnInfoPtr pScrn);
|
||||
void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn);
|
||||
void i830_set_default_screen_size(ScrnInfoPtr pScrn);
|
||||
DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/* i830_randr.c */
|
||||
Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
|
||||
Bool I830RandRInit(ScreenPtr pScreen, int rotation);
|
||||
Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
|
||||
RRScreenSizePtr pSize);
|
||||
Rotation I830GetRotation(ScreenPtr pScreen);
|
||||
void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
|
||||
Bool I830RandRPreInit (ScrnInfoPtr pScrn);
|
||||
|
||||
/* i830_tv.c */
|
||||
void i830_tv_init(ScrnInfoPtr pScrn);
|
||||
|
||||
/*
|
||||
* 12288 is set as the maximum, chosen because it is enough for
|
||||
|
|
@ -582,6 +731,14 @@ Rotation I830GetRotation(ScreenPtr pScreen);
|
|||
#define _845_DRAM_RW_CONTROL 0x90
|
||||
#define DRAM_WRITE 0x33330000
|
||||
|
||||
/* Compat definitions for older X Servers. */
|
||||
#ifndef M_T_PREFERRED
|
||||
#define M_T_PREFERRED 0x08
|
||||
#endif
|
||||
#ifndef M_T_DRIVER
|
||||
#define M_T_DRIVER 0x40
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Xserver MM compatibility. Remove code guarded by this when the
|
||||
* XServer contains the libdrm mm code
|
||||
|
|
|
|||
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#undef VERSION /* XXX edid.h has a VERSION too */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _PARSE_EDID_
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_bios.h"
|
||||
#include "edid.h"
|
||||
|
||||
#define INTEL_BIOS_8(_addr) (bios[_addr])
|
||||
#define INTEL_BIOS_16(_addr) (bios[_addr] | \
|
||||
(bios[_addr + 1] << 8))
|
||||
#define INTEL_BIOS_32(_addr) (bios[_addr] | \
|
||||
(bios[_addr + 1] << 8) \
|
||||
(bios[_addr + 2] << 16) \
|
||||
(bios[_addr + 3] << 24))
|
||||
|
||||
/* XXX */
|
||||
#define INTEL_VBIOS_SIZE (64 * 1024)
|
||||
|
||||
static void
|
||||
i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios)
|
||||
{
|
||||
const char *filename = "/tmp/xf86-video-intel-VBIOS";
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, "w");
|
||||
if (f == NULL) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename);
|
||||
return;
|
||||
}
|
||||
if (fwrite(bios, INTEL_VBIOS_SIZE, 1, f) != 1) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n");
|
||||
}
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Wrote BIOS contents to %s\n",
|
||||
filename);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the Video BIOS and checks that the VBT exists.
|
||||
*
|
||||
* VBT existence is a sanity check that is relied on by other i830_bios.c code.
|
||||
* Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
|
||||
* feed an updated VBT back through that, compared to what we'll fetch using
|
||||
* this method of groping around in the BIOS data.
|
||||
*/
|
||||
static unsigned char *
|
||||
i830GetBIOS(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
struct vbt_header *vbt;
|
||||
int vbt_off;
|
||||
unsigned char *bios;
|
||||
vbeInfoPtr pVbe;
|
||||
|
||||
bios = xalloc(INTEL_VBIOS_SIZE);
|
||||
if (bios == NULL)
|
||||
return NULL;
|
||||
|
||||
pVbe = VBEInit (NULL, pI830->pEnt->index);
|
||||
if (pVbe != NULL) {
|
||||
memcpy(bios, xf86int10Addr(pVbe->pInt10,
|
||||
pVbe->pInt10->BIOSseg << 4),
|
||||
INTEL_VBIOS_SIZE);
|
||||
vbeFree (pVbe);
|
||||
} else {
|
||||
xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE);
|
||||
}
|
||||
|
||||
if (0)
|
||||
i830DumpBIOSToFile(pScrn, bios);
|
||||
|
||||
vbt_off = INTEL_BIOS_16(0x1a);
|
||||
if (vbt_off >= INTEL_VBIOS_SIZE) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
|
||||
vbt_off);
|
||||
xfree(bios);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vbt = (struct vbt_header *)(bios + vbt_off);
|
||||
|
||||
if (memcmp(vbt->signature, "$VBT", 4) != 0) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n");
|
||||
xfree(bios);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bios;
|
||||
}
|
||||
|
||||
Bool
|
||||
i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
struct vbt_header *vbt;
|
||||
struct bdb_header *bdb;
|
||||
int vbt_off, bdb_off, bdb_block_off, block_size;
|
||||
int panel_type = -1;
|
||||
unsigned char *bios;
|
||||
Bool found_panel_info = FALSE;
|
||||
|
||||
bios = i830GetBIOS(pScrn);
|
||||
|
||||
if (bios == NULL)
|
||||
return FALSE;
|
||||
|
||||
vbt_off = INTEL_BIOS_16(0x1a);
|
||||
vbt = (struct vbt_header *)(bios + vbt_off);
|
||||
bdb_off = vbt_off + vbt->bdb_offset;
|
||||
bdb = (struct bdb_header *)(bios + bdb_off);
|
||||
|
||||
if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n");
|
||||
xfree(bios);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
|
||||
bdb_block_off += block_size)
|
||||
{
|
||||
int start = bdb_off + bdb_block_off;
|
||||
int id;
|
||||
struct lvds_bdb_1 *lvds1;
|
||||
struct lvds_bdb_2 *lvds2;
|
||||
struct lvds_bdb_2_fp_params *fpparam;
|
||||
struct lvds_bdb_2_fp_edid_dtd *fptiming;
|
||||
CARD8 *timing_ptr;
|
||||
|
||||
id = INTEL_BIOS_8(start);
|
||||
block_size = INTEL_BIOS_16(start + 1) + 3;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found BDB block type %d\n", id);
|
||||
switch (id) {
|
||||
case 40:
|
||||
lvds1 = (struct lvds_bdb_1 *)(bios + start);
|
||||
panel_type = lvds1->panel_type;
|
||||
if (lvds1->caps & LVDS_CAP_DITHER)
|
||||
pI830->panel_wants_dither = TRUE;
|
||||
break;
|
||||
case 41:
|
||||
if (panel_type == -1)
|
||||
break;
|
||||
|
||||
lvds2 = (struct lvds_bdb_2 *)(bios + start);
|
||||
fpparam = (struct lvds_bdb_2_fp_params *)(bios +
|
||||
bdb_off + lvds2->panels[panel_type].fp_params_offset);
|
||||
fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios +
|
||||
bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset);
|
||||
timing_ptr = bios + bdb_off +
|
||||
lvds2->panels[panel_type].fp_edid_dtd_offset;
|
||||
|
||||
if (fpparam->terminator != 0xffff) {
|
||||
/* Apparently the offsets are wrong for some BIOSes, so we
|
||||
* try the other offsets if we find a bad terminator.
|
||||
*/
|
||||
fpparam = (struct lvds_bdb_2_fp_params *)(bios +
|
||||
bdb_off + lvds2->panels[panel_type].fp_params_offset + 8);
|
||||
fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios +
|
||||
bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8);
|
||||
timing_ptr = bios + bdb_off +
|
||||
lvds2->panels[panel_type].fp_edid_dtd_offset + 8;
|
||||
|
||||
if (fpparam->terminator != 0xffff)
|
||||
continue;
|
||||
}
|
||||
|
||||
pI830->PanelXRes = fpparam->x_res;
|
||||
pI830->PanelYRes = fpparam->y_res;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Found panel of size %dx%d in BIOS VBT tables\n",
|
||||
pI830->PanelXRes, pI830->PanelYRes);
|
||||
|
||||
/* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
|
||||
* block, pull the contents out using EDID macros.
|
||||
*/
|
||||
pI830->panel_fixed_clock = _PIXEL_CLOCK(timing_ptr) / 1000;
|
||||
pI830->panel_fixed_hactive = _H_ACTIVE(timing_ptr);
|
||||
pI830->panel_fixed_hblank = _H_BLANK(timing_ptr);
|
||||
pI830->panel_fixed_hsyncoff = _H_SYNC_OFF(timing_ptr);
|
||||
pI830->panel_fixed_hsyncwidth = _H_SYNC_WIDTH(timing_ptr);
|
||||
|
||||
pI830->panel_fixed_vactive = _V_ACTIVE(timing_ptr);
|
||||
pI830->panel_fixed_vblank = _V_BLANK(timing_ptr);
|
||||
pI830->panel_fixed_vsyncoff = _V_SYNC_OFF(timing_ptr);
|
||||
pI830->panel_fixed_vsyncwidth = _V_SYNC_WIDTH(timing_ptr);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Panel mode h active %d blank %d rate %f v active %d blank %d rate %f\n",
|
||||
pI830->panel_fixed_hactive, pI830->panel_fixed_hblank,
|
||||
(double) pI830->panel_fixed_clock / (pI830->panel_fixed_hactive + pI830->panel_fixed_hblank),
|
||||
pI830->panel_fixed_vactive, pI830->panel_fixed_vblank,
|
||||
(double) pI830->panel_fixed_clock /
|
||||
((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank) * (pI830->panel_fixed_vactive + pI830->panel_fixed_vblank)));
|
||||
found_panel_info = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xfree(bios);
|
||||
return found_panel_info;
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
struct vbt_header {
|
||||
char signature[20]; /**< Always starts with 'VBT$' */
|
||||
CARD16 version; /**< decimal */
|
||||
CARD16 header_size; /**< in bytes */
|
||||
CARD16 vbt_size; /**< in bytes */
|
||||
CARD8 vbt_checksum;
|
||||
CARD8 reserved0;
|
||||
CARD32 bdb_offset; /**< from beginning of VBT */
|
||||
CARD32 aim1_offset; /**< from beginning of VBT */
|
||||
CARD32 aim2_offset; /**< from beginning of VBT */
|
||||
CARD32 aim3_offset; /**< from beginning of VBT */
|
||||
CARD32 aim4_offset; /**< from beginning of VBT */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct bdb_header {
|
||||
char signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
|
||||
CARD16 version; /**< decimal */
|
||||
CARD16 header_size; /**< in bytes */
|
||||
CARD16 bdb_size; /**< in bytes */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define LVDS_CAP_EDID (1 << 6)
|
||||
#define LVDS_CAP_DITHER (1 << 5)
|
||||
#define LVDS_CAP_PFIT_AUTO_RATIO (1 << 4)
|
||||
#define LVDS_CAP_PFIT_GRAPHICS_MODE (1 << 3)
|
||||
#define LVDS_CAP_PFIT_TEXT_MODE (1 << 2)
|
||||
#define LVDS_CAP_PFIT_GRAPHICS (1 << 1)
|
||||
#define LVDS_CAP_PFIT_TEXT (1 << 0)
|
||||
struct lvds_bdb_1 {
|
||||
CARD8 id; /**< 40 */
|
||||
CARD16 size;
|
||||
CARD8 panel_type;
|
||||
CARD8 reserved0;
|
||||
CARD16 caps;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct lvds_bdb_2_fp_params {
|
||||
CARD16 x_res;
|
||||
CARD16 y_res;
|
||||
CARD32 lvds_reg;
|
||||
CARD32 lvds_reg_val;
|
||||
CARD32 pp_on_reg;
|
||||
CARD32 pp_on_reg_val;
|
||||
CARD32 pp_off_reg;
|
||||
CARD32 pp_off_reg_val;
|
||||
CARD32 pp_cycle_reg;
|
||||
CARD32 pp_cycle_reg_val;
|
||||
CARD32 pfit_reg;
|
||||
CARD32 pfit_reg_val;
|
||||
CARD16 terminator;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct lvds_bdb_2_fp_edid_dtd {
|
||||
CARD16 dclk; /**< In 10khz */
|
||||
CARD8 hactive;
|
||||
CARD8 hblank;
|
||||
CARD8 high_h; /**< 7:4 = hactive 11:8, 3:0 = hblank 11:8 */
|
||||
CARD8 vactive;
|
||||
CARD8 vblank;
|
||||
CARD8 high_v; /**< 7:4 = vactive 11:8, 3:0 = vblank 11:8 */
|
||||
CARD8 hsync_off;
|
||||
CARD8 hsync_pulse_width;
|
||||
CARD8 vsync_off;
|
||||
CARD8 high_hsync_off; /**< 7:6 = hsync off 9:8 */
|
||||
CARD8 h_image;
|
||||
CARD8 v_image;
|
||||
CARD8 max_hv;
|
||||
CARD8 h_border;
|
||||
CARD8 v_border;
|
||||
CARD8 flags;
|
||||
#define FP_EDID_FLAG_VSYNC_POSITIVE (1 << 2)
|
||||
#define FP_EDID_FLAG_HSYNC_POSITIVE (1 << 1)
|
||||
} __attribute__((packed));
|
||||
|
||||
struct lvds_bdb_2_entry {
|
||||
CARD16 fp_params_offset; /**< From beginning of BDB */
|
||||
CARD8 fp_params_size;
|
||||
CARD16 fp_edid_dtd_offset;
|
||||
CARD8 fp_edid_dtd_size;
|
||||
CARD16 fp_edid_pid_offset;
|
||||
CARD8 fp_edid_pid_size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct lvds_bdb_2 {
|
||||
CARD8 id; /**< 41 */
|
||||
CARD16 size;
|
||||
CARD8 table_size; /* not sure on this one */
|
||||
struct lvds_bdb_2_entry panels[16];
|
||||
} __attribute__((packed));
|
||||
|
||||
Bool
|
||||
i830GetLVDSInfoFromBIOS(ScrnInfoPtr pScrn);
|
||||
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_xf86Modes.h"
|
||||
#include "i830_display.h"
|
||||
|
||||
static void
|
||||
i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 temp;
|
||||
|
||||
temp = INREG(ADPA);
|
||||
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
|
||||
temp &= ~ADPA_DAC_ENABLE;
|
||||
|
||||
switch(mode) {
|
||||
case DPMSModeOn:
|
||||
temp |= ADPA_DAC_ENABLE;
|
||||
break;
|
||||
case DPMSModeStandby:
|
||||
temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
case DPMSModeSuspend:
|
||||
temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
case DPMSModeOff:
|
||||
temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
OUTREG(ADPA, temp);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_crt_save(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
pI830->saveADPA = INREG(ADPA);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
OUTREG(ADPA, pI830->saveADPA);
|
||||
}
|
||||
|
||||
static int
|
||||
i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
if (pMode->Flags & V_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
if (pMode->Clock > 400000 || pMode->Clock < 25000)
|
||||
return MODE_CLOCK_RANGE;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
|
||||
CARD32 adpa, dpll_md;
|
||||
|
||||
/*
|
||||
* Disable separate mode multiplier used when cloning SDVO to CRT
|
||||
* XXX this needs to be adjusted when we really are cloning
|
||||
*/
|
||||
if (IS_I965G(pI830))
|
||||
{
|
||||
dpll_md = INREG(dpll_md_reg);
|
||||
OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
}
|
||||
|
||||
adpa = ADPA_DAC_ENABLE;
|
||||
|
||||
if (pMode->Flags & V_PHSYNC)
|
||||
adpa |= ADPA_HSYNC_ACTIVE_HIGH;
|
||||
if (pMode->Flags & V_PVSYNC)
|
||||
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (output->pipe == 0)
|
||||
adpa |= ADPA_PIPE_A_SELECT;
|
||||
else
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
|
||||
OUTREG(ADPA, adpa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
|
||||
*
|
||||
* Only for I945G/GM.
|
||||
*
|
||||
* \return TRUE if CRT is connected.
|
||||
* \return FALSE if CRT is disconnected.
|
||||
*/
|
||||
static Bool
|
||||
i830_crt_detect_hotplug(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 temp;
|
||||
const int timeout_ms = 1000;
|
||||
int starttime, curtime;
|
||||
|
||||
temp = INREG(PORT_HOTPLUG_EN);
|
||||
|
||||
OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
|
||||
|
||||
for (curtime = starttime = GetTimeInMillis();
|
||||
(curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
|
||||
{
|
||||
if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
|
||||
CRT_HOTPLUG_MONITOR_COLOR)
|
||||
{
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects CRT presence by checking for load.
|
||||
*
|
||||
* Requires that the current pipe's DPLL is active. This will cause flicker
|
||||
* on the CRT, so it should not be used while the display is being used. Only
|
||||
* color (not monochrome) displays are detected.
|
||||
*
|
||||
* \return TRUE if CRT is connected.
|
||||
* \return FALSE if CRT is disconnected.
|
||||
*/
|
||||
static Bool
|
||||
i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 save_adpa, adpa, pipeconf, bclrpat;
|
||||
CARD8 st00;
|
||||
int pipeconf_reg, bclrpat_reg, dpll_reg;
|
||||
int pipe;
|
||||
|
||||
pipe = output->pipe;
|
||||
if (pipe == 0) {
|
||||
bclrpat_reg = BCLRPAT_A;
|
||||
pipeconf_reg = PIPEACONF;
|
||||
dpll_reg = DPLL_A;
|
||||
} else {
|
||||
bclrpat_reg = BCLRPAT_B;
|
||||
pipeconf_reg = PIPEBCONF;
|
||||
dpll_reg = DPLL_B;
|
||||
}
|
||||
|
||||
adpa = INREG(ADPA);
|
||||
save_adpa = adpa;
|
||||
|
||||
/* Enable CRT output. */
|
||||
adpa |= ADPA_DAC_ENABLE;
|
||||
if (pipe == 1)
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
else
|
||||
adpa &= ~ADPA_PIPE_B_SELECT;
|
||||
adpa |= ADPA_VSYNC_CNTL_ENABLE | ADPA_HSYNC_CNTL_ENABLE;
|
||||
OUTREG(ADPA, adpa);
|
||||
|
||||
/* Set the border color to purple. Maybe we should save/restore this
|
||||
* reg.
|
||||
*/
|
||||
bclrpat = INREG(bclrpat_reg);
|
||||
OUTREG(bclrpat_reg, 0x00500050);
|
||||
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
/* Force the border color through the active region */
|
||||
pipeconf = INREG(pipeconf_reg);
|
||||
OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
|
||||
|
||||
/* Read the ST00 VGA status register */
|
||||
st00 = pI830->readStandard(pI830, 0x3c2);
|
||||
|
||||
/* Restore previous settings */
|
||||
OUTREG(bclrpat_reg, bclrpat);
|
||||
OUTREG(pipeconf_reg, pipeconf);
|
||||
OUTREG(ADPA, save_adpa);
|
||||
|
||||
if (st00 & (1 << 4))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects CRT presence by probing for a response on the DDC address.
|
||||
*
|
||||
* This takes approximately 5ms in testing on an i915GM, with CRT connected or
|
||||
* not.
|
||||
*
|
||||
* \return TRUE if the CRT is connected and responded to DDC.
|
||||
* \return FALSE if no DDC response was detected.
|
||||
*/
|
||||
static Bool
|
||||
i830_crt_detect_ddc(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
struct _I830OutputRec *output;
|
||||
|
||||
output = &pI830->output[0];
|
||||
/* CRT should always be at 0, but check anyway */
|
||||
if (output->type != I830_OUTPUT_ANALOG)
|
||||
return FALSE;
|
||||
|
||||
return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to detect CRT presence through any method available.
|
||||
*
|
||||
* @param allow_disturb enables detection methods that may cause flickering
|
||||
* on active displays.
|
||||
*/
|
||||
static enum detect_status
|
||||
i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
|
||||
if (i830_crt_detect_hotplug(pScrn))
|
||||
return OUTPUT_STATUS_CONNECTED;
|
||||
else
|
||||
return OUTPUT_STATUS_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (i830_crt_detect_ddc(pScrn))
|
||||
return OUTPUT_STATUS_CONNECTED;
|
||||
|
||||
/* Use the load-detect method if we have no other way of telling. */
|
||||
if (i830GetLoadDetectPipe(pScrn, output) != -1) {
|
||||
Bool connected = i830_crt_detect_load(pScrn, output);
|
||||
|
||||
i830ReleaseLoadDetectPipe(pScrn, output);
|
||||
if (connected)
|
||||
return OUTPUT_STATUS_CONNECTED;
|
||||
else
|
||||
return OUTPUT_STATUS_DISCONNECTED;
|
||||
}
|
||||
|
||||
return OUTPUT_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
static DisplayModePtr
|
||||
i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
DisplayModePtr modes;
|
||||
MonRec fixed_mon;
|
||||
|
||||
modes = i830_ddc_get_modes(pScrn, output);
|
||||
if (modes != NULL)
|
||||
return modes;
|
||||
|
||||
if (output->detect(pScrn, output) == OUTPUT_STATUS_DISCONNECTED)
|
||||
return NULL;
|
||||
|
||||
/* We've got a potentially-connected monitor that we can't DDC. Return a
|
||||
* fixed set of VESA plus user modes for a presumed multisync monitor with
|
||||
* some reasonable limits.
|
||||
*/
|
||||
fixed_mon.nHsync = 1;
|
||||
fixed_mon.hsync[0].lo = 31.0;
|
||||
fixed_mon.hsync[0].hi = 100.0;
|
||||
fixed_mon.nVrefresh = 1;
|
||||
fixed_mon.vrefresh[0].lo = 50.0;
|
||||
fixed_mon.vrefresh[0].hi = 70.0;
|
||||
|
||||
modes = i830xf86DuplicateModes(pScrn, pScrn->monitor->Modes);
|
||||
i830xf86ValidateModesSync(pScrn, modes, &fixed_mon);
|
||||
i830xf86PruneInvalidModes(pScrn, &modes, TRUE);
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
void
|
||||
i830_crt_init(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG;
|
||||
pI830->output[pI830->num_outputs].dpms = i830_crt_dpms;
|
||||
pI830->output[pI830->num_outputs].save = i830_crt_save;
|
||||
pI830->output[pI830->num_outputs].restore = i830_crt_restore;
|
||||
pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid;
|
||||
pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode;
|
||||
pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
|
||||
pI830->output[pI830->num_outputs].detect = i830_crt_detect;
|
||||
pI830->output[pI830->num_outputs].get_modes = i830_crt_get_modes;
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
|
||||
GPIOA, "CRTDDC_A");
|
||||
|
||||
pI830->num_outputs++;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
/* -*- c-basic-offset: 3 -*- */
|
||||
/**************************************************************************
|
||||
|
||||
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
|
|
@ -79,52 +79,126 @@ static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
|
|||
static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
|
||||
#endif
|
||||
|
||||
static void
|
||||
I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
|
||||
I830MemRange *cursor_mem;
|
||||
|
||||
if (pipe >= pI830->num_pipes)
|
||||
FatalError("Bad pipe number for cursor base setting\n");
|
||||
|
||||
if (pI830->CursorIsARGB)
|
||||
cursor_mem = pI830->CursorMemARGB;
|
||||
else
|
||||
cursor_mem = pI830->CursorMem;
|
||||
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
OUTREG(cursor_base, cursor_mem->Physical);
|
||||
} else {
|
||||
OUTREG(cursor_base, cursor_mem->Start);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
|
||||
CARD32 temp;
|
||||
Bool show;
|
||||
|
||||
if (!pI830Pipe->enabled)
|
||||
return;
|
||||
|
||||
show = pI830->cursorOn && pI830Pipe->cursorInRange;
|
||||
if (show && (force || !pI830Pipe->cursorShown))
|
||||
{
|
||||
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
|
||||
int cursor_control;
|
||||
if (pipe == 0)
|
||||
cursor_control = CURSOR_A_CONTROL;
|
||||
else
|
||||
cursor_control = CURSOR_B_CONTROL;
|
||||
temp = INREG(cursor_control);
|
||||
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
|
||||
if (pI830->CursorIsARGB) {
|
||||
temp |= CURSOR_MODE_64_ARGB_AX;
|
||||
if (pI830Pipe->gammaEnabled)
|
||||
temp |= MCURSOR_GAMMA_ENABLE;
|
||||
} else
|
||||
temp |= CURSOR_MODE_64_4C_AX;
|
||||
|
||||
temp |= (pipe << 28); /* Connect to correct pipe */
|
||||
/* Need to set mode, then address. */
|
||||
OUTREG(cursor_control, temp);
|
||||
} else {
|
||||
temp = INREG(CURSOR_CONTROL);
|
||||
temp &= ~(CURSOR_FORMAT_MASK);
|
||||
temp |= CURSOR_ENABLE;
|
||||
if (pI830->CursorIsARGB) {
|
||||
temp |= CURSOR_FORMAT_ARGB;
|
||||
if (pI830Pipe->gammaEnabled)
|
||||
temp |= CURSOR_GAMMA_ENABLE;
|
||||
} else
|
||||
temp |= CURSOR_FORMAT_3C;
|
||||
OUTREG(CURSOR_CONTROL, temp);
|
||||
}
|
||||
pI830Pipe->cursorShown = TRUE;
|
||||
}
|
||||
else if (!show && (force || pI830Pipe->cursorShown))
|
||||
{
|
||||
if (IS_MOBILE(pI830) || IS_I9XX(pI830))
|
||||
{
|
||||
int cursor_control;
|
||||
if (pipe == 0)
|
||||
cursor_control = CURSOR_A_CONTROL;
|
||||
else
|
||||
cursor_control = CURSOR_B_CONTROL;
|
||||
temp = INREG(cursor_control);
|
||||
temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
|
||||
temp |= CURSOR_MODE_DISABLE;
|
||||
OUTREG(cursor_control, temp);
|
||||
} else {
|
||||
temp = INREG(CURSOR_CONTROL);
|
||||
temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
|
||||
OUTREG(CURSOR_CONTROL, temp);
|
||||
}
|
||||
pI830Pipe->cursorShown = FALSE;
|
||||
}
|
||||
|
||||
/* Flush cursor changes. */
|
||||
I830SetPipeCursorBase(pScrn, pipe);
|
||||
}
|
||||
|
||||
void
|
||||
I830InitHWCursor(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 temp;
|
||||
int i;
|
||||
|
||||
DPRINTF(PFX, "I830InitHWCursor\n");
|
||||
for (i = 0; i < pI830->num_pipes; i++)
|
||||
pI830->pipes[i].cursorShown = FALSE;
|
||||
/* Initialise the HW cursor registers, leaving the cursor hidden. */
|
||||
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
|
||||
temp = INREG(CURSOR_A_CONTROL);
|
||||
temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
|
||||
MCURSOR_PIPE_SELECT);
|
||||
temp |= CURSOR_MODE_DISABLE;
|
||||
temp |= (pI830->pipe << 28);
|
||||
if (pI830->CursorIsARGB)
|
||||
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
|
||||
else
|
||||
temp |= CURSOR_MODE_64_4C_AX;
|
||||
/* Need to set control, then address. */
|
||||
OUTREG(CURSOR_A_CONTROL, temp);
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
|
||||
} else {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start);
|
||||
}
|
||||
if (pI830->Clone || pI830->MergedFB) {
|
||||
temp &= ~MCURSOR_PIPE_SELECT;
|
||||
temp |= (!pI830->pipe << 28);
|
||||
OUTREG(CURSOR_B_CONTROL, temp);
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
|
||||
} else {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start);
|
||||
}
|
||||
for (i = 0; i < pI830->num_pipes; i++)
|
||||
{
|
||||
int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
|
||||
temp = INREG(cursor_control);
|
||||
temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE |
|
||||
MCURSOR_MEM_TYPE_LOCAL |
|
||||
MCURSOR_PIPE_SELECT);
|
||||
temp |= (i << 28);
|
||||
if (pI830->CursorIsARGB)
|
||||
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
|
||||
else
|
||||
temp |= CURSOR_MODE_64_4C_AX;
|
||||
/* Need to set control, then address. */
|
||||
OUTREG(cursor_control, temp);
|
||||
I830SetPipeCursorBase(pScrn, i);
|
||||
}
|
||||
} else {
|
||||
temp = INREG(CURSOR_CONTROL);
|
||||
|
|
@ -137,10 +211,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
|
|||
/* This initialises the format and leave the cursor disabled. */
|
||||
OUTREG(CURSOR_CONTROL, temp);
|
||||
/* Need to set address and size after disabling. */
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
|
||||
I830SetPipeCursorBase(pScrn, 0);
|
||||
temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
|
||||
((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
|
||||
OUTREG(CURSOR_SIZE, temp);
|
||||
|
|
@ -374,239 +445,99 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define CDMPTR ((I830ModePrivatePtr)pI830->currentMode->Private)->merged
|
||||
|
||||
static void
|
||||
I830SetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
ScrnInfoPtr pScrn2 = pI830->pScrn_2;
|
||||
DisplayModePtr mode1 = CDMPTR.First;
|
||||
Bool hide = FALSE, show = FALSE;
|
||||
DisplayModePtr mode2 = CDMPTR.Second;
|
||||
int x1, y1, x2, y2;
|
||||
int total_y1 = pScrn->frameY1 - pScrn->frameY0;
|
||||
int total_y2 = pScrn2->frameY1 - pScrn2->frameY0;
|
||||
CARD32 temp = 0, temp2 = 0;
|
||||
|
||||
x += pScrn->frameX0;
|
||||
y += pScrn->frameY0;
|
||||
|
||||
x1 = x - pI830->FirstframeX0;
|
||||
y1 = y - pI830->FirstframeY0;
|
||||
|
||||
x2 = x - pScrn2->frameX0;
|
||||
y2 = y - pScrn2->frameY0;
|
||||
|
||||
if (y1 > total_y1)
|
||||
y1 = total_y1;
|
||||
if (y2 > total_y2)
|
||||
y2 = total_y2;
|
||||
|
||||
/* move cursor offscreen */
|
||||
if (y1 >= 0 && y2 >= mode2->VDisplay) {
|
||||
y2 = -I810_CURSOR_Y;
|
||||
} else if (y2 >= 0 && y1 >= mode1->VDisplay) {
|
||||
y1 = -I810_CURSOR_Y;
|
||||
}
|
||||
if (x1 >= 0 && x2 >= mode2->HDisplay) {
|
||||
x2 = -I810_CURSOR_X;
|
||||
} else if (x2 >= 0 && x1 >= mode1->HDisplay) {
|
||||
x1 = -I810_CURSOR_X;
|
||||
}
|
||||
|
||||
/* Clamp the cursor position to the visible screen area */
|
||||
if (x1 >= mode1->HDisplay) x1 = mode1->HDisplay - 1;
|
||||
if (y1 >= mode1->VDisplay) y1 = mode1->VDisplay - 1;
|
||||
if (x1 <= -I810_CURSOR_X) x1 = -I810_CURSOR_X + 1;
|
||||
if (y1 <= -I810_CURSOR_Y) y1 = -I810_CURSOR_Y + 1;
|
||||
if (x2 >= mode2->HDisplay) x2 = mode2->HDisplay - 1;
|
||||
if (y2 >= mode2->VDisplay) y2 = mode2->VDisplay - 1;
|
||||
if (x2 <= -I810_CURSOR_X) x2 = -I810_CURSOR_X + 1;
|
||||
if (y2 <= -I810_CURSOR_Y) y2 = -I810_CURSOR_Y + 1;
|
||||
|
||||
if (x1 < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
|
||||
x1 = -x1;
|
||||
}
|
||||
if (y1 < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
|
||||
y1 = -y1;
|
||||
}
|
||||
if (x2 < 0) {
|
||||
temp2 |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
|
||||
x2 = -x2;
|
||||
}
|
||||
if (y2 < 0) {
|
||||
temp2 |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
|
||||
y2 = -y2;
|
||||
}
|
||||
|
||||
temp |= ((x1 & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
|
||||
temp |= ((y1 & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
|
||||
temp2 |= ((x2 & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
|
||||
temp2 |= ((y2 & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
|
||||
|
||||
OUTREG(CURSOR_A_POSITION, temp);
|
||||
OUTREG(CURSOR_B_POSITION, temp2);
|
||||
|
||||
if (pI830->cursorOn) {
|
||||
if (hide)
|
||||
pI830->CursorInfoRec->HideCursor(pScrn);
|
||||
else if (show)
|
||||
pI830->CursorInfoRec->ShowCursor(pScrn);
|
||||
pI830->cursorOn = TRUE;
|
||||
}
|
||||
|
||||
/* have to upload the base for the new position */
|
||||
if (IS_I9XX(pI830)) {
|
||||
if (pI830->CursorIsARGB) {
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
|
||||
} else {
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 temp = 0;
|
||||
Bool hide = FALSE, show = FALSE;
|
||||
int oldx = x, oldy = y;
|
||||
int hotspotx = 0, hotspoty = 0;
|
||||
#if 0
|
||||
static Bool outsideViewport = FALSE;
|
||||
#endif
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 temp;
|
||||
Bool inrange;
|
||||
int oldx = x, oldy = y;
|
||||
int hotspotx = 0, hotspoty = 0;
|
||||
int pipe;
|
||||
|
||||
if (pI830->MergedFB) {
|
||||
I830SetCursorPositionMerged(pScrn, x, y);
|
||||
return;
|
||||
}
|
||||
oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
|
||||
oldy += pScrn->frameY0;
|
||||
|
||||
oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
|
||||
oldy += pScrn->frameY0;
|
||||
switch (pI830->rotation) {
|
||||
case RR_Rotate_0:
|
||||
x = oldx;
|
||||
y = oldy;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
x = oldy;
|
||||
y = pScrn->pScreen->width - oldx;
|
||||
hotspoty = I810_CURSOR_X;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
x = pScrn->pScreen->width - oldx;
|
||||
y = pScrn->pScreen->height - oldy;
|
||||
hotspotx = I810_CURSOR_X;
|
||||
hotspoty = I810_CURSOR_Y;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
x = pScrn->pScreen->height - oldy;
|
||||
y = oldx;
|
||||
hotspotx = I810_CURSOR_Y;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pI830->rotation) {
|
||||
case RR_Rotate_0:
|
||||
x = oldx;
|
||||
y = oldy;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
x = oldy;
|
||||
y = pScrn->pScreen->width - oldx;
|
||||
hotspoty = I810_CURSOR_X;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
x = pScrn->pScreen->width - oldx;
|
||||
y = pScrn->pScreen->height - oldy;
|
||||
hotspotx = I810_CURSOR_X;
|
||||
hotspoty = I810_CURSOR_Y;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
x = pScrn->pScreen->height - oldy;
|
||||
y = oldx;
|
||||
hotspotx = I810_CURSOR_Y;
|
||||
break;
|
||||
}
|
||||
x -= hotspotx;
|
||||
y -= hotspoty;
|
||||
|
||||
x -= hotspotx;
|
||||
y -= hotspoty;
|
||||
for (pipe = 0; pipe < pI830->num_pipes; pipe++)
|
||||
{
|
||||
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
|
||||
DisplayModePtr mode = &pI830Pipe->curMode;
|
||||
int thisx = x - pI830Pipe->x;
|
||||
int thisy = y - pI830Pipe->y;
|
||||
|
||||
/* Now, readjust */
|
||||
x -= pScrn->frameX0;
|
||||
y -= pScrn->frameY0;
|
||||
if (!pI830Pipe->enabled)
|
||||
continue;
|
||||
|
||||
if (pScrn->currentMode) {
|
||||
/* Clamp the cursor position to the visible screen area */
|
||||
if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1;
|
||||
if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1;
|
||||
if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
|
||||
if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
|
||||
} else {
|
||||
/* Can't ensure the cursor will be visible, so hide it */
|
||||
hide = TRUE;
|
||||
show = FALSE;
|
||||
}
|
||||
/*
|
||||
* There is a screen display problem when the cursor position is set
|
||||
* wholely outside of the viewport. We trap that here, turning the
|
||||
* cursor off when that happens, and back on when it comes back into
|
||||
* the viewport.
|
||||
*/
|
||||
inrange = TRUE;
|
||||
if (thisx >= mode->HDisplay ||
|
||||
thisy >= mode->VDisplay ||
|
||||
thisx <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y)
|
||||
{
|
||||
inrange = FALSE;
|
||||
thisx = 0;
|
||||
thisy = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* There is a screen display problem when the cursor position is set
|
||||
* wholely outside of the viewport. We trap that here, turning the
|
||||
* cursor off when that happens, and back on when it comes back into
|
||||
* the viewport.
|
||||
*/
|
||||
if (x >= pScrn->currentMode->HDisplay ||
|
||||
y >= pScrn->currentMode->VDisplay ||
|
||||
x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) {
|
||||
hide = TRUE;
|
||||
outsideViewport = TRUE;
|
||||
} else if (outsideViewport) {
|
||||
show = TRUE;
|
||||
outsideViewport = FALSE;
|
||||
}
|
||||
#endif
|
||||
temp = 0;
|
||||
if (thisx < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
|
||||
thisx = -thisx;
|
||||
}
|
||||
if (thisy < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
|
||||
thisy = -thisy;
|
||||
}
|
||||
temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
|
||||
temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
|
||||
|
||||
if (x < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0) {
|
||||
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
|
||||
y = -y;
|
||||
}
|
||||
temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
|
||||
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
|
||||
if (pipe == 0)
|
||||
OUTREG(CURSOR_A_POSITION, temp);
|
||||
if (pipe == 1)
|
||||
OUTREG(CURSOR_B_POSITION, temp);
|
||||
|
||||
OUTREG(CURSOR_A_POSITION, temp);
|
||||
if (pI830->Clone)
|
||||
OUTREG(CURSOR_B_POSITION, temp);
|
||||
|
||||
if (pI830->cursorOn) {
|
||||
if (hide)
|
||||
pI830->CursorInfoRec->HideCursor(pScrn);
|
||||
else if (show)
|
||||
pI830->CursorInfoRec->ShowCursor(pScrn);
|
||||
pI830->cursorOn = TRUE;
|
||||
}
|
||||
|
||||
/* have to upload the base for the new position */
|
||||
if (IS_I9XX(pI830)) {
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
|
||||
} else {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start);
|
||||
}
|
||||
if (pI830->Clone) {
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
|
||||
} else {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start);
|
||||
}
|
||||
}
|
||||
}
|
||||
pI830Pipe->cursorInRange = inrange;
|
||||
|
||||
I830SetPipeCursor (pScrn, pipe, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
I830ShowCursor(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 temp;
|
||||
int pipe;
|
||||
|
||||
DPRINTF(PFX, "I830ShowCursor\n");
|
||||
DPRINTF(PFX,
|
||||
|
|
@ -618,91 +549,22 @@ I830ShowCursor(ScrnInfoPtr pScrn)
|
|||
" Value of CursorMemARGB->Start is %x ",
|
||||
pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
|
||||
|
||||
pI830->cursorOn = TRUE;
|
||||
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
|
||||
temp = INREG(CURSOR_A_CONTROL);
|
||||
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT | MCURSOR_GAMMA_ENABLE);
|
||||
if (pI830->CursorIsARGB)
|
||||
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
|
||||
else
|
||||
temp |= CURSOR_MODE_64_4C_AX;
|
||||
temp |= (pI830->pipe << 28); /* Connect to correct pipe */
|
||||
/* Need to set mode, then address. */
|
||||
OUTREG(CURSOR_A_CONTROL, temp);
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
|
||||
} else {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start);
|
||||
}
|
||||
if (pI830->Clone || pI830->MergedFB) {
|
||||
temp &= ~MCURSOR_PIPE_SELECT;
|
||||
temp |= (!pI830->pipe << 28);
|
||||
OUTREG(CURSOR_B_CONTROL, temp);
|
||||
if (pI830->CursorNeedsPhysical) {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
|
||||
} else {
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
temp = INREG(CURSOR_CONTROL);
|
||||
temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE);
|
||||
temp |= CURSOR_ENABLE;
|
||||
if (pI830->CursorIsARGB)
|
||||
temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
|
||||
else
|
||||
temp |= CURSOR_FORMAT_3C;
|
||||
OUTREG(CURSOR_CONTROL, temp);
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
|
||||
else
|
||||
OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
|
||||
}
|
||||
pI830->cursorOn = TRUE;
|
||||
for (pipe = 0; pipe < pI830->num_pipes; pipe++)
|
||||
I830SetPipeCursor (pScrn, pipe, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
I830HideCursor(ScrnInfoPtr pScrn)
|
||||
{
|
||||
CARD32 temp;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int pipe;
|
||||
|
||||
DPRINTF(PFX, "I830HideCursor\n");
|
||||
|
||||
pI830->cursorOn = FALSE;
|
||||
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
|
||||
temp = INREG(CURSOR_A_CONTROL);
|
||||
temp &= ~CURSOR_MODE;
|
||||
temp |= CURSOR_MODE_DISABLE;
|
||||
OUTREG(CURSOR_A_CONTROL, temp);
|
||||
/* This is needed to flush the above change. */
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
|
||||
if (pI830->Clone || pI830->MergedFB) {
|
||||
OUTREG(CURSOR_B_CONTROL, temp);
|
||||
if (pI830->CursorIsARGB)
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
|
||||
else
|
||||
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
|
||||
}
|
||||
} else {
|
||||
temp = INREG(CURSOR_CONTROL);
|
||||
temp &= ~CURSOR_ENABLE;
|
||||
OUTREG(CURSOR_CONTROL, temp);
|
||||
}
|
||||
for (pipe = 0; pipe < pI830->num_pipes; pipe++)
|
||||
I830SetPipeCursor (pScrn, pipe, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -718,11 +580,15 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
|
|||
|
||||
DPRINTF(PFX, "I830SetCursorColors\n");
|
||||
|
||||
OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff);
|
||||
OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff);
|
||||
OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff);
|
||||
OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff);
|
||||
if (pI830->Clone || pI830->MergedFB) {
|
||||
if (pI830->pipes[0].enabled)
|
||||
{
|
||||
OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff);
|
||||
OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff);
|
||||
OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff);
|
||||
OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff);
|
||||
}
|
||||
if (pI830->pipes[1].enabled)
|
||||
{
|
||||
OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
|
||||
OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
|
||||
OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_debug.h"
|
||||
|
||||
#define DEFINEREG(reg) \
|
||||
{ reg, #reg, 0 }
|
||||
|
||||
static struct i830SnapshotRec {
|
||||
int reg;
|
||||
char *name;
|
||||
CARD32 regval;
|
||||
} i830_snapshot[] = {
|
||||
DEFINEREG(VCLK_DIVISOR_VGA0),
|
||||
DEFINEREG(VCLK_DIVISOR_VGA1),
|
||||
DEFINEREG(VCLK_POST_DIV),
|
||||
DEFINEREG(DPLL_TEST),
|
||||
DEFINEREG(D_STATE),
|
||||
DEFINEREG(DSPCLK_GATE_D),
|
||||
DEFINEREG(RENCLK_GATE_D1),
|
||||
DEFINEREG(RENCLK_GATE_D2),
|
||||
/* DEFINEREG(RAMCLK_GATE_D), CRL only */
|
||||
DEFINEREG(SDVOB),
|
||||
DEFINEREG(SDVOC),
|
||||
/* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */
|
||||
/* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */
|
||||
DEFINEREG(SDVOUDI),
|
||||
DEFINEREG(DSPARB),
|
||||
DEFINEREG(DSPFW1),
|
||||
DEFINEREG(DSPFW2),
|
||||
DEFINEREG(DSPFW3),
|
||||
|
||||
DEFINEREG(ADPA),
|
||||
DEFINEREG(LVDS),
|
||||
DEFINEREG(DVOA),
|
||||
DEFINEREG(DVOB),
|
||||
DEFINEREG(DVOC),
|
||||
DEFINEREG(DVOA_SRCDIM),
|
||||
DEFINEREG(DVOB_SRCDIM),
|
||||
DEFINEREG(DVOC_SRCDIM),
|
||||
|
||||
DEFINEREG(PP_CONTROL),
|
||||
DEFINEREG(PP_STATUS),
|
||||
DEFINEREG(PFIT_CONTROL),
|
||||
DEFINEREG(PFIT_PGM_RATIOS),
|
||||
DEFINEREG(PORT_HOTPLUG_EN),
|
||||
DEFINEREG(PORT_HOTPLUG_STAT),
|
||||
|
||||
DEFINEREG(DSPACNTR),
|
||||
DEFINEREG(DSPASTRIDE),
|
||||
DEFINEREG(DSPAPOS),
|
||||
DEFINEREG(DSPASIZE),
|
||||
DEFINEREG(DSPABASE),
|
||||
DEFINEREG(DSPASURF),
|
||||
DEFINEREG(DSPATILEOFF),
|
||||
DEFINEREG(PIPEACONF),
|
||||
DEFINEREG(PIPEASRC),
|
||||
|
||||
DEFINEREG(FPA0),
|
||||
DEFINEREG(FPA1),
|
||||
DEFINEREG(DPLL_A),
|
||||
DEFINEREG(DPLL_A_MD),
|
||||
DEFINEREG(HTOTAL_A),
|
||||
DEFINEREG(HBLANK_A),
|
||||
DEFINEREG(HSYNC_A),
|
||||
DEFINEREG(VTOTAL_A),
|
||||
DEFINEREG(VBLANK_A),
|
||||
DEFINEREG(VSYNC_A),
|
||||
DEFINEREG(BCLRPAT_A),
|
||||
DEFINEREG(VSYNCSHIFT_A),
|
||||
|
||||
DEFINEREG(DSPBCNTR),
|
||||
DEFINEREG(DSPBSTRIDE),
|
||||
DEFINEREG(DSPBPOS),
|
||||
DEFINEREG(DSPBSIZE),
|
||||
DEFINEREG(DSPBBASE),
|
||||
DEFINEREG(DSPBSURF),
|
||||
DEFINEREG(DSPBTILEOFF),
|
||||
DEFINEREG(PIPEBCONF),
|
||||
DEFINEREG(PIPEBSRC),
|
||||
|
||||
DEFINEREG(FPB0),
|
||||
DEFINEREG(FPB1),
|
||||
DEFINEREG(DPLL_B),
|
||||
DEFINEREG(DPLL_B_MD),
|
||||
DEFINEREG(HTOTAL_B),
|
||||
DEFINEREG(HBLANK_B),
|
||||
DEFINEREG(HSYNC_B),
|
||||
DEFINEREG(VTOTAL_B),
|
||||
DEFINEREG(VBLANK_B),
|
||||
DEFINEREG(VSYNC_B),
|
||||
DEFINEREG(BCLRPAT_B),
|
||||
DEFINEREG(VSYNCSHIFT_B),
|
||||
|
||||
DEFINEREG(VCLK_DIVISOR_VGA0),
|
||||
DEFINEREG(VCLK_DIVISOR_VGA1),
|
||||
DEFINEREG(VCLK_POST_DIV),
|
||||
DEFINEREG(VGACNTRL),
|
||||
};
|
||||
#undef DEFINEREG
|
||||
#define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
|
||||
|
||||
void i830TakeRegSnapshot(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
|
||||
i830_snapshot[i].regval = INREG(i830_snapshot[i].reg);
|
||||
}
|
||||
}
|
||||
|
||||
void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Comparing regs before/after X's VT usage\n");
|
||||
for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
|
||||
CARD32 val = INREG(i830_snapshot[i].reg);
|
||||
if (i830_snapshot[i].regval != val) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
|
||||
i830_snapshot[i].reg, i830_snapshot[i].name,
|
||||
(int)i830_snapshot[i].regval, (int)val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
for (i = min; i <= max; i++) {
|
||||
OUTREG8 (id, i);
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%18.18s%02x: 0x%02x\n",
|
||||
name, i, INREG8(val));
|
||||
}
|
||||
}
|
||||
|
||||
void i830DumpRegs (ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
int fp, dpll;
|
||||
int pipe;
|
||||
int n, m1, m2, m, p1, p2;
|
||||
int ref;
|
||||
int dot;
|
||||
int phase;
|
||||
int msr;
|
||||
int crt;
|
||||
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsBegin\n");
|
||||
for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%08x\n",
|
||||
i830_snapshot[i].name, (unsigned int) INREG(i830_snapshot[i].reg));
|
||||
}
|
||||
i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
|
||||
msr = INREG8(0x3cc);
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "%20.20s: 0x%02x\n",
|
||||
"MSR", (unsigned int) msr);
|
||||
|
||||
if (msr & 1)
|
||||
crt = 0x3d0;
|
||||
else
|
||||
crt = 0x3b0;
|
||||
i830DumpIndexed (pScrn, "CR", crt + 4, crt + 5, 0, 0x24);
|
||||
for (pipe = 0; pipe <= 1; pipe++)
|
||||
{
|
||||
fp = INREG(pipe == 0 ? FPA0 : FPB0);
|
||||
dpll = INREG(pipe == 0 ? DPLL_A : DPLL_B);
|
||||
switch ((dpll >> 24) & 0x3) {
|
||||
case 0:
|
||||
p2 = 10;
|
||||
break;
|
||||
case 1:
|
||||
p2 = 5;
|
||||
break;
|
||||
default:
|
||||
p2 = 1;
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p2 out of range\n");
|
||||
break;
|
||||
}
|
||||
switch ((dpll >> 16) & 0xff) {
|
||||
case 1:
|
||||
p1 = 1; break;
|
||||
case 2:
|
||||
p1 = 2; break;
|
||||
case 4:
|
||||
p1 = 3; break;
|
||||
case 8:
|
||||
p1 = 4; break;
|
||||
case 16:
|
||||
p1 = 5; break;
|
||||
case 32:
|
||||
p1 = 6; break;
|
||||
case 64:
|
||||
p1 = 7; break;
|
||||
case 128:
|
||||
p1 = 8; break;
|
||||
default:
|
||||
p1 = 1;
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "p1 out of range\n");
|
||||
break;
|
||||
}
|
||||
switch ((dpll >> 13) & 0x3) {
|
||||
case 0:
|
||||
ref = 96000;
|
||||
break;
|
||||
default:
|
||||
ref = 0;
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "ref out of range\n");
|
||||
break;
|
||||
}
|
||||
phase = (dpll >> 9) & 0xf;
|
||||
switch (phase) {
|
||||
case 6:
|
||||
break;
|
||||
default:
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "phase %d out of range\n", phase);
|
||||
break;
|
||||
}
|
||||
switch ((dpll >> 8) & 1) {
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "fp select out of range\n");
|
||||
break;
|
||||
}
|
||||
n = ((fp >> 16) & 0x3f);
|
||||
m1 = ((fp >> 8) & 0x3f);
|
||||
m2 = ((fp >> 0) & 0x3f);
|
||||
m = 5 * (m1 + 2) + (m2 + 2);
|
||||
dot = (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2);
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
|
||||
pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2);
|
||||
}
|
||||
xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "DumpRegsEnd\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
|
||||
void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn);
|
||||
void i830DumpRegs (ScrnInfoPtr pScrn);
|
||||
|
|
@ -99,31 +99,6 @@ I830DGAInit(ScreenPtr pScreen)
|
|||
|
||||
while (pMode) {
|
||||
|
||||
if(pI830->MergedFB) {
|
||||
Bool nogood = FALSE;
|
||||
/* Filter out all meta modes that would require driver-side panning */
|
||||
switch(((I830ModePrivatePtr)pMode->Private)->merged.SecondPosition) {
|
||||
case PosRightOf:
|
||||
case PosLeftOf:
|
||||
if( (((I830ModePrivatePtr)pMode->Private)->merged.First->VDisplay !=
|
||||
((I830ModePrivatePtr)pMode->Private)->merged.Second->VDisplay) ||
|
||||
(((I830ModePrivatePtr)pMode->Private)->merged.First->VDisplay != pMode->VDisplay) )
|
||||
nogood = TRUE;
|
||||
break;
|
||||
default:
|
||||
if( (((I830ModePrivatePtr)pMode->Private)->merged.First->HDisplay !=
|
||||
((I830ModePrivatePtr)pMode->Private)->merged.Second->HDisplay) ||
|
||||
(((I830ModePrivatePtr)pMode->Private)->merged.First->HDisplay != pMode->HDisplay) )
|
||||
nogood = TRUE;
|
||||
}
|
||||
if(nogood) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"DGA: MetaMode %dx%d not suitable for DGA, skipping\n",
|
||||
pMode->HDisplay, pMode->VDisplay);
|
||||
goto mode_nogood;
|
||||
}
|
||||
}
|
||||
|
||||
newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
|
||||
|
||||
if (!newmodes) {
|
||||
|
|
@ -180,7 +155,6 @@ I830DGAInit(ScreenPtr pScreen)
|
|||
currentMode->maxViewportY = currentMode->imageHeight -
|
||||
currentMode->viewportHeight;
|
||||
|
||||
mode_nogood:
|
||||
pMode = pMode->next;
|
||||
if (pMode == firstMode)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,971 @@
|
|||
/* -*- c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_bios.h"
|
||||
#include "i830_display.h"
|
||||
#include "i830_debug.h"
|
||||
#include "i830_xf86Modes.h"
|
||||
|
||||
/** Returns the pixel clock for the given refclk and divisors. */
|
||||
static int i830_clock(int refclk, int m1, int m2, int n, int p1, int p2)
|
||||
{
|
||||
return refclk * (5 * m1 + m2) / n / (p1 * p2);
|
||||
}
|
||||
|
||||
static void
|
||||
i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2)
|
||||
{
|
||||
int dotclock;
|
||||
|
||||
dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
|
||||
|
||||
ErrorF("%s: dotclock %d ((%d, %d), %d, (%d, %d))\n", prefix, dotclock,
|
||||
m1, m2, n, p1, p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether any output on the specified pipe is an LVDS output
|
||||
*/
|
||||
Bool
|
||||
i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pI830->num_outputs; i++)
|
||||
if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
|
||||
{
|
||||
if (pI830->output[i].type == type)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given set of divisors are valid for a given refclk with
|
||||
* the given outputs.
|
||||
*
|
||||
* The equation for these divisors would be:
|
||||
* clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
|
||||
*/
|
||||
static Bool
|
||||
i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
|
||||
int n, int p1, int p2)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int p, m, vco, dotclock;
|
||||
int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n;
|
||||
int min_p1, max_p1, min_p, max_p, min_vco, max_vco, min_dot, max_dot;
|
||||
|
||||
if (IS_I9XX(pI830)) {
|
||||
min_m1 = 10;
|
||||
max_m1 = 20;
|
||||
min_m2 = 5;
|
||||
max_m2 = 9;
|
||||
min_m = 70;
|
||||
max_m = 120;
|
||||
min_n = 3;
|
||||
max_n = 8;
|
||||
min_p1 = 1;
|
||||
max_p1 = 8;
|
||||
if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
|
||||
min_p = 7;
|
||||
max_p = 98;
|
||||
} else {
|
||||
min_p = 5;
|
||||
max_p = 80;
|
||||
}
|
||||
min_vco = 1400000;
|
||||
max_vco = 2800000;
|
||||
min_dot = 20000;
|
||||
max_dot = 400000;
|
||||
} else {
|
||||
min_m1 = 18;
|
||||
max_m1 = 26;
|
||||
min_m2 = 6;
|
||||
max_m2 = 16;
|
||||
min_m = 96;
|
||||
max_m = 140;
|
||||
min_n = 3;
|
||||
max_n = 16;
|
||||
min_p1 = 2;
|
||||
max_p1 = 18;
|
||||
min_vco = 930000;
|
||||
max_vco = 1400000;
|
||||
min_dot = 20000;
|
||||
max_dot = 350000;
|
||||
min_p = 4;
|
||||
max_p = 128;
|
||||
}
|
||||
|
||||
p = p1 * p2;
|
||||
m = 5 * m1 + m2;
|
||||
vco = refclk * m / n;
|
||||
dotclock = i830_clock(refclk, m1, m2, n, p1, p2);
|
||||
|
||||
if (p1 < min_p1 || p1 > max_p1)
|
||||
return FALSE;
|
||||
if (p < min_p || p > max_p)
|
||||
return FALSE;
|
||||
if (m2 < min_m2 || m2 > max_m2)
|
||||
return FALSE;
|
||||
if (m1 < min_m1 || m1 > max_m1)
|
||||
return FALSE;
|
||||
if (m1 <= m2)
|
||||
return FALSE;
|
||||
if (m < min_m || m > max_m)
|
||||
return FALSE;
|
||||
if (n < min_n || n > max_n)
|
||||
return FALSE;
|
||||
if (vco < min_vco || vco > max_vco)
|
||||
return FALSE;
|
||||
/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
|
||||
* output, etc., rather than just a single range.
|
||||
*/
|
||||
if (dotclock < min_dot || dotclock > max_dot)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of divisors for the desired target clock with the given refclk,
|
||||
* or FALSE. Divisor values are the actual divisors for
|
||||
* clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
|
||||
*/
|
||||
static Bool
|
||||
i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
|
||||
int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int m1, m2, n, p1, p2;
|
||||
int err = target;
|
||||
int min_m1, max_m1, min_m2, max_m2, min_n, max_n, min_p1, max_p1;
|
||||
|
||||
if (IS_I9XX(pI830)) {
|
||||
min_m1 = 10;
|
||||
max_m1 = 20;
|
||||
min_m2 = 5;
|
||||
max_m2 = 9;
|
||||
min_n = 3;
|
||||
max_n = 8;
|
||||
min_p1 = 1;
|
||||
max_p1 = 8;
|
||||
if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
|
||||
/* The single-channel range is 25-112Mhz, and dual-channel
|
||||
* is 80-224Mhz. Prefer single channel as much as possible.
|
||||
*/
|
||||
if (target < 112000)
|
||||
p2 = 14;
|
||||
else
|
||||
p2 = 7;
|
||||
} else {
|
||||
if (target < 200000)
|
||||
p2 = 10;
|
||||
else
|
||||
p2 = 5;
|
||||
}
|
||||
} else {
|
||||
min_m1 = 18;
|
||||
max_m1 = 26;
|
||||
min_m2 = 6;
|
||||
max_m2 = 16;
|
||||
min_n = 3;
|
||||
max_n = 16;
|
||||
min_p1 = 2;
|
||||
max_p1 = 18;
|
||||
if (target < 165000)
|
||||
p2 = 4;
|
||||
else
|
||||
p2 = 2;
|
||||
}
|
||||
|
||||
|
||||
for (m1 = min_m1; m1 <= max_m1; m1++) {
|
||||
for (m2 = min_m2; m2 < max_m2; m2++) {
|
||||
for (n = min_n; n <= max_n; n++) {
|
||||
for (p1 = min_p1; p1 <= max_p1; p1++) {
|
||||
int clock, this_err;
|
||||
|
||||
if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n,
|
||||
p1, p2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clock = i830_clock(refclk, m1, m2, n, p1, p2);
|
||||
this_err = abs(clock - target);
|
||||
if (this_err < err) {
|
||||
*outm1 = m1;
|
||||
*outm2 = m2;
|
||||
*outn = n;
|
||||
*outp1 = p1;
|
||||
*outp2 = p2;
|
||||
err = this_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (err != target);
|
||||
}
|
||||
|
||||
void
|
||||
i830WaitForVblank(ScrnInfoPtr pScreen)
|
||||
{
|
||||
/* Wait for 20ms, i.e. one cycle at 50hz. */
|
||||
usleep(20000);
|
||||
}
|
||||
|
||||
void
|
||||
i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
|
||||
unsigned long Start;
|
||||
int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
|
||||
int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
|
||||
|
||||
if (I830IsPrimary(pScrn))
|
||||
Start = pI830->FrontBuffer.Start;
|
||||
else {
|
||||
I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
|
||||
Start = pI8301->FrontBuffer2.Start;
|
||||
}
|
||||
|
||||
if (IS_I965G(pI830)) {
|
||||
OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp));
|
||||
OUTREG(dspsurf, Start);
|
||||
} else {
|
||||
OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
|
||||
}
|
||||
|
||||
pI830Pipe->x = x;
|
||||
pI830Pipe->y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the current world order, there are lists of modes per output, which may
|
||||
* or may not include the mode that was asked to be set by XFree86's mode
|
||||
* selection. Find the closest one, in the following preference order:
|
||||
*
|
||||
* - Equality
|
||||
* - Closer in size to the requested mode, but no larger
|
||||
* - Closer in refresh rate to the requested mode.
|
||||
*/
|
||||
DisplayModePtr
|
||||
i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
DisplayModePtr pBest = NULL, pScan = NULL;
|
||||
int i;
|
||||
|
||||
/* Assume that there's only one output connected to the given CRTC. */
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
if (pI830->output[i].pipe == pipe &&
|
||||
pI830->output[i].enabled &&
|
||||
pI830->output[i].probed_modes != NULL)
|
||||
{
|
||||
pScan = pI830->output[i].probed_modes;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the pipe doesn't have any detected modes, just let the system try to
|
||||
* spam the desired mode in.
|
||||
*/
|
||||
if (pScan == NULL) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"No pipe mode list for pipe %d,"
|
||||
"continuing with desired mode\n", pipe);
|
||||
return pMode;
|
||||
}
|
||||
|
||||
for (; pScan != NULL; pScan = pScan->next) {
|
||||
assert(pScan->VRefresh != 0.0);
|
||||
|
||||
/* If there's an exact match, we're done. */
|
||||
if (I830ModesEqual(pScan, pMode)) {
|
||||
pBest = pMode;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reject if it's larger than the desired mode. */
|
||||
if (pScan->HDisplay > pMode->HDisplay ||
|
||||
pScan->VDisplay > pMode->VDisplay)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pBest == NULL) {
|
||||
pBest = pScan;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find if it's closer to the right size than the current best
|
||||
* option.
|
||||
*/
|
||||
if ((pScan->HDisplay > pBest->HDisplay &&
|
||||
pScan->VDisplay >= pBest->VDisplay) ||
|
||||
(pScan->HDisplay >= pBest->HDisplay &&
|
||||
pScan->VDisplay > pBest->VDisplay))
|
||||
{
|
||||
pBest = pScan;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find if it's still closer to the right refresh than the current
|
||||
* best resolution.
|
||||
*/
|
||||
if (pScan->HDisplay == pBest->HDisplay &&
|
||||
pScan->VDisplay == pBest->VDisplay &&
|
||||
(fabs(pScan->VRefresh - pMode->VRefresh) <
|
||||
fabs(pBest->VRefresh - pMode->VRefresh))) {
|
||||
pBest = pScan;
|
||||
}
|
||||
}
|
||||
|
||||
if (pBest == NULL) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"No suitable mode found to program for the pipe.\n"
|
||||
" continuing with desired mode %dx%d@%.1f\n",
|
||||
pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
|
||||
} else if (!I830ModesEqual(pBest, pMode)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
|
||||
"mode %dx%d@%.1f\n", pipe,
|
||||
pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
|
||||
pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
|
||||
pMode = pBest;
|
||||
}
|
||||
return pMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether any outputs are connected to the specified pipe
|
||||
*/
|
||||
|
||||
Bool
|
||||
i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pI830->num_outputs; i++)
|
||||
if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given video mode on the given pipe.
|
||||
*
|
||||
* Plane A is always output to pipe A, and plane B to pipe B. The plane
|
||||
* will not be enabled if plane_enable is FALSE, which is used for
|
||||
* load detection, when something else will be output to the pipe other than
|
||||
* display data.
|
||||
*/
|
||||
Bool
|
||||
i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
|
||||
Bool plane_enable)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
|
||||
int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
|
||||
CARD32 dpll = 0, fp = 0, temp;
|
||||
CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
|
||||
CARD32 pipesrc, dspsize;
|
||||
Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
|
||||
Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
|
||||
int refclk, pixel_clock;
|
||||
int i;
|
||||
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int fp_reg = (pipe == 0) ? FPA0 : FPB0;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
|
||||
int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
|
||||
int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
|
||||
int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
|
||||
int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
|
||||
int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
|
||||
int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
|
||||
int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
|
||||
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
|
||||
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
|
||||
Bool ret = FALSE;
|
||||
#ifdef XF86DRI
|
||||
Bool didLock = FALSE;
|
||||
#endif
|
||||
|
||||
if (I830ModesEqual(&pI830Pipe->curMode, pMode))
|
||||
return TRUE;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
|
||||
pMode->Clock);
|
||||
|
||||
pI830->pipes[pipe].enabled = i830PipeInUse (pScrn, pipe);
|
||||
|
||||
if (!pI830->pipes[pipe].enabled)
|
||||
return TRUE;
|
||||
|
||||
#ifdef XF86DRI
|
||||
didLock = I830DRILock(pScrn);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled)
|
||||
continue;
|
||||
|
||||
pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
|
||||
|
||||
switch (pI830->output[i].type) {
|
||||
case I830_OUTPUT_LVDS:
|
||||
is_lvds = TRUE;
|
||||
break;
|
||||
case I830_OUTPUT_SDVO:
|
||||
is_sdvo = TRUE;
|
||||
break;
|
||||
case I830_OUTPUT_DVO:
|
||||
is_dvo = TRUE;
|
||||
break;
|
||||
case I830_OUTPUT_TVOUT:
|
||||
is_tv = TRUE;
|
||||
break;
|
||||
case I830_OUTPUT_ANALOG:
|
||||
is_crt = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_lvds && (is_sdvo || is_dvo || is_tv || is_crt)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't enable LVDS and non-LVDS on the same pipe\n");
|
||||
goto done;
|
||||
}
|
||||
if (is_tv && (is_sdvo || is_dvo || is_crt || is_lvds)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't enable a TV and any other output on the same "
|
||||
"pipe\n");
|
||||
goto done;
|
||||
}
|
||||
if (pipe == 0 && is_lvds) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Can't support LVDS on pipe A\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
|
||||
hblank = (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16);
|
||||
hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16);
|
||||
vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16);
|
||||
vblank = (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16);
|
||||
vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16);
|
||||
pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1);
|
||||
dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1);
|
||||
pixel_clock = pMode->Clock;
|
||||
|
||||
if (is_lvds && pI830->panel_fixed_hactive != 0) {
|
||||
/* To enable panel fitting, we need to set the pipe timings to that of
|
||||
* the screen at its full resolution. So, drop the timings from the
|
||||
* BIOS VBT tables here.
|
||||
*/
|
||||
htot = (pI830->panel_fixed_hactive - 1) |
|
||||
((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
|
||||
<< 16);
|
||||
hblank = (pI830->panel_fixed_hactive - 1) |
|
||||
((pI830->panel_fixed_hactive + pI830->panel_fixed_hblank - 1)
|
||||
<< 16);
|
||||
hsync = (pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff - 1) |
|
||||
((pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff +
|
||||
pI830->panel_fixed_hsyncwidth - 1) << 16);
|
||||
|
||||
vtot = (pI830->panel_fixed_vactive - 1) |
|
||||
((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
|
||||
<< 16);
|
||||
vblank = (pI830->panel_fixed_vactive - 1) |
|
||||
((pI830->panel_fixed_vactive + pI830->panel_fixed_vblank - 1)
|
||||
<< 16);
|
||||
vsync = (pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff - 1) |
|
||||
((pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff +
|
||||
pI830->panel_fixed_vsyncwidth - 1) << 16);
|
||||
pixel_clock = pI830->panel_fixed_clock;
|
||||
|
||||
if (pMode->HDisplay <= pI830->panel_fixed_hactive &&
|
||||
pMode->HDisplay <= pI830->panel_fixed_vactive)
|
||||
{
|
||||
pipesrc = ((pMode->HDisplay - 1) << 16) |
|
||||
(pMode->VDisplay - 1);
|
||||
dspsize = ((pMode->VDisplay - 1) << 16) |
|
||||
(pMode->HDisplay - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the clock for pixel multiplication.
|
||||
* See DPLL_MD_UDI_MULTIPLIER_MASK.
|
||||
*/
|
||||
if (is_sdvo) {
|
||||
pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode);
|
||||
}
|
||||
|
||||
if (IS_I9XX(pI830)) {
|
||||
refclk = 96000;
|
||||
} else {
|
||||
refclk = 48000;
|
||||
}
|
||||
ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n,
|
||||
&p1, &p2);
|
||||
if (!ok) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Couldn't find PLL settings for mode!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS;
|
||||
if (IS_I9XX(pI830)) {
|
||||
if (is_lvds)
|
||||
dpll |= DPLLB_MODE_LVDS;
|
||||
else
|
||||
dpll |= DPLLB_MODE_DAC_SERIAL;
|
||||
dpll |= (1 << (p1 - 1)) << 16;
|
||||
switch (p2) {
|
||||
case 5:
|
||||
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
|
||||
break;
|
||||
case 7:
|
||||
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
|
||||
break;
|
||||
case 10:
|
||||
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
|
||||
break;
|
||||
case 14:
|
||||
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
|
||||
break;
|
||||
}
|
||||
if (IS_I965G(pI830))
|
||||
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
|
||||
} else {
|
||||
dpll |= (p1 - 2) << 16;
|
||||
if (p2 == 4)
|
||||
dpll |= PLL_P2_DIVIDE_BY_4;
|
||||
}
|
||||
|
||||
if (is_tv)
|
||||
dpll |= PLL_REF_INPUT_TVCLKINBC;
|
||||
#if 0
|
||||
else if (is_lvds)
|
||||
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
||||
#endif
|
||||
else
|
||||
dpll |= PLL_REF_INPUT_DREFCLK;
|
||||
|
||||
fp = ((n - 2) << 16) | ((m1 - 2) << 8) | (m2 - 2);
|
||||
|
||||
#if 1
|
||||
ErrorF("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n",
|
||||
(int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1,
|
||||
(int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1,
|
||||
(int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1);
|
||||
ErrorF("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n",
|
||||
(int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1,
|
||||
(int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1,
|
||||
(int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1);
|
||||
ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n",
|
||||
(int)(pipesrc >> 16) + 1, (int)(pipesrc & 0xffff) + 1,
|
||||
(int)(dspsize & 0xffff) + 1, (int)(dspsize >> 16) + 1);
|
||||
#endif
|
||||
|
||||
i830PrintPll("chosen", refclk, m1, m2, n, p1, p2);
|
||||
ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
|
||||
|
||||
dspcntr = DISPLAY_PLANE_ENABLE;
|
||||
switch (pScrn->bitsPerPixel) {
|
||||
case 8:
|
||||
dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
|
||||
break;
|
||||
case 16:
|
||||
if (pScrn->depth == 15)
|
||||
dspcntr |= DISPPLANE_15_16BPP;
|
||||
else
|
||||
dspcntr |= DISPPLANE_16BPP;
|
||||
break;
|
||||
case 32:
|
||||
dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
|
||||
break;
|
||||
default:
|
||||
FatalError("unknown display bpp\n");
|
||||
}
|
||||
|
||||
if (pI830Pipe->gammaEnabled) {
|
||||
dspcntr |= DISPPLANE_GAMMA_ENABLE;
|
||||
}
|
||||
|
||||
if (pipe == 0)
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_A;
|
||||
else
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
|
||||
OUTREG(VGACNTRL, VGA_DISP_DISABLE);
|
||||
|
||||
/* Finally, set the mode. */
|
||||
/* First, disable display planes */
|
||||
temp = INREG(dspcntr_reg);
|
||||
OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
/* Next, disable display pipes */
|
||||
temp = INREG(pipeconf_reg);
|
||||
OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
|
||||
|
||||
OUTREG(fp_reg, fp);
|
||||
OUTREG(dpll_reg, dpll);
|
||||
|
||||
/*
|
||||
* If the panel fitter is stuck on our pipe, turn it off.
|
||||
* The LVDS output will set it as necessary in post_set_mode.
|
||||
*/
|
||||
if (!IS_I830(pI830)) {
|
||||
if (((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
|
||||
OUTREG(PFIT_CONTROL, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
if (pI830->output[i].pipe == pipe)
|
||||
pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode);
|
||||
}
|
||||
|
||||
OUTREG(htot_reg, htot);
|
||||
OUTREG(hblank_reg, hblank);
|
||||
OUTREG(hsync_reg, hsync);
|
||||
OUTREG(vtot_reg, vtot);
|
||||
OUTREG(vblank_reg, vblank);
|
||||
OUTREG(vsync_reg, vsync);
|
||||
OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
|
||||
OUTREG(dspsize_reg, dspsize);
|
||||
OUTREG(dsppos_reg, 0);
|
||||
i830PipeSetBase(pScrn, pipe, pI830Pipe->x, pI830Pipe->y);
|
||||
OUTREG(pipesrc_reg, pipesrc);
|
||||
|
||||
/* Then, turn the pipe on first */
|
||||
temp = INREG(pipeconf_reg);
|
||||
OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
|
||||
|
||||
if (plane_enable) {
|
||||
/* And then turn the plane on */
|
||||
OUTREG(dspcntr_reg, dspcntr);
|
||||
}
|
||||
|
||||
pI830Pipe->curMode = *pMode;
|
||||
|
||||
ret = TRUE;
|
||||
done:
|
||||
#ifdef XF86DRI
|
||||
if (didLock)
|
||||
I830DRIUnlock(pScrn);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int output, pipe;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
|
||||
|
||||
for (output = 0; output < pI830->num_outputs; output++) {
|
||||
if (!pI830->output[output].enabled)
|
||||
pI830->output[output].dpms(pScrn, &pI830->output[output], DPMSModeOff);
|
||||
}
|
||||
|
||||
/* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915
|
||||
* internal TV) should have no outputs trying to pull data out of it, so
|
||||
* we're ready to turn those off.
|
||||
*/
|
||||
for (pipe = 0; pipe < pI830->num_pipes; pipe++) {
|
||||
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
|
||||
int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
|
||||
int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
|
||||
int dpll_reg = pipe == 0 ? DPLL_A : DPLL_B;
|
||||
CARD32 dspcntr, pipeconf, dpll;
|
||||
char *pipe_name = pipe == 0 ? "A" : "B";
|
||||
|
||||
if (pI830Pipe->enabled)
|
||||
continue;
|
||||
|
||||
dspcntr = INREG(dspcntr_reg);
|
||||
if (dspcntr & DISPLAY_PLANE_ENABLE) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling plane %s\n",
|
||||
pipe_name);
|
||||
|
||||
OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
|
||||
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
i830WaitForVblank(pScrn);
|
||||
}
|
||||
|
||||
pipeconf = INREG(pipeconf_reg);
|
||||
if (pipeconf & PIPEACONF_ENABLE) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling pipe %s\n",
|
||||
pipe_name);
|
||||
OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
|
||||
}
|
||||
|
||||
dpll = INREG(dpll_reg);
|
||||
if (dpll & DPLL_VCO_ENABLE) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DPLL %s\n",
|
||||
pipe_name);
|
||||
OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
|
||||
}
|
||||
|
||||
memset(&pI830Pipe->curMode, 0, sizeof(pI830Pipe->curMode));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function configures the screens in clone mode on
|
||||
* all active outputs using a mode similar to the specified mode.
|
||||
*/
|
||||
Bool
|
||||
i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
Bool ok = TRUE;
|
||||
int i;
|
||||
|
||||
DPRINTF(PFX, "i830SetMode\n");
|
||||
|
||||
for (i = 0; i < pI830->num_pipes; i++)
|
||||
{
|
||||
ok = i830PipeSetMode(pScrn,
|
||||
i830PipeFindClosestMode(pScrn, i, pMode),
|
||||
i, TRUE);
|
||||
if (!ok)
|
||||
goto done;
|
||||
}
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
|
||||
(int)(pMode->HDisplay * pMode->VDisplay *
|
||||
pMode->VRefresh / 1000000));
|
||||
|
||||
if (pI830->savedCurrentMode) {
|
||||
/* We're done with the currentMode that the last randr probe had left
|
||||
* behind, so free it.
|
||||
*/
|
||||
xfree(pI830->savedCurrentMode->name);
|
||||
xfree(pI830->savedCurrentMode);
|
||||
pI830->savedCurrentMode = NULL;
|
||||
|
||||
/* If we might have enabled/disabled some pipes, we need to reset
|
||||
* cloning mode support.
|
||||
*/
|
||||
if (pI830->pipes[0].enabled && pI830->pipes[1].enabled)
|
||||
pI830->Clone = TRUE;
|
||||
else
|
||||
pI830->Clone = FALSE;
|
||||
|
||||
/* If HW cursor currently showing, reset cursor state */
|
||||
if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn)
|
||||
pI830->CursorInfoRec->ShowCursor(pScrn);
|
||||
}
|
||||
|
||||
i830DisableUnusedFunctions(pScrn);
|
||||
|
||||
i830DescribeOutputConfiguration(pScrn);
|
||||
|
||||
#ifdef XF86DRI
|
||||
I830DRISetVBlankInterrupt (pScrn, TRUE);
|
||||
#endif
|
||||
done:
|
||||
i830DumpRegs (pScrn);
|
||||
i830_sdvo_dump(pScrn);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
|
||||
|
||||
for (i = 0; i < pI830->num_pipes; i++) {
|
||||
CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
|
||||
CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
|
||||
Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
|
||||
Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
" Pipe %c is %s\n",
|
||||
'A' + i, pI830->pipes[i].enabled ? "on" : "off");
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
" Display plane %c is now %s and connected to pipe %c.\n",
|
||||
'A' + i,
|
||||
pI830->pipes[i].enabled ? "enabled" : "disabled",
|
||||
dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
|
||||
if (hw_pipe_enable != pI830->pipes[i].enabled) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
" Hardware claims pipe %c is %s while software "
|
||||
"believes it is %s\n",
|
||||
'A' + i, hw_pipe_enable ? "on" : "off",
|
||||
pI830->pipes[i].enabled ? "on" : "off");
|
||||
}
|
||||
if (hw_plane_enable != pI830->pipes[i].enabled) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
" Hardware claims plane %c is %s while software "
|
||||
"believes it is %s\n",
|
||||
'A' + i, hw_plane_enable ? "on" : "off",
|
||||
pI830->pipes[i].enabled ? "on" : "off");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
const char *name = NULL;
|
||||
|
||||
switch (pI830->output[i].type) {
|
||||
case I830_OUTPUT_ANALOG:
|
||||
name = "CRT";
|
||||
break;
|
||||
case I830_OUTPUT_LVDS:
|
||||
name = "LVDS";
|
||||
break;
|
||||
case I830_OUTPUT_SDVO:
|
||||
name = "SDVO";
|
||||
break;
|
||||
case I830_OUTPUT_DVO:
|
||||
name = "DVO";
|
||||
break;
|
||||
case I830_OUTPUT_TVOUT:
|
||||
name = "TV";
|
||||
break;
|
||||
}
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
" Output %s is %sabled and connected to pipe %c\n",
|
||||
name, pI830->output[i].enabled ? "en" : "dis",
|
||||
pI830->output[i].pipe == 0 ? 'A' : 'B');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a pipe with a simple mode set on it for doing load-based monitor
|
||||
* detection.
|
||||
*
|
||||
* It will be up to the load-detect code to adjust the pipe as appropriate for
|
||||
* its requirements. The pipe will be connected to no other outputs.
|
||||
*
|
||||
* Currently this code will only succeed if there is a pipe with no outputs
|
||||
* configured for it. In the future, it could choose to temporarily disable
|
||||
* some outputs to free up a pipe for its use.
|
||||
*
|
||||
* \return monitor number, or -1 if no pipes are available.
|
||||
*/
|
||||
int
|
||||
i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int i;
|
||||
/* VESA 640x480x72Hz mode to set on the pipe */
|
||||
DisplayModeRec mode = {
|
||||
NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
|
||||
31500,
|
||||
640, 664, 704, 832, 0,
|
||||
480, 489, 491, 520, 0,
|
||||
V_NHSYNC | V_NVSYNC,
|
||||
0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
|
||||
};
|
||||
|
||||
/* If the output is not marked disabled, check if it's already assigned
|
||||
* to an active pipe, and is alone on that pipe. If so, we're done.
|
||||
*/
|
||||
if (output->enabled) {
|
||||
int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
|
||||
if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) {
|
||||
/* Actually, maybe we don't need to be all alone on the pipe.
|
||||
* The worst that should happen is false positives. Need to test,
|
||||
* but actually fixing this during server startup is messy.
|
||||
*/
|
||||
#if 0
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
if (&pI830->output[i] != output &&
|
||||
pI830->output[i].pipe == output->pipe)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return output->pipe;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pI830->num_pipes; i++)
|
||||
if (!i830PipeInUse(pScrn, i))
|
||||
break;
|
||||
|
||||
if (i == pI830->num_pipes)
|
||||
return -1;
|
||||
|
||||
output->load_detect_temp = TRUE;
|
||||
output->pipe = i;
|
||||
output->enabled = TRUE;
|
||||
|
||||
I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
|
||||
|
||||
i830PipeSetMode(pScrn, &mode, i, FALSE);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
if (output->load_detect_temp) {
|
||||
output->enabled = FALSE;
|
||||
i830DisableUnusedFunctions(pScrn);
|
||||
output->load_detect_temp = FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/* i830_display.c */
|
||||
DisplayModePtr
|
||||
i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode);
|
||||
Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
|
||||
Bool plane_enable);
|
||||
void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
|
||||
Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
|
||||
void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
|
||||
void i830WaitForVblank(ScrnInfoPtr pScrn);
|
||||
void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
|
||||
int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe);
|
||||
|
|
@ -1513,11 +1513,12 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on)
|
|||
|
||||
if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
|
||||
if (on) {
|
||||
if (pI830->planeEnabled[1]) {
|
||||
if (pI830->pipes[1].enabled) {
|
||||
if (pI830->drmMinor >= 6)
|
||||
pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B;
|
||||
else
|
||||
pipe.pipe = DRM_I830_VBLANK_PIPE_B;
|
||||
pipe.pipe = DRM_I830_VBLANK_PIPE_B;
|
||||
} else
|
||||
pipe.pipe = DRM_I830_VBLANK_PIPE_A;
|
||||
} else {
|
||||
|
|
|
|||
6398
src/i830_driver.c
6398
src/i830_driver.c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,236 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
******
|
||||
********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i810_reg.h"
|
||||
|
||||
#include "sil164/sil164.h"
|
||||
#include "ch7xxx/ch7xxx.h"
|
||||
|
||||
static const char *SIL164Symbols[] = {
|
||||
"Sil164VidOutput",
|
||||
NULL
|
||||
};
|
||||
static const char *CH7xxxSymbols[] = {
|
||||
"CH7xxxVidOutput",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* driver list */
|
||||
struct _I830DVODriver i830_dvo_drivers[] =
|
||||
{
|
||||
{ I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
|
||||
(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
|
||||
{ I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
|
||||
(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
|
||||
};
|
||||
|
||||
#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
|
||||
|
||||
static void
|
||||
i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
|
||||
{
|
||||
if (mode == DPMSModeOn)
|
||||
output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE);
|
||||
else
|
||||
output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
/* Each output should probably just save the registers it touches, but for
|
||||
* now, use more overkill.
|
||||
*/
|
||||
pI830->saveDVOA = INREG(DVOA);
|
||||
pI830->saveDVOB = INREG(DVOB);
|
||||
pI830->saveDVOC = INREG(DVOC);
|
||||
|
||||
output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
OUTREG(DVOA, pI830->saveDVOA);
|
||||
OUTREG(DVOB, pI830->saveDVOB);
|
||||
OUTREG(DVOC, pI830->saveDVOC);
|
||||
|
||||
output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
|
||||
}
|
||||
|
||||
static int
|
||||
i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
if (pMode->Flags & V_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
/* XXX: Validate clock range */
|
||||
|
||||
if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode))
|
||||
return MODE_OK;
|
||||
else
|
||||
return MODE_BAD;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode);
|
||||
|
||||
OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 dvo;
|
||||
int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
|
||||
|
||||
/* Save the data order, since I don't know what it should be set to. */
|
||||
dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
|
||||
dvo |= DVO_ENABLE;
|
||||
dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
|
||||
|
||||
if (output->pipe == 1)
|
||||
dvo |= DVO_PIPE_B_SELECT;
|
||||
|
||||
if (pMode->Flags & V_PHSYNC)
|
||||
dvo |= DVO_HSYNC_ACTIVE_HIGH;
|
||||
if (pMode->Flags & V_PVSYNC)
|
||||
dvo |= DVO_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED);
|
||||
|
||||
/*OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
|
||||
OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
|
||||
/*OUTREG(DVOB, dvo);*/
|
||||
OUTREG(DVOC, dvo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the output connection on our DVO device.
|
||||
*
|
||||
* Unimplemented.
|
||||
*/
|
||||
static enum detect_status
|
||||
i830_dvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
return OUTPUT_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
|
||||
struct _I830DVODriver **retdrv)
|
||||
{
|
||||
int i;
|
||||
void *ret_ptr;
|
||||
struct _I830DVODriver *drv;
|
||||
|
||||
for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
|
||||
drv = &i830_dvo_drivers[i];
|
||||
drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
|
||||
if (drv->modhandle == NULL)
|
||||
continue;
|
||||
|
||||
xf86LoaderReqSymLists(drv->symbols, NULL);
|
||||
|
||||
ret_ptr = NULL;
|
||||
drv->vid_rec = LoaderSymbol(drv->fntablename);
|
||||
if (drv->vid_rec != NULL)
|
||||
ret_ptr = drv->vid_rec->Detect(pI2CBus, drv->address);
|
||||
|
||||
if (ret_ptr != NULL) {
|
||||
drv->dev_priv = ret_ptr;
|
||||
*retdrv = drv;
|
||||
return TRUE;
|
||||
}
|
||||
xf86UnloadSubModule(drv->modhandle);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
i830_dvo_init(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
Bool ret;
|
||||
int i = pI830->num_outputs;
|
||||
|
||||
pI830->output[i].type = I830_OUTPUT_DVO;
|
||||
pI830->output[i].dpms = i830_dvo_dpms;
|
||||
pI830->output[i].save = i830_dvo_save;
|
||||
pI830->output[i].restore = i830_dvo_restore;
|
||||
pI830->output[i].mode_valid = i830_dvo_mode_valid;
|
||||
pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode;
|
||||
pI830->output[i].post_set_mode = i830_dvo_post_set_mode;
|
||||
pI830->output[i].detect = i830_dvo_detect;
|
||||
pI830->output[i].get_modes = i830_ddc_get_modes;
|
||||
|
||||
/* Set up the I2C and DDC buses */
|
||||
ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
ret = I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
|
||||
if (!ret) {
|
||||
xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now, try to find a controller */
|
||||
ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
|
||||
&pI830->output[i].i2c_drv);
|
||||
if (ret) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
|
||||
pI830->output[i].i2c_drv->modulename,
|
||||
pI830->output[i].pI2CBus->DriverPrivate.uval);
|
||||
} else {
|
||||
xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
|
||||
xf86DestroyI2CBusRec(pI830->output[i].pDDCBus, TRUE, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
pI830->num_outputs++;
|
||||
}
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
#define DEBUG_VERB 2
|
||||
/*
|
||||
* Copyright © 2002 David Dawes
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of the author(s) shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or other
|
||||
* dealings in this Software without prior written authorization from
|
||||
* the author(s).
|
||||
*
|
||||
* Authors: David Dawes <dawes@xfree86.org>
|
||||
*
|
||||
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $
|
||||
*/
|
||||
/*
|
||||
* Modified by Alan Hourihane <alanh@tungstengraphics.com>
|
||||
* to support extended BIOS modes for the Intel chipsets
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xf86.h"
|
||||
#include "vbe.h"
|
||||
#include "vbeModes.h"
|
||||
#include "i830.h"
|
||||
#include "i830_xf86Modes.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define rint(x) floor(x)
|
||||
|
||||
#define MARGIN_PERCENT 1.8 /* % of active vertical image */
|
||||
#define CELL_GRAN 8.0 /* assumed character cell granularity */
|
||||
#define MIN_PORCH 1 /* minimum front porch */
|
||||
#define V_SYNC_RQD 3 /* width of vsync in lines */
|
||||
#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */
|
||||
#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
|
||||
#define M 600.0 /* blanking formula gradient */
|
||||
#define C 40.0 /* blanking formula offset */
|
||||
#define K 128.0 /* blanking formula scaling factor */
|
||||
#define J 20.0 /* blanking formula scaling factor */
|
||||
|
||||
/* C' and M' are part of the Blanking Duty Cycle computation */
|
||||
|
||||
#define C_PRIME (((C - J) * K/256.0) + J)
|
||||
#define M_PRIME (K/256.0 * M)
|
||||
|
||||
DisplayModePtr
|
||||
i830GetGTF(int h_pixels, int v_lines, float freq, int interlaced, int margins)
|
||||
{
|
||||
float h_pixels_rnd;
|
||||
float v_lines_rnd;
|
||||
float v_field_rate_rqd;
|
||||
float top_margin;
|
||||
float bottom_margin;
|
||||
float interlace;
|
||||
float h_period_est;
|
||||
float vsync_plus_bp;
|
||||
float v_back_porch;
|
||||
float total_v_lines;
|
||||
float v_field_rate_est;
|
||||
float h_period;
|
||||
float v_field_rate;
|
||||
float v_frame_rate;
|
||||
float left_margin;
|
||||
float right_margin;
|
||||
float total_active_pixels;
|
||||
float ideal_duty_cycle;
|
||||
float h_blank;
|
||||
float total_pixels;
|
||||
float pixel_freq;
|
||||
float h_freq;
|
||||
|
||||
float h_sync;
|
||||
float h_front_porch;
|
||||
float v_odd_front_porch_lines;
|
||||
DisplayModePtr m;
|
||||
|
||||
m = xnfcalloc(sizeof(DisplayModeRec), 1);
|
||||
|
||||
|
||||
/* 1. In order to give correct results, the number of horizontal
|
||||
* pixels requested is first processed to ensure that it is divisible
|
||||
* by the character size, by rounding it to the nearest character
|
||||
* cell boundary:
|
||||
*
|
||||
* [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
|
||||
*/
|
||||
|
||||
h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
|
||||
|
||||
|
||||
/* 2. If interlace is requested, the number of vertical lines assumed
|
||||
* by the calculation must be halved, as the computation calculates
|
||||
* the number of vertical lines per field. In either case, the
|
||||
* number of lines is rounded to the nearest integer.
|
||||
*
|
||||
* [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
|
||||
* ROUND([V LINES],0))
|
||||
*/
|
||||
|
||||
v_lines_rnd = interlaced ?
|
||||
rint((float) v_lines) / 2.0 :
|
||||
rint((float) v_lines);
|
||||
|
||||
/* 3. Find the frame rate required:
|
||||
*
|
||||
* [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
|
||||
* [I/P FREQ RQD])
|
||||
*/
|
||||
|
||||
v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
|
||||
|
||||
/* 4. Find number of lines in Top margin:
|
||||
*
|
||||
* [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
|
||||
* ROUND(([MARGIN%]/100*[V LINES RND]),0),
|
||||
* 0)
|
||||
*/
|
||||
|
||||
top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
|
||||
|
||||
/* 5. Find number of lines in Bottom margin:
|
||||
*
|
||||
* [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
|
||||
* ROUND(([MARGIN%]/100*[V LINES RND]),0),
|
||||
* 0)
|
||||
*/
|
||||
|
||||
bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
|
||||
|
||||
/* 6. If interlace is required, then set variable [INTERLACE]=0.5:
|
||||
*
|
||||
* [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
|
||||
*/
|
||||
|
||||
interlace = interlaced ? 0.5 : 0.0;
|
||||
|
||||
/* 7. Estimate the Horizontal period
|
||||
*
|
||||
* [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
|
||||
* ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
|
||||
* [MIN PORCH RND]+[INTERLACE]) * 1000000
|
||||
*/
|
||||
|
||||
h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
|
||||
/ (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
|
||||
* 1000000.0);
|
||||
|
||||
/* 8. Find the number of lines in V sync + back porch:
|
||||
*
|
||||
* [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
|
||||
*/
|
||||
|
||||
vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
|
||||
|
||||
/* 9. Find the number of lines in V back porch alone:
|
||||
*
|
||||
* [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
|
||||
*
|
||||
* XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
|
||||
*/
|
||||
|
||||
v_back_porch = vsync_plus_bp - V_SYNC_RQD;
|
||||
|
||||
/* 10. Find the total number of lines in Vertical field period:
|
||||
*
|
||||
* [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
|
||||
* [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
|
||||
* [MIN PORCH RND]
|
||||
*/
|
||||
|
||||
total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
|
||||
interlace + MIN_PORCH;
|
||||
|
||||
/* 11. Estimate the Vertical field frequency:
|
||||
*
|
||||
* [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
|
||||
*/
|
||||
|
||||
v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
|
||||
|
||||
/* 12. Find the actual horizontal period:
|
||||
*
|
||||
* [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
|
||||
*/
|
||||
|
||||
h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
|
||||
|
||||
/* 13. Find the actual Vertical field frequency:
|
||||
*
|
||||
* [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
|
||||
*/
|
||||
|
||||
v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
|
||||
|
||||
/* 14. Find the Vertical frame frequency:
|
||||
*
|
||||
* [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
|
||||
*/
|
||||
|
||||
v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
|
||||
|
||||
/* 15. Find number of pixels in left margin:
|
||||
*
|
||||
* [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
|
||||
* (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
|
||||
* [CELL GRAN RND]),0)) * [CELL GRAN RND],
|
||||
* 0))
|
||||
*/
|
||||
|
||||
left_margin = margins ?
|
||||
rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
|
||||
0.0;
|
||||
|
||||
/* 16. Find number of pixels in right margin:
|
||||
*
|
||||
* [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
|
||||
* (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
|
||||
* [CELL GRAN RND]),0)) * [CELL GRAN RND],
|
||||
* 0))
|
||||
*/
|
||||
|
||||
right_margin = margins ?
|
||||
rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
|
||||
0.0;
|
||||
|
||||
/* 17. Find total number of active pixels in image and left and right
|
||||
* margins:
|
||||
*
|
||||
* [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
|
||||
* [RIGHT MARGIN (PIXELS)]
|
||||
*/
|
||||
|
||||
total_active_pixels = h_pixels_rnd + left_margin + right_margin;
|
||||
|
||||
/* 18. Find the ideal blanking duty cycle from the blanking duty cycle
|
||||
* equation:
|
||||
*
|
||||
* [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
|
||||
*/
|
||||
|
||||
ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
|
||||
|
||||
/* 19. Find the number of pixels in the blanking time to the nearest
|
||||
* double character cell:
|
||||
*
|
||||
* [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
|
||||
* [IDEAL DUTY CYCLE] /
|
||||
* (100-[IDEAL DUTY CYCLE]) /
|
||||
* (2*[CELL GRAN RND])), 0))
|
||||
* * (2*[CELL GRAN RND])
|
||||
*/
|
||||
|
||||
h_blank = rint(total_active_pixels *
|
||||
ideal_duty_cycle /
|
||||
(100.0 - ideal_duty_cycle) /
|
||||
(2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
|
||||
|
||||
/* 20. Find total number of pixels:
|
||||
*
|
||||
* [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
|
||||
*/
|
||||
|
||||
total_pixels = total_active_pixels + h_blank;
|
||||
|
||||
/* 21. Find pixel clock frequency:
|
||||
*
|
||||
* [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
|
||||
*/
|
||||
|
||||
pixel_freq = total_pixels / h_period;
|
||||
|
||||
/* 22. Find horizontal frequency:
|
||||
*
|
||||
* [H FREQ] = 1000 / [H PERIOD]
|
||||
*/
|
||||
|
||||
h_freq = 1000.0 / h_period;
|
||||
|
||||
|
||||
/* Stage 1 computations are now complete; I should really pass
|
||||
the results to another function and do the Stage 2
|
||||
computations, but I only need a few more values so I'll just
|
||||
append the computations here for now */
|
||||
|
||||
|
||||
|
||||
/* 17. Find the number of pixels in the horizontal sync period:
|
||||
*
|
||||
* [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
|
||||
* [CELL GRAN RND]),0))*[CELL GRAN RND]
|
||||
*/
|
||||
|
||||
h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
|
||||
|
||||
/* 18. Find the number of pixels in the horizontal front porch period:
|
||||
*
|
||||
* [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
|
||||
*/
|
||||
|
||||
h_front_porch = (h_blank / 2.0) - h_sync;
|
||||
|
||||
/* 36. Find the number of lines in the odd front porch period:
|
||||
*
|
||||
* [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
|
||||
*/
|
||||
|
||||
v_odd_front_porch_lines = MIN_PORCH + interlace;
|
||||
|
||||
/* finally, pack the results in the DisplayMode struct */
|
||||
|
||||
m->HDisplay = (int) (h_pixels_rnd);
|
||||
m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
|
||||
m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
|
||||
m->HTotal = (int) (total_pixels);
|
||||
|
||||
m->VDisplay = (int) (v_lines_rnd);
|
||||
m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
|
||||
m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
|
||||
m->VTotal = (int) (total_v_lines);
|
||||
|
||||
m->Clock = (int)(pixel_freq * 1000);
|
||||
m->SynthClock = m->Clock;
|
||||
m->HSync = h_freq;
|
||||
m->VRefresh = v_frame_rate /* freq */;
|
||||
|
||||
i830xf86SetModeDefaultName(m);
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "xf86_OSproc.h"
|
||||
#include "xf86Resources.h"
|
||||
#include "xf86RAC.h"
|
||||
#include "xf86cmap.h"
|
||||
#include "compiler.h"
|
||||
#include "mibstore.h"
|
||||
#include "vgaHW.h"
|
||||
#include "mipointer.h"
|
||||
#include "micmap.h"
|
||||
#include "shadowfb.h"
|
||||
#include <X11/extensions/randr.h>
|
||||
#include "fb.h"
|
||||
#include "miscstruct.h"
|
||||
#include "xf86xv.h"
|
||||
#include <X11/extensions/Xv.h>
|
||||
#include "shadow.h"
|
||||
#include "i830.h"
|
||||
|
||||
#define AIRLIED_I2C 0
|
||||
|
||||
#if AIRLIED_I2C
|
||||
|
||||
#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */
|
||||
#define I2C_TRACE(x) /*(x)*/ /* Report progress */
|
||||
|
||||
static void i830_setscl(I2CBusPtr b, int state)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 val;
|
||||
|
||||
OUTREG(b->DriverPrivate.uval,
|
||||
(state ? GPIO_CLOCK_VAL_OUT : 0) | GPIO_CLOCK_DIR_OUT |
|
||||
GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK);
|
||||
val = INREG(b->DriverPrivate.uval);
|
||||
}
|
||||
|
||||
static void i830_setsda(I2CBusPtr b, int state)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 val;
|
||||
|
||||
OUTREG(b->DriverPrivate.uval,
|
||||
(state ? GPIO_DATA_VAL_OUT : 0) | GPIO_DATA_DIR_OUT |
|
||||
GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK);
|
||||
val = INREG(b->DriverPrivate.uval);
|
||||
}
|
||||
|
||||
static void i830_getscl(I2CBusPtr b, int *state)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 val;
|
||||
|
||||
OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK);
|
||||
OUTREG(b->DriverPrivate.uval, 0);
|
||||
val = INREG(b->DriverPrivate.uval);
|
||||
*state = ((val & GPIO_DATA_VAL_IN) != 0);
|
||||
}
|
||||
|
||||
static int i830_getsda(I2CBusPtr b)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 val;
|
||||
|
||||
OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK);
|
||||
OUTREG(b->DriverPrivate.uval, 0);
|
||||
val = INREG(b->DriverPrivate.uval);
|
||||
return ((val & GPIO_DATA_VAL_IN) != 0);
|
||||
}
|
||||
|
||||
static inline void sdalo(I2CBusPtr b)
|
||||
{
|
||||
i830_setsda(b, 0);
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
}
|
||||
|
||||
static inline void sdahi(I2CBusPtr b)
|
||||
{
|
||||
i830_setsda(b, 1);
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
}
|
||||
|
||||
static inline void scllo(I2CBusPtr b)
|
||||
{
|
||||
i830_setscl(b, 0);
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
}
|
||||
|
||||
static inline int sclhi(I2CBusPtr b, int timeout)
|
||||
{
|
||||
int scl = 0;
|
||||
int i;
|
||||
|
||||
i830_setscl(b, 1);
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
|
||||
for (i = timeout; i > 0; i -= b->RiseFallTime) {
|
||||
i830_getscl(b, &scl);
|
||||
if (scl) break;
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
}
|
||||
|
||||
if (i <= 0) {
|
||||
I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]",
|
||||
b->BusName, timeout));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
|
||||
{
|
||||
I2CBusPtr b = d->pI2CBus;
|
||||
int i, sda;
|
||||
unsigned char indata = 0;
|
||||
|
||||
sdahi(b);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (sclhi(b, d->BitTimeout) == FALSE) {
|
||||
I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i));
|
||||
return FALSE;
|
||||
};
|
||||
indata *= 2;
|
||||
if (i830_getsda(b))
|
||||
indata |= 0x01;
|
||||
scllo(b);
|
||||
}
|
||||
|
||||
if (last) {
|
||||
sdahi(b);
|
||||
} else {
|
||||
sdalo(b);
|
||||
}
|
||||
|
||||
if (sclhi(b, d->BitTimeout) == FALSE) {
|
||||
sdahi(b);
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
scllo(b);
|
||||
sdahi(b);
|
||||
|
||||
*data = indata & 0xff;
|
||||
I2C_TRACE(ErrorF("R%02x ", (int) *data));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830I2CPutByte(I2CDevPtr d, I2CByte c)
|
||||
{
|
||||
Bool r;
|
||||
int i, scl, sda;
|
||||
int sb, ack;
|
||||
I2CBusPtr b = d->pI2CBus;
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
sb = c & (1 << i);
|
||||
i830_setsda(b, sb);
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
|
||||
if (sclhi(b, d->ByteTimeout) == FALSE) {
|
||||
sdahi(b);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
i830_setscl(b, 0);
|
||||
b->I2CUDelay(b, b->RiseFallTime);
|
||||
}
|
||||
sdahi(b);
|
||||
if (sclhi(b, d->ByteTimeout) == FALSE) {
|
||||
I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]",
|
||||
b->BusName, c, d->BitTimeout,
|
||||
d->ByteTimeout, d->AcknTimeout));
|
||||
return FALSE;
|
||||
}
|
||||
ack = i830_getsda(b);
|
||||
I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack));
|
||||
|
||||
scllo(b);
|
||||
return (0 == ack);
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830I2CStart(I2CBusPtr b, int timeout)
|
||||
{
|
||||
if (sclhi(b, timeout) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
sdalo(b);
|
||||
scllo(b);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
I830I2CStop(I2CDevPtr d)
|
||||
{
|
||||
I2CBusPtr b = d->pI2CBus;
|
||||
|
||||
sdalo(b);
|
||||
sclhi(b, d->ByteTimeout);
|
||||
sdahi(b);
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
|
||||
{
|
||||
if (I830I2CStart(d->pI2CBus, d->StartTimeout)) {
|
||||
if (I830I2CPutByte(d, addr & 0xFF)) {
|
||||
if ((addr & 0xF8) != 0xF0 &&
|
||||
(addr & 0xFE) != 0x00)
|
||||
return TRUE;
|
||||
|
||||
if (I830I2CPutByte(d, (addr >> 8) & 0xFF))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
I830I2CStop(d);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
i830I2CGetBits(I2CBusPtr b, int *clock, int *data)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 val;
|
||||
|
||||
val = INREG(b->DriverPrivate.uval);
|
||||
*data = (val & GPIO_DATA_VAL_IN) != 0;
|
||||
*clock = (val & GPIO_CLOCK_VAL_IN) != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
i830I2CPutBits(I2CBusPtr b, int clock, int data)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
OUTREG(b->DriverPrivate.uval,
|
||||
(data ? GPIO_DATA_VAL_OUT : 0) |
|
||||
(clock ? GPIO_CLOCK_VAL_OUT : 0) |
|
||||
GPIO_CLOCK_DIR_OUT |
|
||||
GPIO_DATA_DIR_OUT |
|
||||
GPIO_CLOCK_DIR_MASK |
|
||||
GPIO_CLOCK_VAL_MASK |
|
||||
GPIO_DATA_DIR_MASK |
|
||||
GPIO_DATA_VAL_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* the i830 has a number of I2C Buses */
|
||||
Bool
|
||||
I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
|
||||
{
|
||||
I2CBusPtr pI2CBus;
|
||||
|
||||
pI2CBus = xf86CreateI2CBusRec();
|
||||
|
||||
if (!pI2CBus)
|
||||
return FALSE;
|
||||
|
||||
pI2CBus->BusName = name;
|
||||
pI2CBus->scrnIndex = pScrn->scrnIndex;
|
||||
#if AIRLIED_I2C
|
||||
pI2CBus->I2CGetByte = I830I2CGetByte;
|
||||
pI2CBus->I2CPutByte = I830I2CPutByte;
|
||||
pI2CBus->I2CStart = I830I2CStart;
|
||||
pI2CBus->I2CStop = I830I2CStop;
|
||||
pI2CBus->I2CAddress = I830I2CAddress;
|
||||
#else
|
||||
pI2CBus->I2CGetBits = i830I2CGetBits;
|
||||
pI2CBus->I2CPutBits = i830I2CPutBits;
|
||||
#endif
|
||||
pI2CBus->DriverPrivate.uval = i2c_reg;
|
||||
|
||||
if (!xf86I2CBusInit(pI2CBus))
|
||||
return FALSE;
|
||||
|
||||
*bus_ptr = pI2CBus;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_bios.h"
|
||||
|
||||
/**
|
||||
* Sets the power state for the panel.
|
||||
*/
|
||||
static void
|
||||
i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 pp_status, pp_control;
|
||||
CARD32 blc_pwm_ctl;
|
||||
int backlight_duty_cycle;
|
||||
|
||||
blc_pwm_ctl = INREG (BLC_PWM_CTL);
|
||||
backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
if (backlight_duty_cycle)
|
||||
pI830->backlight_duty_cycle = backlight_duty_cycle;
|
||||
|
||||
if (on) {
|
||||
OUTREG(PP_STATUS, INREG(PP_STATUS) | PP_ON);
|
||||
OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
|
||||
do {
|
||||
pp_status = INREG(PP_STATUS);
|
||||
pp_control = INREG(PP_CONTROL);
|
||||
} while (!(pp_status & PP_ON) && !(pp_control & POWER_TARGET_ON));
|
||||
OUTREG(BLC_PWM_CTL,
|
||||
(blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
|
||||
pI830->backlight_duty_cycle);
|
||||
} else {
|
||||
OUTREG(BLC_PWM_CTL,
|
||||
(blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
|
||||
|
||||
OUTREG(PP_STATUS, INREG(PP_STATUS) & ~PP_ON);
|
||||
OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
|
||||
do {
|
||||
pp_status = INREG(PP_STATUS);
|
||||
pp_control = INREG(PP_CONTROL);
|
||||
} while ((pp_status & PP_ON) || (pp_control & POWER_TARGET_ON));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
|
||||
{
|
||||
if (mode == DPMSModeOn)
|
||||
i830SetLVDSPanelPower(pScrn, TRUE);
|
||||
else
|
||||
i830SetLVDSPanelPower(pScrn, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
pI830->savePP_ON = INREG(LVDSPP_ON);
|
||||
pI830->savePP_OFF = INREG(LVDSPP_OFF);
|
||||
pI830->saveLVDS = INREG(LVDS);
|
||||
pI830->savePP_CONTROL = INREG(PP_CONTROL);
|
||||
pI830->savePP_CYCLE = INREG(PP_CYCLE);
|
||||
pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
|
||||
pI830->backlight_duty_cycle = (pI830->saveBLC_PWM_CTL &
|
||||
BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
|
||||
/*
|
||||
* If the light is off at server startup, just make it full brightness
|
||||
*/
|
||||
if (pI830->backlight_duty_cycle == 0) {
|
||||
pI830->backlight_duty_cycle =
|
||||
(pI830->saveBLC_PWM_CTL & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
|
||||
OUTREG(LVDSPP_ON, pI830->savePP_ON);
|
||||
OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
|
||||
OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
|
||||
OUTREG(LVDS, pI830->saveLVDS);
|
||||
OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
|
||||
if (pI830->savePP_CONTROL & POWER_TARGET_ON)
|
||||
i830SetLVDSPanelPower(pScrn, TRUE);
|
||||
else
|
||||
i830SetLVDSPanelPower(pScrn, FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
/* Always make sure the LVDS is off before we play with DPLLs and pipe
|
||||
* configuration. We can skip this in some cases (for example, going
|
||||
* between hi-res modes with automatic panel scaling are fine), but be
|
||||
* conservative for now.
|
||||
*/
|
||||
i830SetLVDSPanelPower(pScrn, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
CARD32 pfit_control;
|
||||
|
||||
/* Enable automatic panel scaling so that non-native modes fill the
|
||||
* screen. Should be enabled before the pipe is enabled, according to
|
||||
* register description.
|
||||
*/
|
||||
pfit_control = (PFIT_ENABLE |
|
||||
VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
|
||||
VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
|
||||
|
||||
if (pI830->panel_wants_dither)
|
||||
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
|
||||
|
||||
OUTREG(PFIT_CONTROL, pfit_control);
|
||||
|
||||
/* Disable the PLL before messing with LVDS enable */
|
||||
OUTREG(FPB0, INREG(FPB0) & ~DPLL_VCO_ENABLE);
|
||||
|
||||
/* LVDS must be powered on before PLL is enabled and before power
|
||||
* sequencing the panel.
|
||||
*/
|
||||
OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
|
||||
|
||||
/* Re-enable the PLL */
|
||||
OUTREG(FPB0, INREG(FPB0) | DPLL_VCO_ENABLE);
|
||||
|
||||
i830SetLVDSPanelPower(pScrn, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the LVDS connection.
|
||||
*
|
||||
* This always returns OUTPUT_STATUS_CONNECTED. This output should only have
|
||||
* been set up if the LVDS was actually connected anyway.
|
||||
*/
|
||||
static enum detect_status
|
||||
i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
return OUTPUT_STATUS_CONNECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
|
||||
*/
|
||||
static DisplayModePtr
|
||||
i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
DisplayModePtr modes, new;
|
||||
char stmp[32];
|
||||
|
||||
modes = i830_ddc_get_modes(pScrn, output);
|
||||
if (modes != NULL)
|
||||
return modes;
|
||||
|
||||
new = xnfcalloc(1, sizeof (DisplayModeRec));
|
||||
sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
|
||||
new->name = xnfalloc(strlen(stmp) + 1);
|
||||
strcpy(new->name, stmp);
|
||||
new->HDisplay = pI830->PanelXRes;
|
||||
new->VDisplay = pI830->PanelYRes;
|
||||
new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
|
||||
new->HSyncEnd = new->HSyncStart + pI830->panel_fixed_hsyncwidth;
|
||||
new->HTotal = new->HSyncEnd + 1;
|
||||
new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
|
||||
new->VSyncEnd = new->VSyncStart + pI830->panel_fixed_vsyncwidth;
|
||||
new->VTotal = new->VSyncEnd + 1;
|
||||
new->Clock = pI830->panel_fixed_clock;
|
||||
|
||||
new->type = M_T_PREFERRED;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
i830_lvds_init(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
/* Get the LVDS fixed mode out of the BIOS. We should support LVDS with
|
||||
* the BIOS being unavailable or broken, but lack the configuration options
|
||||
* for now.
|
||||
*/
|
||||
if (!i830GetLVDSInfoFromBIOS(pScrn))
|
||||
return;
|
||||
|
||||
/* Blacklist machines with BIOSes that list an LVDS panel without actually
|
||||
* having one.
|
||||
*/
|
||||
if (pI830->PciInfo->chipType == PCI_CHIP_I945_GM) {
|
||||
if (pI830->PciInfo->subsysVendor == 0xa0a0) /* aopen mini pc */
|
||||
return;
|
||||
|
||||
if ((pI830->PciInfo->subsysVendor == 0x8086) &&
|
||||
(pI830->PciInfo->subsysCard == 0x7270)) {
|
||||
/* It's a Mac Mini or Macbook Pro.
|
||||
*
|
||||
* Apple hardware is out to get us. The macbook pro has a real
|
||||
* LVDS panel, but the mac mini does not, and they have the same
|
||||
* device IDs. We'll distinguish by panel size, on the assumption
|
||||
* that Apple isn't about to make any machines with an 800x600
|
||||
* display.
|
||||
*/
|
||||
|
||||
if (pI830->PanelXRes == 800 && pI830->PanelYRes == 600) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Suspected Mac Mini, ignoring the LVDS\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pI830->output[pI830->num_outputs].type = I830_OUTPUT_LVDS;
|
||||
pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms;
|
||||
pI830->output[pI830->num_outputs].save = i830_lvds_save;
|
||||
pI830->output[pI830->num_outputs].restore = i830_lvds_restore;
|
||||
pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid;
|
||||
pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode;
|
||||
pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
|
||||
pI830->output[pI830->num_outputs].detect = i830_lvds_detect;
|
||||
pI830->output[pI830->num_outputs].get_modes = i830_lvds_get_modes;
|
||||
|
||||
/* Set up the LVDS DDC channel. Most panels won't support it, but it can
|
||||
* be useful if available.
|
||||
*/
|
||||
I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
|
||||
GPIOC, "LVDSDDC_C");
|
||||
|
||||
pI830->num_outputs++;
|
||||
}
|
||||
|
|
@ -65,10 +65,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
static int nextTile = 0;
|
||||
static unsigned int tileGeneration = -1;
|
||||
|
||||
#ifndef ALLOCATE_ALL_BIOSMEM
|
||||
#define ALLOCATE_ALL_BIOSMEM 1
|
||||
#endif
|
||||
|
||||
static unsigned long
|
||||
GetBestTileAlignment(unsigned long size)
|
||||
{
|
||||
|
|
@ -252,11 +248,7 @@ I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range)
|
|||
* USE CAUTION when changing anything here...
|
||||
*/
|
||||
I830MemPool *Pool = range->Pool;
|
||||
if (pI830->overrideBIOSMemSize &&
|
||||
pI830->BIOSMemorySize > pI830->StolenMemory.Size)
|
||||
Pool->Total.End = pI830->BIOSMemorySize;
|
||||
else
|
||||
Pool->Total.End = pI830->StolenMemory.End;
|
||||
Pool->Total.End = pI830->StolenMemory.End;
|
||||
|
||||
if (pI830->StolenOnly)
|
||||
Pool->Free.End += range->Size;
|
||||
|
|
@ -783,7 +775,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
|
|||
pI830->FbMemBox.x1 = 0;
|
||||
pI830->FbMemBox.x2 = pScrn->displayWidth;
|
||||
pI830->FbMemBox.y1 = 0;
|
||||
if (!pI830->MergedFB && pScrn->virtualX > pScrn->virtualY)
|
||||
if (pScrn->virtualX > pScrn->virtualY)
|
||||
pI830->FbMemBox.y2 = pScrn->virtualX;
|
||||
else
|
||||
pI830->FbMemBox.y2 = pScrn->virtualY;
|
||||
|
|
@ -855,7 +847,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
|
|||
}
|
||||
|
||||
#if 1 /* ROTATION */
|
||||
if (!pI830->MergedFB && pScrn->virtualX > pScrn->virtualY)
|
||||
if (pScrn->virtualX > pScrn->virtualY)
|
||||
size = lineSize * (pScrn->virtualX + cacheLines);
|
||||
else
|
||||
size = lineSize * (pScrn->virtualY + cacheLines);
|
||||
|
|
@ -1115,13 +1107,6 @@ I830ResetAllocations(ScrnInfoPtr pScrn, const int flags)
|
|||
#endif
|
||||
pI830->StolenPool.Fixed = pI830->StolenMemory;
|
||||
pI830->StolenPool.Total = pI830->StolenMemory;
|
||||
#if ALLOCATE_ALL_BIOSMEM
|
||||
if (pI830->overrideBIOSMemSize &&
|
||||
pI830->BIOSMemorySize > pI830->StolenMemory.Size) {
|
||||
pI830->StolenPool.Total.End = pI830->BIOSMemorySize;
|
||||
pI830->StolenPool.Total.Size = pI830->BIOSMemorySize;
|
||||
}
|
||||
#endif
|
||||
pI830->StolenPool.Free = pI830->StolenPool.Total;
|
||||
pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
|
||||
pI830->allocatedMemory = 0;
|
||||
|
|
|
|||
1297
src/i830_modes.c
1297
src/i830_modes.c
File diff suppressed because it is too large
Load Diff
961
src/i830_randr.c
961
src/i830_randr.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
|
||||
|
||||
int
|
||||
i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode);
|
||||
|
||||
void
|
||||
i830_sdvo_dump(ScrnInfoPtr pScrn);
|
||||
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file SDVO command definitions and structures.
|
||||
*/
|
||||
|
||||
struct i830_sdvo_output_flags {
|
||||
unsigned int tmds0:1;
|
||||
unsigned int rgb0:1;
|
||||
unsigned int cvbs0:1;
|
||||
unsigned int svid0:1;
|
||||
unsigned int yprpb0:1;
|
||||
unsigned int scart0:1;
|
||||
unsigned int lvds0:1;
|
||||
unsigned int pad0:1;
|
||||
unsigned int tmds1:1;
|
||||
unsigned int pad1:4;
|
||||
unsigned int rgb1:1;
|
||||
unsigned int lvds1:1;
|
||||
unsigned int pad2:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct i830_sdvo_caps {
|
||||
CARD8 vendor_id;
|
||||
CARD8 device_id;
|
||||
CARD8 device_rev_id;
|
||||
CARD8 sdvo_version_major;
|
||||
CARD8 sdvo_version_minor;
|
||||
unsigned int sdvo_inputs_mask:2;
|
||||
unsigned int smooth_scaling:1;
|
||||
unsigned int sharp_scaling:1;
|
||||
unsigned int up_scaling:1;
|
||||
unsigned int down_scaling:1;
|
||||
unsigned int stall_support:1;
|
||||
unsigned int pad:1;
|
||||
struct i830_sdvo_output_flags output_flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** This matches the EDID DTD structure, more or less */
|
||||
struct i830_sdvo_dtd {
|
||||
struct {
|
||||
CARD16 clock; /**< pixel clock, in 10kHz units */
|
||||
CARD8 h_active; /**< lower 8 bits (pixels) */
|
||||
CARD8 h_blank; /**< lower 8 bits (pixels) */
|
||||
CARD8 h_high; /**< upper 4 bits each h_active, h_blank */
|
||||
CARD8 v_active; /**< lower 8 bits (lines) */
|
||||
CARD8 v_blank; /**< lower 8 bits (lines) */
|
||||
CARD8 v_high; /**< upper 4 bits each v_active, v_blank */
|
||||
} part1;
|
||||
|
||||
struct {
|
||||
CARD8 h_sync_off; /**< lower 8 bits, from hblank start */
|
||||
CARD8 h_sync_width; /**< lower 8 bits (pixels) */
|
||||
/** lower 4 bits each vsync offset, vsync width */
|
||||
CARD8 v_sync_off_width;
|
||||
/**
|
||||
* 2 high bits of hsync offset, 2 high bits of hsync width,
|
||||
* bits 4-5 of vsync offset, and 2 high bits of vsync width.
|
||||
*/
|
||||
CARD8 sync_off_width_high;
|
||||
CARD8 dtd_flags;
|
||||
CARD8 sdvo_flags;
|
||||
/** bits 6-7 of vsync offset at bits 6-7 */
|
||||
CARD8 v_sync_off_high;
|
||||
CARD8 reserved;
|
||||
} part2;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct i830_sdvo_pixel_clock_range {
|
||||
CARD16 min; /**< pixel clock, in 10kHz units */
|
||||
CARD16 max; /**< pixel clock, in 10kHz units */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct i830_sdvo_preferred_input_timing_args {
|
||||
CARD16 clock;
|
||||
CARD16 width;
|
||||
CARD16 height;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* I2C registers for SDVO */
|
||||
#define SDVO_I2C_ARG_0 0x07
|
||||
#define SDVO_I2C_ARG_1 0x06
|
||||
#define SDVO_I2C_ARG_2 0x05
|
||||
#define SDVO_I2C_ARG_3 0x04
|
||||
#define SDVO_I2C_ARG_4 0x03
|
||||
#define SDVO_I2C_ARG_5 0x02
|
||||
#define SDVO_I2C_ARG_6 0x01
|
||||
#define SDVO_I2C_ARG_7 0x00
|
||||
#define SDVO_I2C_OPCODE 0x08
|
||||
#define SDVO_I2C_CMD_STATUS 0x09
|
||||
#define SDVO_I2C_RETURN_0 0x0a
|
||||
#define SDVO_I2C_RETURN_1 0x0b
|
||||
#define SDVO_I2C_RETURN_2 0x0c
|
||||
#define SDVO_I2C_RETURN_3 0x0d
|
||||
#define SDVO_I2C_RETURN_4 0x0e
|
||||
#define SDVO_I2C_RETURN_5 0x0f
|
||||
#define SDVO_I2C_RETURN_6 0x10
|
||||
#define SDVO_I2C_RETURN_7 0x11
|
||||
#define SDVO_I2C_VENDOR_BEGIN 0x20
|
||||
|
||||
/* Status results */
|
||||
#define SDVO_CMD_STATUS_POWER_ON 0x0
|
||||
#define SDVO_CMD_STATUS_SUCCESS 0x1
|
||||
#define SDVO_CMD_STATUS_NOTSUPP 0x2
|
||||
#define SDVO_CMD_STATUS_INVALID_ARG 0x3
|
||||
#define SDVO_CMD_STATUS_PENDING 0x4
|
||||
#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5
|
||||
#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
|
||||
|
||||
/* SDVO commands, argument/result registers */
|
||||
|
||||
#define SDVO_CMD_RESET 0x01
|
||||
|
||||
/** Returns a struct i830_sdvo_caps */
|
||||
#define SDVO_CMD_GET_DEVICE_CAPS 0x02
|
||||
|
||||
#define SDVO_CMD_GET_FIRMWARE_REV 0x86
|
||||
# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
|
||||
# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
|
||||
# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2
|
||||
|
||||
/**
|
||||
* Reports which inputs are trained (managed to sync).
|
||||
*
|
||||
* Devices must have trained within 2 vsyncs of a mode change.
|
||||
*/
|
||||
#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
|
||||
struct i830_sdvo_get_trained_inputs_response {
|
||||
unsigned int input0_trained:1;
|
||||
unsigned int input1_trained:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** Returns a struct i830_sdvo_output_flags of active outputs. */
|
||||
#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
|
||||
|
||||
/**
|
||||
* Sets the current set of active outputs.
|
||||
*
|
||||
* Takes a struct i830_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP
|
||||
* on multi-output devices.
|
||||
*/
|
||||
#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
|
||||
|
||||
/**
|
||||
* Returns the current mapping of SDVO inputs to outputs on the device.
|
||||
*
|
||||
* Returns two struct i830_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_GET_IN_OUT_MAP 0x06
|
||||
|
||||
/**
|
||||
* Sets the current mapping of SDVO inputs to outputs on the device.
|
||||
*
|
||||
* Takes two struct i380_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_SET_IN_OUT_MAP 0x07
|
||||
|
||||
/**
|
||||
* Returns a struct i830_sdvo_output_flags of attached displays.
|
||||
*/
|
||||
#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
|
||||
|
||||
/**
|
||||
* Returns a struct i830_sdvo_ouptut_flags of displays supporting hot plugging.
|
||||
*/
|
||||
#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
|
||||
|
||||
/**
|
||||
* Takes a struct i830_sdvo_output_flags.
|
||||
*/
|
||||
#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
|
||||
|
||||
/**
|
||||
* Returns a struct i830_sdvo_output_flags of displays with hot plug
|
||||
* interrupts enabled.
|
||||
*/
|
||||
#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
|
||||
|
||||
#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f
|
||||
struct i830_sdvo_get_interrupt_event_source_response {
|
||||
struct i830_sdvo_output_flags interrupt_status;
|
||||
unsigned int ambient_light_interrupt:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Selects which input is affected by future input commands.
|
||||
*
|
||||
* Commands affected include SET_INPUT_TIMINGS_PART[12],
|
||||
* GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
|
||||
* GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
|
||||
*/
|
||||
#define SDVO_CMD_SET_TARGET_INPUT 0x10
|
||||
struct i830_sdvo_set_target_input_args {
|
||||
unsigned int target_1:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Takes a struct i830_sdvo_output_flags of which outputs are targetted by
|
||||
* future output commands.
|
||||
*
|
||||
* Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
|
||||
* GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
|
||||
*/
|
||||
#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
|
||||
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
|
||||
/* Part 1 */
|
||||
# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
|
||||
# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
|
||||
/* Part 2 */
|
||||
# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
|
||||
# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
|
||||
# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
|
||||
# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
|
||||
# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
|
||||
# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4)
|
||||
# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
|
||||
|
||||
/**
|
||||
* Generates a DTD based on the given width, height, and flags.
|
||||
*
|
||||
* This will be supported by any device supporting scaling or interlaced
|
||||
* modes.
|
||||
*/
|
||||
#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
|
||||
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
|
||||
|
||||
/** Returns a struct i830_sdvo_pixel_clock_range */
|
||||
#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
|
||||
/** Returns a struct i830_sdvo_pixel_clock_range */
|
||||
#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
|
||||
|
||||
/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
|
||||
#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f
|
||||
|
||||
/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
|
||||
#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20
|
||||
/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
|
||||
#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21
|
||||
# define SDVO_CLOCK_RATE_MULT_1X (1 << 0)
|
||||
# define SDVO_CLOCK_RATE_MULT_2X (1 << 1)
|
||||
# define SDVO_CLOCK_RATE_MULT_4X (1 << 3)
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
|
||||
|
||||
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
||||
|
||||
#define SDVO_CMD_SET_TV_FORMAT 0x29
|
||||
|
||||
#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
|
||||
|
||||
#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
|
||||
# define SDVO_CONTROL_BUS_PROM 0x0
|
||||
# define SDVO_CONTROL_BUS_DDC1 0x1
|
||||
# define SDVO_CONTROL_BUS_DDC2 0x2
|
||||
# define SDVO_CONTROL_BUS_DDC3 0x3
|
||||
|
||||
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Integrated TV-out support for the 915GM and 945GM.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_display.h"
|
||||
|
||||
enum tv_type {
|
||||
TV_TYPE_UNKNOWN,
|
||||
TV_TYPE_COMPOSITE,
|
||||
TV_TYPE_SVIDEO,
|
||||
TV_TYPE_COMPONENT
|
||||
};
|
||||
|
||||
/** Private structure for the integrated TV support */
|
||||
struct i830_tv_priv {
|
||||
CARD32 save_TV_H_CTL_1;
|
||||
CARD32 save_TV_H_CTL_2;
|
||||
CARD32 save_TV_H_CTL_3;
|
||||
CARD32 save_TV_V_CTL_1;
|
||||
CARD32 save_TV_V_CTL_2;
|
||||
CARD32 save_TV_V_CTL_3;
|
||||
CARD32 save_TV_V_CTL_4;
|
||||
CARD32 save_TV_V_CTL_5;
|
||||
CARD32 save_TV_V_CTL_6;
|
||||
CARD32 save_TV_V_CTL_7;
|
||||
CARD32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3;
|
||||
CARD32 save_TV_DAC;
|
||||
CARD32 save_TV_CTL;
|
||||
};
|
||||
|
||||
enum burst_modes {
|
||||
TV_SC_NTSC_MJ,
|
||||
TV_SC_PAL,
|
||||
TV_SC_PAL_NC,
|
||||
TV_SC_PAL_M,
|
||||
TV_SC_NTSC_443
|
||||
};
|
||||
|
||||
const struct tv_sc_mode {
|
||||
char *name;
|
||||
int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
|
||||
CARD32 sc_reset;
|
||||
Bool pal_burst;
|
||||
} tv_sc_modes[] = {
|
||||
[TV_SC_NTSC_MJ] = {
|
||||
"NTSC M/J",
|
||||
27456, 0, 135, 20800, 0,
|
||||
TV_SC_RESET_EVERY_4,
|
||||
FALSE
|
||||
},
|
||||
[TV_SC_PAL] = {
|
||||
"PAL",
|
||||
27648, 625, 168, 4122, 67,
|
||||
TV_SC_RESET_EVERY_8,
|
||||
TRUE
|
||||
},
|
||||
[TV_SC_PAL_NC] = {
|
||||
"PAL Nc",
|
||||
27648, 625, 135, 23578, 134,
|
||||
TV_SC_RESET_EVERY_8,
|
||||
TRUE
|
||||
},
|
||||
[TV_SC_PAL_M] = {
|
||||
"PAL M",
|
||||
27456, 0, 135, 16704, 0,
|
||||
TV_SC_RESET_EVERY_8,
|
||||
TRUE
|
||||
},
|
||||
[TV_SC_NTSC_443] = {
|
||||
"NTSC-4.43",
|
||||
27456, 525, 168, 4093, 310,
|
||||
TV_SC_RESET_NEVER,
|
||||
FALSE
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Register programming values for TV modes.
|
||||
*
|
||||
* These values account for -1s required.
|
||||
*/
|
||||
const struct tv_mode {
|
||||
char *name;
|
||||
CARD32 oversample;
|
||||
int hsync_end, hblank_end, hblank_start, htotal;
|
||||
Bool progressive;
|
||||
int vsync_start_f1, vsync_start_f2, vsync_len;
|
||||
Bool veq_ena;
|
||||
int veq_start_f1, veq_start_f2, veq_len;
|
||||
int vi_end_f1, vi_end_f2, nbr_end;
|
||||
Bool burst_ena;
|
||||
int hburst_start, hburst_len;
|
||||
int vburst_start_f1, vburst_end_f1;
|
||||
int vburst_start_f2, vburst_end_f2;
|
||||
int vburst_start_f3, vburst_end_f3;
|
||||
int vburst_start_f4, vburst_end_f4;
|
||||
} tv_modes[] = {
|
||||
{
|
||||
"480i",
|
||||
TV_OVERSAMPLE_8X,
|
||||
64, 124, 836, 857,
|
||||
FALSE,
|
||||
6, 7, 6,
|
||||
TRUE, 0, 1, 18,
|
||||
20, 21, 240,
|
||||
TRUE,
|
||||
72, 34, 9, 240, 10, 240, 9, 240, 10, 240
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
CARD32 save_tv_ctl, save_tv_dac;
|
||||
CARD32 tv_ctl, tv_dac;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
save_tv_ctl = INREG(TV_CTL);
|
||||
save_tv_dac = INREG(TV_DAC);
|
||||
|
||||
/* First, we have to disable the encoder but source from the right pipe,
|
||||
* which is already enabled.
|
||||
*/
|
||||
tv_ctl = INREG(TV_CTL) & ~(TV_ENC_ENABLE | TV_ENC_PIPEB_SELECT);
|
||||
if (output->pipe == 1)
|
||||
tv_ctl |= TV_ENC_PIPEB_SELECT;
|
||||
OUTREG(TV_CTL, tv_ctl);
|
||||
|
||||
/* Then set the voltage overrides. */
|
||||
tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V;
|
||||
OUTREG(TV_DAC, tv_dac);
|
||||
|
||||
/* Enable sensing of the load. */
|
||||
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
|
||||
OUTREG(TV_CTL, tv_ctl);
|
||||
|
||||
tv_dac |= TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL |
|
||||
TVDAC_C_SENSE_CTL;
|
||||
OUTREG(TV_DAC, tv_dac);
|
||||
|
||||
/* Wait for things to take effect. */
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
tv_dac = INREG(TV_DAC);
|
||||
|
||||
OUTREG(TV_DAC, save_tv_dac);
|
||||
OUTREG(TV_CTL, save_tv_ctl);
|
||||
|
||||
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Detected Composite TV connection\n");
|
||||
return TV_TYPE_COMPOSITE;
|
||||
} else if ((tv_dac & TVDAC_SENSE_MASK) == TVDAC_A_SENSE) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Detected S-Video TV connection\n");
|
||||
return TV_TYPE_SVIDEO;
|
||||
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Detected Component TV connection\n");
|
||||
return TV_TYPE_COMPONENT;
|
||||
} else {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Couldn't detect TV connection\n");
|
||||
return TV_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
switch(mode) {
|
||||
case DPMSModeOn:
|
||||
OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
|
||||
break;
|
||||
case DPMSModeStandby:
|
||||
case DPMSModeSuspend:
|
||||
case DPMSModeOff:
|
||||
OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
struct i830_tv_priv *dev_priv = output->dev_priv;
|
||||
|
||||
dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1);
|
||||
dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2);
|
||||
dev_priv->save_TV_H_CTL_3 = INREG(TV_H_CTL_3);
|
||||
dev_priv->save_TV_V_CTL_1 = INREG(TV_V_CTL_1);
|
||||
dev_priv->save_TV_V_CTL_2 = INREG(TV_V_CTL_2);
|
||||
dev_priv->save_TV_V_CTL_3 = INREG(TV_V_CTL_3);
|
||||
dev_priv->save_TV_V_CTL_4 = INREG(TV_V_CTL_4);
|
||||
dev_priv->save_TV_V_CTL_5 = INREG(TV_V_CTL_5);
|
||||
dev_priv->save_TV_V_CTL_6 = INREG(TV_V_CTL_6);
|
||||
dev_priv->save_TV_V_CTL_7 = INREG(TV_V_CTL_7);
|
||||
dev_priv->save_TV_SC_CTL_1 = INREG(TV_SC_CTL_1);
|
||||
dev_priv->save_TV_SC_CTL_2 = INREG(TV_SC_CTL_2);
|
||||
dev_priv->save_TV_SC_CTL_3 = INREG(TV_SC_CTL_3);
|
||||
|
||||
dev_priv->save_TV_DAC = INREG(TV_DAC);
|
||||
dev_priv->save_TV_CTL = INREG(TV_CTL);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
struct i830_tv_priv *dev_priv = output->dev_priv;
|
||||
|
||||
OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1);
|
||||
OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2);
|
||||
OUTREG(TV_H_CTL_3, dev_priv->save_TV_H_CTL_3);
|
||||
OUTREG(TV_V_CTL_1, dev_priv->save_TV_V_CTL_1);
|
||||
OUTREG(TV_V_CTL_2, dev_priv->save_TV_V_CTL_2);
|
||||
OUTREG(TV_V_CTL_3, dev_priv->save_TV_V_CTL_3);
|
||||
OUTREG(TV_V_CTL_4, dev_priv->save_TV_V_CTL_4);
|
||||
OUTREG(TV_V_CTL_5, dev_priv->save_TV_V_CTL_5);
|
||||
OUTREG(TV_V_CTL_6, dev_priv->save_TV_V_CTL_6);
|
||||
OUTREG(TV_V_CTL_7, dev_priv->save_TV_V_CTL_7);
|
||||
OUTREG(TV_SC_CTL_1, dev_priv->save_TV_SC_CTL_1);
|
||||
OUTREG(TV_SC_CTL_2, dev_priv->save_TV_SC_CTL_2);
|
||||
OUTREG(TV_SC_CTL_3, dev_priv->save_TV_SC_CTL_3);
|
||||
|
||||
OUTREG(TV_DAC, dev_priv->save_TV_DAC);
|
||||
OUTREG(TV_CTL, dev_priv->save_TV_CTL);
|
||||
}
|
||||
|
||||
static int
|
||||
i830_tv_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
/* Disable the encoder while we set up the pipe. */
|
||||
OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
|
||||
DisplayModePtr pMode)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
enum tv_type type;
|
||||
const struct tv_mode *tv_mode;
|
||||
const struct tv_sc_mode *sc_mode;
|
||||
CARD32 tv_ctl, tv_filter_ctl;
|
||||
CARD32 hctl1, hctl2, hctl3;
|
||||
CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
|
||||
CARD32 scctl1, scctl2, scctl3;
|
||||
|
||||
/* Need to actually choose or construct the appropriate
|
||||
* mode. For now, just set the first one in the list, with
|
||||
* NTSC format.
|
||||
*/
|
||||
tv_mode = &tv_modes[0];
|
||||
sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
|
||||
|
||||
type = i830_tv_detect_type(pScrn, output);
|
||||
if (type == TV_TYPE_UNKNOWN) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Defaulting TV to SVIDEO\n");
|
||||
type = TV_TYPE_SVIDEO;
|
||||
}
|
||||
|
||||
hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
|
||||
(tv_mode->htotal << TV_HTOTAL_SHIFT);
|
||||
|
||||
hctl2 = (tv_mode->hburst_start << 16) |
|
||||
(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
|
||||
if (tv_mode->burst_ena)
|
||||
hctl2 |= TV_BURST_ENA;
|
||||
|
||||
hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
|
||||
(tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
|
||||
|
||||
vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
|
||||
(tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
|
||||
(tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
|
||||
|
||||
vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
|
||||
(tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
|
||||
(tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
|
||||
|
||||
vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
|
||||
(tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
|
||||
(tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
|
||||
if (tv_mode->veq_ena)
|
||||
vctl3 |= TV_EQUAL_ENA;
|
||||
|
||||
vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
|
||||
(tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
|
||||
|
||||
vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
|
||||
(tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
|
||||
|
||||
vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
|
||||
(tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
|
||||
|
||||
vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
|
||||
(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
|
||||
|
||||
tv_ctl = TV_ENC_ENABLE;
|
||||
if (output->pipe == 1)
|
||||
tv_ctl |= TV_ENC_PIPEB_SELECT;
|
||||
|
||||
switch (type) {
|
||||
case TV_TYPE_COMPOSITE:
|
||||
tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
|
||||
break;
|
||||
case TV_TYPE_COMPONENT:
|
||||
tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
|
||||
break;
|
||||
default:
|
||||
case TV_TYPE_SVIDEO:
|
||||
tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
|
||||
break;
|
||||
}
|
||||
tv_ctl |= tv_mode->oversample;
|
||||
if (tv_mode->progressive)
|
||||
tv_ctl |= TV_PROGRESSIVE;
|
||||
if (sc_mode->pal_burst)
|
||||
tv_ctl |= TV_PAL_BURST;
|
||||
|
||||
scctl1 = TV_SC_DDA1_EN | TV_SC_DDA1_EN;
|
||||
if (sc_mode->dda3_size != 0)
|
||||
scctl1 |= TV_SC_DDA3_EN;
|
||||
scctl1 |= sc_mode->sc_reset;
|
||||
/* XXX: set the burst level */
|
||||
scctl1 |= sc_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
|
||||
|
||||
scctl2 = sc_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
|
||||
sc_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
|
||||
|
||||
scctl3 = sc_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
|
||||
sc_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
|
||||
|
||||
/* Enable two fixes for the chips that need them. */
|
||||
if (pI830->PciInfo->chipType < PCI_CHIP_I945_G)
|
||||
tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
|
||||
|
||||
tv_filter_ctl = TV_AUTO_SCALE;
|
||||
if (pMode->HDisplay > 1024)
|
||||
tv_ctl |= TV_V_FILTER_BYPASS;
|
||||
|
||||
OUTREG(TV_H_CTL_1, hctl1);
|
||||
OUTREG(TV_H_CTL_2, hctl2);
|
||||
OUTREG(TV_H_CTL_3, hctl3);
|
||||
OUTREG(TV_V_CTL_1, vctl1);
|
||||
OUTREG(TV_V_CTL_2, vctl2);
|
||||
OUTREG(TV_V_CTL_3, vctl3);
|
||||
OUTREG(TV_V_CTL_4, vctl4);
|
||||
OUTREG(TV_V_CTL_5, vctl5);
|
||||
OUTREG(TV_V_CTL_6, vctl6);
|
||||
OUTREG(TV_V_CTL_7, vctl7);
|
||||
OUTREG(TV_SC_CTL_1, scctl1);
|
||||
OUTREG(TV_SC_CTL_2, scctl2);
|
||||
OUTREG(TV_SC_CTL_3, scctl3);
|
||||
|
||||
OUTREG(TV_DAC, 0);
|
||||
OUTREG(TV_CTL, tv_ctl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the TV connection.
|
||||
*
|
||||
* Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure
|
||||
* we have a pipe programmed in order to probe the TV.
|
||||
*/
|
||||
static enum detect_status
|
||||
i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
return OUTPUT_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub get_modes function.
|
||||
*
|
||||
* This should probably return a set of fixed modes, unless we can figure out
|
||||
* how to probe modes off of TV connections.
|
||||
*/
|
||||
static DisplayModePtr
|
||||
i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
i830_tv_init(ScrnInfoPtr pScrn)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
|
||||
if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
|
||||
return;
|
||||
|
||||
pI830->output[pI830->num_outputs].dev_priv =
|
||||
malloc(sizeof(struct i830_tv_priv));
|
||||
if (pI830->output[pI830->num_outputs].dev_priv == NULL)
|
||||
return;
|
||||
|
||||
pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG;
|
||||
pI830->output[pI830->num_outputs].dpms = i830_tv_dpms;
|
||||
pI830->output[pI830->num_outputs].save = i830_tv_save;
|
||||
pI830->output[pI830->num_outputs].restore = i830_tv_restore;
|
||||
pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid;
|
||||
pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode;
|
||||
pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode;
|
||||
pI830->output[pI830->num_outputs].detect = i830_tv_detect;
|
||||
pI830->output[pI830->num_outputs].get_modes = i830_tv_get_modes;
|
||||
|
||||
pI830->num_outputs++;
|
||||
}
|
||||
134
src/i830_video.c
134
src/i830_video.c
|
|
@ -125,7 +125,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
|
|||
|
||||
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
|
||||
|
||||
static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer;
|
||||
static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvDoubleBuffer;
|
||||
static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
|
||||
|
||||
#define IMAGE_MAX_WIDTH 1920
|
||||
|
|
@ -294,11 +294,12 @@ static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = {
|
|||
{XvSettable | XvGettable, 0, 1, "XV_PIPE"}
|
||||
};
|
||||
|
||||
#define NUM_ATTRIBUTES 4
|
||||
#define NUM_ATTRIBUTES 5
|
||||
static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
|
||||
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
|
||||
{XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
|
||||
{XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
|
||||
{XvSettable | XvGettable, 0, 1023, "XV_SATURATION"},
|
||||
{XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
|
||||
};
|
||||
|
||||
|
|
@ -445,19 +446,6 @@ I830InitVideo(ScreenPtr pScreen)
|
|||
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
|
||||
xvContrast = MAKE_ATOM("XV_CONTRAST");
|
||||
|
||||
/* Set up overlay video if we can do it at this depth. */
|
||||
if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) {
|
||||
overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
|
||||
if (overlayAdaptor != NULL) {
|
||||
adaptors[num_adaptors++] = overlayAdaptor;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
|
||||
} else {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Failed to set up overlay video\n");
|
||||
}
|
||||
I830InitOffscreenImages(pScreen);
|
||||
}
|
||||
|
||||
/* Set up textured video if we can do it at this depth and we are on
|
||||
* supported hardware.
|
||||
*/
|
||||
|
|
@ -472,6 +460,19 @@ I830InitVideo(ScreenPtr pScreen)
|
|||
}
|
||||
}
|
||||
|
||||
/* Set up overlay video if we can do it at this depth. */
|
||||
if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) {
|
||||
overlayAdaptor = I830SetupImageVideoOverlay(pScreen);
|
||||
if (overlayAdaptor != NULL) {
|
||||
adaptors[num_adaptors++] = overlayAdaptor;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
|
||||
} else {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Failed to set up overlay video\n");
|
||||
}
|
||||
I830InitOffscreenImages(pScreen);
|
||||
}
|
||||
|
||||
if (num_adaptors)
|
||||
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
|
||||
|
||||
|
|
@ -503,7 +504,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
|
|||
overlay->SWIDTHSW = 0;
|
||||
overlay->SHEIGHT = 0;
|
||||
overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
|
||||
overlay->OCLRC1 = 0x00000080; /* saturation: bypass */
|
||||
overlay->OCLRC1 = pPriv->saturation;
|
||||
#if 0
|
||||
overlay->AWINPOS = 0;
|
||||
overlay->AWINSZ = 0;
|
||||
|
|
@ -712,7 +713,8 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen)
|
|||
pPriv->videoStatus = 0;
|
||||
pPriv->brightness = 0;
|
||||
pPriv->contrast = 64;
|
||||
pPriv->pipe = pI830->pipe; /* default to current pipe */
|
||||
pPriv->saturation = 128;
|
||||
pPriv->pipe = 0; /* XXX must choose pipe wisely */
|
||||
pPriv->linear = NULL;
|
||||
pPriv->currentBuf = 0;
|
||||
pPriv->gamma5 = 0xc0c0c0;
|
||||
|
|
@ -745,6 +747,9 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen)
|
|||
pScreen->BlockHandler = I830BlockHandler;
|
||||
|
||||
xvColorKey = MAKE_ATOM("XV_COLORKEY");
|
||||
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
|
||||
xvContrast = MAKE_ATOM("XV_CONTRAST");
|
||||
xvSaturation = MAKE_ATOM("XV_SATURATION");
|
||||
xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
|
||||
|
||||
/* Allow the pipe to be switched from pipe A to B when in clone mode */
|
||||
|
|
@ -942,6 +947,13 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
|
|||
overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
|
||||
ErrorF("CONTRAST\n");
|
||||
OVERLAY_UPDATE;
|
||||
} else if (attribute == xvSaturation) {
|
||||
if ((value < 0) || (value > 1023))
|
||||
return BadValue;
|
||||
pPriv->saturation = value;
|
||||
overlay->OCLRC1 = pPriv->saturation;
|
||||
overlay->OCMD &= ~OVERLAY_ENABLE;
|
||||
OVERLAY_UPDATE;
|
||||
} else if (pI830->Clone && attribute == xvPipe) {
|
||||
if ((value < 0) || (value > 1))
|
||||
return BadValue;
|
||||
|
|
@ -1023,6 +1035,8 @@ I830GetPortAttribute(ScrnInfoPtr pScrn,
|
|||
*value = pPriv->brightness;
|
||||
} else if (attribute == xvContrast) {
|
||||
*value = pPriv->contrast;
|
||||
} else if (attribute == xvSaturation) {
|
||||
*value = pPriv->saturation;
|
||||
} else if (attribute == xvPipe) {
|
||||
*value = pPriv->pipe;
|
||||
} else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
|
||||
|
|
@ -1528,7 +1542,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
|
|||
unsigned int swidth;
|
||||
unsigned int mask, shift, offsety, offsetu;
|
||||
int tmp;
|
||||
BoxRec dstBox2;
|
||||
|
||||
ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
|
||||
dstPitch);
|
||||
|
|
@ -1542,22 +1555,10 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
|
|||
|
||||
switch (pI830->rotation) {
|
||||
case RR_Rotate_0:
|
||||
if (pI830->MergedFB) {
|
||||
memcpy(&dstBox2, dstBox, sizeof(BoxRec));
|
||||
dstBox->x1 -= pI830->FirstframeX0;
|
||||
dstBox->x2 -= pI830->FirstframeX0;
|
||||
dstBox->y1 -= pI830->FirstframeY0;
|
||||
dstBox->y2 -= pI830->FirstframeY0;
|
||||
dstBox2.x1 -= pI830->pScrn_2->frameX0;
|
||||
dstBox2.x2 -= pI830->pScrn_2->frameX0;
|
||||
dstBox2.y1 -= pI830->pScrn_2->frameY0;
|
||||
dstBox2.y2 -= pI830->pScrn_2->frameY0;
|
||||
} else {
|
||||
dstBox->x1 -= pScrn->frameX0;
|
||||
dstBox->x2 -= pScrn->frameX0;
|
||||
dstBox->y1 -= pScrn->frameY0;
|
||||
dstBox->y2 -= pScrn->frameY0;
|
||||
}
|
||||
dstBox->x1 -= pScrn->frameX0;
|
||||
dstBox->x2 -= pScrn->frameX0;
|
||||
dstBox->y1 -= pScrn->frameY0;
|
||||
dstBox->y2 -= pScrn->frameY0;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
tmp = dstBox->x1;
|
||||
|
|
@ -1591,66 +1592,10 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
|
|||
break;
|
||||
}
|
||||
|
||||
if (pI830->MergedFB) {
|
||||
I830ModePrivatePtr mp = (I830ModePrivatePtr)pScrn->currentMode->Private;
|
||||
int w1, h1, w2, h2;
|
||||
|
||||
/* Clip the video to the independent modes of the merged screens */
|
||||
if (dstBox->x1 > mp->merged.First->HDisplay) dstBox->x1 = mp->merged.First->HDisplay - 1;
|
||||
if (dstBox->x2 > mp->merged.First->HDisplay) dstBox->x2 = mp->merged.First->HDisplay - 1;
|
||||
if (dstBox2.x1 > mp->merged.Second->HDisplay) dstBox2.x1 = mp->merged.Second->HDisplay - 1;
|
||||
if (dstBox2.x2 > mp->merged.Second->HDisplay) dstBox2.x2 = mp->merged.Second->HDisplay - 1;
|
||||
if (dstBox->y1 > mp->merged.First->VDisplay) dstBox->y1 = mp->merged.First->VDisplay - 1;
|
||||
if (dstBox->y2 > mp->merged.First->VDisplay) dstBox->y2 = mp->merged.First->VDisplay - 1;
|
||||
if (dstBox2.y1 > mp->merged.Second->VDisplay) dstBox2.y1 = mp->merged.Second->VDisplay - 1;
|
||||
if (dstBox2.y2 > mp->merged.Second->VDisplay) dstBox2.y2 = mp->merged.Second->VDisplay - 1;
|
||||
if (dstBox->y1 < 0) dstBox->y1 = 0;
|
||||
if (dstBox->y2 < 0) dstBox->y2 = 0;
|
||||
if (dstBox->x1 < 0) dstBox->x1 = 0;
|
||||
if (dstBox->x2 < 0) dstBox->x2 = 0;
|
||||
if (dstBox2.y1 < 0) dstBox2.y1 = 0;
|
||||
if (dstBox2.y2 < 0) dstBox2.y2 = 0;
|
||||
if (dstBox2.x1 < 0) dstBox2.x1 = 0;
|
||||
if (dstBox2.x2 < 0) dstBox2.x2 = 0;
|
||||
|
||||
w1 = dstBox->x2 - dstBox->x1;
|
||||
w2 = dstBox2.x2 - dstBox2.x1;
|
||||
h1 = dstBox->y2 - dstBox->y1;
|
||||
h2 = dstBox2.y2 - dstBox2.y1;
|
||||
|
||||
switch (pI830->SecondPosition) {
|
||||
case PosRightOf:
|
||||
case PosBelow:
|
||||
if ((w2 > 0 && w1 == 0) ||
|
||||
(h2 > 0 && h1 == 0)) {
|
||||
pPriv->pipe = !pI830->pipe;
|
||||
dstBox->x1 = dstBox2.x1;
|
||||
dstBox->y1 = dstBox2.y1;
|
||||
dstBox->x2 = dstBox2.x2;
|
||||
dstBox->y2 = dstBox2.y2;
|
||||
} else
|
||||
pPriv->pipe = pI830->pipe;
|
||||
break;
|
||||
case PosLeftOf:
|
||||
case PosAbove:
|
||||
if ((w1 > 0 && w2 == 0) ||
|
||||
(h1 > 0 && h2 == 0)) {
|
||||
pPriv->pipe = pI830->pipe;
|
||||
} else {
|
||||
pPriv->pipe = !pI830->pipe;
|
||||
dstBox->x1 = dstBox2.x1;
|
||||
dstBox->y1 = dstBox2.y1;
|
||||
dstBox->x2 = dstBox2.x2;
|
||||
dstBox->y2 = dstBox2.y2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* When in dual head with different bpp setups we need to refresh the
|
||||
* color key, so let's reset the video parameters and refresh here.
|
||||
* In MergedFB mode, we may need to flip pipes too. */
|
||||
if (pI830->entityPrivate || pI830->MergedFB)
|
||||
if (pI830->entityPrivate)
|
||||
I830ResetVideo(pScrn);
|
||||
|
||||
/* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
|
||||
|
|
@ -3611,6 +3556,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|||
|
||||
pPriv->overlayOK = TRUE;
|
||||
|
||||
#if 0
|
||||
/* XXX Must choose pipe wisely */
|
||||
/* ensure pipe is updated on mode switch */
|
||||
if (!pI830->Clone) {
|
||||
if (pPriv->pipe != pI830->pipe) {
|
||||
|
|
@ -3619,6 +3566,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|||
pPriv->pipe = pI830->pipe;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IS_I965G(pI830)) {
|
||||
if (pPriv->pipe == 0) {
|
||||
|
|
@ -3647,8 +3595,8 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
|||
}
|
||||
|
||||
/* Check we have an LFP connected */
|
||||
if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
|
||||
(pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
|
||||
if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS))
|
||||
{
|
||||
size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
|
||||
hsize = (size >> 16) & 0x7FF;
|
||||
vsize = size & 0x7FF;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ typedef struct {
|
|||
|
||||
int brightness;
|
||||
int contrast;
|
||||
int saturation;
|
||||
int pipe;
|
||||
int doubleBuffer;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,641 @@
|
|||
/* -*- c-basic-offset: 4 -*- */
|
||||
/* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */
|
||||
/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2003 by The XFree86 Project, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of the copyright holder(s)
|
||||
* and author(s) shall not be used in advertising or otherwise to promote
|
||||
* the sale, use or other dealings in this Software without prior written
|
||||
* authorization from the copyright holder(s) and author(s).
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xf86.h"
|
||||
#include "i830.h"
|
||||
#include "i830_xf86Modes.h"
|
||||
|
||||
/**
|
||||
* @file this file contains symbols from xf86Mode.c and friends that are static
|
||||
* there but we still want to use. We need to come up with better API here.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the horizontal sync rate of a mode.
|
||||
*
|
||||
* Exact copy of xf86Mode.c's.
|
||||
*/
|
||||
double
|
||||
i830xf86ModeHSync(DisplayModePtr mode)
|
||||
{
|
||||
double hsync = 0.0;
|
||||
|
||||
if (mode->HSync > 0.0)
|
||||
hsync = mode->HSync;
|
||||
else if (mode->HTotal > 0)
|
||||
hsync = (float)mode->Clock / (float)mode->HTotal;
|
||||
|
||||
return hsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the vertical refresh rate of a mode.
|
||||
*
|
||||
* Exact copy of xf86Mode.c's.
|
||||
*/
|
||||
double
|
||||
i830xf86ModeVRefresh(DisplayModePtr mode)
|
||||
{
|
||||
double refresh = 0.0;
|
||||
|
||||
if (mode->VRefresh > 0.0)
|
||||
refresh = mode->VRefresh;
|
||||
else if (mode->HTotal > 0 && mode->VTotal > 0) {
|
||||
refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
|
||||
if (mode->Flags & V_INTERLACE)
|
||||
refresh *= 2.0;
|
||||
if (mode->Flags & V_DBLSCAN)
|
||||
refresh /= 2.0;
|
||||
if (mode->VScan > 1)
|
||||
refresh /= (float)(mode->VScan);
|
||||
}
|
||||
return refresh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default mode name of <width>x<height>x<refresh> on a mode.
|
||||
*
|
||||
* The refresh rate doesn't contain decimals, as that's expected to be
|
||||
* unimportant from the user's perspective for non-custom modelines.
|
||||
*/
|
||||
void
|
||||
i830xf86SetModeDefaultName(DisplayModePtr mode)
|
||||
{
|
||||
if (mode->name != NULL)
|
||||
xfree(mode->name);
|
||||
|
||||
mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay);
|
||||
}
|
||||
|
||||
/*
|
||||
* I830xf86SetModeCrtc
|
||||
*
|
||||
* Initialises the Crtc parameters for a mode. The initialisation includes
|
||||
* adjustments for interlaced and double scan modes.
|
||||
*
|
||||
* Exact copy of xf86Mode.c's.
|
||||
*/
|
||||
void
|
||||
I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
|
||||
{
|
||||
if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
|
||||
return;
|
||||
|
||||
p->CrtcHDisplay = p->HDisplay;
|
||||
p->CrtcHSyncStart = p->HSyncStart;
|
||||
p->CrtcHSyncEnd = p->HSyncEnd;
|
||||
p->CrtcHTotal = p->HTotal;
|
||||
p->CrtcHSkew = p->HSkew;
|
||||
p->CrtcVDisplay = p->VDisplay;
|
||||
p->CrtcVSyncStart = p->VSyncStart;
|
||||
p->CrtcVSyncEnd = p->VSyncEnd;
|
||||
p->CrtcVTotal = p->VTotal;
|
||||
if (p->Flags & V_INTERLACE) {
|
||||
if (adjustFlags & INTERLACE_HALVE_V) {
|
||||
p->CrtcVDisplay /= 2;
|
||||
p->CrtcVSyncStart /= 2;
|
||||
p->CrtcVSyncEnd /= 2;
|
||||
p->CrtcVTotal /= 2;
|
||||
}
|
||||
/* Force interlaced modes to have an odd VTotal */
|
||||
/* maybe we should only do this when INTERLACE_HALVE_V is set? */
|
||||
p->CrtcVTotal |= 1;
|
||||
}
|
||||
|
||||
if (p->Flags & V_DBLSCAN) {
|
||||
p->CrtcVDisplay *= 2;
|
||||
p->CrtcVSyncStart *= 2;
|
||||
p->CrtcVSyncEnd *= 2;
|
||||
p->CrtcVTotal *= 2;
|
||||
}
|
||||
if (p->VScan > 1) {
|
||||
p->CrtcVDisplay *= p->VScan;
|
||||
p->CrtcVSyncStart *= p->VScan;
|
||||
p->CrtcVSyncEnd *= p->VScan;
|
||||
p->CrtcVTotal *= p->VScan;
|
||||
}
|
||||
p->CrtcHAdjusted = FALSE;
|
||||
p->CrtcVAdjusted = FALSE;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* The following is taken from VGA, but applies to other cores as well.
|
||||
*/
|
||||
p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
|
||||
p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
|
||||
if ((p->CrtcVBlankEnd - p->CrtcVBlankStart) >= 127) {
|
||||
/*
|
||||
* V Blanking size must be < 127.
|
||||
* Moving blank start forward is safer than moving blank end
|
||||
* back, since monitors clamp just AFTER the sync pulse (or in
|
||||
* the sync pulse), but never before.
|
||||
*/
|
||||
p->CrtcVBlankStart = p->CrtcVBlankEnd - 127;
|
||||
/*
|
||||
* If VBlankStart is now > VSyncStart move VBlankStart
|
||||
* to VSyncStart using the maximum width that fits into
|
||||
* VTotal.
|
||||
*/
|
||||
if (p->CrtcVBlankStart > p->CrtcVSyncStart) {
|
||||
p->CrtcVBlankStart = p->CrtcVSyncStart;
|
||||
p->CrtcVBlankEnd = min(p->CrtcHBlankStart + 127, p->CrtcVTotal);
|
||||
}
|
||||
}
|
||||
p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
|
||||
p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
|
||||
|
||||
if ((p->CrtcHBlankEnd - p->CrtcHBlankStart) >= 63 * 8) {
|
||||
/*
|
||||
* H Blanking size must be < 63*8. Same remark as above.
|
||||
*/
|
||||
p->CrtcHBlankStart = p->CrtcHBlankEnd - 63 * 8;
|
||||
if (p->CrtcHBlankStart > p->CrtcHSyncStart) {
|
||||
p->CrtcHBlankStart = p->CrtcHSyncStart;
|
||||
p->CrtcHBlankEnd = min(p->CrtcHBlankStart + 63 * 8, p->CrtcHTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a copy of pMode, including pointers within pMode.
|
||||
*/
|
||||
DisplayModePtr
|
||||
i830xf86DuplicateMode(DisplayModePtr pMode)
|
||||
{
|
||||
DisplayModePtr pNew;
|
||||
|
||||
pNew = xnfalloc(sizeof(DisplayModeRec));
|
||||
*pNew = *pMode;
|
||||
pNew->next = NULL;
|
||||
pNew->prev = NULL;
|
||||
if (pNew->name == NULL) {
|
||||
i830xf86SetModeDefaultName(pMode);
|
||||
} else {
|
||||
pNew->name = xnfstrdup(pMode->name);
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates every mode in the given list and returns a pointer to the first
|
||||
* mode.
|
||||
*
|
||||
* \param modeList doubly-linked mode list
|
||||
*/
|
||||
DisplayModePtr
|
||||
i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
|
||||
{
|
||||
DisplayModePtr first = NULL, last = NULL;
|
||||
DisplayModePtr mode;
|
||||
|
||||
for (mode = modeList; mode != NULL; mode = mode->next) {
|
||||
DisplayModePtr new;
|
||||
|
||||
new = i830xf86DuplicateMode(mode);
|
||||
|
||||
/* Insert pNew into modeList */
|
||||
if (last) {
|
||||
last->next = new;
|
||||
new->prev = last;
|
||||
} else {
|
||||
first = new;
|
||||
new->prev = NULL;
|
||||
}
|
||||
new->next = NULL;
|
||||
last = new;
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given modes should program to the same timings.
|
||||
*
|
||||
* This doesn't use Crtc values, as it might be used on ModeRecs without the
|
||||
* Crtc values set. So, it's assumed that the other numbers are enough.
|
||||
*
|
||||
* This isn't in xf86Modes.c, but it might deserve to be there.
|
||||
*/
|
||||
Bool
|
||||
I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
|
||||
{
|
||||
if (pMode1->Clock == pMode2->Clock &&
|
||||
pMode1->HDisplay == pMode2->HDisplay &&
|
||||
pMode1->HSyncStart == pMode2->HSyncStart &&
|
||||
pMode1->HSyncEnd == pMode2->HSyncEnd &&
|
||||
pMode1->HTotal == pMode2->HTotal &&
|
||||
pMode1->HSkew == pMode2->HSkew &&
|
||||
pMode1->VDisplay == pMode2->VDisplay &&
|
||||
pMode1->VSyncStart == pMode2->VSyncStart &&
|
||||
pMode1->VSyncEnd == pMode2->VSyncEnd &&
|
||||
pMode1->VTotal == pMode2->VTotal &&
|
||||
pMode1->VScan == pMode2->VScan &&
|
||||
pMode1->Flags == pMode2->Flags)
|
||||
{
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* exact copy of xf86Mode.c */
|
||||
static void
|
||||
add(char **p, char *new)
|
||||
{
|
||||
*p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
|
||||
strcat(*p, " ");
|
||||
strcat(*p, new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out a modeline.
|
||||
*
|
||||
* Convenient VRefresh printing was added, though, compared to xf86Mode.c
|
||||
*/
|
||||
void
|
||||
PrintModeline(int scrnIndex,DisplayModePtr mode)
|
||||
{
|
||||
char tmp[256];
|
||||
char *flags = xnfcalloc(1, 1);
|
||||
|
||||
if (mode->HSkew) {
|
||||
snprintf(tmp, 256, "hskew %i", mode->HSkew);
|
||||
add(&flags, tmp);
|
||||
}
|
||||
if (mode->VScan) {
|
||||
snprintf(tmp, 256, "vscan %i", mode->VScan);
|
||||
add(&flags, tmp);
|
||||
}
|
||||
if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
|
||||
if (mode->Flags & V_CSYNC) add(&flags, "composite");
|
||||
if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
|
||||
if (mode->Flags & V_BCAST) add(&flags, "bcast");
|
||||
if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
|
||||
if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
|
||||
if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
|
||||
if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
|
||||
if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
|
||||
if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
|
||||
#if 0
|
||||
if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
|
||||
#endif
|
||||
xf86DrvMsg(scrnIndex, X_INFO,
|
||||
"Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s "
|
||||
"(%.01f kHz)\n",
|
||||
mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
|
||||
mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
|
||||
mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
|
||||
mode->VTotal, flags, i830xf86ModeHSync(mode));
|
||||
xfree(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks as bad any modes with unsupported flags.
|
||||
*
|
||||
* \param modeList doubly-linked or circular list of modes.
|
||||
* \param flags flags supported by the driver.
|
||||
*
|
||||
* \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough?
|
||||
*
|
||||
* This is not in xf86Modes.c, but would be part of the proposed new API.
|
||||
*/
|
||||
void
|
||||
i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int flags)
|
||||
{
|
||||
DisplayModePtr mode;
|
||||
|
||||
for (mode = modeList; mode != NULL; mode = mode->next) {
|
||||
if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE))
|
||||
mode->status = MODE_NO_INTERLACE;
|
||||
if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN))
|
||||
mode->status = MODE_NO_DBLESCAN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks as bad any modes extending beyond the given max X, Y, or pitch.
|
||||
*
|
||||
* \param modeList doubly-linked or circular list of modes.
|
||||
*
|
||||
* This is not in xf86Modes.c, but would be part of the proposed new API.
|
||||
*/
|
||||
void
|
||||
i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int maxX, int maxY, int maxPitch)
|
||||
{
|
||||
DisplayModePtr mode;
|
||||
|
||||
for (mode = modeList; mode != NULL; mode = mode->next) {
|
||||
if (maxPitch > 0 && mode->HDisplay > maxPitch)
|
||||
mode->status = MODE_BAD_WIDTH;
|
||||
|
||||
if (maxX > 0 && mode->HDisplay > maxX)
|
||||
mode->status = MODE_VIRTUAL_X;
|
||||
|
||||
if (maxY > 0 && mode->VDisplay > maxY)
|
||||
mode->status = MODE_VIRTUAL_Y;
|
||||
|
||||
if (mode->next == modeList)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks as bad any modes that aren't supported by the given monitor's
|
||||
* hsync and vrefresh ranges.
|
||||
*
|
||||
* \param modeList doubly-linked or circular list of modes.
|
||||
*
|
||||
* This is not in xf86Modes.c, but would be part of the proposed new API.
|
||||
*/
|
||||
void
|
||||
i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
MonPtr mon)
|
||||
{
|
||||
DisplayModePtr mode;
|
||||
|
||||
for (mode = modeList; mode != NULL; mode = mode->next) {
|
||||
Bool bad;
|
||||
int i;
|
||||
|
||||
bad = TRUE;
|
||||
for (i = 0; i < mon->nHsync; i++) {
|
||||
if (i830xf86ModeHSync(mode) >= mon->hsync[i].lo &&
|
||||
i830xf86ModeHSync(mode) <= mon->hsync[i].hi)
|
||||
{
|
||||
bad = FALSE;
|
||||
}
|
||||
}
|
||||
if (bad)
|
||||
mode->status = MODE_HSYNC;
|
||||
|
||||
bad = TRUE;
|
||||
for (i = 0; i < mon->nVrefresh; i++) {
|
||||
if (i830xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
|
||||
i830xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
|
||||
{
|
||||
bad = FALSE;
|
||||
}
|
||||
}
|
||||
if (bad)
|
||||
mode->status = MODE_VSYNC;
|
||||
|
||||
if (mode->next == modeList)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks as bad any modes extending beyond outside of the given clock ranges.
|
||||
*
|
||||
* \param modeList doubly-linked or circular list of modes.
|
||||
* \param min pointer to minimums of clock ranges
|
||||
* \param max pointer to maximums of clock ranges
|
||||
* \param n_ranges number of ranges.
|
||||
*
|
||||
* This is not in xf86Modes.c, but would be part of the proposed new API.
|
||||
*/
|
||||
void
|
||||
i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int *min, int *max, int n_ranges)
|
||||
{
|
||||
DisplayModePtr mode;
|
||||
int i;
|
||||
|
||||
for (mode = modeList; mode != NULL; mode = mode->next) {
|
||||
Bool good = FALSE;
|
||||
for (i = 0; i < n_ranges; i++) {
|
||||
if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
|
||||
good = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good)
|
||||
mode->status = MODE_CLOCK_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user has specified a set of mode names to use, mark as bad any modes
|
||||
* not listed.
|
||||
*
|
||||
* The user mode names specified are prefixes to names of modes, so "1024x768"
|
||||
* will match modes named "1024x768", "1024x768x75", "1024x768-good", but
|
||||
* "1024x768x75" would only match "1024x768x75" from that list.
|
||||
*
|
||||
* MODE_BAD is used as the rejection flag, for lack of a better flag.
|
||||
*
|
||||
* \param modeList doubly-linked or circular list of modes.
|
||||
*
|
||||
* This is not in xf86Modes.c, but would be part of the proposed new API.
|
||||
*/
|
||||
void
|
||||
i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
|
||||
{
|
||||
DisplayModePtr mode;
|
||||
|
||||
if (pScrn->display->modes[0] == NULL)
|
||||
return;
|
||||
|
||||
for (mode = modeList; mode != NULL; mode = mode->next) {
|
||||
int i;
|
||||
Bool good = FALSE;
|
||||
|
||||
for (i = 0; pScrn->display->modes[i] != NULL; i++) {
|
||||
if (strncmp(pScrn->display->modes[i], mode->name,
|
||||
strlen(pScrn->display->modes[i])) == 0) {
|
||||
good = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good)
|
||||
mode->status = MODE_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees any modes from the list with a status other than MODE_OK.
|
||||
*
|
||||
* \param modeList pointer to a doubly-linked or circular list of modes.
|
||||
* \param verbose determines whether the reason for mode invalidation is
|
||||
* printed.
|
||||
*
|
||||
* This is not in xf86Modes.c, but would be part of the proposed new API.
|
||||
*/
|
||||
void
|
||||
i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
|
||||
Bool verbose)
|
||||
{
|
||||
DisplayModePtr mode;
|
||||
|
||||
for (mode = *modeList; mode != NULL;) {
|
||||
DisplayModePtr next = mode->next, first = *modeList;
|
||||
|
||||
if (mode->status != MODE_OK) {
|
||||
if (verbose) {
|
||||
char *type = "";
|
||||
if (mode->type & M_T_BUILTIN)
|
||||
type = "built-in ";
|
||||
else if (mode->type & M_T_DEFAULT)
|
||||
type = "default ";
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Not using %smode \"%s\" (%s)\n", type, mode->name,
|
||||
xf86ModeStatusToString(mode->status));
|
||||
}
|
||||
xf86DeleteMode(modeList, mode);
|
||||
}
|
||||
|
||||
if (next == first)
|
||||
break;
|
||||
mode = next;
|
||||
}
|
||||
}
|
||||
|
||||
#define MODEPREFIX(name) NULL, NULL, name, MODE_OK, M_T_DEFAULT
|
||||
#define MODESUFFIX 0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
|
||||
|
||||
/**
|
||||
* List of VESA established modes, taken from xf86DefaultModes but trimmed down.
|
||||
* (not trimming should be harmless).
|
||||
*/
|
||||
DisplayModeRec I830xf86DefaultModes[] = {
|
||||
/* 640x350 @ 85Hz (VESA) hsync: 37.9kHz */
|
||||
{MODEPREFIX("640x350"),31500, 640,672,736,832,0, 350,382,385,445,0, V_PHSYNC | V_NVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("320x175"),15750, 320,336,368,416,0, 175,191,192,222,0, V_PHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 640x400 @ 85Hz (VESA) hsync: 37.9kHz */
|
||||
{MODEPREFIX("640x400"),31500, 640,672,736,832,0, 400,401,404,445,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("320x200"),15750, 320,336,368,416,0, 200,200,202,222,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 720x400 @ 85Hz (VESA) hsync: 37.9kHz */
|
||||
{MODEPREFIX("720x400"),35500, 720,756,828,936,0, 400,401,404,446,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("360x200"),17750, 360,378,414,468,0, 200,200,202,223,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 640x480 @ 72Hz (VESA) hsync: 37.9kHz */
|
||||
{MODEPREFIX("640x480"),31500, 640,664,704,832,0, 480,489,491,520,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("320x240"),15750, 320,332,352,416,0, 240,244,245,260,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 640x480 @ 75Hz (VESA) hsync: 37.5kHz */
|
||||
{MODEPREFIX("640x480"),31500, 640,656,720,840,0, 480,481,484,500,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("320x240"),15750, 320,328,360,420,0, 240,240,242,250,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 640x480 @ 85Hz (VESA) hsync: 43.3kHz */
|
||||
{MODEPREFIX("640x480"),36000, 640,696,752,832,0, 480,481,484,509,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("320x240"),18000, 320,348,376,416,0, 240,240,242,254,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 800x600 @ 56Hz (VESA) hsync: 35.2kHz */
|
||||
{MODEPREFIX("800x600"),36000, 800,824,896,1024,0, 600,601,603,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("400x300"),18000, 400,412,448,512,0, 300,300,301,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 800x600 @ 60Hz (VESA) hsync: 37.9kHz */
|
||||
{MODEPREFIX("800x600"),40000, 800,840,968,1056,0, 600,601,605,628,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("400x300"),20000, 400,420,484,528,0, 300,300,302,314,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 800x600 @ 72Hz (VESA) hsync: 48.1kHz */
|
||||
{MODEPREFIX("800x600"),50000, 800,856,976,1040,0, 600,637,643,666,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("400x300"),25000, 400,428,488,520,0, 300,318,321,333,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 800x600 @ 75Hz (VESA) hsync: 46.9kHz */
|
||||
{MODEPREFIX("800x600"),49500, 800,816,896,1056,0, 600,601,604,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("400x300"),24750, 400,408,448,528,0, 300,300,302,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 800x600 @ 85Hz (VESA) hsync: 53.7kHz */
|
||||
{MODEPREFIX("800x600"),56300, 800,832,896,1048,0, 600,601,604,631,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("400x300"),28150, 400,416,448,524,0, 300,300,302,315,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1024x768 @ 60Hz (VESA) hsync: 48.4kHz */
|
||||
{MODEPREFIX("1024x768"),65000, 1024,1048,1184,1344,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("512x384"),32500, 512,524,592,672,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1024x768 @ 70Hz (VESA) hsync: 56.5kHz */
|
||||
{MODEPREFIX("1024x768"),75000, 1024,1048,1184,1328,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("512x384"),37500, 512,524,592,664,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1024x768 @ 75Hz (VESA) hsync: 60.0kHz */
|
||||
{MODEPREFIX("1024x768"),78800, 1024,1040,1136,1312,0, 768,769,772,800,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("512x384"),39400, 512,520,568,656,0, 384,384,386,400,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1024x768 @ 85Hz (VESA) hsync: 68.7kHz */
|
||||
{MODEPREFIX("1024x768"),94500, 1024,1072,1168,1376,0, 768,769,772,808,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("512x384"),47250, 512,536,584,688,0, 384,384,386,404,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1152x864 @ 75Hz (VESA) hsync: 67.5kHz */
|
||||
{MODEPREFIX("1152x864"),108000, 1152,1216,1344,1600,0, 864,865,868,900,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("576x432"),54000, 576,608,672,800,0, 432,432,434,450,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1280x960 @ 60Hz (VESA) hsync: 60.0kHz */
|
||||
{MODEPREFIX("1280x960"),108000, 1280,1376,1488,1800,0, 960,961,964,1000,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("640x480"),54000, 640,688,744,900,0, 480,480,482,500,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1280x960 @ 85Hz (VESA) hsync: 85.9kHz */
|
||||
{MODEPREFIX("1280x960"),148500, 1280,1344,1504,1728,0, 960,961,964,1011,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("640x480"),74250, 640,672,752,864,0, 480,480,482,505,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz */
|
||||
{MODEPREFIX("1280x1024"),108000, 1280,1328,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("640x512"),54000, 640,664,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz */
|
||||
{MODEPREFIX("1280x1024"),135000, 1280,1296,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("640x512"),67500, 640,648,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz */
|
||||
{MODEPREFIX("1280x1024"),157500, 1280,1344,1504,1728,0, 1024,1025,1028,1072,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("640x512"),78750, 640,672,752,864,0, 512,512,514,536,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz */
|
||||
{MODEPREFIX("1600x1200"),162000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("800x600"),81000, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz */
|
||||
{MODEPREFIX("1600x1200"),175500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("800x600"),87750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz */
|
||||
{MODEPREFIX("1600x1200"),189000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("800x600"),94500, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz */
|
||||
{MODEPREFIX("1600x1200"),202500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("800x600"),101250, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz */
|
||||
{MODEPREFIX("1600x1200"),229500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("800x600"),114750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz */
|
||||
{MODEPREFIX("1792x1344"),204800, 1792,1920,2120,2448,0, 1344,1345,1348,1394,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("896x672"),102400, 896,960,1060,1224,0, 672,672,674,697,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz */
|
||||
{MODEPREFIX("1792x1344"),261000, 1792,1888,2104,2456,0, 1344,1345,1348,1417,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("896x672"),130500, 896,944,1052,1228,0, 672,672,674,708,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz */
|
||||
{MODEPREFIX("1856x1392"),218300, 1856,1952,2176,2528,0, 1392,1393,1396,1439,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("928x696"),109150, 928,976,1088,1264,0, 696,696,698,719,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz */
|
||||
{MODEPREFIX("1856x1392"),288000, 1856,1984,2208,2560,0, 1392,1393,1396,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("928x696"),144000, 928,992,1104,1280,0, 696,696,698,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz */
|
||||
{MODEPREFIX("1920x1440"),234000, 1920,2048,2256,2600,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("960x720"),117000, 960,1024,1128,1300,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
/* 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz */
|
||||
{MODEPREFIX("1920x1440"),297000, 1920,2064,2288,2640,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
|
||||
{MODEPREFIX("960x720"),148500, 960,1032,1144,1320,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
|
||||
|
||||
/* Terminator */
|
||||
{MODEPREFIX(NULL), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX}
|
||||
};
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
double
|
||||
i830xf86ModeHSync(DisplayModePtr mode);
|
||||
|
||||
double
|
||||
i830xf86ModeVRefresh(DisplayModePtr mode);
|
||||
|
||||
DisplayModePtr
|
||||
i830xf86DuplicateMode(DisplayModePtr pMode);
|
||||
|
||||
DisplayModePtr
|
||||
i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList);
|
||||
|
||||
void
|
||||
i830xf86SetModeDefaultName(DisplayModePtr mode);
|
||||
|
||||
void
|
||||
I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
|
||||
|
||||
Bool
|
||||
I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
|
||||
|
||||
void
|
||||
i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int flags);
|
||||
|
||||
void
|
||||
i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int *min, int *max, int n_ranges);
|
||||
|
||||
void
|
||||
i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int maxX, int maxY, int maxPitch);
|
||||
|
||||
void
|
||||
i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
MonPtr mon);
|
||||
|
||||
void
|
||||
i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
|
||||
Bool verbose);
|
||||
|
||||
void
|
||||
i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
|
||||
int flags);
|
||||
|
||||
void
|
||||
i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
|
||||
|
||||
void
|
||||
PrintModeline(int scrnIndex,DisplayModePtr mode);
|
||||
|
||||
extern DisplayModeRec I830xf86DefaultModes[];
|
||||
|
|
@ -65,8 +65,10 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
|
|||
int nbox, dxo, dyo;
|
||||
Bool planar;
|
||||
|
||||
#if 0
|
||||
ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height,
|
||||
video_pitch);
|
||||
#endif
|
||||
|
||||
switch (id) {
|
||||
case FOURCC_UYVY:
|
||||
|
|
@ -78,7 +80,9 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
|
|||
planar = TRUE;
|
||||
break;
|
||||
default:
|
||||
#if 0
|
||||
ErrorF("Unknown format 0x%x\n", id);
|
||||
#endif
|
||||
planar = FALSE;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# this is obnoxious:
|
||||
# -module lets us name the module exactly how we want
|
||||
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
|
||||
# _ladir passes a dummy rpath to libtool so the thing will actually link
|
||||
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
|
||||
AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
|
||||
|
||||
sil164_la_LTLIBRARIES = sil164.la
|
||||
sil164_la_LDFLAGS = -module -avoid-version
|
||||
sil164_ladir = @moduledir@/drivers
|
||||
|
||||
sil164_la_SOURCES = \
|
||||
sil164.c \
|
||||
sil164_module.c \
|
||||
sil164.h \
|
||||
sil164_reg.h
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
/* -*- c-basic-offset: 4 -*- */
|
||||
/**************************************************************************
|
||||
|
||||
Copyright © 2006 Dave Airlie
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sub license, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the
|
||||
next paragraph) shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
#include "xf86.h"
|
||||
#include "xf86_OSproc.h"
|
||||
#include "xf86Resources.h"
|
||||
#include "compiler.h"
|
||||
#include "miscstruct.h"
|
||||
#include "xf86i2c.h"
|
||||
|
||||
#include "../i2c_vid.h"
|
||||
#include "sil164.h"
|
||||
#include "sil164_reg.h"
|
||||
|
||||
static void
|
||||
sil164PrintRegs(I2CDevPtr d);
|
||||
static void
|
||||
sil164Power(I2CDevPtr d, Bool On);
|
||||
|
||||
static Bool
|
||||
sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *ch)
|
||||
{
|
||||
if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
|
||||
"Unable to read from %s Slave %d.\n",
|
||||
sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
sil164WriteByte(SIL164Ptr sil, int addr, CARD8 ch)
|
||||
{
|
||||
if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
|
||||
"Unable to write to %s Slave %d.\n",
|
||||
sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Silicon Image 164 driver for chip on i2c bus */
|
||||
static void *
|
||||
sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
|
||||
{
|
||||
/* this will detect the SIL164 chip on the specified i2c bus */
|
||||
SIL164Ptr sil;
|
||||
unsigned char ch;
|
||||
|
||||
xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
|
||||
|
||||
sil = xcalloc(1, sizeof(SIL164Rec));
|
||||
if (sil == NULL)
|
||||
return NULL;
|
||||
|
||||
sil->d.DevName = "SIL164 TMDS Controller";
|
||||
sil->d.SlaveAddr = addr;
|
||||
sil->d.pI2CBus = b;
|
||||
sil->d.StartTimeout = b->StartTimeout;
|
||||
sil->d.BitTimeout = b->BitTimeout;
|
||||
sil->d.AcknTimeout = b->AcknTimeout;
|
||||
sil->d.ByteTimeout = b->ByteTimeout;
|
||||
sil->d.DriverPrivate.ptr = sil;
|
||||
|
||||
if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
|
||||
goto out;
|
||||
|
||||
if (ch!=(SIL164_VID & 0xFF)) {
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
|
||||
"sil164 not detected got %d: from %s Slave %d.\n",
|
||||
ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
|
||||
goto out;
|
||||
|
||||
if (ch!=(SIL164_DID & 0xFF)) {
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
|
||||
"sil164 not detected got %d: from %s Slave %d.\n",
|
||||
ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xf86I2CDevInit(&(sil->d))) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
return sil;
|
||||
|
||||
out:
|
||||
xfree(sil);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
sil164Init(I2CDevPtr d)
|
||||
{
|
||||
/* not much to do */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ModeStatus
|
||||
sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164Mode(I2CDevPtr d, DisplayModePtr mode)
|
||||
{
|
||||
sil164Power(d, TRUE);
|
||||
sil164PrintRegs(d);
|
||||
|
||||
/* recommended programming sequence from doc */
|
||||
/*sil164WriteByte(sil, 0x08, 0x30);
|
||||
sil164WriteByte(sil, 0x09, 0x00);
|
||||
sil164WriteByte(sil, 0x0a, 0x90);
|
||||
sil164WriteByte(sil, 0x0c, 0x89);
|
||||
sil164WriteByte(sil, 0x08, 0x31);*/
|
||||
/* don't do much */
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the SIL164 power state */
|
||||
static void
|
||||
sil164Power(I2CDevPtr d, Bool On)
|
||||
{
|
||||
SIL164Ptr sil = SILPTR(d);
|
||||
int ret;
|
||||
unsigned char ch;
|
||||
|
||||
ret = sil164ReadByte(sil, SIL164_REG8, &ch);
|
||||
if (ret == FALSE)
|
||||
return;
|
||||
|
||||
if (On)
|
||||
ch |= SIL164_8_PD;
|
||||
else
|
||||
ch &= ~SIL164_8_PD;
|
||||
|
||||
sil164WriteByte(sil, SIL164_REG8, ch);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164PrintRegs(I2CDevPtr d)
|
||||
{
|
||||
SIL164Ptr sil = SILPTR(d);
|
||||
CARD8 val;
|
||||
|
||||
sil164ReadByte(sil, SIL164_FREQ_LO, &val);
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_LO: 0x%02x\n",
|
||||
val);
|
||||
sil164ReadByte(sil, SIL164_FREQ_HI, &val);
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_HI: 0x%02x\n",
|
||||
val);
|
||||
sil164ReadByte(sil, SIL164_REG8, &val);
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG8: 0x%02x\n", val);
|
||||
sil164ReadByte(sil, SIL164_REG9, &val);
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG9: 0x%02x\n", val);
|
||||
sil164ReadByte(sil, SIL164_REGC, &val);
|
||||
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REGC: 0x%02x\n", val);
|
||||
}
|
||||
|
||||
static void
|
||||
sil164SaveRegs(I2CDevPtr d)
|
||||
{
|
||||
SIL164Ptr sil = SILPTR(d);
|
||||
|
||||
if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
|
||||
return;
|
||||
|
||||
if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
|
||||
return;
|
||||
|
||||
if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164RestoreRegs(I2CDevPtr d)
|
||||
{
|
||||
SIL164Ptr sil = SILPTR(d);
|
||||
|
||||
/* Restore it powered down initially */
|
||||
sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8 & ~0x1);
|
||||
|
||||
sil164WriteByte(sil, SIL164_REG9, sil->SavedReg.reg9);
|
||||
sil164WriteByte(sil, SIL164_REGC, sil->SavedReg.regc);
|
||||
sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8);
|
||||
}
|
||||
|
||||
|
||||
I830I2CVidOutputRec SIL164VidOutput = {
|
||||
sil164Detect,
|
||||
sil164Init,
|
||||
sil164ModeValid,
|
||||
sil164Mode,
|
||||
sil164Power,
|
||||
sil164PrintRegs,
|
||||
sil164SaveRegs,
|
||||
sil164RestoreRegs,
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SIL164_H
|
||||
#define SIL164_H
|
||||
|
||||
#define SIL164_ADDR_1 0x38
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- c-basic-offset: 4 -*- */
|
||||
|
||||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "xf86Module.h"
|
||||
|
||||
static MODULESETUPPROTO(sil164Setup);
|
||||
|
||||
static XF86ModuleVersionInfo sil164VersRec = {
|
||||
"sil164",
|
||||
MODULEVENDORSTRING,
|
||||
MODINFOSTRING1,
|
||||
MODINFOSTRING2,
|
||||
XORG_VERSION_CURRENT,
|
||||
1, 0, 0,
|
||||
ABI_CLASS_VIDEODRV,
|
||||
ABI_VIDEODRV_VERSION,
|
||||
MOD_CLASS_NONE,
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
_X_EXPORT XF86ModuleData sil164ModuleData = {
|
||||
&sil164VersRec,
|
||||
sil164Setup,
|
||||
NULL
|
||||
};
|
||||
|
||||
static pointer
|
||||
sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin)
|
||||
{
|
||||
return (pointer)1;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- c-basic-offset: 4 -*- */
|
||||
/**************************************************************************
|
||||
|
||||
Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SIL164_REG_H
|
||||
#define SIL164_REG_H
|
||||
|
||||
#define SIL164_VID 0x0001
|
||||
#define SIL164_DID 0x0006
|
||||
|
||||
#define SIL164_VID_LO 0x00
|
||||
#define SIL164_VID_HI 0x01
|
||||
#define SIL164_DID_LO 0x02
|
||||
#define SIL164_DID_HI 0x03
|
||||
#define SIL164_REV 0x04
|
||||
#define SIL164_RSVD 0x05
|
||||
#define SIL164_FREQ_LO 0x06
|
||||
#define SIL164_FREQ_HI 0x07
|
||||
|
||||
#define SIL164_REG8 0x08
|
||||
#define SIL164_8_VEN (1<<5)
|
||||
#define SIL164_8_HEN (1<<4)
|
||||
#define SIL164_8_DSEL (1<<3)
|
||||
#define SIL164_8_BSEL (1<<2)
|
||||
#define SIL164_8_EDGE (1<<1)
|
||||
#define SIL164_8_PD (1<<0)
|
||||
|
||||
#define SIL164_REG9 0x09
|
||||
#define SIL164_9_VLOW (1<<7)
|
||||
#define SIL164_9_MSEL_MASK (0x7<<4)
|
||||
#define SIL164_9_TSEL (1<<3)
|
||||
#define SIL164_9_RSEN (1<<2)
|
||||
#define SIL164_9_HTPLG (1<<1)
|
||||
#define SIL164_9_MDI (1<<0)
|
||||
|
||||
#define SIL164_REGC 0x0c
|
||||
|
||||
typedef struct _Sil164SaveRec {
|
||||
CARD8 reg8;
|
||||
CARD8 reg9;
|
||||
CARD8 regc;
|
||||
} SIL164SaveRec;
|
||||
|
||||
typedef struct {
|
||||
I2CDevRec d;
|
||||
SIL164SaveRec SavedReg;
|
||||
SIL164SaveRec ModeReg;
|
||||
} SIL164Rec, *SIL164Ptr;
|
||||
|
||||
#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.la
|
||||
*.lo
|
||||
|
|
@ -1558,6 +1558,11 @@ static __inline__ void renderDualPrimeinField(uint **datay,uint **datau,
|
|||
// Description: inline function that sets hardware parameters for a Field
|
||||
// encoded macroblock in a frame picture.
|
||||
***************************************************************************/
|
||||
typedef union {
|
||||
short s[4];
|
||||
uint u[2];
|
||||
} su_t;
|
||||
|
||||
static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
||||
uint **datav,
|
||||
XvMCMacroBlock *mb,short *block_ptr,
|
||||
|
|
@ -1568,8 +1573,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
register uint *dv = *datav;
|
||||
|
||||
/* Motion Vectors */
|
||||
short fmv[4];
|
||||
short bmv[4];
|
||||
su_t fmv;
|
||||
su_t bmv;
|
||||
/* gfxblock dword 1 */
|
||||
uint dw1[2];
|
||||
|
||||
|
|
@ -1589,23 +1594,23 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
(((mb->coded_block_pattern & 0x3) |
|
||||
((mb->coded_block_pattern & 0xc)<<2))<<22);
|
||||
|
||||
fmv[0] = mb->PMV[0][0][1]/2;
|
||||
fmv[1] = mb->PMV[0][0][0];
|
||||
fmv[2] = mb->PMV[1][0][1]/2;
|
||||
fmv[3] = mb->PMV[1][0][0];
|
||||
fmv.s[0] = mb->PMV[0][0][1]/2;
|
||||
fmv.s[1] = mb->PMV[0][0][0];
|
||||
fmv.s[2] = mb->PMV[1][0][1]/2;
|
||||
fmv.s[3] = mb->PMV[1][0][0];
|
||||
|
||||
bmv[0] = mb->PMV[0][1][1]/2;
|
||||
bmv[1] = mb->PMV[0][1][0];
|
||||
bmv[2] = mb->PMV[1][1][1]/2;
|
||||
bmv[3] = mb->PMV[1][1][0];
|
||||
bmv.s[0] = mb->PMV[0][1][1]/2;
|
||||
bmv.s[1] = mb->PMV[0][1][0];
|
||||
bmv.s[2] = mb->PMV[1][1][1]/2;
|
||||
bmv.s[3] = mb->PMV[1][1][0];
|
||||
|
||||
/* First Y Block */
|
||||
*dy++ = GFXBLOCK + 4 + (y1size>>2);
|
||||
*dy++ = (1<<30) | (2<<28) | dw1[0];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)&fmv[0];
|
||||
*dy++ = *(uint *)&bmv[0];
|
||||
*dy++ = fmv.u[0];
|
||||
*dy++ = bmv.u[0];
|
||||
PACK_CORR_DATA(dy,block_ptr,y1size);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + y1size);
|
||||
|
||||
|
|
@ -1614,21 +1619,21 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (2<<28) | dw1[1];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)&fmv[2];
|
||||
*dy++ = *(uint *)&bmv[2];
|
||||
*dy++ = fmv.u[1];
|
||||
*dy++ = bmv.u[1];
|
||||
PACK_CORR_DATA(dy,block_ptr,y2size);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + y2size);
|
||||
/* End Y Blocks */
|
||||
|
||||
fmv[0] /= 2;
|
||||
fmv[1] /= 2;
|
||||
fmv[2] /= 2;
|
||||
fmv[3] /= 2;
|
||||
fmv.s[0] /= 2;
|
||||
fmv.s[1] /= 2;
|
||||
fmv.s[2] /= 2;
|
||||
fmv.s[3] /= 2;
|
||||
|
||||
bmv[0] /= 2;
|
||||
bmv[1] /= 2;
|
||||
bmv[2] /= 2;
|
||||
bmv[3] /= 2;
|
||||
bmv.s[0] /= 2;
|
||||
bmv.s[1] /= 2;
|
||||
bmv.s[2] /= 2;
|
||||
bmv.s[3] /= 2;
|
||||
|
||||
xy >>= 1;
|
||||
|
||||
|
|
@ -1637,8 +1642,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[0];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)&fmv[0];
|
||||
*du++ = *(uint *)&bmv[0];
|
||||
*du++ = fmv.u[0];
|
||||
*du++ = bmv.u[0];
|
||||
if(usize) {
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
}
|
||||
|
|
@ -1648,8 +1653,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[1];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)&fmv[2];
|
||||
*du++ = *(uint *)&bmv[2];
|
||||
*du++ = fmv.u[1];
|
||||
*du++ = bmv.u[1];
|
||||
if(usize) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
|
|
@ -1662,8 +1667,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[0];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)&fmv[0];
|
||||
*dv++ = *(uint *)&bmv[0];
|
||||
*dv++ = fmv.u[0];
|
||||
*dv++ = bmv.u[0];
|
||||
if(vsize) {
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
}
|
||||
|
|
@ -1673,8 +1678,8 @@ static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[1];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)&fmv[2];
|
||||
*dv++ = *(uint *)&bmv[2];
|
||||
*dv++ = fmv.u[1];
|
||||
*dv++ = bmv.u[1];
|
||||
if(vsize) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
|
|
@ -1701,8 +1706,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
register uint *dv = *datav;
|
||||
|
||||
/* Motion Vectors */
|
||||
short fmv[4];
|
||||
short bmv[4];
|
||||
su_t fmv;
|
||||
su_t bmv;
|
||||
/* CBP */
|
||||
uint cbp = (uint)mb->coded_block_pattern;
|
||||
/* gfxblock dword 1 */
|
||||
|
|
@ -1728,15 +1733,15 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
((cbp | ((cbp<<2) & 0x30))<<22);
|
||||
|
||||
|
||||
fmv[0] = mb->PMV[0][0][1]/2;
|
||||
fmv[1] = mb->PMV[0][0][0];
|
||||
fmv[2] = mb->PMV[1][0][1]/2;
|
||||
fmv[3] = mb->PMV[1][0][0];
|
||||
fmv.s[0] = mb->PMV[0][0][1]/2;
|
||||
fmv.s[1] = mb->PMV[0][0][0];
|
||||
fmv.s[2] = mb->PMV[1][0][1]/2;
|
||||
fmv.s[3] = mb->PMV[1][0][0];
|
||||
|
||||
bmv[0] = mb->PMV[0][1][1]/2;
|
||||
bmv[1] = mb->PMV[0][1][0];
|
||||
bmv[2] = mb->PMV[1][1][1]/2;
|
||||
bmv[3] = mb->PMV[1][1][0];
|
||||
bmv.s[0] = mb->PMV[0][1][1]/2;
|
||||
bmv.s[1] = mb->PMV[0][1][0];
|
||||
bmv.s[2] = mb->PMV[1][1][1]/2;
|
||||
bmv.s[3] = mb->PMV[1][1][0];
|
||||
|
||||
/*
|
||||
The i810 cannot use DCT0 directly with field motion, we have to
|
||||
|
|
@ -1772,8 +1777,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (2<<28) | dw1[0];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)&fmv[0];
|
||||
*dy++ = *(uint *)&bmv[0];
|
||||
*dy++ = fmv.u[0];
|
||||
*dy++ = bmv.u[0];
|
||||
if(dw1[0] & (1<<27)) {
|
||||
PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
|
||||
}
|
||||
|
|
@ -1786,8 +1791,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (2<<28) | dw1[1];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)&fmv[2];
|
||||
*dy++ = *(uint *)&bmv[2];
|
||||
*dy++ = fmv.u[1];
|
||||
*dy++ = bmv.u[1];
|
||||
if(dw1[1] & (1<<27)) {
|
||||
top_left_b = (short *)((unsigned long)top_left_b + 16);
|
||||
bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
|
||||
|
|
@ -1800,15 +1805,15 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
}
|
||||
/* End Y Blocks */
|
||||
|
||||
fmv[0] /= 2;
|
||||
fmv[1] /= 2;
|
||||
fmv[2] /= 2;
|
||||
fmv[3] /= 2;
|
||||
fmv.s[0] /= 2;
|
||||
fmv.s[1] /= 2;
|
||||
fmv.s[2] /= 2;
|
||||
fmv.s[3] /= 2;
|
||||
|
||||
bmv[0] /= 2;
|
||||
bmv[1] /= 2;
|
||||
bmv[2] /= 2;
|
||||
bmv[3] /= 2;
|
||||
bmv.s[0] /= 2;
|
||||
bmv.s[1] /= 2;
|
||||
bmv.s[2] /= 2;
|
||||
bmv.s[3] /= 2;
|
||||
|
||||
xy >>= 1;
|
||||
|
||||
|
|
@ -1817,8 +1822,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[0];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)&fmv[0];
|
||||
*du++ = *(uint *)&bmv[0];
|
||||
*du++ = fmv.u[0];
|
||||
*du++ = bmv.u[0];
|
||||
if(usize) {
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
}
|
||||
|
|
@ -1828,8 +1833,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[1];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)&fmv[2];
|
||||
*du++ = *(uint *)&bmv[2];
|
||||
*du++ = fmv.u[1];
|
||||
*du++ = bmv.u[1];
|
||||
if(usize) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
|
|
@ -1842,8 +1847,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[0];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)&fmv[0];
|
||||
*dv++ = *(uint *)&bmv[0];
|
||||
*dv++ = fmv.u[0];
|
||||
*dv++ = bmv.u[0];
|
||||
if(vsize) {
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
}
|
||||
|
|
@ -1853,8 +1858,8 @@ static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[1];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)&fmv[2];
|
||||
*dv++ = *(uint *)&bmv[2];
|
||||
*dv++ = fmv.u[1];
|
||||
*dv++ = bmv.u[1];
|
||||
if(vsize) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
|
|
@ -1882,8 +1887,8 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
|
|||
register uint *dv = *datav;
|
||||
|
||||
/* Motion Vectors */
|
||||
short fmv[2];
|
||||
short bmv[2];
|
||||
su_t fmv;
|
||||
su_t bmv;
|
||||
/* gfxblock dword 1 */
|
||||
uint dw1;
|
||||
|
||||
|
|
@ -1897,28 +1902,28 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
|
|||
(((uint)mb->coded_block_pattern)<<22);
|
||||
|
||||
|
||||
fmv[0] = mb->PMV[0][0][1];
|
||||
fmv[1] = mb->PMV[0][0][0];
|
||||
fmv.s[0] = mb->PMV[0][0][1];
|
||||
fmv.s[1] = mb->PMV[0][0][0];
|
||||
|
||||
bmv[0] = mb->PMV[0][1][1];
|
||||
bmv[1] = mb->PMV[0][1][0];
|
||||
bmv.s[0] = mb->PMV[0][1][1];
|
||||
bmv.s[1] = mb->PMV[0][1][0];
|
||||
|
||||
/* Y Block */
|
||||
*dy++ = GFXBLOCK + 4 + (ysize>>2);
|
||||
*dy++ = (1<<30) | (3<<28) | dw1;
|
||||
*dy++ = xy;
|
||||
*dy++ = (16<<16) | 16;
|
||||
*dy++ = *(uint *)fmv;
|
||||
*dy++ = *(uint *)bmv;
|
||||
*dy++ = fmv.u[0];
|
||||
*dy++ = bmv.u[0];
|
||||
PACK_CORR_DATA(dy,block_ptr,ysize);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + ysize);
|
||||
/* End Y Blocks */
|
||||
|
||||
fmv[0] /= 2;
|
||||
fmv[1] /= 2;
|
||||
fmv.s[0] /= 2;
|
||||
fmv.s[1] /= 2;
|
||||
|
||||
bmv[0] /= 2;
|
||||
bmv[1] /= 2;
|
||||
bmv.s[0] /= 2;
|
||||
bmv.s[1] /= 2;
|
||||
|
||||
xy >>= 1;
|
||||
|
||||
|
|
@ -1927,8 +1932,8 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1;
|
||||
*du++ = xy;
|
||||
*du++ = (8<<16) | 8;
|
||||
*du++ = *(uint *)fmv;
|
||||
*du++ = *(uint *)bmv;
|
||||
*du++ = fmv.u[0];
|
||||
*du++ = bmv.u[0];
|
||||
PACK_CORR_DATA(du,block_ptr,usize);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + usize);
|
||||
/* End U Block */
|
||||
|
|
@ -1938,8 +1943,8 @@ static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1;
|
||||
*dv++ = xy;
|
||||
*dv++ = (8<<16) | 8;
|
||||
*dv++ = *(uint *)fmv;
|
||||
*dv++ = *(uint *)bmv;
|
||||
*dv++ = fmv.u[0];
|
||||
*dv++ = bmv.u[0];
|
||||
PACK_CORR_DATA(dv,block_ptr,vsize);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + vsize);
|
||||
/* End V Block */
|
||||
|
|
@ -1963,8 +1968,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
|
|||
register uint *dv = *datav;
|
||||
|
||||
/* Motion Vectors */
|
||||
short fmv[4];
|
||||
short bmv[4];
|
||||
su_t fmv;
|
||||
su_t bmv;
|
||||
|
||||
short * top_left_b = NULL;
|
||||
short * top_right_b = NULL;
|
||||
|
|
@ -1982,11 +1987,11 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
|
|||
uint dw1 = type_table[mb->macroblock_type & 0xf] |
|
||||
(((uint)mb->coded_block_pattern)<<22);
|
||||
|
||||
fmv[0] = mb->PMV[0][0][1];
|
||||
fmv[1] = mb->PMV[0][0][0];
|
||||
fmv.s[0] = mb->PMV[0][0][1];
|
||||
fmv.s[1] = mb->PMV[0][0][0];
|
||||
|
||||
bmv[0] = mb->PMV[0][1][1];
|
||||
bmv[1] = mb->PMV[0][1][0];
|
||||
bmv.s[0] = mb->PMV[0][1][1];
|
||||
bmv.s[1] = mb->PMV[0][1][0];
|
||||
|
||||
/*
|
||||
It is easiest to find out what blocks are in need of reading first
|
||||
|
|
@ -2026,8 +2031,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (3<<28) | dw1;
|
||||
*dy++ = xy;
|
||||
*dy++ = (16<<16) | 16;
|
||||
*dy++ = *(uint *)fmv;
|
||||
*dy++ = *(uint *)bmv;
|
||||
*dy++ = fmv.u[0];
|
||||
*dy++ = bmv.u[0];
|
||||
if(dw1 & (1<<27)) {
|
||||
PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
|
||||
top_left_b = (short *)((unsigned long)top_left_b + 64);
|
||||
|
|
@ -2046,11 +2051,11 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
|
|||
}
|
||||
/* End Y Block */
|
||||
|
||||
fmv[0] /= 2;
|
||||
fmv[1] /= 2;
|
||||
fmv.s[0] /= 2;
|
||||
fmv.s[1] /= 2;
|
||||
|
||||
bmv[0] /= 2;
|
||||
bmv[1] /= 2;
|
||||
bmv.s[0] /= 2;
|
||||
bmv.s[1] /= 2;
|
||||
|
||||
xy >>= 1;
|
||||
|
||||
|
|
@ -2059,8 +2064,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1;
|
||||
*du++ = xy;
|
||||
*du++ = (8<<16) | 8;
|
||||
*du++ = *(uint *)fmv;
|
||||
*du++ = *(uint *)bmv;
|
||||
*du++ = fmv.u[0];
|
||||
*du++ = bmv.u[0];
|
||||
PACK_CORR_DATA(du,block_ptr,usize);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + usize);
|
||||
|
||||
|
|
@ -2069,8 +2074,8 @@ static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1;
|
||||
*dv++ = xy;
|
||||
*dv++ = (8<<16) | 8;
|
||||
*dv++ = *(uint *)fmv;
|
||||
*dv++ = *(uint *)bmv;
|
||||
*dv++ = fmv.u[0];
|
||||
*dv++ = bmv.u[0];
|
||||
PACK_CORR_DATA(dv,block_ptr,vsize);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + vsize);
|
||||
|
||||
|
|
@ -2093,8 +2098,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
register uint *dv = *datav;
|
||||
|
||||
/* Motion Vectors */
|
||||
short fmv[4];
|
||||
short bmv[4];
|
||||
su_t fmv;
|
||||
su_t bmv;
|
||||
/* gfxblock dword 1 */
|
||||
uint dw1[2];
|
||||
|
||||
|
|
@ -2115,23 +2120,23 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
((mb->coded_block_pattern & 0xc)<<2))<<22) |
|
||||
3<<12 | 3<<6 | 3<<3 | 2;
|
||||
|
||||
fmv[0] = mb->PMV[0][0][1];
|
||||
fmv[1] = mb->PMV[0][0][0];
|
||||
bmv[0] = mb->PMV[1][0][1];
|
||||
bmv[1] = mb->PMV[1][0][0];
|
||||
fmv.s[0] = mb->PMV[0][0][1];
|
||||
fmv.s[1] = mb->PMV[0][0][0];
|
||||
bmv.s[0] = mb->PMV[1][0][1];
|
||||
bmv.s[1] = mb->PMV[1][0][0];
|
||||
|
||||
fmv[2] = mb->PMV[0][0][1];
|
||||
fmv[3] = mb->PMV[0][0][0];
|
||||
bmv[2] = mb->PMV[1][1][1];
|
||||
bmv[3] = mb->PMV[1][1][0];
|
||||
fmv.s[2] = mb->PMV[0][0][1];
|
||||
fmv.s[3] = mb->PMV[0][0][0];
|
||||
bmv.s[2] = mb->PMV[1][1][1];
|
||||
bmv.s[3] = mb->PMV[1][1][0];
|
||||
|
||||
/* First Y Block */
|
||||
*dy++ = GFXBLOCK + 4 + (y1size>>2);
|
||||
*dy++ = (1<<30) | (2<<28) | dw1[0];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)fmv;
|
||||
*dy++ = *(uint *)bmv;;
|
||||
*dy++ = fmv.u[0];
|
||||
*dy++ = bmv.u[0];;
|
||||
PACK_CORR_DATA(dy,block_ptr,y1size);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + y1size);
|
||||
|
||||
|
|
@ -2140,20 +2145,20 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (2<<28) | dw1[1];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)&fmv[2];
|
||||
*dy++ = *(uint *)&bmv[2];
|
||||
*dy++ = fmv.u[1];
|
||||
*dy++ = bmv.u[1];
|
||||
PACK_CORR_DATA(dy,block_ptr,y2size);
|
||||
block_ptr = (short *)((unsigned long)block_ptr + y2size);
|
||||
|
||||
fmv[0] /= 2;
|
||||
fmv[1] /= 2;
|
||||
bmv[0] /= 2;
|
||||
bmv[1] /= 2;
|
||||
fmv.s[0] /= 2;
|
||||
fmv.s[1] /= 2;
|
||||
bmv.s[0] /= 2;
|
||||
bmv.s[1] /= 2;
|
||||
|
||||
fmv[2] /= 2;
|
||||
fmv[3] /= 2;
|
||||
bmv[2] /= 2;
|
||||
bmv[3] /= 2;
|
||||
fmv.s[2] /= 2;
|
||||
fmv.s[3] /= 2;
|
||||
bmv.s[2] /= 2;
|
||||
bmv.s[3] /= 2;
|
||||
|
||||
xy >>= 1;
|
||||
|
||||
|
|
@ -2162,8 +2167,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[0];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)fmv;
|
||||
*du++ = *(uint *)bmv;
|
||||
*du++ = fmv.u[0];
|
||||
*du++ = bmv.u[0];
|
||||
if(dw1[0] & (1<<23)) {
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
}
|
||||
|
|
@ -2173,8 +2178,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[1];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)&fmv[2];
|
||||
*du++ = *(uint *)&bmv[2];
|
||||
*du++ = fmv.u[1];
|
||||
*du++ = bmv.u[1];
|
||||
if(dw1[1] & (1<<23)) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
|
|
@ -2187,8 +2192,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[0];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)fmv;
|
||||
*dv++ = *(uint *)bmv;
|
||||
*dv++ = fmv.u[0];
|
||||
*dv++ = bmv.u[0];
|
||||
if(dw1[0] & (1<<22)) {
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
}
|
||||
|
|
@ -2198,8 +2203,8 @@ static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[1];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)&fmv[2];
|
||||
*dv++ = *(uint *)&bmv[2];
|
||||
*dv++ = fmv.u[1];
|
||||
*dv++ = bmv.u[1];
|
||||
if(dw1[1] & (1<<22)) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
|
|
@ -2228,8 +2233,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
register uint *dv = *datav;
|
||||
|
||||
/* Motion Vectors */
|
||||
short fmv[4];
|
||||
short bmv[4];
|
||||
su_t fmv;
|
||||
su_t bmv;
|
||||
/* gfxblock dword 1 */
|
||||
uint dw1[2];
|
||||
|
||||
|
|
@ -2255,15 +2260,15 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) |
|
||||
3<<12 | 3<<6 | 3<<3 | 2;
|
||||
|
||||
fmv[0] = mb->PMV[0][0][1];
|
||||
fmv[1] = mb->PMV[0][0][0];
|
||||
bmv[0] = mb->PMV[1][0][1];
|
||||
bmv[1] = mb->PMV[1][0][0];
|
||||
fmv.s[0] = mb->PMV[0][0][1];
|
||||
fmv.s[1] = mb->PMV[0][0][0];
|
||||
bmv.s[0] = mb->PMV[1][0][1];
|
||||
bmv.s[1] = mb->PMV[1][0][0];
|
||||
|
||||
fmv[2] = mb->PMV[0][0][1];
|
||||
fmv[3] = mb->PMV[0][0][0];
|
||||
bmv[2] = mb->PMV[1][1][1];
|
||||
bmv[3] = mb->PMV[1][1][0];
|
||||
fmv.s[2] = mb->PMV[0][0][1];
|
||||
fmv.s[3] = mb->PMV[0][0][0];
|
||||
bmv.s[2] = mb->PMV[1][1][1];
|
||||
bmv.s[3] = mb->PMV[1][1][0];
|
||||
|
||||
/*
|
||||
The i810 cannot use DCT0 directly with field motion, we have to
|
||||
|
|
@ -2299,8 +2304,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (2<<28) | dw1[0];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)fmv;
|
||||
*dy++ = *(uint *)bmv;
|
||||
*dy++ = fmv.u[0];
|
||||
*dy++ = bmv.u[0];
|
||||
if(cbp & 0x20) {
|
||||
PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
|
||||
}
|
||||
|
|
@ -2313,8 +2318,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
*dy++ = (1<<30) | (2<<28) | dw1[1];
|
||||
*dy++ = xy;
|
||||
*dy++ = (8<<16) | 16;
|
||||
*dy++ = *(uint *)&fmv[2];
|
||||
*dy++ = *(uint *)&bmv[2];
|
||||
*dy++ = fmv.u[1];
|
||||
*dy++ = bmv.u[1];
|
||||
if(cbp & 0x20) {
|
||||
top_left_b = (short *)((unsigned long)top_left_b + 16);
|
||||
bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
|
||||
|
|
@ -2328,15 +2333,15 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
/* End Y Blocks */
|
||||
|
||||
|
||||
fmv[0] /= 2;
|
||||
fmv[1] /= 2;
|
||||
bmv[0] /= 2;
|
||||
bmv[1] /= 2;
|
||||
fmv.s[0] /= 2;
|
||||
fmv.s[1] /= 2;
|
||||
bmv.s[0] /= 2;
|
||||
bmv.s[1] /= 2;
|
||||
|
||||
fmv[2] /= 2;
|
||||
fmv[3] /= 2;
|
||||
bmv[2] /= 2;
|
||||
bmv[3] /= 2;
|
||||
fmv.s[2] /= 2;
|
||||
fmv.s[3] /= 2;
|
||||
bmv.s[2] /= 2;
|
||||
bmv.s[3] /= 2;
|
||||
|
||||
xy >>= 1;
|
||||
|
||||
|
|
@ -2345,8 +2350,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[0];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)fmv;
|
||||
*du++ = *(uint *)bmv;
|
||||
*du++ = fmv.u[0];
|
||||
*du++ = bmv.u[0];
|
||||
if(cbp & (1<<23)) {
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
}
|
||||
|
|
@ -2356,8 +2361,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
*du++ = (2<<30) | (1<<28) | dw1[1];
|
||||
*du++ = xy;
|
||||
*du++ = (4<<16) | 8;
|
||||
*du++ = *(uint *)&fmv[2];
|
||||
*du++ = *(uint *)&bmv[2];
|
||||
*du++ = fmv.u[1];
|
||||
*du++ = bmv.u[1];
|
||||
if(cbp & (1<<23)) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(du,block_ptr);
|
||||
|
|
@ -2370,8 +2375,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[0];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)fmv;
|
||||
*dv++ = *(uint *)bmv;
|
||||
*dv++ = fmv.u[0];
|
||||
*dv++ = bmv.u[0];
|
||||
if(cbp & (1<<22)) {
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
}
|
||||
|
|
@ -2381,8 +2386,8 @@ static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
|
|||
*dv++ = (3<<30) | (1<<28) | dw1[1];
|
||||
*dv++ = xy;
|
||||
*dv++ = (4<<16) | 8;
|
||||
*dv++ = *(uint *)&fmv[2];
|
||||
*dv++ = *(uint *)&bmv[2];
|
||||
*dv++ = fmv.u[1];
|
||||
*dv++ = bmv.u[1];
|
||||
if(cbp & (1<<22)) {
|
||||
block_ptr = (short *)((unsigned long)block_ptr + 16);
|
||||
PACK_CORR_DATA_SHORT(dv,block_ptr);
|
||||
|
|
|
|||
Loading…
Reference in New Issue